maintainers:
- Dmitry Osipenko <digetx@gmail.com>
+$ref: /schemas/power/supply/power-supply.yaml
+
properties:
compatible:
items:
reg:
maxItems: 1
- monitored-battery: true
- power-supplies: true
system-power-controller: true
required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
The child node for the charger to hold additional properties. If a
battery is not in use, this node can be omitted.
type: object
+ $ref: /schemas/power/supply/power-supply.yaml
+
properties:
monitored-battery:
description: |
inactive-delay, the GPIO is driven active again. After a delay specified by wait-delay, the
restart handler completes allowing other restart handlers to be attempted.
+allOf:
+ - $ref: restart-handler.yaml#
+
properties:
compatible:
const: gpio-restart
in its inactive state.
priority:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- A priority ranging from 0 to 255 (default 129) according to the following guidelines:
-
- 0: Restart handler of last resort, with limited restart capabilities.
- 128: Default restart handler; use if no other restart handler is expected to be available,
- and/or if restart functionality is sufficient to restart the entire system.
- 255: Highest priority restart handler, will preempt all other restart handlers.
- minimum: 0
- maximum: 255
default: 129
active-delay:
--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/reset/restart-handler.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Restart and shutdown handler generic binding
+
+maintainers:
+ - Sebastian Reichel <sre@kernel.org>
+
+description:
+ Restart and shutdown handler device is responsible for powering off the
+ system, e.g. my cutting off the power. System might have several restart
+ handlers, which usually are tried from most precise to last resort.
+
+properties:
+ priority:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ A priority ranging from 0 to 255 according to the following guidelines::
+ 0:: Restart handler of last resort, with limited restart capabilities.
+ 128:: Typical, default restart handler; use if no other restart handler
+ is expected to be available, and/or if restart functionality is
+ sufficient to restart the entire system.
+ 255:: Highest priority restart handler, will preempt all other restart handlers.
+ minimum: 0
+ maximum: 255
+
+additionalProperties: true
properties:
compatible:
- enum:
- - ti,bq25890
- - ti,bq25892
- - ti,bq25895
- - ti,bq25896
+ oneOf:
+ - enum:
+ - ti,bq25890
+ - items:
+ - enum:
+ - ti,bq25892
+ - ti,bq25895
+ - ti,bq25896
+ - const: ti,bq25890
reg:
maxItems: 1
- ti,boost-voltage
- ti,boost-max-current
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
monitored-battery:
description: |
- phandle of battery characteristics node.
The fuel gauge uses the following battery properties:
- energy-full-design-microwatt-hours
- charge-full-design-microamp-hours
- voltage-min-design-microvolt
Both or neither of the *-full-design-*-hours properties must be set.
- See Documentation/devicetree/bindings/power/supply/battery.yaml
power-supplies: true
maintainers:
- Artur Rojek <contact@artur-rojek.eu>
+$ref: power-supply.yaml#
+
properties:
compatible:
oneOf:
monitored-battery:
description: >
- phandle to a "simple-battery" compatible node.
-
This property must be a phandle to a node using the format described
in battery.yaml, with the following properties being required:
- voltage-min-design-microvolt: drained battery voltage,
Voltage threshold to report battery as over voltage (in mV).
Default is not to report over-voltage events.
+ power-supplies: true
+
required:
- compatible
- reg
This property is added to a supply in order to list the devices which
supply it power, referenced by their phandles.
+ monitored-battery:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ The battery (with "simple-battery" compatible) being monitored by this
+ power supply.
+
additionalProperties: true
provides a Dual-source Battery Charger, two port BC1.2 detection and a
Battery Monitor.
+$ref: power-supply.yaml#
properties:
compatible:
The charger uses the following battery properties
- charge-term-current-microamp: current for charge termination phase.
- constant-charge-voltage-max-microvolt: maximum constant input voltage.
- See Documentation/devicetree/bindings/power/supply/battery.yaml
additionalProperties: false
(chip->id == CHIP_PM8607) ? chip->companion : chip->client;
if (!info->i2c_8606) {
dev_err(&pdev->dev, "Missed I2C address of 88PM8606!\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
info->dev = &pdev->dev;
psy_cfg.drv_data = info;
psy_cfg.supplied_to = pm860x_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
- info->usb = power_supply_register(&pdev->dev, &pm860x_charger_desc,
- &psy_cfg);
+ info->usb = devm_power_supply_register(&pdev->dev, &pm860x_charger_desc,
+ &psy_cfg);
if (IS_ERR(info->usb)) {
- ret = PTR_ERR(info->usb);
- goto out;
+ return PTR_ERR(info->usb);
}
pm860x_init_charger(info);
for (i = 0; i < ARRAY_SIZE(info->irq); i++) {
- ret = request_threaded_irq(info->irq[i], NULL,
- pm860x_irq_descs[i].handler,
- IRQF_ONESHOT, pm860x_irq_descs[i].name, info);
+ ret = devm_request_threaded_irq(&pdev->dev, info->irq[i], NULL,
+ pm860x_irq_descs[i].handler,
+ IRQF_ONESHOT,
+ pm860x_irq_descs[i].name, info);
if (ret < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
info->irq[i], ret);
- goto out_irq;
+ return ret;
}
}
return 0;
-
-out_irq:
- power_supply_unregister(info->usb);
- while (--i >= 0)
- free_irq(info->irq[i], info);
-out:
- return ret;
-}
-
-static int pm860x_charger_remove(struct platform_device *pdev)
-{
- struct pm860x_charger_info *info = platform_get_drvdata(pdev);
- int i;
-
- power_supply_unregister(info->usb);
- for (i = 0; i < info->irq_nums; i++)
- free_irq(info->irq[i], info);
- return 0;
}
static struct platform_driver pm860x_charger_driver = {
.name = "88pm860x-charger",
},
.probe = pm860x_charger_probe,
- .remove = pm860x_charger_remove,
};
module_platform_driver(pm860x_charger_driver);
*
* Due to a asic bug it is necessary to lower the input current to the vbus
* charger when charging with at some specific levels. This issue is only valid
- * for below a certain battery voltage. This function makes sure that the
+ * for below a certain battery voltage. This function makes sure that
* the allowed current limit isn't exceeded.
*/
static void ab8500_charger_check_vbat_work(struct work_struct *work)
if (ret)
return ret;
- return platform_driver_register(&ab8500_charger_driver);
+ ret = platform_driver_register(&ab8500_charger_driver);
+ if (ret) {
+ platform_unregister_drivers(ab8500_charger_component_drivers,
+ ARRAY_SIZE(ab8500_charger_component_drivers));
+ return ret;
+ }
+
+ return 0;
}
static void __exit ab8500_charger_exit(void)
.num_properties = ARRAY_SIZE(adp5061_props),
};
-static int adp5061_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adp5061_probe(struct i2c_client *client)
{
struct power_supply_config psy_cfg = {};
struct adp5061_state *st;
.driver = {
.name = KBUILD_MODNAME,
},
- .probe = adp5061_probe,
+ .probe_new = adp5061_probe,
.id_table = adp5061_id,
};
module_i2c_driver(adp5061_driver);
* Describe the setting in linear_range table.
*/
static const struct linear_range input_current_limit_ranges[] = {
- {
- .min = 0,
- .step = 32000,
- .min_sel = 0x0,
- .max_sel = 0x1ff,
- },
+ LINEAR_RANGE(0, 0x0, 0x1ff, 32000),
};
/* Possible trickle, pre-charging and termination current values */
static const struct linear_range charging_current_ranges[] = {
- {
- .min = 0,
- .step = 64000,
- .min_sel = 0x0,
- .max_sel = 0x10,
- }, {
- .min = 1024000,
- .step = 0,
- .min_sel = 0x11,
- .max_sel = 0x1f,
- },
+ LINEAR_RANGE(0, 0x0, 0x10, 64000),
+ LINEAR_RANGE(1024000, 0x11, 0x1f, 0),
};
/*
* and battery over voltage protection have same possible values
*/
static const struct linear_range charge_voltage_regulation_ranges[] = {
- {
- .min = 2560000,
- .step = 0,
- .min_sel = 0,
- .max_sel = 0xA0,
- }, {
- .min = 2560000,
- .step = 16000,
- .min_sel = 0xA0,
- .max_sel = 0x4B0,
- }, {
- .min = 19200000,
- .step = 0,
- .min_sel = 0x4B0,
- .max_sel = 0x7FF,
- },
+ LINEAR_RANGE(2560000, 0, 0xA0, 0),
+ LINEAR_RANGE(2560000, 0xA0, 0x4B0, 16000),
+ LINEAR_RANGE(19200000, 0x4B0, 0x7FF, 0),
};
/* Possible VSYS voltage regulation values */
static const struct linear_range vsys_voltage_regulation_ranges[] = {
- {
- .min = 2560000,
- .step = 0,
- .min_sel = 0,
- .max_sel = 0x28,
- }, {
- .min = 2560000,
- .step = 64000,
- .min_sel = 0x28,
- .max_sel = 0x12C,
- }, {
- .min = 19200000,
- .step = 0,
- .min_sel = 0x12C,
- .max_sel = 0x1FF,
- },
+ LINEAR_RANGE(2560000, 0, 0x28, 0),
+ LINEAR_RANGE(2560000, 0x28, 0x12C, 64000),
+ LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0),
};
/* Possible settings for switching from trickle to pre-charging limits */
static const struct linear_range trickle_to_pre_threshold_ranges[] = {
- {
- .min = 2048000,
- .step = 0,
- .min_sel = 0,
- .max_sel = 0x20,
- }, {
- .min = 2048000,
- .step = 64000,
- .min_sel = 0x20,
- .max_sel = 0x12C,
- }, {
- .min = 19200000,
- .step = 0,
- .min_sel = 0x12C,
- .max_sel = 0x1FF
- }
+ LINEAR_RANGE(2048000, 0, 0x20, 0),
+ LINEAR_RANGE(2048000, 0x20, 0x12C, 64000),
+ LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0),
};
/* Possible current values for fast-charging constant current phase */
static const struct linear_range fast_charge_current_ranges[] = {
- {
- .min = 0,
- .step = 64000,
- .min_sel = 0,
- .max_sel = 0xFF,
- }
+ LINEAR_RANGE(0, 0, 0xFF, 64000),
};
struct battery_init {
}
/* main bq2415x probe function */
-static int bq2415x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq2415x_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
int ret;
int num;
char *name = NULL;
.of_match_table = of_match_ptr(bq2415x_of_match_table),
.acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match),
},
- .probe = bq2415x_probe,
+ .probe_new = bq2415x_probe,
.remove = bq2415x_remove,
.id_table = bq2415x_i2c_id_table,
};
return 0;
}
-static int bq24190_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq24190_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
struct power_supply_config charger_cfg = {}, battery_cfg = {};
MODULE_DEVICE_TABLE(of, bq24190_of_match);
static struct i2c_driver bq24190_driver = {
- .probe = bq24190_probe,
+ .probe_new = bq24190_probe,
.remove = bq24190_remove,
.shutdown = bq24190_shutdown,
.id_table = bq24190_i2c_ids,
return 0;
}
-static int bq24257_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq24257_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
const struct acpi_device_id *acpi_id;
.acpi_match_table = ACPI_PTR(bq24257_acpi_match),
.pm = &bq24257_pm,
},
- .probe = bq24257_probe,
+ .probe_new = bq24257_probe,
.remove = bq24257_remove,
.id_table = bq24257_i2c_ids,
};
return pdata;
}
-static int bq24735_charger_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq24735_charger_probe(struct i2c_client *client)
{
int ret;
struct bq24735 *charger;
.name = "bq24735-charger",
.of_match_table = bq24735_match_ids,
},
- .probe = bq24735_charger_probe,
+ .probe_new = bq24735_charger_probe,
.id_table = bq24735_charger_id,
};
.volatile_reg = bq2515x_volatile_register,
};
-static int bq2515x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq2515x_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct bq2515x_device *bq2515x;
struct power_supply_config charger_cfg = {};
.name = "bq2515x-charger",
.of_match_table = bq2515x_of_match,
},
- .probe = bq2515x_probe,
+ .probe_new = bq2515x_probe,
.id_table = bq2515x_i2c_ids,
};
module_i2c_driver(bq2515x_driver);
return 0;
}
-static int bq256xx_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq256xx_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct bq256xx_device *bq;
struct power_supply_config psy_cfg = { };
.of_match_table = bq256xx_of_match,
.acpi_match_table = bq256xx_acpi_match,
},
- .probe = bq256xx_probe,
+ .probe_new = bq256xx_probe,
.id_table = bq256xx_i2c_ids,
};
module_i2c_driver(bq256xx_driver);
val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
break;
- case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
- val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ val->intval = bq25890_find_val(bq->init_data.iprechg, TBL_ITERM);
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM);
+ break;
+
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = bq25890_field_read(bq, F_IINLIM);
+ if (ret < 0)
+ return ret;
+
+ val->intval = bq25890_find_val(ret, TBL_IINLIM);
+ break;
+
+ case POWER_SUPPLY_PROP_CURRENT_NOW: /* I_BAT now */
+ /*
+ * This is ADC-sampled immediate charge current supplied
+ * from charger to battery. The property name is confusing,
+ * for clarification refer to:
+ * Documentation/ABI/testing/sysfs-class-power
+ * /sys/class/power_supply/<supply_name>/current_now
+ */
+ ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */
+ if (ret < 0)
+ return ret;
+
+ /* converted_val = ADC_val * 50mA (table 10.3.19) */
+ val->intval = ret * -50000;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: /* I_BAT user limit */
+ /*
+ * This is user-configured constant charge current supplied
+ * from charger to battery in first phase of charging, when
+ * battery voltage is below constant charge voltage.
+ *
+ * This value reflects the current hardware setting.
+ *
+ * The POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX is the
+ * maximum value of this property.
+ */
+ ret = bq25890_field_read(bq, F_ICHG);
+ if (ret < 0)
+ return ret;
+ val->intval = bq25890_find_val(ret, TBL_ICHG);
/* When temperature is too low, charge current is decreased */
if (bq->state.ntc_fault == NTC_FAULT_COOL) {
}
break;
- case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
- if (!state.online) {
- val->intval = 0;
- break;
- }
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: /* I_BAT max */
+ /*
+ * This is maximum allowed constant charge current supplied
+ * from charger to battery in first phase of charging, when
+ * battery voltage is below constant charge voltage.
+ *
+ * This value is constant for each battery and set from DT.
+ */
+ val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW: /* V_BAT now */
+ /*
+ * This is ADC-sampled immediate charge voltage supplied
+ * from charger to battery. The property name is confusing,
+ * for clarification refer to:
+ * Documentation/ABI/testing/sysfs-class-power
+ * /sys/class/power_supply/<supply_name>/voltage_now
+ */
ret = bq25890_field_read(bq, F_BATV); /* read measured value */
if (ret < 0)
return ret;
val->intval = 2304000 + ret * 20000;
break;
- case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
- val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
- break;
-
- case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
- val->intval = bq25890_find_val(bq->init_data.iprechg, TBL_ITERM);
- break;
-
- case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
- val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM);
- break;
-
- case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
- ret = bq25890_field_read(bq, F_IINLIM);
- if (ret < 0)
- return ret;
-
- val->intval = bq25890_find_val(ret, TBL_IINLIM);
- break;
-
- case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- ret = bq25890_field_read(bq, F_SYSV); /* read measured value */
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: /* V_BAT user limit */
+ /*
+ * This is user-configured constant charge voltage supplied
+ * from charger to battery in second phase of charging, when
+ * battery voltage reached constant charge voltage.
+ *
+ * This value reflects the current hardware setting.
+ *
+ * The POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX is the
+ * maximum value of this property.
+ */
+ ret = bq25890_field_read(bq, F_VREG);
if (ret < 0)
return ret;
- /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */
- val->intval = 2304000 + ret * 20000;
+ val->intval = bq25890_find_val(ret, TBL_VREG);
break;
- case POWER_SUPPLY_PROP_CURRENT_NOW:
- ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */
- if (ret < 0)
- return ret;
-
- /* converted_val = ADC_val * 50mA (table 10.3.19) */
- val->intval = ret * -50000;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: /* V_BAT max */
+ /*
+ * This is maximum allowed constant charge voltage supplied
+ * from charger to battery in second phase of charging, when
+ * battery voltage reached constant charge voltage.
+ *
+ * This value is constant for each battery and set from DT.
+ */
+ val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
break;
case POWER_SUPPLY_PROP_TEMP:
const union power_supply_propval *val)
{
struct bq25890_device *bq = power_supply_get_drvdata(psy);
+ int maxval;
u8 lval;
switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ maxval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
+ lval = bq25890_find_idx(min(val->intval, maxval), TBL_ICHG);
+ return bq25890_field_write(bq, F_ICHG, lval);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ maxval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
+ lval = bq25890_find_idx(min(val->intval, maxval), TBL_VREG);
+ return bq25890_field_write(bq, F_VREG, lval);
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
lval = bq25890_find_idx(val->intval, TBL_IINLIM);
return bq25890_field_write(bq, F_IINLIM, lval);
enum power_supply_property psp)
{
switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return true;
default:
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
return bq25890_field_read(bq, F_OTG_CFG);
}
+static int bq25890_vbus_get_voltage(struct regulator_dev *rdev)
+{
+ struct bq25890_device *bq = rdev_get_drvdata(rdev);
+
+ return bq25890_get_vbus_voltage(bq);
+}
+
+static int bq25890_vsys_get_voltage(struct regulator_dev *rdev)
+{
+ struct bq25890_device *bq = rdev_get_drvdata(rdev);
+ int ret;
+
+ /* Should be some output voltage ? */
+ ret = bq25890_field_read(bq, F_SYSV); /* read measured value */
+ if (ret < 0)
+ return ret;
+
+ /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */
+ return 2304000 + ret * 20000;
+}
+
static const struct regulator_ops bq25890_vbus_ops = {
.enable = bq25890_vbus_enable,
.disable = bq25890_vbus_disable,
.is_enabled = bq25890_vbus_is_enabled,
+ .get_voltage = bq25890_vbus_get_voltage,
};
static const struct regulator_desc bq25890_vbus_desc = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.ops = &bq25890_vbus_ops,
- .fixed_uV = 5000000,
- .n_voltages = 1,
};
+
+static const struct regulator_ops bq25890_vsys_ops = {
+ .get_voltage = bq25890_vsys_get_voltage,
+};
+
+static const struct regulator_desc bq25890_vsys_desc = {
+ .name = "vsys",
+ .of_match = "vsys",
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .ops = &bq25890_vsys_ops,
+};
+
+static int bq25890_register_regulator(struct bq25890_device *bq)
+{
+ struct bq25890_platform_data *pdata = dev_get_platdata(bq->dev);
+ struct regulator_config cfg = {
+ .dev = bq->dev,
+ .driver_data = bq,
+ };
+ struct regulator_dev *reg;
+
+ if (pdata)
+ cfg.init_data = pdata->regulator_init_data;
+
+ reg = devm_regulator_register(bq->dev, &bq25890_vbus_desc, &cfg);
+ if (IS_ERR(reg)) {
+ return dev_err_probe(bq->dev, PTR_ERR(reg),
+ "registering vbus regulator");
+ }
+
+ /* pdata->regulator_init_data is for vbus only */
+ cfg.init_data = NULL;
+ reg = devm_regulator_register(bq->dev, &bq25890_vsys_desc, &cfg);
+ if (IS_ERR(reg)) {
+ return dev_err_probe(bq->dev, PTR_ERR(reg),
+ "registering vsys regulator");
+ }
+
+ return 0;
+}
+#else
+static inline int
+bq25890_register_regulator(struct bq25890_device *bq)
+{
+ return 0;
+}
#endif
static int bq25890_get_chip_version(struct bq25890_device *bq)
return 0;
}
-static int bq25890_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static void bq25890_non_devm_cleanup(void *data)
+{
+ struct bq25890_device *bq = data;
+
+ cancel_delayed_work_sync(&bq->pump_express_work);
+}
+
+static int bq25890_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct bq25890_device *bq;
/* OTG reporting */
bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- if (!IS_ERR_OR_NULL(bq->usb_phy)) {
- INIT_WORK(&bq->usb_work, bq25890_usb_work);
- bq->usb_nb.notifier_call = bq25890_usb_notifier;
- usb_register_notifier(bq->usb_phy, &bq->usb_nb);
- }
-#ifdef CONFIG_REGULATOR
- else {
- struct bq25890_platform_data *pdata = dev_get_platdata(dev);
- struct regulator_config cfg = { };
- struct regulator_dev *reg;
-
- cfg.dev = dev;
- cfg.driver_data = bq;
- if (pdata)
- cfg.init_data = pdata->regulator_init_data;
-
- reg = devm_regulator_register(dev, &bq25890_vbus_desc, &cfg);
- if (IS_ERR(reg))
- return dev_err_probe(dev, PTR_ERR(reg), "registering regulator");
- }
-#endif
+
+ /*
+ * This must be before bq25890_power_supply_init(), so that it runs
+ * after devm unregisters the power_supply.
+ */
+ ret = devm_add_action_or_reset(dev, bq25890_non_devm_cleanup, bq);
+ if (ret)
+ return ret;
+
+ ret = bq25890_register_regulator(bq);
+ if (ret)
+ return ret;
ret = bq25890_power_supply_init(bq);
- if (ret < 0) {
- dev_err(dev, "Failed to register power supply\n");
- goto err_unregister_usb_notifier;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "registering power supply\n");
ret = devm_request_threaded_irq(dev, client->irq, NULL,
bq25890_irq_handler_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
BQ25890_IRQ_PIN, bq);
if (ret)
- goto err_unregister_usb_notifier;
-
- return 0;
+ return ret;
-err_unregister_usb_notifier:
- if (!IS_ERR_OR_NULL(bq->usb_phy))
- usb_unregister_notifier(bq->usb_phy, &bq->usb_nb);
+ if (!IS_ERR_OR_NULL(bq->usb_phy)) {
+ INIT_WORK(&bq->usb_work, bq25890_usb_work);
+ bq->usb_nb.notifier_call = bq25890_usb_notifier;
+ usb_register_notifier(bq->usb_phy, &bq->usb_nb);
+ }
- return ret;
+ return 0;
}
static void bq25890_remove(struct i2c_client *client)
{
struct bq25890_device *bq = i2c_get_clientdata(client);
- if (!IS_ERR_OR_NULL(bq->usb_phy))
+ if (!IS_ERR_OR_NULL(bq->usb_phy)) {
usb_unregister_notifier(bq->usb_phy, &bq->usb_nb);
+ cancel_work_sync(&bq->usb_work);
+ }
if (!bq->skip_reset) {
/* reset all registers to default values */
.acpi_match_table = ACPI_PTR(bq25890_acpi_match),
.pm = &bq25890_pm,
},
- .probe = bq25890_probe,
+ .probe_new = bq25890_probe,
.remove = bq25890_remove,
.shutdown = bq25890_shutdown,
.id_table = bq25890_i2c_ids,
return 0;
}
-static int bq25980_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq25980_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct bq25980_device *bq;
int ret;
.name = "bq25980-charger",
.of_match_table = bq25980_of_match,
},
- .probe = bq25980_probe,
+ .probe_new = bq25980_probe,
.id_table = bq25980_i2c_ids,
};
module_i2c_driver(bq25980_driver);
return 0;
}
-static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct bq27xxx_device_info *di;
int ret;
char *name;
.name = "bq27xxx-battery",
.of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
},
- .probe = bq27xxx_battery_i2c_probe,
+ .probe_new = bq27xxx_battery_i2c_probe,
.remove = bq27xxx_battery_i2c_remove,
.id_table = bq27xxx_i2c_id_table,
};
}
cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery");
+ if (!cw_bat->battery_workqueue)
+ return -ENOMEM;
+
devm_delayed_work_autocancel(&client->dev,
&cw_bat->battery_delay_work, cw_bat_work);
queue_delayed_work(cw_bat->battery_workqueue,
}
};
-static int ds278x_battery_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ds278x_battery_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct ds278x_platform_data *pdata = client->dev.platform_data;
struct power_supply_config psy_cfg = {};
struct ds278x_info *info;
.name = "ds2782-battery",
.pm = &ds278x_battery_pm_ops,
},
- .probe = ds278x_battery_probe,
+ .probe_new = ds278x_battery_probe,
.remove = ds278x_battery_remove,
.id_table = ds278x_id,
};
}
#endif
-static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+static int lp8727_probe(struct i2c_client *cl)
{
struct lp8727_chg *pchg;
struct lp8727_platform_data *pdata;
.name = "lp8727",
.of_match_table = of_match_ptr(lp8727_dt_ids),
},
- .probe = lp8727_probe,
+ .probe_new = lp8727_probe,
.remove = lp8727_remove,
.id_table = lp8727_ids,
};
static int lp8788_irq_register(struct platform_device *pdev,
struct lp8788_charger *pchg)
{
- const char *name[] = {
+ static const char * const name[] = {
LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ
};
int i;
POWER_SUPPLY_PROP_CURRENT_NOW,
};
-static int ltc294x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ltc294x_i2c_probe(struct i2c_client *client)
{
struct power_supply_config psy_cfg = {};
struct ltc294x_info *info;
.of_match_table = ltc294x_i2c_of_match,
.pm = LTC294X_PM_OPS,
},
- .probe = ltc294x_i2c_probe,
+ .probe_new = ltc294x_i2c_probe,
.shutdown = ltc294x_i2c_shutdown,
.id_table = ltc294x_i2c_id,
};
regmap_write(info->regmap, LTC4162L_CHARGE_STATUS_ALERTS_REG, 0);
}
-static int ltc4162l_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ltc4162l_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
MODULE_DEVICE_TABLE(of, ltc4162l_of_match);
static struct i2c_driver ltc4162l_driver = {
- .probe = ltc4162l_probe,
+ .probe_new = ltc4162l_probe,
.alert = ltc4162l_alert,
.id_table = ltc4162l_i2c_id_table,
.driver = {
POWER_SUPPLY_PROP_MANUFACTURER,
};
-static int max14656_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max14656_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
.name = "max14656",
.of_match_table = max14656_match_table,
},
- .probe = max14656_probe,
+ .probe_new = max14656_probe,
.id_table = max14656_id,
};
module_i2c_driver(max14656_i2c_driver);
.num_properties = ARRAY_SIZE(max17040_battery_props),
};
-static int max17040_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max17040_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct i2c_adapter *adapter = client->adapter;
struct power_supply_config psy_cfg = {};
struct max17040_chip *chip;
.of_match_table = max17040_of_match,
.pm = MAX17040_PM_OPS,
},
- .probe = max17040_probe,
+ .probe_new = max17040_probe,
.id_table = max17040_id,
};
module_i2c_driver(max17040_i2c_driver);
.num_properties = ARRAY_SIZE(max17042_battery_props) - 2,
};
-static int max17042_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max17042_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct i2c_adapter *adapter = client->adapter;
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
struct power_supply_config psy_cfg = {};
.of_match_table = of_match_ptr(max17042_dt_match),
.pm = &max17042_pm_ops,
},
- .probe = max17042_probe,
+ .probe_new = max17042_probe,
.id_table = max17042_id,
};
module_i2c_driver(max17042_i2c_driver);
MT6360_RANGE_MAX,
};
-#define MT6360_LINEAR_RANGE(idx, _min, _min_sel, _max_sel, _step) \
- [idx] = REGULATOR_LINEAR_RANGE(_min, _min_sel, _max_sel, _step)
-
static const struct linear_range mt6360_chg_range[MT6360_RANGE_MAX] = {
- MT6360_LINEAR_RANGE(MT6360_RANGE_VMIVR, 3900000, 0, 0x5F, 100000),
- MT6360_LINEAR_RANGE(MT6360_RANGE_ICHG, 100000, 0, 0x31, 100000),
- MT6360_LINEAR_RANGE(MT6360_RANGE_VOREG, 3900000, 0, 0x51, 10000),
- MT6360_LINEAR_RANGE(MT6360_RANGE_AICR, 100000, 0, 0x3F, 50000),
- MT6360_LINEAR_RANGE(MT6360_RANGE_IPREC, 100000, 0, 0x0F, 50000),
- MT6360_LINEAR_RANGE(MT6360_RANGE_IEOC, 100000, 0, 0x0F, 50000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_VMIVR, 3900000, 0, 0x5F, 100000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_ICHG, 100000, 0, 0x31, 100000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_VOREG, 3900000, 0, 0x51, 10000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_AICR, 100000, 0, 0x3F, 50000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_IPREC, 100000, 0, 0x0F, 50000),
+ LINEAR_RANGE_IDX(MT6360_RANGE_IEOC, 100000, 0, 0x0F, 50000),
};
struct mt6360_chg_info {
int i, tab_len, size;
propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index);
+ if (!propname) {
+ power_supply_put_battery_info(psy, info);
+ err = -ENOMEM;
+ goto out_put_node;
+ }
list = of_get_property(battery_np, propname, &size);
if (!list || !size) {
dev_err(&psy->dev, "failed to get %s\n", propname);
* power_supply_vbat2ri() - find the battery internal resistance
* from the battery voltage
* @info: The battery information container
- * @table: Pointer to battery resistance temperature table
* @vbat_uv: The battery voltage in microvolt
* @charging: If we are charging (true) or not (false)
*
register_cooler_failed:
psy_unregister_thermal(psy);
register_thermal_failed:
- device_del(dev);
wakeup_init_failed:
+ device_del(dev);
device_add_failed:
check_supplies_failed:
dev_set_name_failed:
return -ENODEV;
charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
- if (!charger)
+ if (!charger) {
+ of_node_put(node);
return -ENOMEM;
+ }
charger->rk808 = rk808;
.num_properties = ARRAY_SIZE(rt5033_battery_props),
};
-static int rt5033_battery_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int rt5033_battery_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct power_supply_config psy_cfg = {};
.name = "rt5033-battery",
.of_match_table = rt5033_battery_of_match,
},
- .probe = rt5033_battery_probe,
+ .probe_new = rt5033_battery_probe,
.remove = rt5033_battery_remove,
.id_table = rt5033_battery_id,
};
.cache_type = REGCACHE_RBTREE,
};
-static int rt9455_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int rt9455_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
#endif
static struct i2c_driver rt9455_driver = {
- .probe = rt9455_probe,
+ .probe_new = rt9455_probe,
.remove = rt9455_remove,
.id_table = rt9455_i2c_id_table,
.driver = {
.get_property = sbs_get_property,
};
-static int sbs_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sbs_probe(struct i2c_client *client)
{
struct power_supply_config psy_cfg = {};
struct sbs_info *chip;
MODULE_DEVICE_TABLE(i2c, sbs_id);
static struct i2c_driver sbs_driver = {
- .probe = sbs_probe,
+ .probe_new = sbs_probe,
.id_table = sbs_id,
.driver = {
.name = "sbs-charger",
i2c_mux_del_adapters(sbsm->muxc);
}
-static int sbsm_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sbsm_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct i2c_adapter *adapter = client->adapter;
struct sbsm_data *data;
struct device *dev = &client->dev;
.name = "sbsm",
.of_match_table = of_match_ptr(sbsm_dt_ids),
},
- .probe = sbsm_probe,
+ .probe_new = sbsm_probe,
.alert = sbsm_alert,
.id_table = sbsm_ids
};
.n_voltages = 1,
};
-static int smb347_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int smb347_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct power_supply_config mains_usb_cfg = {};
struct regulator_config usb_rdev_cfg = {};
struct device *dev = &client->dev;
.name = "smb347",
.of_match_table = smb3xx_of_match,
},
- .probe = smb347_probe,
+ .probe_new = smb347_probe,
.remove = smb347_remove,
.shutdown = smb347_shutdown,
.id_table = smb347_id,
.n_voltages = 1,
};
-static int ucs1002_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
+static int ucs1002_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct power_supply_config charger_config = {};
.name = "ucs1002",
.of_match_table = ucs1002_of_match,
},
- .probe = ucs1002_probe,
+ .probe_new = ucs1002_probe,
};
module_i2c_driver(ucs1002_driver);
return 0;
}
-static int z2_batt_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int z2_batt_probe(struct i2c_client *client)
{
int ret = 0;
int props = 1; /* POWER_SUPPLY_PROP_PRESENT */
charger->charge_gpiod = devm_gpiod_get_optional(&client->dev,
NULL, GPIOD_IN);
- if (IS_ERR(charger->charge_gpiod))
- return dev_err_probe(&client->dev,
+ if (IS_ERR(charger->charge_gpiod)) {
+ ret = dev_err_probe(&client->dev,
PTR_ERR(charger->charge_gpiod),
"failed to get charge GPIO\n");
+ goto err;
+ }
if (charger->charge_gpiod) {
gpiod_set_consumer_name(charger->charge_gpiod, "BATT CHRG");
.name = "z2-battery",
.pm = Z2_BATTERY_PM_OPS
},
- .probe = z2_batt_probe,
+ .probe_new = z2_batt_probe,
.remove = z2_batt_remove,
.id_table = z2_batt_id,
};