regulator: Use container_of_const() when all types are

Merge series from Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>:

Use container_of_const(), which is preferred over container_of(), when
the argument 'ptr' and returned pointer are already const, for better
code safety and readability.

Some drivers already have const everywhere, so container_of_const can be
directly used. In few other drivers, the final pointer can be constified
that way.
This commit is contained in:
Mark Brown
2025-11-26 21:21:57 +00:00
27 changed files with 2168 additions and 35 deletions
@@ -0,0 +1,161 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/nxp,pf1550.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP PF1550 Power Management IC
maintainers:
- Samuel Kayode <samuel.kayode@savoirfairelinux.com>
description:
PF1550 PMIC provides battery charging and power supply for low power IoT and
wearable applications. This device consists of an i2c controlled MFD that
includes regulators, battery charging and an onkey/power button.
$ref: /schemas/power/supply/power-supply.yaml
properties:
compatible:
const: nxp,pf1550
reg:
maxItems: 1
interrupts:
maxItems: 1
wakeup-source: true
regulators:
type: object
additionalProperties: false
patternProperties:
"^(ldo[1-3]|sw[1-3]|vrefddr)$":
type: object
$ref: /schemas/regulator/regulator.yaml
description:
regulator configuration for ldo1-3, buck converters(sw1-3)
and DDR termination reference voltage (vrefddr)
unevaluatedProperties: false
monitored-battery:
description: |
A phandle to a monitored battery node that contains a valid value
for:
constant-charge-voltage-max-microvolt.
nxp,thermal-regulation-celsius:
description:
Temperature threshold for thermal regulation of charger in celsius.
enum: [ 80, 95, 110, 125 ]
nxp,min-system-microvolt:
description:
System specific lower limit voltage.
enum: [ 3500000, 3700000, 4300000 ]
nxp,disable-key-power:
type: boolean
description:
Disable power-down using a long key-press. The onkey driver will remove
support for the KEY_POWER key press when triggered using a long press of
the onkey.
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/input/linux-event-codes.h>
battery: battery-cell {
compatible = "simple-battery";
constant-charge-voltage-max-microvolt = <4400000>;
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@8 {
compatible = "nxp,pf1550";
reg = <0x8>;
interrupt-parent = <&gpio1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
wakeup-source;
monitored-battery = <&battery>;
nxp,min-system-microvolt = <4300000>;
nxp,thermal-regulation-celsius = <80>;
regulators {
sw1_reg: sw1 {
regulator-name = "sw1";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1387500>;
regulator-always-on;
regulator-ramp-delay = <6250>;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-min-microvolt = <1270000>;
};
};
sw2_reg: sw2 {
regulator-name = "sw2";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1387500>;
regulator-always-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
sw3_reg: sw3 {
regulator-name = "sw3";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
vldo1_reg: ldo1 {
regulator-name = "ldo1";
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
vldo2_reg: ldo2 {
regulator-name = "ldo2";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vldo3_reg: ldo3 {
regulator-name = "ldo3";
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
};
+11
View File
@@ -18636,6 +18636,17 @@ S: Maintained
F: Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml
F: drivers/regulator/pf530x-regulator.c
NXP PF1550 PMIC MFD DRIVER
M: Samuel Kayode <samuel.kayode@savoirfairelinux.com>
L: imx@lists.linux.dev
S: Maintained
F: Documentation/devicetree/bindings/mfd/nxp,pf1550.yaml
F: drivers/input/misc/pf1550-onkey.c
F: drivers/mfd/pf1550.c
F: drivers/power/supply/pf1550-charger.c
F: drivers/regulator/pf1550-regulator.c
F: include/linux/mfd/pfd1550.h
NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
M: Jagan Teki <jagan@amarulasolutions.com>
S: Maintained
+11
View File
@@ -190,6 +190,17 @@ config INPUT_PCSPKR
To compile this driver as a module, choose M here: the
module will be called pcspkr.
config INPUT_PF1550_ONKEY
tristate "NXP PF1550 Onkey support"
depends on MFD_PF1550
help
Say Y here if you want support for PF1550 PMIC. Onkey can trigger
release and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press
detect.
To compile this driver as a module, choose M here. The module will be
called pf1550-onkey.
config INPUT_PM8941_PWRKEY
tristate "Qualcomm PM8941 power key support"
depends on MFD_SPMI_PMIC
+1
View File
@@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_PF1550_ONKEY) += pf1550-onkey.o
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
+197
View File
@@ -0,0 +1,197 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the PF1550 ONKEY
* Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
*/
#include <linux/err.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mfd/pf1550.h>
#include <linux/platform_device.h>
#define PF1550_ONKEY_IRQ_NR 6
struct onkey_drv_data {
struct device *dev;
const struct pf1550_ddata *pf1550;
bool wakeup;
struct input_dev *input;
};
static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
{
struct onkey_drv_data *onkey = data;
struct platform_device *pdev = to_platform_device(onkey->dev);
int i, state, irq_type = -1;
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++)
if (irq == platform_get_irq(pdev, i))
irq_type = i;
switch (irq_type) {
case PF1550_ONKEY_IRQ_PUSHI:
state = 0;
break;
case PF1550_ONKEY_IRQ_1SI:
case PF1550_ONKEY_IRQ_2SI:
case PF1550_ONKEY_IRQ_3SI:
case PF1550_ONKEY_IRQ_4SI:
case PF1550_ONKEY_IRQ_8SI:
state = 1;
break;
default:
dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
irq_type);
return IRQ_HANDLED;
}
input_event(onkey->input, EV_KEY, KEY_POWER, state);
input_sync(onkey->input);
return IRQ_HANDLED;
}
static int pf1550_onkey_probe(struct platform_device *pdev)
{
struct onkey_drv_data *onkey;
struct input_dev *input;
bool key_power = false;
int i, irq, error;
onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
if (!onkey)
return -ENOMEM;
onkey->dev = &pdev->dev;
onkey->pf1550 = dev_get_drvdata(pdev->dev.parent);
if (!onkey->pf1550->regmap)
return dev_err_probe(&pdev->dev, -ENODEV,
"failed to get regmap\n");
onkey->wakeup = device_property_read_bool(pdev->dev.parent,
"wakeup-source");
if (device_property_read_bool(pdev->dev.parent,
"nxp,disable-key-power")) {
error = regmap_clear_bits(onkey->pf1550->regmap,
PF1550_PMIC_REG_PWRCTRL1,
PF1550_ONKEY_RST_EN);
if (error)
return dev_err_probe(&pdev->dev, error,
"failed: disable turn system off");
} else {
key_power = true;
}
input = devm_input_allocate_device(&pdev->dev);
if (!input)
return dev_err_probe(&pdev->dev, -ENOMEM,
"failed to allocate the input device\n");
input->name = pdev->name;
input->phys = "pf1550-onkey/input0";
input->id.bustype = BUS_HOST;
if (key_power)
input_set_capability(input, EV_KEY, KEY_POWER);
onkey->input = input;
platform_set_drvdata(pdev, onkey);
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
irq = platform_get_irq(pdev, i);
if (irq < 0)
return irq;
error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
pf1550_onkey_irq_handler,
IRQF_NO_SUSPEND,
"pf1550-onkey", onkey);
if (error)
return dev_err_probe(&pdev->dev, error,
"failed: irq request (IRQ: %d)\n",
i);
}
error = input_register_device(input);
if (error)
return dev_err_probe(&pdev->dev, error,
"failed to register input device\n");
device_init_wakeup(&pdev->dev, onkey->wakeup);
return 0;
}
static int pf1550_onkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
int i, irq;
if (!device_may_wakeup(&pdev->dev))
regmap_write(onkey->pf1550->regmap,
PF1550_PMIC_REG_ONKEY_INT_MASK0,
ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
else
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
irq = platform_get_irq(pdev, i);
if (irq > 0)
enable_irq_wake(irq);
}
return 0;
}
static int pf1550_onkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
int i, irq;
if (!device_may_wakeup(&pdev->dev))
regmap_write(onkey->pf1550->regmap,
PF1550_PMIC_REG_ONKEY_INT_MASK0,
~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI |
ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI |
ONKEY_IRQ_8SI)));
else
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
irq = platform_get_irq(pdev, i);
if (irq > 0)
disable_irq_wake(irq);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
pf1550_onkey_resume);
static const struct platform_device_id pf1550_onkey_id[] = {
{ "pf1550-onkey", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, pf1550_onkey_id);
static struct platform_driver pf1550_onkey_driver = {
.driver = {
.name = "pf1550-onkey",
.pm = pm_sleep_ptr(&pf1550_onkey_pm_ops),
},
.probe = pf1550_onkey_probe,
.id_table = pf1550_onkey_id,
};
module_platform_driver(pf1550_onkey_driver);
MODULE_AUTHOR("Freescale Semiconductor");
MODULE_DESCRIPTION("PF1550 onkey Driver");
MODULE_LICENSE("GPL");
+16
View File
@@ -605,6 +605,22 @@ config MFD_MX25_TSADC
i.MX25 processors. They consist of a conversion queue for general
purpose ADC and a queue for Touchscreens.
config MFD_PF1550
tristate "NXP PF1550 PMIC Support"
depends on I2C=y && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
Say yes here to add support for NXP PF1550. This is a companion Power
Management IC with regulators, onkey, and charger control on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
This driver can also be built as a module and if so will be called
pf1550.
config MFD_HI6421_PMIC
tristate "HiSilicon Hi6421 PMU/Codec IC"
depends on OF
+2
View File
@@ -122,6 +122,8 @@ obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
obj-$(CONFIG_MFD_PF1550) += pf1550.o
obj-$(CONFIG_MFD_NCT6694) += nct6694.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
+367
View File
@@ -0,0 +1,367 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Core driver for the PF1550
*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
* Robin Gong <yibin.gong@freescale.com>
*
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/pf1550.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
static const struct regmap_config pf1550_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = PF1550_PMIC_REG_END,
};
static const struct regmap_irq pf1550_irqs[] = {
REGMAP_IRQ_REG(PF1550_IRQ_CHG, 0, IRQ_CHG),
REGMAP_IRQ_REG(PF1550_IRQ_REGULATOR, 0, IRQ_REGULATOR),
REGMAP_IRQ_REG(PF1550_IRQ_ONKEY, 0, IRQ_ONKEY),
};
static const struct regmap_irq_chip pf1550_irq_chip = {
.name = "pf1550",
.status_base = PF1550_PMIC_REG_INT_CATEGORY,
.init_ack_masked = 1,
.num_regs = 1,
.irqs = pf1550_irqs,
.num_irqs = ARRAY_SIZE(pf1550_irqs),
};
static const struct regmap_irq pf1550_regulator_irqs[] = {
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_LS, 0, PMIC_IRQ_SW1_LS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_LS, 0, PMIC_IRQ_SW2_LS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_LS, 0, PMIC_IRQ_SW3_LS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_HS, 3, PMIC_IRQ_SW1_HS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_HS, 3, PMIC_IRQ_SW2_HS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_HS, 3, PMIC_IRQ_SW3_HS),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO1_FAULT, 16, PMIC_IRQ_LDO1_FAULT),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO2_FAULT, 16, PMIC_IRQ_LDO2_FAULT),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO3_FAULT, 16, PMIC_IRQ_LDO3_FAULT),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_110, 24, PMIC_IRQ_TEMP_110),
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_125, 24, PMIC_IRQ_TEMP_125),
};
static const struct regmap_irq_chip pf1550_regulator_irq_chip = {
.name = "pf1550-regulator",
.status_base = PF1550_PMIC_REG_SW_INT_STAT0,
.ack_base = PF1550_PMIC_REG_SW_INT_STAT0,
.mask_base = PF1550_PMIC_REG_SW_INT_MASK0,
.use_ack = 1,
.init_ack_masked = 1,
.num_regs = 25,
.irqs = pf1550_regulator_irqs,
.num_irqs = ARRAY_SIZE(pf1550_regulator_irqs),
};
static const struct resource regulator_resources[] = {
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_LS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_LS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_LS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_HS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_HS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_HS),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO1_FAULT),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO2_FAULT),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO3_FAULT),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_110),
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_125),
};
static const struct regmap_irq pf1550_onkey_irqs[] = {
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_PUSHI, 0, ONKEY_IRQ_PUSHI),
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_1SI, 0, ONKEY_IRQ_1SI),
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_2SI, 0, ONKEY_IRQ_2SI),
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_3SI, 0, ONKEY_IRQ_3SI),
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_4SI, 0, ONKEY_IRQ_4SI),
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_8SI, 0, ONKEY_IRQ_8SI),
};
static const struct regmap_irq_chip pf1550_onkey_irq_chip = {
.name = "pf1550-onkey",
.status_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
.ack_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
.mask_base = PF1550_PMIC_REG_ONKEY_INT_MASK0,
.use_ack = 1,
.init_ack_masked = 1,
.num_regs = 1,
.irqs = pf1550_onkey_irqs,
.num_irqs = ARRAY_SIZE(pf1550_onkey_irqs),
};
static const struct resource onkey_resources[] = {
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_PUSHI),
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_1SI),
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_2SI),
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_3SI),
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_4SI),
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_8SI),
};
static const struct regmap_irq pf1550_charger_irqs[] = {
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BAT2SOCI, 0, CHARG_IRQ_BAT2SOCI),
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BATI, 0, CHARG_IRQ_BATI),
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_CHGI, 0, CHARG_IRQ_CHGI),
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_VBUSI, 0, CHARG_IRQ_VBUSI),
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_THMI, 0, CHARG_IRQ_THMI),
};
static const struct regmap_irq_chip pf1550_charger_irq_chip = {
.name = "pf1550-charger",
.status_base = PF1550_CHARG_REG_CHG_INT,
.ack_base = PF1550_CHARG_REG_CHG_INT,
.mask_base = PF1550_CHARG_REG_CHG_INT_MASK,
.use_ack = 1,
.init_ack_masked = 1,
.num_regs = 1,
.irqs = pf1550_charger_irqs,
.num_irqs = ARRAY_SIZE(pf1550_charger_irqs),
};
static const struct resource charger_resources[] = {
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BAT2SOCI),
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BATI),
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_CHGI),
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_VBUSI),
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_THMI),
};
static const struct mfd_cell pf1550_regulator_cell = {
.name = "pf1550-regulator",
.num_resources = ARRAY_SIZE(regulator_resources),
.resources = regulator_resources,
};
static const struct mfd_cell pf1550_onkey_cell = {
.name = "pf1550-onkey",
.num_resources = ARRAY_SIZE(onkey_resources),
.resources = onkey_resources,
};
static const struct mfd_cell pf1550_charger_cell = {
.name = "pf1550-charger",
.num_resources = ARRAY_SIZE(charger_resources),
.resources = charger_resources,
};
/*
* The PF1550 is shipped in variants of A0, A1,...A9. Each variant defines a
* configuration of the PMIC in a One-Time Programmable (OTP) memory.
* This memory is accessed indirectly by writing valid keys to specific
* registers of the PMIC. To read the OTP memory after writing the valid keys,
* the OTP register address to be read is written to pf1550 register 0xc4 and
* its value read from pf1550 register 0xc5.
*/
static int pf1550_read_otp(const struct pf1550_ddata *pf1550, unsigned int index,
unsigned int *val)
{
int ret = 0;
ret = regmap_write(pf1550->regmap, PF1550_PMIC_REG_KEY, PF1550_OTP_PMIC_KEY);
if (ret)
goto read_err;
ret = regmap_write(pf1550->regmap, PF1550_CHARG_REG_CHGR_KEY2, PF1550_OTP_CHGR_KEY);
if (ret)
goto read_err;
ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_KEY3, PF1550_OTP_TEST_KEY);
if (ret)
goto read_err;
ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_FMRADDR, index);
if (ret)
goto read_err;
ret = regmap_read(pf1550->regmap, PF1550_TEST_REG_FMRDATA, val);
if (ret)
goto read_err;
return 0;
read_err:
return dev_err_probe(pf1550->dev, ret, "OTP reg %x not found!\n", index);
}
static int pf1550_i2c_probe(struct i2c_client *i2c)
{
const struct mfd_cell *regulator = &pf1550_regulator_cell;
const struct mfd_cell *charger = &pf1550_charger_cell;
const struct mfd_cell *onkey = &pf1550_onkey_cell;
unsigned int reg_data = 0, otp_data = 0;
struct pf1550_ddata *pf1550;
struct irq_domain *domain;
int irq, ret = 0;
pf1550 = devm_kzalloc(&i2c->dev, sizeof(*pf1550), GFP_KERNEL);
if (!pf1550)
return -ENOMEM;
i2c_set_clientdata(i2c, pf1550);
pf1550->dev = &i2c->dev;
pf1550->irq = i2c->irq;
pf1550->regmap = devm_regmap_init_i2c(i2c, &pf1550_regmap_config);
if (IS_ERR(pf1550->regmap))
return dev_err_probe(pf1550->dev, PTR_ERR(pf1550->regmap),
"failed to allocate register map\n");
ret = regmap_read(pf1550->regmap, PF1550_PMIC_REG_DEVICE_ID, &reg_data);
if (ret < 0)
return dev_err_probe(pf1550->dev, ret, "cannot read chip ID\n");
if (reg_data != PF1550_DEVICE_ID)
return dev_err_probe(pf1550->dev, -ENODEV, "invalid device ID: 0x%02x\n", reg_data);
/* Regulator DVS for SW2 */
ret = pf1550_read_otp(pf1550, PF1550_OTP_SW2_SW3, &otp_data);
if (ret)
return ret;
/* When clear, DVS should be enabled */
if (!(otp_data & OTP_SW2_DVS_ENB))
pf1550->dvs2_enable = true;
/* Regulator DVS for SW1 */
ret = pf1550_read_otp(pf1550, PF1550_OTP_SW1_SW2, &otp_data);
if (ret)
return ret;
if (!(otp_data & OTP_SW1_DVS_ENB))
pf1550->dvs1_enable = true;
/* Add top level interrupts */
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, pf1550->irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING,
0, &pf1550_irq_chip,
&pf1550->irq_data);
if (ret)
return ret;
/* Add regulator */
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_REGULATOR);
if (irq < 0)
return dev_err_probe(pf1550->dev, irq,
"Failed to get parent vIRQ(%d) for chip %s\n",
PF1550_IRQ_REGULATOR, pf1550_irq_chip.name);
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
&pf1550_regulator_irq_chip,
&pf1550->irq_data_regulator);
if (ret)
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
pf1550_regulator_irq_chip.name);
domain = regmap_irq_get_domain(pf1550->irq_data_regulator);
ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, regulator, 1, NULL, 0, domain);
if (ret)
return ret;
/* Add onkey */
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_ONKEY);
if (irq < 0)
return dev_err_probe(pf1550->dev, irq,
"Failed to get parent vIRQ(%d) for chip %s\n",
PF1550_IRQ_ONKEY, pf1550_irq_chip.name);
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
&pf1550_onkey_irq_chip,
&pf1550->irq_data_onkey);
if (ret)
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
pf1550_onkey_irq_chip.name);
domain = regmap_irq_get_domain(pf1550->irq_data_onkey);
ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, onkey, 1, NULL, 0, domain);
if (ret)
return ret;
/* Add battery charger */
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_CHG);
if (irq < 0)
return dev_err_probe(pf1550->dev, irq,
"Failed to get parent vIRQ(%d) for chip %s\n",
PF1550_IRQ_CHG, pf1550_irq_chip.name);
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
IRQF_ONESHOT | IRQF_SHARED |
IRQF_TRIGGER_FALLING, 0,
&pf1550_charger_irq_chip,
&pf1550->irq_data_charger);
if (ret)
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
pf1550_charger_irq_chip.name);
domain = regmap_irq_get_domain(pf1550->irq_data_charger);
return devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, charger, 1, NULL, 0, domain);
}
static int pf1550_suspend(struct device *dev)
{
struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
enable_irq_wake(pf1550->irq);
disable_irq(pf1550->irq);
}
return 0;
}
static int pf1550_resume(struct device *dev)
{
struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
disable_irq_wake(pf1550->irq);
enable_irq(pf1550->irq);
}
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(pf1550_pm, pf1550_suspend, pf1550_resume);
static const struct i2c_device_id pf1550_i2c_id[] = {
{ "pf1550" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, pf1550_i2c_id);
static const struct of_device_id pf1550_dt_match[] = {
{ .compatible = "nxp,pf1550" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pf1550_dt_match);
static struct i2c_driver pf1550_i2c_driver = {
.driver = {
.name = "pf1550",
.pm = pm_sleep_ptr(&pf1550_pm),
.of_match_table = pf1550_dt_match,
},
.probe = pf1550_i2c_probe,
.id_table = pf1550_i2c_id,
};
module_i2c_driver(pf1550_i2c_driver);
MODULE_DESCRIPTION("NXP PF1550 core driver");
MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
MODULE_LICENSE("GPL");
+11
View File
@@ -486,6 +486,17 @@ config CHARGER_88PM860X
help
Say Y here to enable charger for Marvell 88PM860x chip.
config CHARGER_PF1550
tristate "NXP PF1550 battery charger driver"
depends on MFD_PF1550
help
Say Y to enable support for the NXP PF1550 battery charger.
The device is a single cell Li-Ion/Li-Polymer battery charger for
portable application.
This driver can also be built as a module. If so, the module will be
called pf1550-charger.
config BATTERY_RX51
tristate "Nokia RX-51 (N900) battery driver"
depends on TWL4030_MADC
+1
View File
@@ -66,6 +66,7 @@ obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o
obj-$(CONFIG_CHARGER_RT9471) += rt9471.o
obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o
obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o
obj-$(CONFIG_CHARGER_PF1550) += pf1550-charger.o
obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o ab8500_chargalg.o
obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o
File diff suppressed because it is too large Load Diff
+9
View File
@@ -1116,6 +1116,15 @@ config REGULATOR_PV88090
Say y here to support the voltage regulators and convertors
on PV88090
config REGULATOR_PF1550
tristate "NXP PF1550 regulator"
depends on MFD_PF1550
help
Say y here to select this option to enable the regulators on
the PF1550 PMICs.
This driver controls the PF1550 regulators via I2C bus.
The regulators include three bucks and three ldos.
config REGULATOR_PWM
tristate "PWM voltage regulator"
depends on PWM
+1
View File
@@ -131,6 +131,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
obj-$(CONFIG_REGULATOR_PF0900) += pf0900-regulator.o
obj-$(CONFIG_REGULATOR_PF9453) += pf9453-regulator.o
obj-$(CONFIG_REGULATOR_PF1550) += pf1550-regulator.o
obj-$(CONFIG_REGULATOR_PF530X) += pf530x-regulator.o
obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
+4 -4
View File
@@ -173,9 +173,9 @@ static int set_hw_dvs_levels(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *cfg)
{
struct bd71815_regulator *data;
const struct bd71815_regulator *data;
data = container_of(desc, struct bd71815_regulator, desc);
data = container_of_const(desc, struct bd71815_regulator, desc);
return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap);
}
@@ -195,10 +195,10 @@ static int buck12_set_hw_dvs_levels(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *cfg)
{
struct bd71815_regulator *data;
const struct bd71815_regulator *data;
int ret = 0, val;
data = container_of(desc, struct bd71815_regulator, desc);
data = container_of_const(desc, struct bd71815_regulator, desc);
if (of_property_present(np, "rohm,dvs-run-voltage") ||
of_property_present(np, "rohm,dvs-suspend-voltage") ||
+2 -2
View File
@@ -95,9 +95,9 @@ static int buck_set_hw_dvs_levels(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *cfg)
{
struct bd71828_regulator_data *data;
const struct bd71828_regulator_data *data;
data = container_of(desc, struct bd71828_regulator_data, desc);
data = container_of_const(desc, struct bd71828_regulator_data, desc);
return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
}
+2 -2
View File
@@ -698,9 +698,9 @@ static int buck_set_hw_dvs_levels(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *cfg)
{
struct bd718xx_regulator_data *data;
const struct bd718xx_regulator_data *data;
data = container_of(desc, struct bd718xx_regulator_data, desc);
data = container_of_const(desc, struct bd718xx_regulator_data, desc);
return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
}
+5 -5
View File
@@ -337,12 +337,12 @@ static int ldo_map_notif(int irq, struct regulator_irq_data *rid,
int i;
for (i = 0; i < rid->num_states; i++) {
struct bd96801_regulator_data *rdata;
const struct bd96801_regulator_data *rdata;
struct regulator_dev *rdev;
rdev = rid->states[i].rdev;
rdata = container_of(rdev->desc, struct bd96801_regulator_data,
desc);
rdata = container_of_const(rdev->desc, struct bd96801_regulator_data,
desc);
rid->states[i].notifs = regulator_err2notif(rdata->ldo_errs);
rid->states[i].errors = rdata->ldo_errs;
*dev_mask |= BIT(i);
@@ -354,9 +354,9 @@ static int bd96801_list_voltage_lr(struct regulator_dev *rdev,
unsigned int selector)
{
int voltage;
struct bd96801_regulator_data *data;
const struct bd96801_regulator_data *data;
data = container_of(rdev->desc, struct bd96801_regulator_data, desc);
data = container_of_const(rdev->desc, struct bd96801_regulator_data, desc);
/*
* The BD096801 has voltage setting in two registers. One giving the
+5 -5
View File
@@ -387,7 +387,7 @@ static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev)
const struct hi6421_regulator_info *info;
unsigned int reg_val;
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & info->mode_mask)
return REGULATOR_MODE_IDLE;
@@ -400,7 +400,7 @@ static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev)
const struct hi6421_regulator_info *info;
unsigned int reg_val;
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & info->mode_mask)
return REGULATOR_MODE_STANDBY;
@@ -414,7 +414,7 @@ static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev,
const struct hi6421_regulator_info *info;
unsigned int new_mode;
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
switch (mode) {
case REGULATOR_MODE_NORMAL:
new_mode = 0;
@@ -439,7 +439,7 @@ static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
const struct hi6421_regulator_info *info;
unsigned int new_mode;
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
switch (mode) {
case REGULATOR_MODE_NORMAL:
new_mode = 0;
@@ -464,7 +464,7 @@ hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
{
const struct hi6421_regulator_info *info;
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
if (load_uA > info->eco_microamp)
return REGULATOR_MODE_NORMAL;
+2 -2
View File
@@ -110,7 +110,7 @@ static unsigned int hi6421v530_regulator_ldo_get_mode(
const struct hi6421v530_regulator_info *info;
unsigned int reg_val;
info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
info = container_of_const(rdev->desc, struct hi6421v530_regulator_info, rdesc);
regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & (info->mode_mask))
@@ -125,7 +125,7 @@ static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
const struct hi6421v530_regulator_info *info;
unsigned int new_mode;
info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
info = container_of_const(rdev->desc, struct hi6421v530_regulator_info, rdesc);
switch (mode) {
case REGULATOR_MODE_NORMAL:
new_mode = 0;
+3 -3
View File
@@ -121,7 +121,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
const struct hi6421_spmi_reg_info *sreg;
unsigned int reg_val;
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & sreg->eco_mode_mask)
@@ -136,7 +136,7 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
const struct hi6421_spmi_reg_info *sreg;
unsigned int val;
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
switch (mode) {
case REGULATOR_MODE_NORMAL:
val = 0;
@@ -162,7 +162,7 @@ hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
{
const struct hi6421_spmi_reg_info *sreg;
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
if (!sreg->eco_uA || ((unsigned int)load_uA > sreg->eco_uA))
return REGULATOR_MODE_NORMAL;

Some files were not shown because too many files have changed in this diff Show More