Commit ab1e2d0f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v6.8-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
 "New features:
   - bq24190: Add support for BQ24296 charger

  Cleanups:
   - all reset drivers: Stop using module_platform_driver_probe()
   - gpio-restart: use devm_register_sys_off_handler
   - pwr-mlxbf: support graceful reboot
   - cw2015: correct time_to_empty units
   - qcom-battmgr: Fix driver initialization sequence
   - bq27xxx: Start/Stop delayed work in suspend/resume
   - minor cleanups and fixes"

* tag 'for-v6.8-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (33 commits)
  power: supply: bq24190_charger: Fix "initializer element is not constant" error
  power: supply: bq24190_charger: Add support for BQ24296
  dt-bindings: power: supply: bq24190: Add BQ24296 compatible
  dt-bindings: power: reset: xilinx: Rename node names in examples
  power: supply: qcom_battmgr: Register the power supplies after PDR is up
  dt-bindings: power: reset: qcom-pon: fix inconsistent example
  power: supply: Fix null pointer dereference in smb2_probe
  power: reset: at91: Drop '__init' from at91_wakeup_status()
  power: supply: Use multiple MODULE_AUTHOR statements
  power: supply: Fix indentation and some other warnings
  power: reset: gpio-restart: Use devm_register_sys_off_handler()
  power: supply: bq256xx: fix some problem in bq256xx_hw_init
  power: supply: cw2015: correct time_to_empty units in sysfs
  power: reset: at91-sama5d2_shdwc: Convert to platform remove callback returning void
  power: reset: at91-reset: Convert to platform remove callback returning void
  power: reset: tps65086-restart: Convert to platform remove callback returning void
  power: reset: syscon-poweroff: Convert to platform remove callback returning void
  power: reset: rmobile-reset: Convert to platform remove callback returning void
  power: reset: restart-poweroff: Convert to platform remove callback returning void
  power: reset: regulator-poweroff: Convert to platform remove callback returning void
  ...
parents 237c31cb 17d49b7e
...@@ -28,17 +28,15 @@ properties: ...@@ -28,17 +28,15 @@ properties:
items: items:
- const: reboot-mode - const: reboot-mode
patternProperties: allOf:
"^mode-.+": - $ref: reboot-mode.yaml#
$ref: /schemas/types.yaml#/definitions/uint32
description: Vendor-specific mode value written to the mode register
required: required:
- compatible - compatible
- nvmem-cells - nvmem-cells
- nvmem-cell-names - nvmem-cell-names
additionalProperties: false unevaluatedProperties: false
examples: examples:
- | - |
......
...@@ -111,21 +111,24 @@ examples: ...@@ -111,21 +111,24 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/input/linux-event-codes.h> #include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/spmi/spmi.h> #include <dt-bindings/spmi/spmi.h>
spmi_bus: spmi@c440000 {
spmi@c440000 {
reg = <0x0c440000 0x1100>; reg = <0x0c440000 0x1100>;
#address-cells = <2>; #address-cells = <2>;
#size-cells = <0>; #size-cells = <0>;
pmk8350: pmic@0 {
pmic@0 {
reg = <0x0 SPMI_USID>; reg = <0x0 SPMI_USID>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
pmk8350_pon: pon_hlos@1300 {
reg = <0x1300>; pon@800 {
compatible = "qcom,pm8998-pon"; compatible = "qcom,pm8998-pon";
reg = <0x800>;
pwrkey { pwrkey {
compatible = "qcom,pm8941-pwrkey"; compatible = "qcom,pm8941-pwrkey";
interrupts = < 0x0 0x8 0 IRQ_TYPE_EDGE_BOTH >; interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
debounce = <15625>; debounce = <15625>;
bias-pull-up; bias-pull-up;
linux,code = <KEY_POWER>; linux,code = <KEY_POWER>;
......
...@@ -29,12 +29,10 @@ properties: ...@@ -29,12 +29,10 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32 $ref: /schemas/types.yaml#/definitions/uint32
description: Offset in the register map for the mode register (in bytes) description: Offset in the register map for the mode register (in bytes)
patternProperties: allOf:
"^mode-.+": - $ref: reboot-mode.yaml#
$ref: /schemas/types.yaml#/definitions/uint32
description: Vendor-specific mode value written to the mode register
additionalProperties: false unevaluatedProperties: false
required: required:
- compatible - compatible
......
...@@ -57,7 +57,7 @@ examples: ...@@ -57,7 +57,7 @@ examples:
firmware { firmware {
zynqmp-firmware { zynqmp-firmware {
zynqmp-power { power-management {
compatible = "xlnx,zynqmp-power"; compatible = "xlnx,zynqmp-power";
interrupts = <0 35 4>; interrupts = <0 35 4>;
}; };
...@@ -70,7 +70,7 @@ examples: ...@@ -70,7 +70,7 @@ examples:
firmware { firmware {
zynqmp-firmware { zynqmp-firmware {
zynqmp-power { power-management {
compatible = "xlnx,zynqmp-power"; compatible = "xlnx,zynqmp-power";
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 35 4>; interrupts = <0 35 4>;
......
...@@ -20,6 +20,7 @@ properties: ...@@ -20,6 +20,7 @@ properties:
- ti,bq24192 - ti,bq24192
- ti,bq24192i - ti,bq24192i
- ti,bq24196 - ti,bq24196
- ti,bq24296
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -61,13 +61,11 @@ static int as3722_poweroff_probe(struct platform_device *pdev) ...@@ -61,13 +61,11 @@ static int as3722_poweroff_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int as3722_poweroff_remove(struct platform_device *pdev) static void as3722_poweroff_remove(struct platform_device *pdev)
{ {
if (pm_power_off == as3722_pm_power_off) if (pm_power_off == as3722_pm_power_off)
pm_power_off = NULL; pm_power_off = NULL;
as3722_pm_poweroff = NULL; as3722_pm_poweroff = NULL;
return 0;
} }
static struct platform_driver as3722_poweroff_driver = { static struct platform_driver as3722_poweroff_driver = {
...@@ -75,7 +73,7 @@ static struct platform_driver as3722_poweroff_driver = { ...@@ -75,7 +73,7 @@ static struct platform_driver as3722_poweroff_driver = {
.name = "as3722-power-off", .name = "as3722-power-off",
}, },
.probe = as3722_poweroff_probe, .probe = as3722_poweroff_probe,
.remove = as3722_poweroff_remove, .remove_new = as3722_poweroff_remove,
}; };
module_platform_driver(as3722_poweroff_driver); module_platform_driver(as3722_poweroff_driver);
......
...@@ -57,7 +57,7 @@ static struct shdwc { ...@@ -57,7 +57,7 @@ static struct shdwc {
void __iomem *mpddrc_base; void __iomem *mpddrc_base;
} at91_shdwc; } at91_shdwc;
static void __init at91_wakeup_status(struct platform_device *pdev) static void at91_wakeup_status(struct platform_device *pdev)
{ {
const char *reason; const char *reason;
u32 reg = readl(at91_shdwc.shdwc_base + AT91_SHDW_SR); u32 reg = readl(at91_shdwc.shdwc_base + AT91_SHDW_SR);
...@@ -149,7 +149,7 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev) ...@@ -149,7 +149,7 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev)
writel(wakeup_mode | mode, at91_shdwc.shdwc_base + AT91_SHDW_MR); writel(wakeup_mode | mode, at91_shdwc.shdwc_base + AT91_SHDW_MR);
} }
static int __init at91_poweroff_probe(struct platform_device *pdev) static int at91_poweroff_probe(struct platform_device *pdev)
{ {
struct device_node *np; struct device_node *np;
u32 ddr_type; u32 ddr_type;
...@@ -202,7 +202,7 @@ static int __init at91_poweroff_probe(struct platform_device *pdev) ...@@ -202,7 +202,7 @@ static int __init at91_poweroff_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __exit at91_poweroff_remove(struct platform_device *pdev) static void at91_poweroff_remove(struct platform_device *pdev)
{ {
if (pm_power_off == at91_poweroff) if (pm_power_off == at91_poweroff)
pm_power_off = NULL; pm_power_off = NULL;
...@@ -211,8 +211,6 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev) ...@@ -211,8 +211,6 @@ static int __exit at91_poweroff_remove(struct platform_device *pdev)
iounmap(at91_shdwc.mpddrc_base); iounmap(at91_shdwc.mpddrc_base);
clk_disable_unprepare(at91_shdwc.sclk); clk_disable_unprepare(at91_shdwc.sclk);
return 0;
} }
static const struct of_device_id at91_poweroff_of_match[] = { static const struct of_device_id at91_poweroff_of_match[] = {
...@@ -224,13 +222,14 @@ static const struct of_device_id at91_poweroff_of_match[] = { ...@@ -224,13 +222,14 @@ static const struct of_device_id at91_poweroff_of_match[] = {
MODULE_DEVICE_TABLE(of, at91_poweroff_of_match); MODULE_DEVICE_TABLE(of, at91_poweroff_of_match);
static struct platform_driver at91_poweroff_driver = { static struct platform_driver at91_poweroff_driver = {
.remove = __exit_p(at91_poweroff_remove), .probe = at91_poweroff_probe,
.remove_new = at91_poweroff_remove,
.driver = { .driver = {
.name = "at91-poweroff", .name = "at91-poweroff",
.of_match_table = at91_poweroff_of_match, .of_match_table = at91_poweroff_of_match,
}, },
}; };
module_platform_driver_probe(at91_poweroff_driver, at91_poweroff_probe); module_platform_driver(at91_poweroff_driver);
MODULE_AUTHOR("Atmel Corporation"); MODULE_AUTHOR("Atmel Corporation");
MODULE_DESCRIPTION("Shutdown driver for Atmel SoCs"); MODULE_DESCRIPTION("Shutdown driver for Atmel SoCs");
......
...@@ -337,7 +337,7 @@ static int at91_rcdev_init(struct at91_reset *reset, ...@@ -337,7 +337,7 @@ static int at91_rcdev_init(struct at91_reset *reset,
return devm_reset_controller_register(&pdev->dev, &reset->rcdev); return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
} }
static int __init at91_reset_probe(struct platform_device *pdev) static int at91_reset_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match; const struct of_device_id *match;
struct at91_reset *reset; struct at91_reset *reset;
...@@ -417,24 +417,23 @@ static int __init at91_reset_probe(struct platform_device *pdev) ...@@ -417,24 +417,23 @@ static int __init at91_reset_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __exit at91_reset_remove(struct platform_device *pdev) static void at91_reset_remove(struct platform_device *pdev)
{ {
struct at91_reset *reset = platform_get_drvdata(pdev); struct at91_reset *reset = platform_get_drvdata(pdev);
unregister_restart_handler(&reset->nb); unregister_restart_handler(&reset->nb);
clk_disable_unprepare(reset->sclk); clk_disable_unprepare(reset->sclk);
return 0;
} }
static struct platform_driver at91_reset_driver = { static struct platform_driver at91_reset_driver = {
.remove = __exit_p(at91_reset_remove), .probe = at91_reset_probe,
.remove_new = at91_reset_remove,
.driver = { .driver = {
.name = "at91-reset", .name = "at91-reset",
.of_match_table = at91_reset_of_match, .of_match_table = at91_reset_of_match,
}, },
}; };
module_platform_driver_probe(at91_reset_driver, at91_reset_probe); module_platform_driver(at91_reset_driver);
MODULE_AUTHOR("Atmel Corporation"); MODULE_AUTHOR("Atmel Corporation");
MODULE_DESCRIPTION("Reset driver for Atmel SoCs"); MODULE_DESCRIPTION("Reset driver for Atmel SoCs");
......
...@@ -107,7 +107,7 @@ static const unsigned long long sdwc_dbc_period[] = { ...@@ -107,7 +107,7 @@ static const unsigned long long sdwc_dbc_period[] = {
0, 3, 32, 512, 4096, 32768, 0, 3, 32, 512, 4096, 32768,
}; };
static void __init at91_wakeup_status(struct platform_device *pdev) static void at91_wakeup_status(struct platform_device *pdev)
{ {
struct shdwc *shdw = platform_get_drvdata(pdev); struct shdwc *shdw = platform_get_drvdata(pdev);
const struct reg_config *rcfg = shdw->rcfg; const struct reg_config *rcfg = shdw->rcfg;
...@@ -329,7 +329,7 @@ static const struct of_device_id at91_pmc_ids[] = { ...@@ -329,7 +329,7 @@ static const struct of_device_id at91_pmc_ids[] = {
{ /* Sentinel. */ } { /* Sentinel. */ }
}; };
static int __init at91_shdwc_probe(struct platform_device *pdev) static int at91_shdwc_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match; const struct of_device_id *match;
struct device_node *np; struct device_node *np;
...@@ -421,7 +421,7 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) ...@@ -421,7 +421,7 @@ static int __init at91_shdwc_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __exit at91_shdwc_remove(struct platform_device *pdev) static void at91_shdwc_remove(struct platform_device *pdev)
{ {
struct shdwc *shdw = platform_get_drvdata(pdev); struct shdwc *shdw = platform_get_drvdata(pdev);
...@@ -437,18 +437,17 @@ static int __exit at91_shdwc_remove(struct platform_device *pdev) ...@@ -437,18 +437,17 @@ static int __exit at91_shdwc_remove(struct platform_device *pdev)
iounmap(shdw->pmc_base); iounmap(shdw->pmc_base);
clk_disable_unprepare(shdw->sclk); clk_disable_unprepare(shdw->sclk);
return 0;
} }
static struct platform_driver at91_shdwc_driver = { static struct platform_driver at91_shdwc_driver = {
.remove = __exit_p(at91_shdwc_remove), .probe = at91_shdwc_probe,
.remove_new = at91_shdwc_remove,
.driver = { .driver = {
.name = "at91-shdwc", .name = "at91-shdwc",
.of_match_table = at91_shdwc_of_match, .of_match_table = at91_shdwc_of_match,
}, },
}; };
module_platform_driver_probe(at91_shdwc_driver, at91_shdwc_probe); module_platform_driver(at91_shdwc_driver);
MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
MODULE_DESCRIPTION("Atmel shutdown controller driver"); MODULE_DESCRIPTION("Atmel shutdown controller driver");
......
...@@ -233,7 +233,7 @@ static int atc260x_pwrc_probe(struct platform_device *pdev) ...@@ -233,7 +233,7 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int atc260x_pwrc_remove(struct platform_device *pdev) static void atc260x_pwrc_remove(struct platform_device *pdev)
{ {
struct atc260x_pwrc *priv = platform_get_drvdata(pdev); struct atc260x_pwrc *priv = platform_get_drvdata(pdev);
...@@ -243,13 +243,11 @@ static int atc260x_pwrc_remove(struct platform_device *pdev) ...@@ -243,13 +243,11 @@ static int atc260x_pwrc_remove(struct platform_device *pdev)
} }
unregister_restart_handler(&priv->restart_nb); unregister_restart_handler(&priv->restart_nb);
return 0;
} }
static struct platform_driver atc260x_pwrc_driver = { static struct platform_driver atc260x_pwrc_driver = {
.probe = atc260x_pwrc_probe, .probe = atc260x_pwrc_probe,
.remove = atc260x_pwrc_remove, .remove_new = atc260x_pwrc_remove,
.driver = { .driver = {
.name = "atc260x-pwrc", .name = "atc260x-pwrc",
}, },
......
...@@ -17,17 +17,14 @@ ...@@ -17,17 +17,14 @@
struct gpio_restart { struct gpio_restart {
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct notifier_block restart_handler;
u32 active_delay_ms; u32 active_delay_ms;
u32 inactive_delay_ms; u32 inactive_delay_ms;
u32 wait_delay_ms; u32 wait_delay_ms;
}; };
static int gpio_restart_notify(struct notifier_block *this, static int gpio_restart_notify(struct sys_off_data *data)
unsigned long mode, void *cmd)
{ {
struct gpio_restart *gpio_restart = struct gpio_restart *gpio_restart = data->cb_data;
container_of(this, struct gpio_restart, restart_handler);
/* drive it active, also inactive->active edge */ /* drive it active, also inactive->active edge */
gpiod_direction_output(gpio_restart->reset_gpio, 1); gpiod_direction_output(gpio_restart->reset_gpio, 1);
...@@ -52,6 +49,7 @@ static int gpio_restart_probe(struct platform_device *pdev) ...@@ -52,6 +49,7 @@ static int gpio_restart_probe(struct platform_device *pdev)
{ {
struct gpio_restart *gpio_restart; struct gpio_restart *gpio_restart;
bool open_source = false; bool open_source = false;
int priority = 129;
u32 property; u32 property;
int ret; int ret;
...@@ -71,8 +69,6 @@ static int gpio_restart_probe(struct platform_device *pdev) ...@@ -71,8 +69,6 @@ static int gpio_restart_probe(struct platform_device *pdev)
return ret; return ret;
} }
gpio_restart->restart_handler.notifier_call = gpio_restart_notify;
gpio_restart->restart_handler.priority = 129;
gpio_restart->active_delay_ms = 100; gpio_restart->active_delay_ms = 100;
gpio_restart->inactive_delay_ms = 100; gpio_restart->inactive_delay_ms = 100;
gpio_restart->wait_delay_ms = 3000; gpio_restart->wait_delay_ms = 3000;
...@@ -83,7 +79,7 @@ static int gpio_restart_probe(struct platform_device *pdev) ...@@ -83,7 +79,7 @@ static int gpio_restart_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Invalid priority property: %u\n", dev_err(&pdev->dev, "Invalid priority property: %u\n",
property); property);
else else
gpio_restart->restart_handler.priority = property; priority = property;
} }
of_property_read_u32(pdev->dev.of_node, "active-delay", of_property_read_u32(pdev->dev.of_node, "active-delay",
...@@ -93,9 +89,11 @@ static int gpio_restart_probe(struct platform_device *pdev) ...@@ -93,9 +89,11 @@ static int gpio_restart_probe(struct platform_device *pdev)
of_property_read_u32(pdev->dev.of_node, "wait-delay", of_property_read_u32(pdev->dev.of_node, "wait-delay",
&gpio_restart->wait_delay_ms); &gpio_restart->wait_delay_ms);
platform_set_drvdata(pdev, gpio_restart); ret = devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_RESTART,
ret = register_restart_handler(&gpio_restart->restart_handler); priority,
gpio_restart_notify,
gpio_restart);
if (ret) { if (ret) {
dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n", dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n",
__func__, ret); __func__, ret);
...@@ -105,19 +103,6 @@ static int gpio_restart_probe(struct platform_device *pdev) ...@@ -105,19 +103,6 @@ static int gpio_restart_probe(struct platform_device *pdev)
return 0; return 0;
} }
static void gpio_restart_remove(struct platform_device *pdev)
{
struct gpio_restart *gpio_restart = platform_get_drvdata(pdev);
int ret;
ret = unregister_restart_handler(&gpio_restart->restart_handler);
if (ret) {
dev_err(&pdev->dev,
"%s: cannot unregister restart handler, %d\n",
__func__, ret);
}
}
static const struct of_device_id of_gpio_restart_match[] = { static const struct of_device_id of_gpio_restart_match[] = {
{ .compatible = "gpio-restart", }, { .compatible = "gpio-restart", },
{}, {},
...@@ -125,7 +110,6 @@ static const struct of_device_id of_gpio_restart_match[] = { ...@@ -125,7 +110,6 @@ static const struct of_device_id of_gpio_restart_match[] = {
static struct platform_driver gpio_restart_driver = { static struct platform_driver gpio_restart_driver = {
.probe = gpio_restart_probe, .probe = gpio_restart_probe,
.remove_new = gpio_restart_remove,
.driver = { .driver = {
.name = "restart-gpio", .name = "restart-gpio",
.of_match_table = of_gpio_restart_match, .of_match_table = of_gpio_restart_match,
......
...@@ -286,7 +286,7 @@ static int ltc2952_poweroff_probe(struct platform_device *pdev) ...@@ -286,7 +286,7 @@ static int ltc2952_poweroff_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int ltc2952_poweroff_remove(struct platform_device *pdev) static void ltc2952_poweroff_remove(struct platform_device *pdev)
{ {
struct ltc2952_poweroff *data = platform_get_drvdata(pdev); struct ltc2952_poweroff *data = platform_get_drvdata(pdev);
...@@ -295,7 +295,6 @@ static int ltc2952_poweroff_remove(struct platform_device *pdev) ...@@ -295,7 +295,6 @@ static int ltc2952_poweroff_remove(struct platform_device *pdev)
hrtimer_cancel(&data->timer_wde); hrtimer_cancel(&data->timer_wde);
atomic_notifier_chain_unregister(&panic_notifier_list, atomic_notifier_chain_unregister(&panic_notifier_list,
&data->panic_notifier); &data->panic_notifier);
return 0;
} }
static const struct of_device_id of_ltc2952_poweroff_match[] = { static const struct of_device_id of_ltc2952_poweroff_match[] = {
...@@ -306,7 +305,7 @@ MODULE_DEVICE_TABLE(of, of_ltc2952_poweroff_match); ...@@ -306,7 +305,7 @@ MODULE_DEVICE_TABLE(of, of_ltc2952_poweroff_match);
static struct platform_driver ltc2952_poweroff_driver = { static struct platform_driver ltc2952_poweroff_driver = {
.probe = ltc2952_poweroff_probe, .probe = ltc2952_poweroff_probe,
.remove = ltc2952_poweroff_remove, .remove_new = ltc2952_poweroff_remove,
.driver = { .driver = {
.name = "ltc2952-poweroff", .name = "ltc2952-poweroff",
.of_match_table = of_ltc2952_poweroff_match, .of_match_table = of_ltc2952_poweroff_match,
......
...@@ -70,12 +70,10 @@ static int mt6323_pwrc_probe(struct platform_device *pdev) ...@@ -70,12 +70,10 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int mt6323_pwrc_remove(struct platform_device *pdev) static void mt6323_pwrc_remove(struct platform_device *pdev)
{ {
if (pm_power_off == &mt6323_do_pwroff) if (pm_power_off == &mt6323_do_pwroff)
pm_power_off = NULL; pm_power_off = NULL;
return 0;
} }
static const struct of_device_id mt6323_pwrc_dt_match[] = { static const struct of_device_id mt6323_pwrc_dt_match[] = {
...@@ -86,7 +84,7 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match); ...@@ -86,7 +84,7 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = { static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe, .probe = mt6323_pwrc_probe,
.remove = mt6323_pwrc_remove, .remove_new = mt6323_pwrc_remove,
.driver = { .driver = {
.name = "mt6323-pwrc", .name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match, .of_match_table = mt6323_pwrc_dt_match,
......
...@@ -17,11 +17,17 @@ ...@@ -17,11 +17,17 @@
#include <linux/types.h> #include <linux/types.h>
struct pwr_mlxbf { struct pwr_mlxbf {
struct work_struct send_work; struct work_struct reboot_work;
struct work_struct shutdown_work;
const char *hid; const char *hid;
}; };
static void pwr_mlxbf_send_work(struct work_struct *work) static void pwr_mlxbf_reboot_work(struct work_struct *work)
{
acpi_bus_generate_netlink_event("button/reboot.*", "Reboot Button", 0x80, 1);
}
static void pwr_mlxbf_shutdown_work(struct work_struct *work)
{ {
acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1); acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1);
} }
...@@ -33,10 +39,10 @@ static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr) ...@@ -33,10 +39,10 @@ static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr)
struct pwr_mlxbf *priv = ptr; struct pwr_mlxbf *priv = ptr;
if (!strncmp(priv->hid, rst_pwr_hid, 8)) if (!strncmp(priv->hid, rst_pwr_hid, 8))
emergency_restart(); schedule_work(&priv->reboot_work);
if (!strncmp(priv->hid, low_pwr_hid, 8)) if (!strncmp(priv->hid, low_pwr_hid, 8))
schedule_work(&priv->send_work); schedule_work(&priv->shutdown_work);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -64,7 +70,11 @@ static int pwr_mlxbf_probe(struct platform_device *pdev) ...@@ -64,7 +70,11 @@ static int pwr_mlxbf_probe(struct platform_device *pdev)
if (irq < 0) if (irq < 0)
return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid); return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid);
err = devm_work_autocancel(dev, &priv->send_work, pwr_mlxbf_send_work); err = devm_work_autocancel(dev, &priv->shutdown_work, pwr_mlxbf_shutdown_work);
if (err)
return err;
err = devm_work_autocancel(dev, &priv->reboot_work, pwr_mlxbf_reboot_work);
if (err) if (err)
return err; return err;
......
...@@ -111,15 +111,14 @@ static int qnap_power_off_probe(struct platform_device *pdev) ...@@ -111,15 +111,14 @@ static int qnap_power_off_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int qnap_power_off_remove(struct platform_device *pdev) static void qnap_power_off_remove(struct platform_device *pdev)
{ {
pm_power_off = NULL; pm_power_off = NULL;
return 0;
} }
static struct platform_driver qnap_power_off_driver = { static struct platform_driver qnap_power_off_driver = {
.probe = qnap_power_off_probe, .probe = qnap_power_off_probe,
.remove = qnap_power_off_remove, .remove_new = qnap_power_off_remove,
.driver = { .driver = {
.name = "qnap_power_off", .name = "qnap_power_off",
.of_match_table = of_match_ptr(qnap_power_off_of_match_table), .of_match_table = of_match_ptr(qnap_power_off_of_match_table),
......
...@@ -52,12 +52,10 @@ static int regulator_poweroff_probe(struct platform_device *pdev) ...@@ -52,12 +52,10 @@ static int regulator_poweroff_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev) static void regulator_poweroff_remove(struct platform_device *pdev)
{ {
if (pm_power_off == &regulator_poweroff_do_poweroff) if (pm_power_off == &regulator_poweroff_do_poweroff)
pm_power_off = NULL; pm_power_off = NULL;
return 0;
} }
static const struct of_device_id of_regulator_poweroff_match[] = { static const struct of_device_id of_regulator_poweroff_match[] = {
...@@ -68,7 +66,7 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match); ...@@ -68,7 +66,7 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);
static struct platform_driver regulator_poweroff_driver = { static struct platform_driver regulator_poweroff_driver = {
.probe = regulator_poweroff_probe, .probe = regulator_poweroff_probe,
.remove = regulator_poweroff_remove, .remove_new = regulator_poweroff_remove,
.driver = { .driver = {
.name = "poweroff-regulator", .name = "poweroff-regulator",
.of_match_table = of_regulator_poweroff_match, .of_match_table = of_regulator_poweroff_match,
......
...@@ -33,12 +33,10 @@ static int restart_poweroff_probe(struct platform_device *pdev) ...@@ -33,12 +33,10 @@ static int restart_poweroff_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int restart_poweroff_remove(struct platform_device *pdev) static void restart_poweroff_remove(struct platform_device *pdev)
{ {
if (pm_power_off == &restart_poweroff_do_poweroff) if (pm_power_off == &restart_poweroff_do_poweroff)
pm_power_off = NULL; pm_power_off = NULL;
return 0;
} }
static const struct of_device_id of_restart_poweroff_match[] = { static const struct of_device_id of_restart_poweroff_match[] = {
...@@ -49,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match); ...@@ -49,7 +47,7 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match);
static struct platform_driver restart_poweroff_driver = { static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe, .probe = restart_poweroff_probe,
.remove = restart_poweroff_remove, .remove_new = restart_poweroff_remove,
.driver = { .driver = {
.name = "poweroff-restart", .name = "poweroff-restart",
.of_match_table = of_restart_poweroff_match, .of_match_table = of_restart_poweroff_match,
......
...@@ -59,11 +59,10 @@ static int rmobile_reset_probe(struct platform_device *pdev) ...@@ -59,11 +59,10 @@ static int rmobile_reset_probe(struct platform_device *pdev)
return error; return error;
} }
static int rmobile_reset_remove(struct platform_device *pdev) static void rmobile_reset_remove(struct platform_device *pdev)
{ {
unregister_restart_handler(&rmobile_reset_nb); unregister_restart_handler(&rmobile_reset_nb);
iounmap(sysc_base2); iounmap(sysc_base2);
return 0;
} }
static const struct of_device_id rmobile_reset_of_match[] = { static const struct of_device_id rmobile_reset_of_match[] = {
...@@ -74,7 +73,7 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match); ...@@ -74,7 +73,7 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match);
static struct platform_driver rmobile_reset_driver = { static struct platform_driver rmobile_reset_driver = {
.probe = rmobile_reset_probe, .probe = rmobile_reset_probe,
.remove = rmobile_reset_remove, .remove_new = rmobile_reset_remove,
.driver = { .driver = {
.name = "rmobile_reset", .name = "rmobile_reset",
.of_match_table = rmobile_reset_of_match, .of_match_table = rmobile_reset_of_match,
......
...@@ -76,12 +76,10 @@ static int syscon_poweroff_probe(struct platform_device *pdev) ...@@ -76,12 +76,10 @@ static int syscon_poweroff_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int syscon_poweroff_remove(struct platform_device *pdev) static void syscon_poweroff_remove(struct platform_device *pdev)
{ {
if (pm_power_off == syscon_poweroff) if (pm_power_off == syscon_poweroff)
pm_power_off = NULL; pm_power_off = NULL;
return 0;
} }
static const struct of_device_id syscon_poweroff_of_match[] = { static const struct of_device_id syscon_poweroff_of_match[] = {
...@@ -91,7 +89,7 @@ static const struct of_device_id syscon_poweroff_of_match[] = { ...@@ -91,7 +89,7 @@ static const struct of_device_id syscon_poweroff_of_match[] = {
static struct platform_driver syscon_poweroff_driver = { static struct platform_driver syscon_poweroff_driver = {
.probe = syscon_poweroff_probe, .probe = syscon_poweroff_probe,
.remove = syscon_poweroff_remove, .remove_new = syscon_poweroff_remove,
.driver = { .driver = {
.name = "syscon-poweroff", .name = "syscon-poweroff",
.of_match_table = syscon_poweroff_of_match, .of_match_table = syscon_poweroff_of_match,
......
...@@ -62,19 +62,21 @@ static int tps65086_restart_probe(struct platform_device *pdev) ...@@ -62,19 +62,21 @@ static int tps65086_restart_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int tps65086_restart_remove(struct platform_device *pdev) static void tps65086_restart_remove(struct platform_device *pdev)
{ {
struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev); struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev);
int ret; int ret;
ret = unregister_restart_handler(&tps65086_restart->handler); ret = unregister_restart_handler(&tps65086_restart->handler);
if (ret) { if (ret) {
/*
* tps65086_restart_probe() registered the restart handler. So
* unregistering should work fine. Checking the error code
* shouldn't be needed, still doing it for completeness.
*/
dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n", dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n",
__func__, ret); __func__, ret);
return -ENODEV;
} }
return 0;
} }
static const struct platform_device_id tps65086_restart_id_table[] = { static const struct platform_device_id tps65086_restart_id_table[] = {
...@@ -88,7 +90,7 @@ static struct platform_driver tps65086_restart_driver = { ...@@ -88,7 +90,7 @@ static struct platform_driver tps65086_restart_driver = {
.name = "tps65086-restart", .name = "tps65086-restart",
}, },
.probe = tps65086_restart_probe, .probe = tps65086_restart_probe,
.remove = tps65086_restart_remove, .remove_new = tps65086_restart_remove,
.id_table = tps65086_restart_id_table, .id_table = tps65086_restart_id_table,
}; };
module_platform_driver(tps65086_restart_driver); module_platform_driver(tps65086_restart_driver);
......
...@@ -36,10 +36,16 @@ ...@@ -36,10 +36,16 @@
#define BQ24190_REG_POC_WDT_RESET_SHIFT 6 #define BQ24190_REG_POC_WDT_RESET_SHIFT 6
#define BQ24190_REG_POC_CHG_CONFIG_MASK (BIT(5) | BIT(4)) #define BQ24190_REG_POC_CHG_CONFIG_MASK (BIT(5) | BIT(4))
#define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4 #define BQ24190_REG_POC_CHG_CONFIG_SHIFT 4
#define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0 #define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0
#define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1 #define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1
#define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2 #define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2
#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3 #define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3
#define BQ24296_REG_POC_OTG_CONFIG_MASK BIT(5)
#define BQ24296_REG_POC_OTG_CONFIG_SHIFT 5
#define BQ24296_REG_POC_CHG_CONFIG_MASK BIT(4)
#define BQ24296_REG_POC_CHG_CONFIG_SHIFT 4
#define BQ24296_REG_POC_OTG_CONFIG_DISABLE 0x0
#define BQ24296_REG_POC_OTG_CONFIG_OTG 0x1
#define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1)) #define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1))
#define BQ24190_REG_POC_SYS_MIN_SHIFT 1 #define BQ24190_REG_POC_SYS_MIN_SHIFT 1
#define BQ24190_REG_POC_SYS_MIN_MIN 3000 #define BQ24190_REG_POC_SYS_MIN_MIN 3000
...@@ -134,58 +140,23 @@ ...@@ -134,58 +140,23 @@
#define BQ24190_REG_F_BAT_FAULT_SHIFT 3 #define BQ24190_REG_F_BAT_FAULT_SHIFT 3
#define BQ24190_REG_F_NTC_FAULT_MASK (BIT(2) | BIT(1) | BIT(0)) #define BQ24190_REG_F_NTC_FAULT_MASK (BIT(2) | BIT(1) | BIT(0))
#define BQ24190_REG_F_NTC_FAULT_SHIFT 0 #define BQ24190_REG_F_NTC_FAULT_SHIFT 0
#define BQ24296_REG_F_NTC_FAULT_MASK (BIT(1) | BIT(0))
#define BQ24296_REG_F_NTC_FAULT_SHIFT 0
#define BQ24190_REG_VPRS 0x0A /* Vendor/Part/Revision Status */ #define BQ24190_REG_VPRS 0x0A /* Vendor/Part/Revision Status */
#define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3)) #define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3))
#define BQ24190_REG_VPRS_PN_SHIFT 3 #define BQ24190_REG_VPRS_PN_SHIFT 3
#define BQ24190_REG_VPRS_PN_24190 0x4 #define BQ24190_REG_VPRS_PN_24190 0x4
#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */ #define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */
#define BQ24190_REG_VPRS_PN_24192I 0x3 #define BQ24190_REG_VPRS_PN_24192I 0x3
#define BQ24296_REG_VPRS_PN_MASK (BIT(7) | BIT(6) | BIT(5))
#define BQ24296_REG_VPRS_PN_SHIFT 5
#define BQ24296_REG_VPRS_PN_24296 0x1
#define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2) #define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2)
#define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2 #define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2
#define BQ24190_REG_VPRS_DEV_REG_MASK (BIT(1) | BIT(0)) #define BQ24190_REG_VPRS_DEV_REG_MASK (BIT(1) | BIT(0))
#define BQ24190_REG_VPRS_DEV_REG_SHIFT 0 #define BQ24190_REG_VPRS_DEV_REG_SHIFT 0
/*
* The FAULT register is latched by the bq24190 (except for NTC_FAULT)
* so the first read after a fault returns the latched value and subsequent
* reads return the current value. In order to return the fault status
* to the user, have the interrupt handler save the reg's value and retrieve
* it in the appropriate health/status routine.
*/
struct bq24190_dev_info {
struct i2c_client *client;
struct device *dev;
struct extcon_dev *edev;
struct power_supply *charger;
struct power_supply *battery;
struct delayed_work input_current_limit_work;
char model_name[I2C_NAME_SIZE];
bool initialized;
bool irq_event;
bool otg_vbus_enabled;
int charge_type;
u16 sys_min;
u16 iprechg;
u16 iterm;
u32 ichg;
u32 ichg_max;
u32 vreg;
u32 vreg_max;
struct mutex f_reg_lock;
u8 f_reg;
u8 ss_reg;
u8 watchdog;
};
static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
const union power_supply_propval *val);
static const unsigned int bq24190_usb_extcon_cable[] = {
EXTCON_USB,
EXTCON_NONE,
};
/* /*
* The tables below provide a 2-way mapping for the value that goes in * The tables below provide a 2-way mapping for the value that goes in
* the register field and the real-world value that it represents. * the register field and the real-world value that it represents.
...@@ -211,6 +182,9 @@ static const int bq24190_ccc_ichg_values[] = { ...@@ -211,6 +182,9 @@ static const int bq24190_ccc_ichg_values[] = {
4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000 4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000
}; };
/* ICHG higher than 3008mA is not supported in BQ24296 */
#define BQ24296_CCC_ICHG_VALUES_LEN 40
/* REG04[7:2] (VREG) in uV */ /* REG04[7:2] (VREG) in uV */
static const int bq24190_cvc_vreg_values[] = { static const int bq24190_cvc_vreg_values[] = {
3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000, 3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000,
...@@ -228,6 +202,68 @@ static const int bq24190_ictrc_treg_values[] = { ...@@ -228,6 +202,68 @@ static const int bq24190_ictrc_treg_values[] = {
600, 800, 1000, 1200 600, 800, 1000, 1200
}; };
enum bq24190_chip {
BQ24190,
BQ24192,
BQ24192i,
BQ24196,
BQ24296,
};
/*
* The FAULT register is latched by the bq24190 (except for NTC_FAULT)
* so the first read after a fault returns the latched value and subsequent
* reads return the current value. In order to return the fault status
* to the user, have the interrupt handler save the reg's value and retrieve
* it in the appropriate health/status routine.
*/
struct bq24190_dev_info {
struct i2c_client *client;
struct device *dev;
struct extcon_dev *edev;
struct power_supply *charger;
struct power_supply *battery;
struct delayed_work input_current_limit_work;
char model_name[I2C_NAME_SIZE];
bool initialized;
bool irq_event;
bool otg_vbus_enabled;
int charge_type;
u16 sys_min;
u16 iprechg;
u16 iterm;
u32 ichg;
u32 ichg_max;
u32 vreg;
u32 vreg_max;
struct mutex f_reg_lock;
u8 f_reg;
u8 ss_reg;
u8 watchdog;
const struct bq24190_chip_info *info;
};
struct bq24190_chip_info {
int ichg_array_size;
#ifdef CONFIG_REGULATOR
const struct regulator_desc *vbus_desc;
#endif
int (*check_chip)(struct bq24190_dev_info *bdi);
int (*set_chg_config)(struct bq24190_dev_info *bdi, const u8 chg_config);
int (*set_otg_vbus)(struct bq24190_dev_info *bdi, bool enable);
u8 ntc_fault_mask;
int (*get_ntc_status)(const u8 value);
};
static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
const union power_supply_propval *val);
static const unsigned int bq24190_usb_extcon_cable[] = {
EXTCON_USB,
EXTCON_NONE,
};
/* /*
* Return the index in 'tbl' of greatest value that is less than or equal to * Return the index in 'tbl' of greatest value that is less than or equal to
* 'val'. The index range returned is 0 to 'tbl_size' - 1. Assumes that * 'val'. The index range returned is 0 to 'tbl_size' - 1. Assumes that
...@@ -529,6 +565,43 @@ static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable) ...@@ -529,6 +565,43 @@ static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
return ret; return ret;
} }
static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
{
int ret;
ret = pm_runtime_resume_and_get(bdi->dev);
if (ret < 0) {
dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
return ret;
}
bdi->otg_vbus_enabled = enable;
if (enable) {
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_CHG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
BQ24190_REG_POC_CHG_CONFIG_DISABLE);
if (ret < 0)
goto out;
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_OTG);
} else
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_DISABLE);
out:
pm_runtime_mark_last_busy(bdi->dev);
pm_runtime_put_autosuspend(bdi->dev);
return ret;
}
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR
static int bq24190_vbus_enable(struct regulator_dev *dev) static int bq24190_vbus_enable(struct regulator_dev *dev)
{ {
...@@ -567,6 +640,43 @@ static int bq24190_vbus_is_enabled(struct regulator_dev *dev) ...@@ -567,6 +640,43 @@ static int bq24190_vbus_is_enabled(struct regulator_dev *dev)
return bdi->otg_vbus_enabled; return bdi->otg_vbus_enabled;
} }
static int bq24296_vbus_enable(struct regulator_dev *dev)
{
return bq24296_set_otg_vbus(rdev_get_drvdata(dev), true);
}
static int bq24296_vbus_disable(struct regulator_dev *dev)
{
return bq24296_set_otg_vbus(rdev_get_drvdata(dev), false);
}
static int bq24296_vbus_is_enabled(struct regulator_dev *dev)
{
struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);
int ret;
u8 val;
ret = pm_runtime_resume_and_get(bdi->dev);
if (ret < 0) {
dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
return ret;
}
ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
BQ24296_REG_POC_OTG_CONFIG_SHIFT, &val);
pm_runtime_mark_last_busy(bdi->dev);
pm_runtime_put_autosuspend(bdi->dev);
if (ret)
return ret;
bdi->otg_vbus_enabled = (val == BQ24296_REG_POC_OTG_CONFIG_OTG);
return bdi->otg_vbus_enabled;
}
static const struct regulator_ops bq24190_vbus_ops = { static const struct regulator_ops bq24190_vbus_ops = {
.enable = bq24190_vbus_enable, .enable = bq24190_vbus_enable,
.disable = bq24190_vbus_disable, .disable = bq24190_vbus_disable,
...@@ -583,6 +693,22 @@ static const struct regulator_desc bq24190_vbus_desc = { ...@@ -583,6 +693,22 @@ static const struct regulator_desc bq24190_vbus_desc = {
.n_voltages = 1, .n_voltages = 1,
}; };
static const struct regulator_ops bq24296_vbus_ops = {
.enable = bq24296_vbus_enable,
.disable = bq24296_vbus_disable,
.is_enabled = bq24296_vbus_is_enabled,
};
static const struct regulator_desc bq24296_vbus_desc = {
.name = "usb_otg_vbus",
.of_match = "usb-otg-vbus",
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.ops = &bq24296_vbus_ops,
.fixed_uV = 5000000,
.n_voltages = 1,
};
static const struct regulator_init_data bq24190_vbus_init_data = { static const struct regulator_init_data bq24190_vbus_init_data = {
.constraints = { .constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS, .valid_ops_mask = REGULATOR_CHANGE_STATUS,
...@@ -602,7 +728,7 @@ static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi) ...@@ -602,7 +728,7 @@ static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi)
else else
cfg.init_data = &bq24190_vbus_init_data; cfg.init_data = &bq24190_vbus_init_data;
cfg.driver_data = bdi; cfg.driver_data = bdi;
reg = devm_regulator_register(bdi->dev, &bq24190_vbus_desc, &cfg); reg = devm_regulator_register(bdi->dev, bdi->info->vbus_desc, &cfg);
if (IS_ERR(reg)) { if (IS_ERR(reg)) {
ret = PTR_ERR(reg); ret = PTR_ERR(reg);
dev_err(bdi->dev, "Can't register regulator: %d\n", ret); dev_err(bdi->dev, "Can't register regulator: %d\n", ret);
...@@ -678,7 +804,7 @@ static int bq24190_set_config(struct bq24190_dev_info *bdi) ...@@ -678,7 +804,7 @@ static int bq24190_set_config(struct bq24190_dev_info *bdi)
BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_MASK,
BQ24190_REG_CCC_ICHG_SHIFT, BQ24190_REG_CCC_ICHG_SHIFT,
bq24190_ccc_ichg_values, bq24190_ccc_ichg_values,
ARRAY_SIZE(bq24190_ccc_ichg_values), bdi->info->ichg_array_size,
bdi->ichg); bdi->ichg);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -777,6 +903,24 @@ static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi, ...@@ -777,6 +903,24 @@ static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi,
return 0; return 0;
} }
static int bq24190_battery_set_chg_config(struct bq24190_dev_info *bdi,
const u8 chg_config)
{
return bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24190_REG_POC_CHG_CONFIG_MASK,
BQ24190_REG_POC_CHG_CONFIG_SHIFT,
chg_config);
}
static int bq24296_battery_set_chg_config(struct bq24190_dev_info *bdi,
const u8 chg_config)
{
return bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_CHG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
chg_config);
}
static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi, static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
const union power_supply_propval *val) const union power_supply_propval *val)
{ {
...@@ -835,9 +979,50 @@ static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi, ...@@ -835,9 +979,50 @@ static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
return ret; return ret;
} }
return bq24190_write_mask(bdi, BQ24190_REG_POC, return bdi->info->set_chg_config(bdi, chg_config);
BQ24190_REG_POC_CHG_CONFIG_MASK, }
BQ24190_REG_POC_CHG_CONFIG_SHIFT, chg_config);
static int bq24190_charger_get_ntc_status(u8 value)
{
int health;
switch (value >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) {
case 0x1: /* TS1 Cold */
case 0x3: /* TS2 Cold */
case 0x5: /* Both Cold */
health = POWER_SUPPLY_HEALTH_COLD;
break;
case 0x2: /* TS1 Hot */
case 0x4: /* TS2 Hot */
case 0x6: /* Both Hot */
health = POWER_SUPPLY_HEALTH_OVERHEAT;
break;
default:
health = POWER_SUPPLY_HEALTH_UNKNOWN;
}
return health;
}
static int bq24296_charger_get_ntc_status(u8 value)
{
int health;
switch (value >> BQ24296_REG_F_NTC_FAULT_SHIFT & 0x3) {
case 0x0: /* Normal */
health = POWER_SUPPLY_HEALTH_GOOD;
break;
case 0x1: /* Hot */
health = POWER_SUPPLY_HEALTH_OVERHEAT;
break;
case 0x2: /* Cold */
health = POWER_SUPPLY_HEALTH_COLD;
break;
default:
health = POWER_SUPPLY_HEALTH_UNKNOWN;
}
return health;
} }
static int bq24190_charger_get_health(struct bq24190_dev_info *bdi, static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
...@@ -850,21 +1035,8 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi, ...@@ -850,21 +1035,8 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
v = bdi->f_reg; v = bdi->f_reg;
mutex_unlock(&bdi->f_reg_lock); mutex_unlock(&bdi->f_reg_lock);
if (v & BQ24190_REG_F_NTC_FAULT_MASK) { if (v & bdi->info->ntc_fault_mask) {
switch (v >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) { health = bdi->info->get_ntc_status(v);
case 0x1: /* TS1 Cold */
case 0x3: /* TS2 Cold */
case 0x5: /* Both Cold */
health = POWER_SUPPLY_HEALTH_COLD;
break;
case 0x2: /* TS1 Hot */
case 0x4: /* TS2 Hot */
case 0x6: /* Both Hot */
health = POWER_SUPPLY_HEALTH_OVERHEAT;
break;
default:
health = POWER_SUPPLY_HEALTH_UNKNOWN;
}
} else if (v & BQ24190_REG_F_BAT_FAULT_MASK) { } else if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
} else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) { } else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) {
...@@ -1015,7 +1187,7 @@ static int bq24190_charger_get_current(struct bq24190_dev_info *bdi, ...@@ -1015,7 +1187,7 @@ static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,
ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC, ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC,
BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT, BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
bq24190_ccc_ichg_values, bq24190_ccc_ichg_values,
ARRAY_SIZE(bq24190_ccc_ichg_values), &curr); bdi->info->ichg_array_size, &curr);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1055,7 +1227,7 @@ static int bq24190_charger_set_current(struct bq24190_dev_info *bdi, ...@@ -1055,7 +1227,7 @@ static int bq24190_charger_set_current(struct bq24190_dev_info *bdi,
ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC, ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC,
BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT, BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
bq24190_ccc_ichg_values, bq24190_ccc_ichg_values,
ARRAY_SIZE(bq24190_ccc_ichg_values), curr); bdi->info->ichg_array_size, curr);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1395,26 +1567,9 @@ static int bq24190_battery_get_health(struct bq24190_dev_info *bdi, ...@@ -1395,26 +1567,9 @@ static int bq24190_battery_get_health(struct bq24190_dev_info *bdi,
if (v & BQ24190_REG_F_BAT_FAULT_MASK) { if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
} else { } else {
v &= BQ24190_REG_F_NTC_FAULT_MASK; v &= bdi->info->ntc_fault_mask;
v >>= BQ24190_REG_F_NTC_FAULT_SHIFT;
switch (v) { health = v ? bdi->info->get_ntc_status(v) : POWER_SUPPLY_HEALTH_GOOD;
case 0x0: /* Normal */
health = POWER_SUPPLY_HEALTH_GOOD;
break;
case 0x1: /* TS1 Cold */
case 0x3: /* TS2 Cold */
case 0x5: /* Both Cold */
health = POWER_SUPPLY_HEALTH_COLD;
break;
case 0x2: /* TS1 Hot */
case 0x4: /* TS2 Hot */
case 0x6: /* Both Hot */
health = POWER_SUPPLY_HEALTH_OVERHEAT;
break;
default:
health = POWER_SUPPLY_HEALTH_UNKNOWN;
}
} }
val->intval = health; val->intval = health;
...@@ -1601,12 +1756,13 @@ static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg) ...@@ -1601,12 +1756,13 @@ static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
static void bq24190_check_status(struct bq24190_dev_info *bdi) static void bq24190_check_status(struct bq24190_dev_info *bdi)
{ {
const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;
const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK;
| BQ24190_REG_F_NTC_FAULT_MASK;
bool alert_charger = false, alert_battery = false; bool alert_charger = false, alert_battery = false;
u8 ss_reg = 0, f_reg = 0; u8 ss_reg = 0, f_reg = 0;
int i, ret; int i, ret;
battery_mask_f |= bdi->info->ntc_fault_mask;
ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg); ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
if (ret < 0) { if (ret < 0) {
dev_err(bdi->dev, "Can't read SS reg: %d\n", ret); dev_err(bdi->dev, "Can't read SS reg: %d\n", ret);
...@@ -1633,7 +1789,7 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi) ...@@ -1633,7 +1789,7 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi)
!!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK), !!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK),
!!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK), !!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK),
!!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK), !!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK),
!!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK)); !!(f_reg & bdi->info->ntc_fault_mask));
mutex_lock(&bdi->f_reg_lock); mutex_lock(&bdi->f_reg_lock);
if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f)) if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f))
...@@ -1696,12 +1852,11 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) ...@@ -1696,12 +1852,11 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int bq24190_hw_init(struct bq24190_dev_info *bdi) static int bq24190_check_chip(struct bq24190_dev_info *bdi)
{ {
u8 v; u8 v;
int ret; int ret;
/* First check that the device really is what its supposed to be */
ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS, ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
BQ24190_REG_VPRS_PN_MASK, BQ24190_REG_VPRS_PN_MASK,
BQ24190_REG_VPRS_PN_SHIFT, BQ24190_REG_VPRS_PN_SHIFT,
...@@ -1719,6 +1874,40 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi) ...@@ -1719,6 +1874,40 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
return -ENODEV; return -ENODEV;
} }
return 0;
}
static int bq24296_check_chip(struct bq24190_dev_info *bdi)
{
u8 v;
int ret;
ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
BQ24296_REG_VPRS_PN_MASK,
BQ24296_REG_VPRS_PN_SHIFT,
&v);
if (ret < 0)
return ret;
switch (v) {
case BQ24296_REG_VPRS_PN_24296:
break;
default:
dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
return -ENODEV;
}
return 0;
}
static int bq24190_hw_init(struct bq24190_dev_info *bdi)
{
int ret;
ret = bdi->info->check_chip(bdi);
if (ret < 0)
return ret;
ret = bq24190_register_reset(bdi); ret = bq24190_register_reset(bdi);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1736,7 +1925,8 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi) ...@@ -1736,7 +1925,8 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
struct power_supply_battery_info *info; struct power_supply_battery_info *info;
int v, idx; int v, idx;
idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1; idx = bdi->info->ichg_array_size - 1;
bdi->ichg_max = bq24190_ccc_ichg_values[idx]; bdi->ichg_max = bq24190_ccc_ichg_values[idx];
idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1; idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1;
...@@ -1781,6 +1971,64 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi) ...@@ -1781,6 +1971,64 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
return 0; return 0;
} }
static const struct bq24190_chip_info bq24190_chip_info_tbl[] = {
[BQ24190] = {
.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),
#ifdef CONFIG_REGULATOR
.vbus_desc = &bq24190_vbus_desc,
#endif
.check_chip = bq24190_check_chip,
.set_chg_config = bq24190_battery_set_chg_config,
.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,
.get_ntc_status = bq24190_charger_get_ntc_status,
.set_otg_vbus = bq24190_set_otg_vbus,
},
[BQ24192] = {
.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),
#ifdef CONFIG_REGULATOR
.vbus_desc = &bq24190_vbus_desc,
#endif
.check_chip = bq24190_check_chip,
.set_chg_config = bq24190_battery_set_chg_config,
.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,
.get_ntc_status = bq24190_charger_get_ntc_status,
.set_otg_vbus = bq24190_set_otg_vbus,
},
[BQ24192i] = {
.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),
#ifdef CONFIG_REGULATOR
.vbus_desc = &bq24190_vbus_desc,
#endif
.check_chip = bq24190_check_chip,
.set_chg_config = bq24190_battery_set_chg_config,
.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,
.get_ntc_status = bq24190_charger_get_ntc_status,
.set_otg_vbus = bq24190_set_otg_vbus,
},
[BQ24196] = {
.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),
#ifdef CONFIG_REGULATOR
.vbus_desc = &bq24190_vbus_desc,
#endif
.check_chip = bq24190_check_chip,
.set_chg_config = bq24190_battery_set_chg_config,
.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,
.get_ntc_status = bq24190_charger_get_ntc_status,
.set_otg_vbus = bq24190_set_otg_vbus,
},
[BQ24296] = {
.ichg_array_size = BQ24296_CCC_ICHG_VALUES_LEN,
#ifdef CONFIG_REGULATOR
.vbus_desc = &bq24296_vbus_desc,
#endif
.check_chip = bq24296_check_chip,
.set_chg_config = bq24296_battery_set_chg_config,
.ntc_fault_mask = BQ24296_REG_F_NTC_FAULT_MASK,
.get_ntc_status = bq24296_charger_get_ntc_status,
.set_otg_vbus = bq24296_set_otg_vbus,
},
};
static int bq24190_probe(struct i2c_client *client) static int bq24190_probe(struct i2c_client *client)
{ {
const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct i2c_device_id *id = i2c_client_get_device_id(client);
...@@ -1804,6 +2052,7 @@ static int bq24190_probe(struct i2c_client *client) ...@@ -1804,6 +2052,7 @@ static int bq24190_probe(struct i2c_client *client)
bdi->client = client; bdi->client = client;
bdi->dev = dev; bdi->dev = dev;
strscpy(bdi->model_name, id->name, sizeof(bdi->model_name)); strscpy(bdi->model_name, id->name, sizeof(bdi->model_name));
bdi->info = i2c_get_match_data(client);
mutex_init(&bdi->f_reg_lock); mutex_init(&bdi->f_reg_lock);
bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST; bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
bdi->f_reg = 0; bdi->f_reg = 0;
...@@ -1940,7 +2189,7 @@ static void bq24190_shutdown(struct i2c_client *client) ...@@ -1940,7 +2189,7 @@ static void bq24190_shutdown(struct i2c_client *client)
struct bq24190_dev_info *bdi = i2c_get_clientdata(client); struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
/* Turn off 5V boost regulator on shutdown */ /* Turn off 5V boost regulator on shutdown */
bq24190_set_otg_vbus(bdi, false); bdi->info->set_otg_vbus(bdi, false);
} }
static __maybe_unused int bq24190_runtime_suspend(struct device *dev) static __maybe_unused int bq24190_runtime_suspend(struct device *dev)
...@@ -2029,19 +2278,21 @@ static const struct dev_pm_ops bq24190_pm_ops = { ...@@ -2029,19 +2278,21 @@ static const struct dev_pm_ops bq24190_pm_ops = {
}; };
static const struct i2c_device_id bq24190_i2c_ids[] = { static const struct i2c_device_id bq24190_i2c_ids[] = {
{ "bq24190" }, { "bq24190", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] },
{ "bq24192" }, { "bq24192", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] },
{ "bq24192i" }, { "bq24192i", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] },
{ "bq24196" }, { "bq24196", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] },
{ "bq24296", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
static const struct of_device_id bq24190_of_match[] = { static const struct of_device_id bq24190_of_match[] = {
{ .compatible = "ti,bq24190", }, { .compatible = "ti,bq24190", .data = &bq24190_chip_info_tbl[BQ24190] },
{ .compatible = "ti,bq24192", }, { .compatible = "ti,bq24192", .data = &bq24190_chip_info_tbl[BQ24192] },
{ .compatible = "ti,bq24192i", }, { .compatible = "ti,bq24192i", .data = &bq24190_chip_info_tbl[BQ24192i] },
{ .compatible = "ti,bq24196", }, { .compatible = "ti,bq24196", .data = &bq24190_chip_info_tbl[BQ24196] },
{ .compatible = "ti,bq24296", .data = &bq24190_chip_info_tbl[BQ24296] },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, bq24190_of_match); MODULE_DEVICE_TABLE(of, bq24190_of_match);
......
...@@ -1574,13 +1574,16 @@ static int bq256xx_hw_init(struct bq256xx_device *bq) ...@@ -1574,13 +1574,16 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
wd_reg_val = i; wd_reg_val = i;
break; break;
} }
if (bq->watchdog_timer > bq256xx_watchdog_time[i] && if (i + 1 < BQ256XX_NUM_WD_VAL &&
bq->watchdog_timer > bq256xx_watchdog_time[i] &&
bq->watchdog_timer < bq256xx_watchdog_time[i + 1]) bq->watchdog_timer < bq256xx_watchdog_time[i + 1])
wd_reg_val = i; wd_reg_val = i;
} }
ret = regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_1, ret = regmap_update_bits(bq->regmap, BQ256XX_CHARGER_CONTROL_1,
BQ256XX_WATCHDOG_MASK, wd_reg_val << BQ256XX_WATCHDOG_MASK, wd_reg_val <<
BQ256XX_WDT_BIT_SHIFT); BQ256XX_WDT_BIT_SHIFT);
if (ret)
return ret;
ret = power_supply_get_battery_info(bq->charger, &bat_info); ret = power_supply_get_battery_info(bq->charger, &bat_info);
if (ret == -ENOMEM) if (ret == -ENOMEM)
......
...@@ -2162,6 +2162,28 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) ...@@ -2162,6 +2162,28 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
} }
EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
#ifdef CONFIG_PM_SLEEP
static int bq27xxx_battery_suspend(struct device *dev)
{
struct bq27xxx_device_info *di = dev_get_drvdata(dev);
cancel_delayed_work(&di->work);
return 0;
}
static int bq27xxx_battery_resume(struct device *dev)
{
struct bq27xxx_device_info *di = dev_get_drvdata(dev);
schedule_delayed_work(&di->work, 0);
return 0;
}
#endif /* CONFIG_PM_SLEEP */
SIMPLE_DEV_PM_OPS(bq27xxx_battery_battery_pm_ops,
bq27xxx_battery_suspend, bq27xxx_battery_resume);
EXPORT_SYMBOL_GPL(bq27xxx_battery_battery_pm_ops);
MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
MODULE_DESCRIPTION("BQ27xxx battery monitor driver"); MODULE_DESCRIPTION("BQ27xxx battery monitor driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -295,6 +295,7 @@ static struct i2c_driver bq27xxx_battery_i2c_driver = { ...@@ -295,6 +295,7 @@ static struct i2c_driver bq27xxx_battery_i2c_driver = {
.driver = { .driver = {
.name = "bq27xxx-battery", .name = "bq27xxx-battery",
.of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table), .of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
.pm = &bq27xxx_battery_battery_pm_ops,
}, },
.probe = bq27xxx_battery_i2c_probe, .probe = bq27xxx_battery_i2c_probe,
.remove = bq27xxx_battery_i2c_remove, .remove = bq27xxx_battery_i2c_remove,
......
...@@ -491,7 +491,7 @@ static int cw_battery_get_property(struct power_supply *psy, ...@@ -491,7 +491,7 @@ static int cw_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
if (cw_battery_valid_time_to_empty(cw_bat)) if (cw_battery_valid_time_to_empty(cw_bat))
val->intval = cw_bat->time_to_empty; val->intval = cw_bat->time_to_empty * 60;
else else
val->intval = 0; val->intval = 0;
break; break;
......
...@@ -861,44 +861,44 @@ const size_t power_supply_battery_info_properties_size = ARRAY_SIZE(power_supply ...@@ -861,44 +861,44 @@ const size_t power_supply_battery_info_properties_size = ARRAY_SIZE(power_supply
EXPORT_SYMBOL_GPL(power_supply_battery_info_properties_size); EXPORT_SYMBOL_GPL(power_supply_battery_info_properties_size);
bool power_supply_battery_info_has_prop(struct power_supply_battery_info *info, bool power_supply_battery_info_has_prop(struct power_supply_battery_info *info,
enum power_supply_property psp) enum power_supply_property psp)
{ {
if (!info) if (!info)
return false; return false;
switch (psp) { switch (psp) {
case POWER_SUPPLY_PROP_TECHNOLOGY: case POWER_SUPPLY_PROP_TECHNOLOGY:
return info->technology != POWER_SUPPLY_TECHNOLOGY_UNKNOWN; return info->technology != POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
return info->energy_full_design_uwh >= 0; return info->energy_full_design_uwh >= 0;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
return info->charge_full_design_uah >= 0; return info->charge_full_design_uah >= 0;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
return info->voltage_min_design_uv >= 0; return info->voltage_min_design_uv >= 0;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
return info->voltage_max_design_uv >= 0; return info->voltage_max_design_uv >= 0;
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
return info->precharge_current_ua >= 0; return info->precharge_current_ua >= 0;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
return info->charge_term_current_ua >= 0; return info->charge_term_current_ua >= 0;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
return info->constant_charge_current_max_ua >= 0; return info->constant_charge_current_max_ua >= 0;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
return info->constant_charge_voltage_max_uv >= 0; return info->constant_charge_voltage_max_uv >= 0;
case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN:
return info->temp_ambient_alert_min > INT_MIN; return info->temp_ambient_alert_min > INT_MIN;
case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX:
return info->temp_ambient_alert_max < INT_MAX; return info->temp_ambient_alert_max < INT_MAX;
case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
return info->temp_alert_min > INT_MIN; return info->temp_alert_min > INT_MIN;
case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
return info->temp_alert_max < INT_MAX; return info->temp_alert_max < INT_MAX;
case POWER_SUPPLY_PROP_TEMP_MIN: case POWER_SUPPLY_PROP_TEMP_MIN:
return info->temp_min > INT_MIN; return info->temp_min > INT_MIN;
case POWER_SUPPLY_PROP_TEMP_MAX: case POWER_SUPPLY_PROP_TEMP_MAX:
return info->temp_max < INT_MAX; return info->temp_max < INT_MAX;
default: default:
return false; return false;
} }
} }
EXPORT_SYMBOL_GPL(power_supply_battery_info_has_prop); EXPORT_SYMBOL_GPL(power_supply_battery_info_has_prop);
...@@ -914,53 +914,53 @@ int power_supply_battery_info_get_prop(struct power_supply_battery_info *info, ...@@ -914,53 +914,53 @@ int power_supply_battery_info_get_prop(struct power_supply_battery_info *info,
return -EINVAL; return -EINVAL;
switch (psp) { switch (psp) {
case POWER_SUPPLY_PROP_TECHNOLOGY: case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = info->technology; val->intval = info->technology;
return 0; return 0;
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
val->intval = info->energy_full_design_uwh; val->intval = info->energy_full_design_uwh;
return 0; return 0;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
val->intval = info->charge_full_design_uah; val->intval = info->charge_full_design_uah;
return 0; return 0;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
val->intval = info->voltage_min_design_uv; val->intval = info->voltage_min_design_uv;
return 0; return 0;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = info->voltage_max_design_uv; val->intval = info->voltage_max_design_uv;
return 0; return 0;
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
val->intval = info->precharge_current_ua; val->intval = info->precharge_current_ua;
return 0; return 0;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
val->intval = info->charge_term_current_ua; val->intval = info->charge_term_current_ua;
return 0; return 0;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
val->intval = info->constant_charge_current_max_ua; val->intval = info->constant_charge_current_max_ua;
return 0; return 0;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
val->intval = info->constant_charge_voltage_max_uv; val->intval = info->constant_charge_voltage_max_uv;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN: case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN:
val->intval = info->temp_ambient_alert_min; val->intval = info->temp_ambient_alert_min;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX: case POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX:
val->intval = info->temp_ambient_alert_max; val->intval = info->temp_ambient_alert_max;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
val->intval = info->temp_alert_min; val->intval = info->temp_alert_min;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
val->intval = info->temp_alert_max; val->intval = info->temp_alert_max;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_MIN: case POWER_SUPPLY_PROP_TEMP_MIN:
val->intval = info->temp_min; val->intval = info->temp_min;
return 0; return 0;
case POWER_SUPPLY_PROP_TEMP_MAX: case POWER_SUPPLY_PROP_TEMP_MAX:
val->intval = info->temp_max; val->intval = info->temp_max;
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
} }
EXPORT_SYMBOL_GPL(power_supply_battery_info_get_prop); EXPORT_SYMBOL_GPL(power_supply_battery_info_get_prop);
...@@ -1255,6 +1255,7 @@ EXPORT_SYMBOL_GPL(power_supply_powers); ...@@ -1255,6 +1255,7 @@ EXPORT_SYMBOL_GPL(power_supply_powers);
static void power_supply_dev_release(struct device *dev) static void power_supply_dev_release(struct device *dev)
{ {
struct power_supply *psy = to_power_supply(dev); struct power_supply *psy = to_power_supply(dev);
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
kfree(psy); kfree(psy);
} }
...@@ -1636,6 +1637,6 @@ subsys_initcall(power_supply_class_init); ...@@ -1636,6 +1637,6 @@ subsys_initcall(power_supply_class_init);
module_exit(power_supply_class_exit); module_exit(power_supply_class_exit);
MODULE_DESCRIPTION("Universal power supply monitor class"); MODULE_DESCRIPTION("Universal power supply monitor class");
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, " MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
"Szabolcs Gyurko, " MODULE_AUTHOR("Szabolcs Gyurko");
"Anton Vorontsov <cbou@mail.ru>"); MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
...@@ -282,6 +282,7 @@ struct qcom_battmgr_wireless { ...@@ -282,6 +282,7 @@ struct qcom_battmgr_wireless {
struct qcom_battmgr { struct qcom_battmgr {
struct device *dev; struct device *dev;
struct auxiliary_device *adev;
struct pmic_glink_client *client; struct pmic_glink_client *client;
enum qcom_battmgr_variant variant; enum qcom_battmgr_variant variant;
...@@ -1293,11 +1294,69 @@ static void qcom_battmgr_enable_worker(struct work_struct *work) ...@@ -1293,11 +1294,69 @@ static void qcom_battmgr_enable_worker(struct work_struct *work)
dev_err(battmgr->dev, "failed to request power notifications\n"); dev_err(battmgr->dev, "failed to request power notifications\n");
} }
static char *qcom_battmgr_battery[] = { "battery" };
static void qcom_battmgr_register_psy(struct qcom_battmgr *battmgr)
{
struct power_supply_config psy_cfg_supply = {};
struct auxiliary_device *adev = battmgr->adev;
struct power_supply_config psy_cfg = {};
struct device *dev = &adev->dev;
psy_cfg.drv_data = battmgr;
psy_cfg.of_node = adev->dev.of_node;
psy_cfg_supply.drv_data = battmgr;
psy_cfg_supply.of_node = adev->dev.of_node;
psy_cfg_supply.supplied_to = qcom_battmgr_battery;
psy_cfg_supply.num_supplicants = 1;
if (battmgr->variant == QCOM_BATTMGR_SC8280XP) {
battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, &psy_cfg);
if (IS_ERR(battmgr->bat_psy))
dev_err(dev, "failed to register battery power supply (%ld)\n",
PTR_ERR(battmgr->bat_psy));
battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->ac_psy))
dev_err(dev, "failed to register AC power supply (%ld)\n",
PTR_ERR(battmgr->ac_psy));
battmgr->usb_psy = devm_power_supply_register(dev, &sc8280xp_usb_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->usb_psy))
dev_err(dev, "failed to register USB power supply (%ld)\n",
PTR_ERR(battmgr->usb_psy));
battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->wls_psy))
dev_err(dev, "failed to register wireless charing power supply (%ld)\n",
PTR_ERR(battmgr->wls_psy));
} else {
battmgr->bat_psy = devm_power_supply_register(dev, &sm8350_bat_psy_desc, &psy_cfg);
if (IS_ERR(battmgr->bat_psy))
dev_err(dev, "failed to register battery power supply (%ld)\n",
PTR_ERR(battmgr->bat_psy));
battmgr->usb_psy = devm_power_supply_register(dev, &sm8350_usb_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->usb_psy))
dev_err(dev, "failed to register USB power supply (%ld)\n",
PTR_ERR(battmgr->usb_psy));
battmgr->wls_psy = devm_power_supply_register(dev, &sm8350_wls_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->wls_psy))
dev_err(dev, "failed to register wireless charing power supply (%ld)\n",
PTR_ERR(battmgr->wls_psy));
}
}
static void qcom_battmgr_pdr_notify(void *priv, int state) static void qcom_battmgr_pdr_notify(void *priv, int state)
{ {
struct qcom_battmgr *battmgr = priv; struct qcom_battmgr *battmgr = priv;
if (state == SERVREG_SERVICE_STATE_UP) { if (state == SERVREG_SERVICE_STATE_UP) {
if (!battmgr->bat_psy)
qcom_battmgr_register_psy(battmgr);
battmgr->service_up = true; battmgr->service_up = true;
schedule_work(&battmgr->enable_work); schedule_work(&battmgr->enable_work);
} else { } else {
...@@ -1312,13 +1371,9 @@ static const struct of_device_id qcom_battmgr_of_variants[] = { ...@@ -1312,13 +1371,9 @@ static const struct of_device_id qcom_battmgr_of_variants[] = {
{} {}
}; };
static char *qcom_battmgr_battery[] = { "battery" };
static int qcom_battmgr_probe(struct auxiliary_device *adev, static int qcom_battmgr_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id) const struct auxiliary_device_id *id)
{ {
struct power_supply_config psy_cfg_supply = {};
struct power_supply_config psy_cfg = {};
const struct of_device_id *match; const struct of_device_id *match;
struct qcom_battmgr *battmgr; struct qcom_battmgr *battmgr;
struct device *dev = &adev->dev; struct device *dev = &adev->dev;
...@@ -1328,14 +1383,7 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, ...@@ -1328,14 +1383,7 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev,
return -ENOMEM; return -ENOMEM;
battmgr->dev = dev; battmgr->dev = dev;
battmgr->adev = adev;
psy_cfg.drv_data = battmgr;
psy_cfg.of_node = adev->dev.of_node;
psy_cfg_supply.drv_data = battmgr;
psy_cfg_supply.of_node = adev->dev.of_node;
psy_cfg_supply.supplied_to = qcom_battmgr_battery;
psy_cfg_supply.num_supplicants = 1;
INIT_WORK(&battmgr->enable_work, qcom_battmgr_enable_worker); INIT_WORK(&battmgr->enable_work, qcom_battmgr_enable_worker);
mutex_init(&battmgr->lock); mutex_init(&battmgr->lock);
...@@ -1347,43 +1395,6 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev, ...@@ -1347,43 +1395,6 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev,
else else
battmgr->variant = QCOM_BATTMGR_SM8350; battmgr->variant = QCOM_BATTMGR_SM8350;
if (battmgr->variant == QCOM_BATTMGR_SC8280XP) {
battmgr->bat_psy = devm_power_supply_register(dev, &sc8280xp_bat_psy_desc, &psy_cfg);
if (IS_ERR(battmgr->bat_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy),
"failed to register battery power supply\n");
battmgr->ac_psy = devm_power_supply_register(dev, &sc8280xp_ac_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->ac_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->ac_psy),
"failed to register AC power supply\n");
battmgr->usb_psy = devm_power_supply_register(dev, &sc8280xp_usb_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->usb_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy),
"failed to register USB power supply\n");
battmgr->wls_psy = devm_power_supply_register(dev, &sc8280xp_wls_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->wls_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy),
"failed to register wireless charing power supply\n");
} else {
battmgr->bat_psy = devm_power_supply_register(dev, &sm8350_bat_psy_desc, &psy_cfg);
if (IS_ERR(battmgr->bat_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->bat_psy),
"failed to register battery power supply\n");
battmgr->usb_psy = devm_power_supply_register(dev, &sm8350_usb_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->usb_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->usb_psy),
"failed to register USB power supply\n");
battmgr->wls_psy = devm_power_supply_register(dev, &sm8350_wls_psy_desc, &psy_cfg_supply);
if (IS_ERR(battmgr->wls_psy))
return dev_err_probe(dev, PTR_ERR(battmgr->wls_psy),
"failed to register wireless charing power supply\n");
}
battmgr->client = devm_pmic_glink_register_client(dev, battmgr->client = devm_pmic_glink_register_client(dev,
PMIC_GLINK_OWNER_BATTMGR, PMIC_GLINK_OWNER_BATTMGR,
qcom_battmgr_callback, qcom_battmgr_callback,
......
...@@ -972,10 +972,14 @@ static int smb2_probe(struct platform_device *pdev) ...@@ -972,10 +972,14 @@ static int smb2_probe(struct platform_device *pdev)
supply_config.of_node = pdev->dev.of_node; supply_config.of_node = pdev->dev.of_node;
desc = devm_kzalloc(chip->dev, sizeof(smb2_psy_desc), GFP_KERNEL); desc = devm_kzalloc(chip->dev, sizeof(smb2_psy_desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
memcpy(desc, &smb2_psy_desc, sizeof(smb2_psy_desc)); memcpy(desc, &smb2_psy_desc, sizeof(smb2_psy_desc));
desc->name = desc->name =
devm_kasprintf(chip->dev, GFP_KERNEL, "%s-charger", devm_kasprintf(chip->dev, GFP_KERNEL, "%s-charger",
(const char *)device_get_match_data(chip->dev)); (const char *)device_get_match_data(chip->dev));
if (!desc->name)
return -ENOMEM;
chip->chg_psy = chip->chg_psy =
devm_power_supply_register(chip->dev, desc, &supply_config); devm_power_supply_register(chip->dev, desc, &supply_config);
......
...@@ -83,5 +83,6 @@ struct bq27xxx_device_info { ...@@ -83,5 +83,6 @@ struct bq27xxx_device_info {
void bq27xxx_battery_update(struct bq27xxx_device_info *di); void bq27xxx_battery_update(struct bq27xxx_device_info *di);
int bq27xxx_battery_setup(struct bq27xxx_device_info *di); int bq27xxx_battery_setup(struct bq27xxx_device_info *di);
void bq27xxx_battery_teardown(struct bq27xxx_device_info *di); void bq27xxx_battery_teardown(struct bq27xxx_device_info *di);
extern const struct dev_pm_ops bq27xxx_battery_battery_pm_ops;
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment