diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 09:28:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 09:28:08 -0400 |
commit | df132e4062afe06ddc9938802243d704906a884a (patch) | |
tree | d7fd08f6bea2c431440fb965f7c43335ce12c391 | |
parent | 96f2f66a985699d201b3a84222b8dd42262a71fe (diff) | |
parent | cfb347979e71d3ce6be59a988b3357f541c9eacf (diff) |
Merge tag 'for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel:
- Add Spreadtrum SC2731 charger driver
- bq25890-charger: Add BQ25896 support
- bq27xxx-battery: Add support for BQ27411
- qcom-pon: Add pms405 pon support
- cros-charger: add support for dedicated port
- misc fixes
* tag 'for-v4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (28 commits)
power: max8925: mark expected switch fall-through
power: supply: fix spelling mistake "Gauage" -> "Gauge"
power: reset: qcom-pon: Add pms405 pon support
power: supply: bq27xxx: Add support for BQ27411
power: supply: Add Spreadtrum SC2731 charger support
dt-bindings: power: Add Spreadtrum SC2731 charger documentation
power: supply: twl4030_charger: disable eoc interrupt on linear charge
power: supply: twl4030_charger: fix charging current out-of-bounds
power: supply: bq25890_charger: fix semicolon.cocci warnings
power: supply: max8998-charger: Fix platform data retrieval
power: supply: cros: add support for dedicated port
mfd: cros: add charger port count command definition
power: reset: at91-poweroff: do not procede if at91_shdwc is allocated
power: reset: at91-poweroff: rename at91_shdwc_base member of struct shdwc
power: reset: at91-poweroff: make sclk part of struct shdwc
power: reset: at91-poweroff: make mpddrc_base part of struct shdwc
power: reset: at91-poweroff: use only one poweroff function
power: reset: at91-poweroff: switch to slow clock before shutdown
power: reset: convert to SPDX identifiers
power: supply: ab8500_fg: silence uninitialized variable warnings
...
30 files changed, 922 insertions, 213 deletions
diff --git a/Documentation/devicetree/bindings/power/reset/qcom,pon.txt b/Documentation/devicetree/bindings/power/reset/qcom,pon.txt index 651491bb63b7..5705f575862d 100644 --- a/Documentation/devicetree/bindings/power/reset/qcom,pon.txt +++ b/Documentation/devicetree/bindings/power/reset/qcom,pon.txt | |||
@@ -6,7 +6,10 @@ and resin along with the Android reboot-mode. | |||
6 | This DT node has pwrkey and resin as sub nodes. | 6 | This DT node has pwrkey and resin as sub nodes. |
7 | 7 | ||
8 | Required Properties: | 8 | Required Properties: |
9 | -compatible: "qcom,pm8916-pon" | 9 | -compatible: Must be one of: |
10 | "qcom,pm8916-pon" | ||
11 | "qcom,pms405-pon" | ||
12 | |||
10 | -reg: Specifies the physical address of the pon register | 13 | -reg: Specifies the physical address of the pon register |
11 | 14 | ||
12 | Optional subnode: | 15 | Optional subnode: |
diff --git a/Documentation/devicetree/bindings/power/supply/bq25890.txt b/Documentation/devicetree/bindings/power/supply/bq25890.txt index c9dd17d142ad..dc0568933359 100644 --- a/Documentation/devicetree/bindings/power/supply/bq25890.txt +++ b/Documentation/devicetree/bindings/power/supply/bq25890.txt | |||
@@ -1,5 +1,8 @@ | |||
1 | Binding for TI bq25890 Li-Ion Charger | 1 | Binding for TI bq25890 Li-Ion Charger |
2 | 2 | ||
3 | This driver will support the bq25896 and the bq25890. There are other ICs | ||
4 | in the same family but those have not been tested. | ||
5 | |||
3 | Required properties: | 6 | Required properties: |
4 | - compatible: Should contain one of the following: | 7 | - compatible: Should contain one of the following: |
5 | * "ti,bq25890" | 8 | * "ti,bq25890" |
diff --git a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt index 37994fdb18ca..4fa8e08df2b6 100644 --- a/Documentation/devicetree/bindings/power/supply/bq27xxx.txt +++ b/Documentation/devicetree/bindings/power/supply/bq27xxx.txt | |||
@@ -23,6 +23,7 @@ Required properties: | |||
23 | * "ti,bq27546" - BQ27546 | 23 | * "ti,bq27546" - BQ27546 |
24 | * "ti,bq27742" - BQ27742 | 24 | * "ti,bq27742" - BQ27742 |
25 | * "ti,bq27545" - BQ27545 | 25 | * "ti,bq27545" - BQ27545 |
26 | * "ti,bq27411" - BQ27411 | ||
26 | * "ti,bq27421" - BQ27421 | 27 | * "ti,bq27421" - BQ27421 |
27 | * "ti,bq27425" - BQ27425 | 28 | * "ti,bq27425" - BQ27425 |
28 | * "ti,bq27426" - BQ27426 | 29 | * "ti,bq27426" - BQ27426 |
diff --git a/Documentation/devicetree/bindings/power/supply/sc2731_charger.txt b/Documentation/devicetree/bindings/power/supply/sc2731_charger.txt new file mode 100644 index 000000000000..5266fab16575 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/sc2731_charger.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | Spreadtrum SC2731 PMIC battery charger binding | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "sprd,sc2731-charger". | ||
5 | - reg: Address offset of charger register. | ||
6 | - phys: Contains a phandle to the USB phy. | ||
7 | |||
8 | Optional Properties: | ||
9 | - monitored-battery: phandle of battery characteristics devicetree node. | ||
10 | The charger uses the following battery properties: | ||
11 | - charge-term-current-microamp: current for charge termination phase. | ||
12 | - constant-charge-voltage-max-microvolt: maximum constant input voltage. | ||
13 | See Documentation/devicetree/bindings/power/supply/battery.txt | ||
14 | |||
15 | Example: | ||
16 | |||
17 | bat: battery { | ||
18 | compatible = "simple-battery"; | ||
19 | charge-term-current-microamp = <120000>; | ||
20 | constant-charge-voltage-max-microvolt = <4350000>; | ||
21 | ...... | ||
22 | }; | ||
23 | |||
24 | sc2731_pmic: pmic@0 { | ||
25 | compatible = "sprd,sc2731"; | ||
26 | reg = <0>; | ||
27 | spi-max-frequency = <26000000>; | ||
28 | interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; | ||
29 | interrupt-controller; | ||
30 | #interrupt-cells = <2>; | ||
31 | #address-cells = <1>; | ||
32 | #size-cells = <0>; | ||
33 | |||
34 | charger@0 { | ||
35 | compatible = "sprd,sc2731-charger"; | ||
36 | reg = <0x0>; | ||
37 | phys = <&ssphy>; | ||
38 | monitored-battery = <&bat>; | ||
39 | }; | ||
40 | }; | ||
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index a7c6ae13c945..bfe1c4d06901 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S | |||
@@ -149,6 +149,14 @@ exit_suspend: | |||
149 | ENDPROC(at91_pm_suspend_in_sram) | 149 | ENDPROC(at91_pm_suspend_in_sram) |
150 | 150 | ||
151 | ENTRY(at91_backup_mode) | 151 | ENTRY(at91_backup_mode) |
152 | /* Switch the master clock source to slow clock. */ | ||
153 | ldr pmc, .pmc_base | ||
154 | ldr tmp1, [pmc, #AT91_PMC_MCKR] | ||
155 | bic tmp1, tmp1, #AT91_PMC_CSS | ||
156 | str tmp1, [pmc, #AT91_PMC_MCKR] | ||
157 | |||
158 | wait_mckrdy | ||
159 | |||
152 | /*BUMEN*/ | 160 | /*BUMEN*/ |
153 | ldr r0, .sfr | 161 | ldr r0, .sfr |
154 | mov tmp1, #0x1 | 162 | mov tmp1, #0x1 |
diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c index 0206cce328b3..2b686c55b717 100644 --- a/drivers/power/reset/at91-sama5d2_shdwc.c +++ b/drivers/power/reset/at91-sama5d2_shdwc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/clk/at91_pmc.h> | ||
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/of.h> | 25 | #include <linux/of.h> |
@@ -69,7 +70,10 @@ struct shdwc_config { | |||
69 | 70 | ||
70 | struct shdwc { | 71 | struct shdwc { |
71 | const struct shdwc_config *cfg; | 72 | const struct shdwc_config *cfg; |
72 | void __iomem *at91_shdwc_base; | 73 | struct clk *sclk; |
74 | void __iomem *shdwc_base; | ||
75 | void __iomem *mpddrc_base; | ||
76 | void __iomem *pmc_base; | ||
73 | }; | 77 | }; |
74 | 78 | ||
75 | /* | 79 | /* |
@@ -77,8 +81,6 @@ struct shdwc { | |||
77 | * since pm_power_off itself is global. | 81 | * since pm_power_off itself is global. |
78 | */ | 82 | */ |
79 | static struct shdwc *at91_shdwc; | 83 | static struct shdwc *at91_shdwc; |
80 | static struct clk *sclk; | ||
81 | static void __iomem *mpddrc_base; | ||
82 | 84 | ||
83 | static const unsigned long long sdwc_dbc_period[] = { | 85 | static const unsigned long long sdwc_dbc_period[] = { |
84 | 0, 3, 32, 512, 4096, 32768, | 86 | 0, 3, 32, 512, 4096, 32768, |
@@ -90,7 +92,7 @@ static void __init at91_wakeup_status(struct platform_device *pdev) | |||
90 | u32 reg; | 92 | u32 reg; |
91 | char *reason = "unknown"; | 93 | char *reason = "unknown"; |
92 | 94 | ||
93 | reg = readl(shdw->at91_shdwc_base + AT91_SHDW_SR); | 95 | reg = readl(shdw->shdwc_base + AT91_SHDW_SR); |
94 | 96 | ||
95 | dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg); | 97 | dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg); |
96 | 98 | ||
@@ -108,12 +110,6 @@ static void __init at91_wakeup_status(struct platform_device *pdev) | |||
108 | 110 | ||
109 | static void at91_poweroff(void) | 111 | static void at91_poweroff(void) |
110 | { | 112 | { |
111 | writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, | ||
112 | at91_shdwc->at91_shdwc_base + AT91_SHDW_CR); | ||
113 | } | ||
114 | |||
115 | static void at91_lpddr_poweroff(void) | ||
116 | { | ||
117 | asm volatile( | 113 | asm volatile( |
118 | /* Align to cache lines */ | 114 | /* Align to cache lines */ |
119 | ".balign 32\n\t" | 115 | ".balign 32\n\t" |
@@ -122,16 +118,29 @@ static void at91_lpddr_poweroff(void) | |||
122 | " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" | 118 | " ldr r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" |
123 | 119 | ||
124 | /* Power down SDRAM0 */ | 120 | /* Power down SDRAM0 */ |
121 | " tst %0, #0\n\t" | ||
122 | " beq 1f\n\t" | ||
125 | " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" | 123 | " str %1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t" |
124 | |||
125 | /* Switch the master clock source to slow clock. */ | ||
126 | "1: ldr r6, [%4, #" __stringify(AT91_PMC_MCKR) "]\n\t" | ||
127 | " bic r6, r6, #" __stringify(AT91_PMC_CSS) "\n\t" | ||
128 | " str r6, [%4, #" __stringify(AT91_PMC_MCKR) "]\n\t" | ||
129 | /* Wait for clock switch. */ | ||
130 | "2: ldr r6, [%4, #" __stringify(AT91_PMC_SR) "]\n\t" | ||
131 | " tst r6, #" __stringify(AT91_PMC_MCKRDY) "\n\t" | ||
132 | " beq 2b\n\t" | ||
133 | |||
126 | /* Shutdown CPU */ | 134 | /* Shutdown CPU */ |
127 | " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" | 135 | " str %3, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t" |
128 | 136 | ||
129 | " b .\n\t" | 137 | " b .\n\t" |
130 | : | 138 | : |
131 | : "r" (mpddrc_base), | 139 | : "r" (at91_shdwc->mpddrc_base), |
132 | "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF), | 140 | "r" cpu_to_le32(AT91_DDRSDRC_LPDDR2_PWOFF), |
133 | "r" (at91_shdwc->at91_shdwc_base), | 141 | "r" (at91_shdwc->shdwc_base), |
134 | "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW) | 142 | "r" cpu_to_le32(AT91_SHDW_KEY | AT91_SHDW_SHDW), |
143 | "r" (at91_shdwc->pmc_base) | ||
135 | : "r6"); | 144 | : "r6"); |
136 | } | 145 | } |
137 | 146 | ||
@@ -213,10 +222,10 @@ static void at91_shdwc_dt_configure(struct platform_device *pdev) | |||
213 | mode |= SHDW_RTCWKEN(shdw->cfg); | 222 | mode |= SHDW_RTCWKEN(shdw->cfg); |
214 | 223 | ||
215 | dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode); | 224 | dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode); |
216 | writel(mode, shdw->at91_shdwc_base + AT91_SHDW_MR); | 225 | writel(mode, shdw->shdwc_base + AT91_SHDW_MR); |
217 | 226 | ||
218 | input = at91_shdwc_get_wakeup_input(pdev, np); | 227 | input = at91_shdwc_get_wakeup_input(pdev, np); |
219 | writel(input, shdw->at91_shdwc_base + AT91_SHDW_WUIR); | 228 | writel(input, shdw->shdwc_base + AT91_SHDW_WUIR); |
220 | } | 229 | } |
221 | 230 | ||
222 | static const struct shdwc_config sama5d2_shdwc_config = { | 231 | static const struct shdwc_config sama5d2_shdwc_config = { |
@@ -246,6 +255,9 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) | |||
246 | if (!pdev->dev.of_node) | 255 | if (!pdev->dev.of_node) |
247 | return -ENODEV; | 256 | return -ENODEV; |
248 | 257 | ||
258 | if (at91_shdwc) | ||
259 | return -EBUSY; | ||
260 | |||
249 | at91_shdwc = devm_kzalloc(&pdev->dev, sizeof(*at91_shdwc), GFP_KERNEL); | 261 | at91_shdwc = devm_kzalloc(&pdev->dev, sizeof(*at91_shdwc), GFP_KERNEL); |
250 | if (!at91_shdwc) | 262 | if (!at91_shdwc) |
251 | return -ENOMEM; | 263 | return -ENOMEM; |
@@ -253,20 +265,20 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) | |||
253 | platform_set_drvdata(pdev, at91_shdwc); | 265 | platform_set_drvdata(pdev, at91_shdwc); |
254 | 266 | ||
255 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 267 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
256 | at91_shdwc->at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); | 268 | at91_shdwc->shdwc_base = devm_ioremap_resource(&pdev->dev, res); |
257 | if (IS_ERR(at91_shdwc->at91_shdwc_base)) { | 269 | if (IS_ERR(at91_shdwc->shdwc_base)) { |
258 | dev_err(&pdev->dev, "Could not map reset controller address\n"); | 270 | dev_err(&pdev->dev, "Could not map reset controller address\n"); |
259 | return PTR_ERR(at91_shdwc->at91_shdwc_base); | 271 | return PTR_ERR(at91_shdwc->shdwc_base); |
260 | } | 272 | } |
261 | 273 | ||
262 | match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node); | 274 | match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node); |
263 | at91_shdwc->cfg = match->data; | 275 | at91_shdwc->cfg = match->data; |
264 | 276 | ||
265 | sclk = devm_clk_get(&pdev->dev, NULL); | 277 | at91_shdwc->sclk = devm_clk_get(&pdev->dev, NULL); |
266 | if (IS_ERR(sclk)) | 278 | if (IS_ERR(at91_shdwc->sclk)) |
267 | return PTR_ERR(sclk); | 279 | return PTR_ERR(at91_shdwc->sclk); |
268 | 280 | ||
269 | ret = clk_prepare_enable(sclk); | 281 | ret = clk_prepare_enable(at91_shdwc->sclk); |
270 | if (ret) { | 282 | if (ret) { |
271 | dev_err(&pdev->dev, "Could not enable slow clock\n"); | 283 | dev_err(&pdev->dev, "Could not enable slow clock\n"); |
272 | return ret; | 284 | return ret; |
@@ -276,41 +288,70 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) | |||
276 | 288 | ||
277 | at91_shdwc_dt_configure(pdev); | 289 | at91_shdwc_dt_configure(pdev); |
278 | 290 | ||
279 | pm_power_off = at91_poweroff; | 291 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-pmc"); |
292 | if (!np) { | ||
293 | ret = -ENODEV; | ||
294 | goto clk_disable; | ||
295 | } | ||
296 | |||
297 | at91_shdwc->pmc_base = of_iomap(np, 0); | ||
298 | of_node_put(np); | ||
299 | |||
300 | if (!at91_shdwc->pmc_base) { | ||
301 | ret = -ENOMEM; | ||
302 | goto clk_disable; | ||
303 | } | ||
280 | 304 | ||
281 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc"); | 305 | np = of_find_compatible_node(NULL, NULL, "atmel,sama5d3-ddramc"); |
282 | if (!np) | 306 | if (!np) { |
283 | return 0; | 307 | ret = -ENODEV; |
308 | goto unmap; | ||
309 | } | ||
284 | 310 | ||
285 | mpddrc_base = of_iomap(np, 0); | 311 | at91_shdwc->mpddrc_base = of_iomap(np, 0); |
286 | of_node_put(np); | 312 | of_node_put(np); |
287 | 313 | ||
288 | if (!mpddrc_base) | 314 | if (!at91_shdwc->mpddrc_base) { |
289 | return 0; | 315 | ret = -ENOMEM; |
316 | goto unmap; | ||
317 | } | ||
290 | 318 | ||
291 | ddr_type = readl(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD; | 319 | pm_power_off = at91_poweroff; |
292 | if ((ddr_type == AT91_DDRSDRC_MD_LPDDR2) || | 320 | |
293 | (ddr_type == AT91_DDRSDRC_MD_LPDDR3)) | 321 | ddr_type = readl(at91_shdwc->mpddrc_base + AT91_DDRSDRC_MDR) & |
294 | pm_power_off = at91_lpddr_poweroff; | 322 | AT91_DDRSDRC_MD; |
295 | else | 323 | if (ddr_type != AT91_DDRSDRC_MD_LPDDR2 && |
296 | iounmap(mpddrc_base); | 324 | ddr_type != AT91_DDRSDRC_MD_LPDDR3) { |
325 | iounmap(at91_shdwc->mpddrc_base); | ||
326 | at91_shdwc->mpddrc_base = NULL; | ||
327 | } | ||
297 | 328 | ||
298 | return 0; | 329 | return 0; |
330 | |||
331 | unmap: | ||
332 | iounmap(at91_shdwc->pmc_base); | ||
333 | clk_disable: | ||
334 | clk_disable_unprepare(at91_shdwc->sclk); | ||
335 | |||
336 | return ret; | ||
299 | } | 337 | } |
300 | 338 | ||
301 | static int __exit at91_shdwc_remove(struct platform_device *pdev) | 339 | static int __exit at91_shdwc_remove(struct platform_device *pdev) |
302 | { | 340 | { |
303 | struct shdwc *shdw = platform_get_drvdata(pdev); | 341 | struct shdwc *shdw = platform_get_drvdata(pdev); |
304 | 342 | ||
305 | if (pm_power_off == at91_poweroff || | 343 | if (pm_power_off == at91_poweroff) |
306 | pm_power_off == at91_lpddr_poweroff) | ||
307 | pm_power_off = NULL; | 344 | pm_power_off = NULL; |
308 | 345 | ||
309 | /* Reset values to disable wake-up features */ | 346 | /* Reset values to disable wake-up features */ |
310 | writel(0, shdw->at91_shdwc_base + AT91_SHDW_MR); | 347 | writel(0, shdw->shdwc_base + AT91_SHDW_MR); |
311 | writel(0, shdw->at91_shdwc_base + AT91_SHDW_WUIR); | 348 | writel(0, shdw->shdwc_base + AT91_SHDW_WUIR); |
349 | |||
350 | if (shdw->mpddrc_base) | ||
351 | iounmap(shdw->mpddrc_base); | ||
352 | iounmap(shdw->pmc_base); | ||
312 | 353 | ||
313 | clk_disable_unprepare(sclk); | 354 | clk_disable_unprepare(shdw->sclk); |
314 | 355 | ||
315 | return 0; | 356 | return 0; |
316 | } | 357 | } |
diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index 0c4caaa7e88f..3fa1642d4c54 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c | |||
@@ -74,6 +74,7 @@ static int pm8916_pon_probe(struct platform_device *pdev) | |||
74 | 74 | ||
75 | static const struct of_device_id pm8916_pon_id_table[] = { | 75 | static const struct of_device_id pm8916_pon_id_table[] = { |
76 | { .compatible = "qcom,pm8916-pon" }, | 76 | { .compatible = "qcom,pm8916-pon" }, |
77 | { .compatible = "qcom,pms405-pon" }, | ||
77 | { } | 78 | { } |
78 | }; | 79 | }; |
79 | MODULE_DEVICE_TABLE(of, pm8916_pon_id_table); | 80 | MODULE_DEVICE_TABLE(of, pm8916_pon_id_table); |
diff --git a/drivers/power/reset/rmobile-reset.c b/drivers/power/reset/rmobile-reset.c index e6569df76941..bd3b396558e0 100644 --- a/drivers/power/reset/rmobile-reset.c +++ b/drivers/power/reset/rmobile-reset.c | |||
@@ -1,11 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Renesas R-Mobile Reset Driver | 3 | * Renesas R-Mobile Reset Driver |
3 | * | 4 | * |
4 | * Copyright (C) 2014 Glider bvba | 5 | * Copyright (C) 2014 Glider bvba |
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | 6 | */ |
10 | 7 | ||
11 | #include <linux/io.h> | 8 | #include <linux/io.h> |
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index ff6dab0bf0dd..f27cf0709500 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig | |||
@@ -645,4 +645,11 @@ config CHARGER_CROS_USBPD | |||
645 | what is connected to USB PD ports from the EC and converts | 645 | what is connected to USB PD ports from the EC and converts |
646 | that into power_supply properties. | 646 | that into power_supply properties. |
647 | 647 | ||
648 | config CHARGER_SC2731 | ||
649 | tristate "Spreadtrum SC2731 charger driver" | ||
650 | depends on MFD_SC27XX_PMIC || COMPILE_TEST | ||
651 | help | ||
652 | Say Y here to enable support for battery charging with SC2731 | ||
653 | PMIC chips. | ||
654 | |||
648 | endif # POWER_SUPPLY | 655 | endif # POWER_SUPPLY |
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index a26b402c45d9..767105b88d00 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile | |||
@@ -85,3 +85,4 @@ obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o | |||
85 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o | 85 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o |
86 | obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o | 86 | obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o |
87 | obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o | 87 | obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o |
88 | obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o | ||
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 02356f9b5f22..776102c31305 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c | |||
@@ -2433,17 +2433,14 @@ static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf, | |||
2433 | size_t count) | 2433 | size_t count) |
2434 | { | 2434 | { |
2435 | unsigned long charge_full; | 2435 | unsigned long charge_full; |
2436 | ssize_t ret; | 2436 | int ret; |
2437 | 2437 | ||
2438 | ret = kstrtoul(buf, 10, &charge_full); | 2438 | ret = kstrtoul(buf, 10, &charge_full); |
2439 | if (ret) | ||
2440 | return ret; | ||
2439 | 2441 | ||
2440 | dev_dbg(di->dev, "Ret %zd charge_full %lu", ret, charge_full); | 2442 | di->bat_cap.max_mah = (int) charge_full; |
2441 | 2443 | return count; | |
2442 | if (!ret) { | ||
2443 | di->bat_cap.max_mah = (int) charge_full; | ||
2444 | ret = count; | ||
2445 | } | ||
2446 | return ret; | ||
2447 | } | 2444 | } |
2448 | 2445 | ||
2449 | static ssize_t charge_now_show(struct ab8500_fg *di, char *buf) | 2446 | static ssize_t charge_now_show(struct ab8500_fg *di, char *buf) |
@@ -2455,20 +2452,16 @@ static ssize_t charge_now_store(struct ab8500_fg *di, const char *buf, | |||
2455 | size_t count) | 2452 | size_t count) |
2456 | { | 2453 | { |
2457 | unsigned long charge_now; | 2454 | unsigned long charge_now; |
2458 | ssize_t ret; | 2455 | int ret; |
2459 | 2456 | ||
2460 | ret = kstrtoul(buf, 10, &charge_now); | 2457 | ret = kstrtoul(buf, 10, &charge_now); |
2458 | if (ret) | ||
2459 | return ret; | ||
2461 | 2460 | ||
2462 | dev_dbg(di->dev, "Ret %zd charge_now %lu was %d", | 2461 | di->bat_cap.user_mah = (int) charge_now; |
2463 | ret, charge_now, di->bat_cap.prev_mah); | 2462 | di->flags.user_cap = true; |
2464 | 2463 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | |
2465 | if (!ret) { | 2464 | return count; |
2466 | di->bat_cap.user_mah = (int) charge_now; | ||
2467 | di->flags.user_cap = true; | ||
2468 | ret = count; | ||
2469 | queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); | ||
2470 | } | ||
2471 | return ret; | ||
2472 | } | 2465 | } |
2473 | 2466 | ||
2474 | static struct ab8500_fg_sysfs_entry charge_full_attr = | 2467 | static struct ab8500_fg_sysfs_entry charge_full_attr = |
@@ -2582,11 +2575,12 @@ static ssize_t ab8505_powercut_flagtime_write(struct device *dev, | |||
2582 | const char *buf, size_t count) | 2575 | const char *buf, size_t count) |
2583 | { | 2576 | { |
2584 | int ret; | 2577 | int ret; |
2585 | long unsigned reg_value; | 2578 | int reg_value; |
2586 | struct power_supply *psy = dev_get_drvdata(dev); | 2579 | struct power_supply *psy = dev_get_drvdata(dev); |
2587 | struct ab8500_fg *di = power_supply_get_drvdata(psy); | 2580 | struct ab8500_fg *di = power_supply_get_drvdata(psy); |
2588 | 2581 | ||
2589 | reg_value = simple_strtoul(buf, NULL, 10); | 2582 | if (kstrtoint(buf, 10, ®_value)) |
2583 | goto fail; | ||
2590 | 2584 | ||
2591 | if (reg_value > 0x7F) { | 2585 | if (reg_value > 0x7F) { |
2592 | dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n"); | 2586 | dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n"); |
@@ -2636,7 +2630,9 @@ static ssize_t ab8505_powercut_maxtime_write(struct device *dev, | |||
2636 | struct power_supply *psy = dev_get_drvdata(dev); | 2630 | struct power_supply *psy = dev_get_drvdata(dev); |
2637 | struct ab8500_fg *di = power_supply_get_drvdata(psy); | 2631 | struct ab8500_fg *di = power_supply_get_drvdata(psy); |
2638 | 2632 | ||
2639 | reg_value = simple_strtoul(buf, NULL, 10); | 2633 | if (kstrtoint(buf, 10, ®_value)) |
2634 | goto fail; | ||
2635 | |||
2640 | if (reg_value > 0x7F) { | 2636 | if (reg_value > 0x7F) { |
2641 | dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n"); | 2637 | dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n"); |
2642 | goto fail; | 2638 | goto fail; |
@@ -2684,7 +2680,9 @@ static ssize_t ab8505_powercut_restart_write(struct device *dev, | |||
2684 | struct power_supply *psy = dev_get_drvdata(dev); | 2680 | struct power_supply *psy = dev_get_drvdata(dev); |
2685 | struct ab8500_fg *di = power_supply_get_drvdata(psy); | 2681 | struct ab8500_fg *di = power_supply_get_drvdata(psy); |
2686 | 2682 | ||
2687 | reg_value = simple_strtoul(buf, NULL, 10); | 2683 | if (kstrtoint(buf, 10, ®_value)) |
2684 | goto fail; | ||
2685 | |||
2688 | if (reg_value > 0xF) { | 2686 | if (reg_value > 0xF) { |
2689 | dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n"); | 2687 | dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n"); |
2690 | goto fail; | 2688 | goto fail; |
@@ -2777,7 +2775,9 @@ static ssize_t ab8505_powercut_write(struct device *dev, | |||
2777 | struct power_supply *psy = dev_get_drvdata(dev); | 2775 | struct power_supply *psy = dev_get_drvdata(dev); |
2778 | struct ab8500_fg *di = power_supply_get_drvdata(psy); | 2776 | struct ab8500_fg *di = power_supply_get_drvdata(psy); |
2779 | 2777 | ||
2780 | reg_value = simple_strtoul(buf, NULL, 10); | 2778 | if (kstrtoint(buf, 10, ®_value)) |
2779 | goto fail; | ||
2780 | |||
2781 | if (reg_value > 0x1) { | 2781 | if (reg_value > 0x1) { |
2782 | dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n"); | 2782 | dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n"); |
2783 | goto fail; | 2783 | goto fail; |
@@ -2849,7 +2849,9 @@ static ssize_t ab8505_powercut_debounce_write(struct device *dev, | |||
2849 | struct power_supply *psy = dev_get_drvdata(dev); | 2849 | struct power_supply *psy = dev_get_drvdata(dev); |
2850 | struct ab8500_fg *di = power_supply_get_drvdata(psy); | 2850 | struct ab8500_fg *di = power_supply_get_drvdata(psy); |
2851 | 2851 | ||
2852 | reg_value = simple_strtoul(buf, NULL, 10); | 2852 | if (kstrtoint(buf, 10, ®_value)) |
2853 | goto fail; | ||
2854 | |||
2853 | if (reg_value > 0x7) { | 2855 | if (reg_value > 0x7) { |
2854 | dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n"); | 2856 | dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n"); |
2855 | goto fail; | 2857 | goto fail; |
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 8e2c41ded171..70b90db5ae38 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #define BQ25890_IRQ_PIN "bq25890_irq" | 32 | #define BQ25890_IRQ_PIN "bq25890_irq" |
33 | 33 | ||
34 | #define BQ25890_ID 3 | 34 | #define BQ25890_ID 3 |
35 | #define BQ25896_ID 0 | ||
35 | 36 | ||
36 | enum bq25890_fields { | 37 | enum bq25890_fields { |
37 | F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ | 38 | F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ |
@@ -153,8 +154,8 @@ static const struct reg_field bq25890_reg_fields[] = { | |||
153 | [F_CONV_RATE] = REG_FIELD(0x02, 6, 6), | 154 | [F_CONV_RATE] = REG_FIELD(0x02, 6, 6), |
154 | [F_BOOSTF] = REG_FIELD(0x02, 5, 5), | 155 | [F_BOOSTF] = REG_FIELD(0x02, 5, 5), |
155 | [F_ICO_EN] = REG_FIELD(0x02, 4, 4), | 156 | [F_ICO_EN] = REG_FIELD(0x02, 4, 4), |
156 | [F_HVDCP_EN] = REG_FIELD(0x02, 3, 3), | 157 | [F_HVDCP_EN] = REG_FIELD(0x02, 3, 3), // reserved on BQ25896 |
157 | [F_MAXC_EN] = REG_FIELD(0x02, 2, 2), | 158 | [F_MAXC_EN] = REG_FIELD(0x02, 2, 2), // reserved on BQ25896 |
158 | [F_FORCE_DPM] = REG_FIELD(0x02, 1, 1), | 159 | [F_FORCE_DPM] = REG_FIELD(0x02, 1, 1), |
159 | [F_AUTO_DPDM_EN] = REG_FIELD(0x02, 0, 0), | 160 | [F_AUTO_DPDM_EN] = REG_FIELD(0x02, 0, 0), |
160 | /* REG03 */ | 161 | /* REG03 */ |
@@ -163,6 +164,7 @@ static const struct reg_field bq25890_reg_fields[] = { | |||
163 | [F_OTG_CFG] = REG_FIELD(0x03, 5, 5), | 164 | [F_OTG_CFG] = REG_FIELD(0x03, 5, 5), |
164 | [F_CHG_CFG] = REG_FIELD(0x03, 4, 4), | 165 | [F_CHG_CFG] = REG_FIELD(0x03, 4, 4), |
165 | [F_SYSVMIN] = REG_FIELD(0x03, 1, 3), | 166 | [F_SYSVMIN] = REG_FIELD(0x03, 1, 3), |
167 | /* MIN_VBAT_SEL on BQ25896 */ | ||
166 | /* REG04 */ | 168 | /* REG04 */ |
167 | [F_PUMPX_EN] = REG_FIELD(0x04, 7, 7), | 169 | [F_PUMPX_EN] = REG_FIELD(0x04, 7, 7), |
168 | [F_ICHG] = REG_FIELD(0x04, 0, 6), | 170 | [F_ICHG] = REG_FIELD(0x04, 0, 6), |
@@ -181,7 +183,7 @@ static const struct reg_field bq25890_reg_fields[] = { | |||
181 | [F_CHG_TMR] = REG_FIELD(0x07, 1, 2), | 183 | [F_CHG_TMR] = REG_FIELD(0x07, 1, 2), |
182 | [F_JEITA_ISET] = REG_FIELD(0x07, 0, 0), | 184 | [F_JEITA_ISET] = REG_FIELD(0x07, 0, 0), |
183 | /* REG08 */ | 185 | /* REG08 */ |
184 | [F_BATCMP] = REG_FIELD(0x08, 6, 7), | 186 | [F_BATCMP] = REG_FIELD(0x08, 6, 7), // 5-7 on BQ25896 |
185 | [F_VCLAMP] = REG_FIELD(0x08, 2, 4), | 187 | [F_VCLAMP] = REG_FIELD(0x08, 2, 4), |
186 | [F_TREG] = REG_FIELD(0x08, 0, 1), | 188 | [F_TREG] = REG_FIELD(0x08, 0, 1), |
187 | /* REG09 */ | 189 | /* REG09 */ |
@@ -195,12 +197,13 @@ static const struct reg_field bq25890_reg_fields[] = { | |||
195 | [F_PUMPX_DN] = REG_FIELD(0x09, 0, 0), | 197 | [F_PUMPX_DN] = REG_FIELD(0x09, 0, 0), |
196 | /* REG0A */ | 198 | /* REG0A */ |
197 | [F_BOOSTV] = REG_FIELD(0x0A, 4, 7), | 199 | [F_BOOSTV] = REG_FIELD(0x0A, 4, 7), |
200 | /* PFM_OTG_DIS 3 on BQ25896 */ | ||
198 | [F_BOOSTI] = REG_FIELD(0x0A, 0, 2), | 201 | [F_BOOSTI] = REG_FIELD(0x0A, 0, 2), |
199 | /* REG0B */ | 202 | /* REG0B */ |
200 | [F_VBUS_STAT] = REG_FIELD(0x0B, 5, 7), | 203 | [F_VBUS_STAT] = REG_FIELD(0x0B, 5, 7), |
201 | [F_CHG_STAT] = REG_FIELD(0x0B, 3, 4), | 204 | [F_CHG_STAT] = REG_FIELD(0x0B, 3, 4), |
202 | [F_PG_STAT] = REG_FIELD(0x0B, 2, 2), | 205 | [F_PG_STAT] = REG_FIELD(0x0B, 2, 2), |
203 | [F_SDP_STAT] = REG_FIELD(0x0B, 1, 1), | 206 | [F_SDP_STAT] = REG_FIELD(0x0B, 1, 1), // reserved on BQ25896 |
204 | [F_VSYS_STAT] = REG_FIELD(0x0B, 0, 0), | 207 | [F_VSYS_STAT] = REG_FIELD(0x0B, 0, 0), |
205 | /* REG0C */ | 208 | /* REG0C */ |
206 | [F_WD_FAULT] = REG_FIELD(0x0C, 7, 7), | 209 | [F_WD_FAULT] = REG_FIELD(0x0C, 7, 7), |
@@ -244,10 +247,7 @@ enum bq25890_table_ids { | |||
244 | /* range tables */ | 247 | /* range tables */ |
245 | TBL_ICHG, | 248 | TBL_ICHG, |
246 | TBL_ITERM, | 249 | TBL_ITERM, |
247 | TBL_IPRECHG, | ||
248 | TBL_VREG, | 250 | TBL_VREG, |
249 | TBL_BATCMP, | ||
250 | TBL_VCLAMP, | ||
251 | TBL_BOOSTV, | 251 | TBL_BOOSTV, |
252 | TBL_SYSVMIN, | 252 | TBL_SYSVMIN, |
253 | 253 | ||
@@ -287,8 +287,6 @@ static const union { | |||
287 | [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ | 287 | [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ |
288 | [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ | 288 | [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ |
289 | [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ | 289 | [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ |
290 | [TBL_BATCMP] = { .rt = {0, 140, 20} }, /* mOhm */ | ||
291 | [TBL_VCLAMP] = { .rt = {0, 224000, 32000} }, /* uV */ | ||
292 | [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ | 290 | [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ |
293 | [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ | 291 | [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ |
294 | 292 | ||
@@ -401,6 +399,16 @@ static int bq25890_power_supply_get_property(struct power_supply *psy, | |||
401 | val->strval = BQ25890_MANUFACTURER; | 399 | val->strval = BQ25890_MANUFACTURER; |
402 | break; | 400 | break; |
403 | 401 | ||
402 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
403 | if (bq->chip_id == BQ25890_ID) | ||
404 | val->strval = "BQ25890"; | ||
405 | else if (bq->chip_id == BQ25896_ID) | ||
406 | val->strval = "BQ25896"; | ||
407 | else | ||
408 | val->strval = "UNKNOWN"; | ||
409 | |||
410 | break; | ||
411 | |||
404 | case POWER_SUPPLY_PROP_ONLINE: | 412 | case POWER_SUPPLY_PROP_ONLINE: |
405 | val->intval = state.online; | 413 | val->intval = state.online; |
406 | break; | 414 | break; |
@@ -453,6 +461,15 @@ static int bq25890_power_supply_get_property(struct power_supply *psy, | |||
453 | val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); | 461 | val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); |
454 | break; | 462 | break; |
455 | 463 | ||
464 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
465 | ret = bq25890_field_read(bq, F_SYSV); /* read measured value */ | ||
466 | if (ret < 0) | ||
467 | return ret; | ||
468 | |||
469 | /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */ | ||
470 | val->intval = 2304000 + ret * 20000; | ||
471 | break; | ||
472 | |||
456 | default: | 473 | default: |
457 | return -EINVAL; | 474 | return -EINVAL; |
458 | } | 475 | } |
@@ -608,30 +625,40 @@ static int bq25890_hw_init(struct bq25890_device *bq) | |||
608 | }; | 625 | }; |
609 | 626 | ||
610 | ret = bq25890_chip_reset(bq); | 627 | ret = bq25890_chip_reset(bq); |
611 | if (ret < 0) | 628 | if (ret < 0) { |
629 | dev_dbg(bq->dev, "Reset failed %d\n", ret); | ||
612 | return ret; | 630 | return ret; |
631 | } | ||
613 | 632 | ||
614 | /* disable watchdog */ | 633 | /* disable watchdog */ |
615 | ret = bq25890_field_write(bq, F_WD, 0); | 634 | ret = bq25890_field_write(bq, F_WD, 0); |
616 | if (ret < 0) | 635 | if (ret < 0) { |
636 | dev_dbg(bq->dev, "Disabling watchdog failed %d\n", ret); | ||
617 | return ret; | 637 | return ret; |
638 | } | ||
618 | 639 | ||
619 | /* initialize currents/voltages and other parameters */ | 640 | /* initialize currents/voltages and other parameters */ |
620 | for (i = 0; i < ARRAY_SIZE(init_data); i++) { | 641 | for (i = 0; i < ARRAY_SIZE(init_data); i++) { |
621 | ret = bq25890_field_write(bq, init_data[i].id, | 642 | ret = bq25890_field_write(bq, init_data[i].id, |
622 | init_data[i].value); | 643 | init_data[i].value); |
623 | if (ret < 0) | 644 | if (ret < 0) { |
645 | dev_dbg(bq->dev, "Writing init data failed %d\n", ret); | ||
624 | return ret; | 646 | return ret; |
647 | } | ||
625 | } | 648 | } |
626 | 649 | ||
627 | /* Configure ADC for continuous conversions. This does not enable it. */ | 650 | /* Configure ADC for continuous conversions. This does not enable it. */ |
628 | ret = bq25890_field_write(bq, F_CONV_RATE, 1); | 651 | ret = bq25890_field_write(bq, F_CONV_RATE, 1); |
629 | if (ret < 0) | 652 | if (ret < 0) { |
653 | dev_dbg(bq->dev, "Config ADC failed %d\n", ret); | ||
630 | return ret; | 654 | return ret; |
655 | } | ||
631 | 656 | ||
632 | ret = bq25890_get_chip_state(bq, &state); | 657 | ret = bq25890_get_chip_state(bq, &state); |
633 | if (ret < 0) | 658 | if (ret < 0) { |
659 | dev_dbg(bq->dev, "Get state failed %d\n", ret); | ||
634 | return ret; | 660 | return ret; |
661 | } | ||
635 | 662 | ||
636 | mutex_lock(&bq->lock); | 663 | mutex_lock(&bq->lock); |
637 | bq->state = state; | 664 | bq->state = state; |
@@ -642,6 +669,7 @@ static int bq25890_hw_init(struct bq25890_device *bq) | |||
642 | 669 | ||
643 | static enum power_supply_property bq25890_power_supply_props[] = { | 670 | static enum power_supply_property bq25890_power_supply_props[] = { |
644 | POWER_SUPPLY_PROP_MANUFACTURER, | 671 | POWER_SUPPLY_PROP_MANUFACTURER, |
672 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
645 | POWER_SUPPLY_PROP_STATUS, | 673 | POWER_SUPPLY_PROP_STATUS, |
646 | POWER_SUPPLY_PROP_ONLINE, | 674 | POWER_SUPPLY_PROP_ONLINE, |
647 | POWER_SUPPLY_PROP_HEALTH, | 675 | POWER_SUPPLY_PROP_HEALTH, |
@@ -650,6 +678,7 @@ static enum power_supply_property bq25890_power_supply_props[] = { | |||
650 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | 678 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, |
651 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | 679 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, |
652 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | 680 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, |
681 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
653 | }; | 682 | }; |
654 | 683 | ||
655 | static char *bq25890_charger_supplied_to[] = { | 684 | static char *bq25890_charger_supplied_to[] = { |
@@ -767,6 +796,9 @@ static int bq25890_fw_read_u32_props(struct bq25890_device *bq) | |||
767 | if (props[i].optional) | 796 | if (props[i].optional) |
768 | continue; | 797 | continue; |
769 | 798 | ||
799 | dev_err(bq->dev, "Unable to read property %d %s\n", ret, | ||
800 | props[i].name); | ||
801 | |||
770 | return ret; | 802 | return ret; |
771 | } | 803 | } |
772 | 804 | ||
@@ -840,7 +872,7 @@ static int bq25890_probe(struct i2c_client *client, | |||
840 | return bq->chip_id; | 872 | return bq->chip_id; |
841 | } | 873 | } |
842 | 874 | ||
843 | if (bq->chip_id != BQ25890_ID) { | 875 | if ((bq->chip_id != BQ25890_ID) && (bq->chip_id != BQ25896_ID)) { |
844 | dev_err(dev, "Chip with ID=%d, not supported!\n", bq->chip_id); | 876 | dev_err(dev, "Chip with ID=%d, not supported!\n", bq->chip_id); |
845 | return -ENODEV; | 877 | return -ENODEV; |
846 | } | 878 | } |
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index f022e1b550df..6dbbe95844a3 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c | |||
@@ -432,6 +432,7 @@ static u8 | |||
432 | [BQ27XXX_REG_AP] = 0x18, | 432 | [BQ27XXX_REG_AP] = 0x18, |
433 | BQ27XXX_DM_REG_ROWS, | 433 | BQ27XXX_DM_REG_ROWS, |
434 | }; | 434 | }; |
435 | #define bq27411_regs bq27421_regs | ||
435 | #define bq27425_regs bq27421_regs | 436 | #define bq27425_regs bq27421_regs |
436 | #define bq27426_regs bq27421_regs | 437 | #define bq27426_regs bq27421_regs |
437 | #define bq27441_regs bq27421_regs | 438 | #define bq27441_regs bq27421_regs |
@@ -665,6 +666,7 @@ static enum power_supply_property bq27421_props[] = { | |||
665 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | 666 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, |
666 | POWER_SUPPLY_PROP_MANUFACTURER, | 667 | POWER_SUPPLY_PROP_MANUFACTURER, |
667 | }; | 668 | }; |
669 | #define bq27411_props bq27421_props | ||
668 | #define bq27425_props bq27421_props | 670 | #define bq27425_props bq27421_props |
669 | #define bq27426_props bq27421_props | 671 | #define bq27426_props bq27421_props |
670 | #define bq27441_props bq27421_props | 672 | #define bq27441_props bq27421_props |
@@ -725,6 +727,12 @@ static struct bq27xxx_dm_reg bq27545_dm_regs[] = { | |||
725 | #define bq27545_dm_regs 0 | 727 | #define bq27545_dm_regs 0 |
726 | #endif | 728 | #endif |
727 | 729 | ||
730 | static struct bq27xxx_dm_reg bq27411_dm_regs[] = { | ||
731 | [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 32767 }, | ||
732 | [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, | ||
733 | [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2800, 3700 }, | ||
734 | }; | ||
735 | |||
728 | static struct bq27xxx_dm_reg bq27421_dm_regs[] = { | 736 | static struct bq27xxx_dm_reg bq27421_dm_regs[] = { |
729 | [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 }, | 737 | [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 }, |
730 | [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, | 738 | [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, |
@@ -802,6 +810,7 @@ static struct { | |||
802 | [BQ27546] = BQ27XXX_DATA(bq27546, 0 , BQ27XXX_O_OTDC), | 810 | [BQ27546] = BQ27XXX_DATA(bq27546, 0 , BQ27XXX_O_OTDC), |
803 | [BQ27742] = BQ27XXX_DATA(bq27742, 0 , BQ27XXX_O_OTDC), | 811 | [BQ27742] = BQ27XXX_DATA(bq27742, 0 , BQ27XXX_O_OTDC), |
804 | [BQ27545] = BQ27XXX_DATA(bq27545, 0x04143672, BQ27XXX_O_OTDC), | 812 | [BQ27545] = BQ27XXX_DATA(bq27545, 0x04143672, BQ27XXX_O_OTDC), |
813 | [BQ27411] = BQ27XXX_DATA(bq27411, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), | ||
805 | [BQ27421] = BQ27XXX_DATA(bq27421, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), | 814 | [BQ27421] = BQ27XXX_DATA(bq27421, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), |
806 | [BQ27425] = BQ27XXX_DATA(bq27425, 0x04143672, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP), | 815 | [BQ27425] = BQ27XXX_DATA(bq27425, 0x04143672, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP), |
807 | [BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), | 816 | [BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), |
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index 40069128ad44..2677c38a8a42 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c | |||
@@ -247,6 +247,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { | |||
247 | { "bq27546", BQ27546 }, | 247 | { "bq27546", BQ27546 }, |
248 | { "bq27742", BQ27742 }, | 248 | { "bq27742", BQ27742 }, |
249 | { "bq27545", BQ27545 }, | 249 | { "bq27545", BQ27545 }, |
250 | { "bq27411", BQ27411 }, | ||
250 | { "bq27421", BQ27421 }, | 251 | { "bq27421", BQ27421 }, |
251 | { "bq27425", BQ27425 }, | 252 | { "bq27425", BQ27425 }, |
252 | { "bq27426", BQ27426 }, | 253 | { "bq27426", BQ27426 }, |
@@ -279,6 +280,7 @@ static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = { | |||
279 | { .compatible = "ti,bq27546" }, | 280 | { .compatible = "ti,bq27546" }, |
280 | { .compatible = "ti,bq27742" }, | 281 | { .compatible = "ti,bq27742" }, |
281 | { .compatible = "ti,bq27545" }, | 282 | { .compatible = "ti,bq27545" }, |
283 | { .compatible = "ti,bq27411" }, | ||
282 | { .compatible = "ti,bq27421" }, | 284 | { .compatible = "ti,bq27421" }, |
283 | { .compatible = "ti,bq27425" }, | 285 | { .compatible = "ti,bq27425" }, |
284 | { .compatible = "ti,bq27426" }, | 286 | { .compatible = "ti,bq27426" }, |
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c index 688a16bacfbb..7e9c3984ef6a 100644 --- a/drivers/power/supply/cros_usbpd-charger.c +++ b/drivers/power/supply/cros_usbpd-charger.c | |||
@@ -12,8 +12,12 @@ | |||
12 | #include <linux/power_supply.h> | 12 | #include <linux/power_supply.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | 14 | ||
15 | #define CHARGER_DIR_NAME "CROS_USBPD_CHARGER%d" | 15 | #define CHARGER_USBPD_DIR_NAME "CROS_USBPD_CHARGER%d" |
16 | #define CHARGER_DIR_NAME_LENGTH sizeof(CHARGER_DIR_NAME) | 16 | #define CHARGER_DEDICATED_DIR_NAME "CROS_DEDICATED_CHARGER" |
17 | #define CHARGER_DIR_NAME_LENGTH (sizeof(CHARGER_USBPD_DIR_NAME) >= \ | ||
18 | sizeof(CHARGER_DEDICATED_DIR_NAME) ? \ | ||
19 | sizeof(CHARGER_USBPD_DIR_NAME) : \ | ||
20 | sizeof(CHARGER_DEDICATED_DIR_NAME)) | ||
17 | #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500) | 21 | #define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500) |
18 | #define CHARGER_MANUFACTURER_MODEL_LENGTH 32 | 22 | #define CHARGER_MANUFACTURER_MODEL_LENGTH 32 |
19 | 23 | ||
@@ -42,6 +46,7 @@ struct charger_data { | |||
42 | struct cros_ec_dev *ec_dev; | 46 | struct cros_ec_dev *ec_dev; |
43 | struct cros_ec_device *ec_device; | 47 | struct cros_ec_device *ec_device; |
44 | int num_charger_ports; | 48 | int num_charger_ports; |
49 | int num_usbpd_ports; | ||
45 | int num_registered_psy; | 50 | int num_registered_psy; |
46 | struct port_data *ports[EC_USB_PD_MAX_PORTS]; | 51 | struct port_data *ports[EC_USB_PD_MAX_PORTS]; |
47 | struct notifier_block notifier; | 52 | struct notifier_block notifier; |
@@ -58,6 +63,12 @@ static enum power_supply_property cros_usbpd_charger_props[] = { | |||
58 | POWER_SUPPLY_PROP_USB_TYPE | 63 | POWER_SUPPLY_PROP_USB_TYPE |
59 | }; | 64 | }; |
60 | 65 | ||
66 | static enum power_supply_property cros_usbpd_dedicated_charger_props[] = { | ||
67 | POWER_SUPPLY_PROP_ONLINE, | ||
68 | POWER_SUPPLY_PROP_STATUS, | ||
69 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
70 | }; | ||
71 | |||
61 | static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { | 72 | static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { |
62 | POWER_SUPPLY_USB_TYPE_UNKNOWN, | 73 | POWER_SUPPLY_USB_TYPE_UNKNOWN, |
63 | POWER_SUPPLY_USB_TYPE_SDP, | 74 | POWER_SUPPLY_USB_TYPE_SDP, |
@@ -69,6 +80,11 @@ static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = { | |||
69 | POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID | 80 | POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID |
70 | }; | 81 | }; |
71 | 82 | ||
83 | static bool cros_usbpd_charger_port_is_dedicated(struct port_data *port) | ||
84 | { | ||
85 | return port->port_number >= port->charger->num_usbpd_ports; | ||
86 | } | ||
87 | |||
72 | static int cros_usbpd_charger_ec_command(struct charger_data *charger, | 88 | static int cros_usbpd_charger_ec_command(struct charger_data *charger, |
73 | unsigned int version, | 89 | unsigned int version, |
74 | unsigned int command, | 90 | unsigned int command, |
@@ -103,6 +119,23 @@ static int cros_usbpd_charger_ec_command(struct charger_data *charger, | |||
103 | 119 | ||
104 | static int cros_usbpd_charger_get_num_ports(struct charger_data *charger) | 120 | static int cros_usbpd_charger_get_num_ports(struct charger_data *charger) |
105 | { | 121 | { |
122 | struct ec_response_charge_port_count resp; | ||
123 | int ret; | ||
124 | |||
125 | ret = cros_usbpd_charger_ec_command(charger, 0, | ||
126 | EC_CMD_CHARGE_PORT_COUNT, | ||
127 | NULL, 0, &resp, sizeof(resp)); | ||
128 | if (ret < 0) { | ||
129 | dev_err(charger->dev, | ||
130 | "Unable to get the number of ports (err:0x%x)\n", ret); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | return resp.port_count; | ||
135 | } | ||
136 | |||
137 | static int cros_usbpd_charger_get_usbpd_num_ports(struct charger_data *charger) | ||
138 | { | ||
106 | struct ec_response_usb_pd_ports resp; | 139 | struct ec_response_usb_pd_ports resp; |
107 | int ret; | 140 | int ret; |
108 | 141 | ||
@@ -246,7 +279,10 @@ static int cros_usbpd_charger_get_power_info(struct port_data *port) | |||
246 | port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; | 279 | port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; |
247 | } | 280 | } |
248 | 281 | ||
249 | port->psy_desc.type = POWER_SUPPLY_TYPE_USB; | 282 | if (cros_usbpd_charger_port_is_dedicated(port)) |
283 | port->psy_desc.type = POWER_SUPPLY_TYPE_MAINS; | ||
284 | else | ||
285 | port->psy_desc.type = POWER_SUPPLY_TYPE_USB; | ||
250 | 286 | ||
251 | dev_dbg(dev, | 287 | dev_dbg(dev, |
252 | "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n", | 288 | "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n", |
@@ -281,7 +317,8 @@ static int cros_usbpd_charger_get_port_status(struct port_data *port, | |||
281 | if (ret < 0) | 317 | if (ret < 0) |
282 | return ret; | 318 | return ret; |
283 | 319 | ||
284 | ret = cros_usbpd_charger_get_discovery_info(port); | 320 | if (!cros_usbpd_charger_port_is_dedicated(port)) |
321 | ret = cros_usbpd_charger_get_discovery_info(port); | ||
285 | port->last_update = jiffies; | 322 | port->last_update = jiffies; |
286 | 323 | ||
287 | return ret; | 324 | return ret; |
@@ -378,12 +415,10 @@ static int cros_usbpd_charger_ec_event(struct notifier_block *nb, | |||
378 | { | 415 | { |
379 | struct cros_ec_device *ec_device; | 416 | struct cros_ec_device *ec_device; |
380 | struct charger_data *charger; | 417 | struct charger_data *charger; |
381 | struct device *dev; | ||
382 | u32 host_event; | 418 | u32 host_event; |
383 | 419 | ||
384 | charger = container_of(nb, struct charger_data, notifier); | 420 | charger = container_of(nb, struct charger_data, notifier); |
385 | ec_device = charger->ec_device; | 421 | ec_device = charger->ec_device; |
386 | dev = charger->dev; | ||
387 | 422 | ||
388 | host_event = cros_ec_get_host_event(ec_device); | 423 | host_event = cros_ec_get_host_event(ec_device); |
389 | if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) { | 424 | if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) { |
@@ -426,17 +461,56 @@ static int cros_usbpd_charger_probe(struct platform_device *pd) | |||
426 | 461 | ||
427 | platform_set_drvdata(pd, charger); | 462 | platform_set_drvdata(pd, charger); |
428 | 463 | ||
464 | /* | ||
465 | * We need to know the number of USB PD ports in order to know whether | ||
466 | * there is a dedicated port. The dedicated port will always be | ||
467 | * after the USB PD ports, and there should be only one. | ||
468 | */ | ||
469 | charger->num_usbpd_ports = | ||
470 | cros_usbpd_charger_get_usbpd_num_ports(charger); | ||
471 | if (charger->num_usbpd_ports <= 0) { | ||
472 | /* | ||
473 | * This can happen on a system that doesn't support USB PD. | ||
474 | * Log a message, but no need to warn. | ||
475 | */ | ||
476 | dev_info(dev, "No USB PD charging ports found\n"); | ||
477 | } | ||
478 | |||
429 | charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger); | 479 | charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger); |
430 | if (charger->num_charger_ports <= 0) { | 480 | if (charger->num_charger_ports < 0) { |
431 | /* | 481 | /* |
432 | * This can happen on a system that doesn't support USB PD. | 482 | * This can happen on a system that doesn't support USB PD. |
433 | * Log a message, but no need to warn. | 483 | * Log a message, but no need to warn. |
484 | * Older ECs do not support the above command, in that case | ||
485 | * let's set up the number of charger ports equal to the number | ||
486 | * of USB PD ports | ||
487 | */ | ||
488 | dev_info(dev, "Could not get charger port count\n"); | ||
489 | charger->num_charger_ports = charger->num_usbpd_ports; | ||
490 | } | ||
491 | |||
492 | if (charger->num_charger_ports <= 0) { | ||
493 | /* | ||
494 | * This can happen on a system that doesn't support USB PD and | ||
495 | * doesn't have a dedicated port. | ||
496 | * Log a message, but no need to warn. | ||
434 | */ | 497 | */ |
435 | dev_info(dev, "No charging ports found\n"); | 498 | dev_info(dev, "No charging ports found\n"); |
436 | ret = -ENODEV; | 499 | ret = -ENODEV; |
437 | goto fail_nowarn; | 500 | goto fail_nowarn; |
438 | } | 501 | } |
439 | 502 | ||
503 | /* | ||
504 | * Sanity checks on the number of ports: | ||
505 | * there should be at most 1 dedicated port | ||
506 | */ | ||
507 | if (charger->num_charger_ports < charger->num_usbpd_ports || | ||
508 | charger->num_charger_ports > (charger->num_usbpd_ports + 1)) { | ||
509 | dev_err(dev, "Unexpected number of charge port count\n"); | ||
510 | ret = -EPROTO; | ||
511 | goto fail_nowarn; | ||
512 | } | ||
513 | |||
440 | for (i = 0; i < charger->num_charger_ports; i++) { | 514 | for (i = 0; i < charger->num_charger_ports; i++) { |
441 | struct power_supply_config psy_cfg = {}; | 515 | struct power_supply_config psy_cfg = {}; |
442 | 516 | ||
@@ -448,22 +522,33 @@ static int cros_usbpd_charger_probe(struct platform_device *pd) | |||
448 | 522 | ||
449 | port->charger = charger; | 523 | port->charger = charger; |
450 | port->port_number = i; | 524 | port->port_number = i; |
451 | sprintf(port->name, CHARGER_DIR_NAME, i); | ||
452 | 525 | ||
453 | psy_desc = &port->psy_desc; | 526 | psy_desc = &port->psy_desc; |
454 | psy_desc->name = port->name; | ||
455 | psy_desc->type = POWER_SUPPLY_TYPE_USB; | ||
456 | psy_desc->get_property = cros_usbpd_charger_get_prop; | 527 | psy_desc->get_property = cros_usbpd_charger_get_prop; |
457 | psy_desc->external_power_changed = | 528 | psy_desc->external_power_changed = |
458 | cros_usbpd_charger_power_changed; | 529 | cros_usbpd_charger_power_changed; |
459 | psy_desc->properties = cros_usbpd_charger_props; | ||
460 | psy_desc->num_properties = | ||
461 | ARRAY_SIZE(cros_usbpd_charger_props); | ||
462 | psy_desc->usb_types = cros_usbpd_charger_usb_types; | ||
463 | psy_desc->num_usb_types = | ||
464 | ARRAY_SIZE(cros_usbpd_charger_usb_types); | ||
465 | psy_cfg.drv_data = port; | 530 | psy_cfg.drv_data = port; |
466 | 531 | ||
532 | if (cros_usbpd_charger_port_is_dedicated(port)) { | ||
533 | sprintf(port->name, CHARGER_DEDICATED_DIR_NAME); | ||
534 | psy_desc->type = POWER_SUPPLY_TYPE_MAINS; | ||
535 | psy_desc->properties = | ||
536 | cros_usbpd_dedicated_charger_props; | ||
537 | psy_desc->num_properties = | ||
538 | ARRAY_SIZE(cros_usbpd_dedicated_charger_props); | ||
539 | } else { | ||
540 | sprintf(port->name, CHARGER_USBPD_DIR_NAME, i); | ||
541 | psy_desc->type = POWER_SUPPLY_TYPE_USB; | ||
542 | psy_desc->properties = cros_usbpd_charger_props; | ||
543 | psy_desc->num_properties = | ||
544 | ARRAY_SIZE(cros_usbpd_charger_props); | ||
545 | psy_desc->usb_types = cros_usbpd_charger_usb_types; | ||
546 | psy_desc->num_usb_types = | ||
547 | ARRAY_SIZE(cros_usbpd_charger_usb_types); | ||
548 | } | ||
549 | |||
550 | psy_desc->name = port->name; | ||
551 | |||
467 | psy = devm_power_supply_register_no_ws(dev, psy_desc, | 552 | psy = devm_power_supply_register_no_ws(dev, psy_desc, |
468 | &psy_cfg); | 553 | &psy_cfg); |
469 | if (IS_ERR(psy)) { | 554 | if (IS_ERR(psy)) { |
diff --git a/drivers/power/supply/ds2780_battery.c b/drivers/power/supply/ds2780_battery.c index 370e9109342b..cad14ba1b648 100644 --- a/drivers/power/supply/ds2780_battery.c +++ b/drivers/power/supply/ds2780_battery.c | |||
@@ -829,5 +829,5 @@ module_platform_driver(ds2780_battery_driver); | |||
829 | 829 | ||
830 | MODULE_LICENSE("GPL"); | 830 | MODULE_LICENSE("GPL"); |
831 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); | 831 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); |
832 | MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); | 832 | MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC driver"); |
833 | MODULE_ALIAS("platform:ds2780-battery"); | 833 | MODULE_ALIAS("platform:ds2780-battery"); |
diff --git a/drivers/power/supply/ds2781_battery.c b/drivers/power/supply/ds2781_battery.c index d1b5a19aae7c..5e794607f732 100644 --- a/drivers/power/supply/ds2781_battery.c +++ b/drivers/power/supply/ds2781_battery.c | |||
@@ -829,6 +829,6 @@ module_platform_driver(ds2781_battery_driver); | |||
829 | 829 | ||
830 | MODULE_LICENSE("GPL"); | 830 | MODULE_LICENSE("GPL"); |
831 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); | 831 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); |
832 | MODULE_DESCRIPTION("Maxim/Dallas DS2781 Stand-Alone Fuel Gauage IC driver"); | 832 | MODULE_DESCRIPTION("Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC driver"); |
833 | MODULE_ALIAS("platform:ds2781-battery"); | 833 | MODULE_ALIAS("platform:ds2781-battery"); |
834 | 834 | ||
diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c index a1b7e0592245..019c58493e3d 100644 --- a/drivers/power/supply/ds2782_battery.c +++ b/drivers/power/supply/ds2782_battery.c | |||
@@ -471,5 +471,5 @@ static struct i2c_driver ds278x_battery_driver = { | |||
471 | module_i2c_driver(ds278x_battery_driver); | 471 | module_i2c_driver(ds278x_battery_driver); |
472 | 472 | ||
473 | MODULE_AUTHOR("Ryan Mallon"); | 473 | MODULE_AUTHOR("Ryan Mallon"); |
474 | MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver"); | 474 | MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauge IC driver"); |
475 | MODULE_LICENSE("GPL"); | 475 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c index 449fc56f09eb..8a59feac6468 100644 --- a/drivers/power/supply/max14577_charger.c +++ b/drivers/power/supply/max14577_charger.c | |||
@@ -1,19 +1,9 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * max14577_charger.c - Battery charger driver for the Maxim 14577/77836 | 2 | // |
3 | * | 3 | // max14577_charger.c - Battery charger driver for the Maxim 14577/77836 |
4 | * Copyright (C) 2013,2014 Samsung Electronics | 4 | // |
5 | * Krzysztof Kozlowski <krzk@kernel.org> | 5 | // Copyright (C) 2013,2014 Samsung Electronics |
6 | * | 6 | // Krzysztof Kozlowski <krzk@kernel.org> |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | 7 | ||
18 | #include <linux/module.h> | 8 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 33c40f79d23d..91cafc7bed30 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c | |||
@@ -1,14 +1,10 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * max17040_battery.c | 2 | // |
3 | * fuel-gauge systems for lithium-ion (Li+) batteries | 3 | // max17040_battery.c |
4 | * | 4 | // fuel-gauge systems for lithium-ion (Li+) batteries |
5 | * Copyright (C) 2009 Samsung Electronics | 5 | // |
6 | * Minkyu Kang <mk7.kang@samsung.com> | 6 | // Copyright (C) 2009 Samsung Electronics |
7 | * | 7 | // Minkyu Kang <mk7.kang@samsung.com> |
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | 8 | ||
13 | #include <linux/module.h> | 9 | #include <linux/module.h> |
14 | #include <linux/init.h> | 10 | #include <linux/init.h> |
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 1a568df383db..2a8d75e5e930 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c | |||
@@ -1,26 +1,12 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * Fuel gauge driver for Maxim 17042 / 8966 / 8997 | 2 | // |
3 | * Note that Maxim 8966 and 8997 are mfd and this is its subdevice. | 3 | // Fuel gauge driver for Maxim 17042 / 8966 / 8997 |
4 | * | 4 | // Note that Maxim 8966 and 8997 are mfd and this is its subdevice. |
5 | * Copyright (C) 2011 Samsung Electronics | 5 | // |
6 | * MyungJoo Ham <myungjoo.ham@samsung.com> | 6 | // Copyright (C) 2011 Samsung Electronics |
7 | * | 7 | // MyungJoo Ham <myungjoo.ham@samsung.com> |
8 | * This program is free software; you can redistribute it and/or modify | 8 | // |
9 | * it under the terms of the GNU General Public License as published by | 9 | // This driver is based on max17040_battery.c |
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | * This driver is based on max17040_battery.c | ||
23 | */ | ||
24 | 10 | ||
25 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
26 | #include <linux/init.h> | 12 | #include <linux/init.h> |
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c index 749c7926e3c9..a2c5c9858639 100644 --- a/drivers/power/supply/max77693_charger.c +++ b/drivers/power/supply/max77693_charger.c | |||
@@ -1,19 +1,9 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * max77693_charger.c - Battery charger driver for the Maxim 77693 | 2 | // |
3 | * | 3 | // max77693_charger.c - Battery charger driver for the Maxim 77693 |
4 | * Copyright (C) 2014 Samsung Electronics | 4 | // |
5 | * Krzysztof Kozlowski <krzk@kernel.org> | 5 | // Copyright (C) 2014 Samsung Electronics |
6 | * | 6 | // Krzysztof Kozlowski <krzk@kernel.org> |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | 7 | ||
18 | #include <linux/module.h> | 8 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
diff --git a/drivers/power/supply/max8925_power.c b/drivers/power/supply/max8925_power.c index 3b94620ce5c1..39b4d5b6ac39 100644 --- a/drivers/power/supply/max8925_power.c +++ b/drivers/power/supply/max8925_power.c | |||
@@ -124,6 +124,7 @@ static irqreturn_t max8925_charger_handler(int irq, void *data) | |||
124 | case MAX8925_IRQ_VCHG_THM_OK_F: | 124 | case MAX8925_IRQ_VCHG_THM_OK_F: |
125 | /* Battery is not ready yet */ | 125 | /* Battery is not ready yet */ |
126 | dev_dbg(chip->dev, "Battery temperature is out of range\n"); | 126 | dev_dbg(chip->dev, "Battery temperature is out of range\n"); |
127 | /* Fall through */ | ||
127 | case MAX8925_IRQ_VCHG_DC_OVP: | 128 | case MAX8925_IRQ_VCHG_DC_OVP: |
128 | dev_dbg(chip->dev, "Error detection\n"); | 129 | dev_dbg(chip->dev, "Error detection\n"); |
129 | __set_charger(info, 0); | 130 | __set_charger(info, 0); |
diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index c73fb4221695..f5e84cd47924 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c | |||
@@ -1,23 +1,9 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966 | 2 | // |
3 | * | 3 | // max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966 |
4 | * Copyright (C) 2011 Samsung Electronics | 4 | // |
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | 5 | // Copyright (C) 2011 Samsung Electronics |
6 | * | 6 | // MyungJoo Ham <myungjoo.ham@samsung.com> |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | 7 | ||
22 | #include <linux/err.h> | 8 | #include <linux/err.h> |
23 | #include <linux/module.h> | 9 | #include <linux/module.h> |
diff --git a/drivers/power/supply/max8998_charger.c b/drivers/power/supply/max8998_charger.c index cad7d1a8feec..9a926c7c0f22 100644 --- a/drivers/power/supply/max8998_charger.c +++ b/drivers/power/supply/max8998_charger.c | |||
@@ -1,23 +1,9 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * max8998_charger.c - Power supply consumer driver for the Maxim 8998/LP3974 | 2 | // |
3 | * | 3 | // max8998_charger.c - Power supply consumer driver for the Maxim 8998/LP3974 |
4 | * Copyright (C) 2009-2010 Samsung Electronics | 4 | // |
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | 5 | // Copyright (C) 2009-2010 Samsung Electronics |
6 | * | 6 | // MyungJoo Ham <myungjoo.ham@samsung.com> |
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | 7 | ||
22 | #include <linux/err.h> | 8 | #include <linux/err.h> |
23 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -86,7 +72,7 @@ static const struct power_supply_desc max8998_battery_desc = { | |||
86 | static int max8998_battery_probe(struct platform_device *pdev) | 72 | static int max8998_battery_probe(struct platform_device *pdev) |
87 | { | 73 | { |
88 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 74 | struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
89 | struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); | 75 | struct max8998_platform_data *pdata = iodev->pdata; |
90 | struct power_supply_config psy_cfg = {}; | 76 | struct power_supply_config psy_cfg = {}; |
91 | struct max8998_battery_data *max8998; | 77 | struct max8998_battery_data *max8998; |
92 | struct i2c_client *i2c; | 78 | struct i2c_client *i2c; |
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 6170ed8b6854..dce24f596160 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c | |||
@@ -131,7 +131,8 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
131 | dev_dbg(dev, "driver has no data for `%s' property\n", | 131 | dev_dbg(dev, "driver has no data for `%s' property\n", |
132 | attr->attr.name); | 132 | attr->attr.name); |
133 | else if (ret != -ENODEV && ret != -EAGAIN) | 133 | else if (ret != -ENODEV && ret != -EAGAIN) |
134 | dev_err(dev, "driver failed to report `%s' property: %zd\n", | 134 | dev_err_ratelimited(dev, |
135 | "driver failed to report `%s' property: %zd\n", | ||
135 | attr->attr.name, ret); | 136 | attr->attr.name, ret); |
136 | return ret; | 137 | return ret; |
137 | } | 138 | } |
diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c new file mode 100644 index 000000000000..525a820537bf --- /dev/null +++ b/drivers/power/supply/sc2731_charger.c | |||
@@ -0,0 +1,504 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (C) 2018 Spreadtrum Communications Inc. | ||
3 | |||
4 | #include <linux/module.h> | ||
5 | #include <linux/platform_device.h> | ||
6 | #include <linux/power_supply.h> | ||
7 | #include <linux/usb/phy.h> | ||
8 | #include <linux/regmap.h> | ||
9 | #include <linux/notifier.h> | ||
10 | #include <linux/of.h> | ||
11 | |||
12 | /* PMIC global registers definition */ | ||
13 | #define SC2731_CHARGE_STATUS 0xedc | ||
14 | #define SC2731_CHARGE_FULL BIT(4) | ||
15 | #define SC2731_MODULE_EN1 0xc0c | ||
16 | #define SC2731_CHARGE_EN BIT(5) | ||
17 | |||
18 | /* SC2731 switch charger registers definition */ | ||
19 | #define SC2731_CHG_CFG0 0x0 | ||
20 | #define SC2731_CHG_CFG1 0x4 | ||
21 | #define SC2731_CHG_CFG2 0x8 | ||
22 | #define SC2731_CHG_CFG3 0xc | ||
23 | #define SC2731_CHG_CFG4 0x10 | ||
24 | #define SC2731_CHG_CFG5 0x28 | ||
25 | |||
26 | /* SC2731_CHG_CFG0 register definition */ | ||
27 | #define SC2731_PRECHG_RNG_SHIFT 11 | ||
28 | #define SC2731_PRECHG_RNG_MASK GENMASK(12, 11) | ||
29 | |||
30 | #define SC2731_TERMINATION_VOL_MASK GENMASK(2, 1) | ||
31 | #define SC2731_TERMINATION_VOL_SHIFT 1 | ||
32 | #define SC2731_TERMINATION_VOL_CAL_MASK GENMASK(8, 3) | ||
33 | #define SC2731_TERMINATION_VOL_CAL_SHIFT 3 | ||
34 | #define SC2731_TERMINATION_CUR_MASK GENMASK(2, 0) | ||
35 | |||
36 | #define SC2731_CC_EN BIT(13) | ||
37 | #define SC2731_CHARGER_PD BIT(0) | ||
38 | |||
39 | /* SC2731_CHG_CFG1 register definition */ | ||
40 | #define SC2731_CUR_MASK GENMASK(5, 0) | ||
41 | |||
42 | /* SC2731_CHG_CFG5 register definition */ | ||
43 | #define SC2731_CUR_LIMIT_SHIFT 8 | ||
44 | #define SC2731_CUR_LIMIT_MASK GENMASK(9, 8) | ||
45 | |||
46 | /* Default current definition (unit is mA) */ | ||
47 | #define SC2731_CURRENT_LIMIT_100 100 | ||
48 | #define SC2731_CURRENT_LIMIT_500 500 | ||
49 | #define SC2731_CURRENT_LIMIT_900 900 | ||
50 | #define SC2731_CURRENT_LIMIT_2000 2000 | ||
51 | #define SC2731_CURRENT_PRECHG 450 | ||
52 | #define SC2731_CURRENT_STEP 50 | ||
53 | |||
54 | struct sc2731_charger_info { | ||
55 | struct device *dev; | ||
56 | struct regmap *regmap; | ||
57 | struct usb_phy *usb_phy; | ||
58 | struct notifier_block usb_notify; | ||
59 | struct power_supply *psy_usb; | ||
60 | struct mutex lock; | ||
61 | bool charging; | ||
62 | u32 base; | ||
63 | }; | ||
64 | |||
65 | static void sc2731_charger_stop_charge(struct sc2731_charger_info *info) | ||
66 | { | ||
67 | regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
68 | SC2731_CC_EN, 0); | ||
69 | |||
70 | regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
71 | SC2731_CHARGER_PD, SC2731_CHARGER_PD); | ||
72 | } | ||
73 | |||
74 | static int sc2731_charger_start_charge(struct sc2731_charger_info *info) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | /* Enable charger constant current mode */ | ||
79 | ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
80 | SC2731_CC_EN, SC2731_CC_EN); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | /* Start charging */ | ||
85 | return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
86 | SC2731_CHARGER_PD, 0); | ||
87 | } | ||
88 | |||
89 | static int sc2731_charger_set_current_limit(struct sc2731_charger_info *info, | ||
90 | u32 limit) | ||
91 | { | ||
92 | u32 val; | ||
93 | |||
94 | if (limit <= SC2731_CURRENT_LIMIT_100) | ||
95 | val = 0; | ||
96 | else if (limit <= SC2731_CURRENT_LIMIT_500) | ||
97 | val = 3; | ||
98 | else if (limit <= SC2731_CURRENT_LIMIT_900) | ||
99 | val = 2; | ||
100 | else | ||
101 | val = 1; | ||
102 | |||
103 | return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG5, | ||
104 | SC2731_CUR_LIMIT_MASK, | ||
105 | val << SC2731_CUR_LIMIT_SHIFT); | ||
106 | } | ||
107 | |||
108 | static int sc2731_charger_set_current(struct sc2731_charger_info *info, u32 cur) | ||
109 | { | ||
110 | u32 val; | ||
111 | int ret; | ||
112 | |||
113 | if (cur > SC2731_CURRENT_LIMIT_2000) | ||
114 | cur = SC2731_CURRENT_LIMIT_2000; | ||
115 | else if (cur < SC2731_CURRENT_PRECHG) | ||
116 | cur = SC2731_CURRENT_PRECHG; | ||
117 | |||
118 | /* Calculate the step value, each step is 50 mA */ | ||
119 | val = (cur - SC2731_CURRENT_PRECHG) / SC2731_CURRENT_STEP; | ||
120 | |||
121 | /* Set pre-charge current as 450 mA */ | ||
122 | ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
123 | SC2731_PRECHG_RNG_MASK, | ||
124 | 0x3 << SC2731_PRECHG_RNG_SHIFT); | ||
125 | if (ret) | ||
126 | return ret; | ||
127 | |||
128 | return regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG1, | ||
129 | SC2731_CUR_MASK, val); | ||
130 | } | ||
131 | |||
132 | static int sc2731_charger_get_status(struct sc2731_charger_info *info) | ||
133 | { | ||
134 | u32 val; | ||
135 | int ret; | ||
136 | |||
137 | ret = regmap_read(info->regmap, SC2731_CHARGE_STATUS, &val); | ||
138 | if (ret) | ||
139 | return ret; | ||
140 | |||
141 | if (val & SC2731_CHARGE_FULL) | ||
142 | return POWER_SUPPLY_STATUS_FULL; | ||
143 | |||
144 | return POWER_SUPPLY_STATUS_CHARGING; | ||
145 | } | ||
146 | |||
147 | static int sc2731_charger_get_current(struct sc2731_charger_info *info, | ||
148 | u32 *cur) | ||
149 | { | ||
150 | int ret; | ||
151 | u32 val; | ||
152 | |||
153 | ret = regmap_read(info->regmap, info->base + SC2731_CHG_CFG1, &val); | ||
154 | if (ret) | ||
155 | return ret; | ||
156 | |||
157 | val &= SC2731_CUR_MASK; | ||
158 | *cur = val * SC2731_CURRENT_STEP + SC2731_CURRENT_PRECHG; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int sc2731_charger_get_current_limit(struct sc2731_charger_info *info, | ||
164 | u32 *cur) | ||
165 | { | ||
166 | int ret; | ||
167 | u32 val; | ||
168 | |||
169 | ret = regmap_read(info->regmap, info->base + SC2731_CHG_CFG5, &val); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | val = (val & SC2731_CUR_LIMIT_MASK) >> SC2731_CUR_LIMIT_SHIFT; | ||
174 | |||
175 | switch (val) { | ||
176 | case 0: | ||
177 | *cur = SC2731_CURRENT_LIMIT_100; | ||
178 | break; | ||
179 | |||
180 | case 1: | ||
181 | *cur = SC2731_CURRENT_LIMIT_2000; | ||
182 | break; | ||
183 | |||
184 | case 2: | ||
185 | *cur = SC2731_CURRENT_LIMIT_900; | ||
186 | break; | ||
187 | |||
188 | case 3: | ||
189 | *cur = SC2731_CURRENT_LIMIT_500; | ||
190 | break; | ||
191 | |||
192 | default: | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int | ||
200 | sc2731_charger_usb_set_property(struct power_supply *psy, | ||
201 | enum power_supply_property psp, | ||
202 | const union power_supply_propval *val) | ||
203 | { | ||
204 | struct sc2731_charger_info *info = power_supply_get_drvdata(psy); | ||
205 | int ret; | ||
206 | |||
207 | mutex_lock(&info->lock); | ||
208 | |||
209 | if (!info->charging) { | ||
210 | mutex_unlock(&info->lock); | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | |||
214 | switch (psp) { | ||
215 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
216 | ret = sc2731_charger_set_current(info, val->intval / 1000); | ||
217 | if (ret < 0) | ||
218 | dev_err(info->dev, "set charge current failed\n"); | ||
219 | break; | ||
220 | |||
221 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
222 | ret = sc2731_charger_set_current_limit(info, | ||
223 | val->intval / 1000); | ||
224 | if (ret < 0) | ||
225 | dev_err(info->dev, "set input current limit failed\n"); | ||
226 | break; | ||
227 | |||
228 | default: | ||
229 | ret = -EINVAL; | ||
230 | } | ||
231 | |||
232 | mutex_unlock(&info->lock); | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static int sc2731_charger_usb_get_property(struct power_supply *psy, | ||
237 | enum power_supply_property psp, | ||
238 | union power_supply_propval *val) | ||
239 | { | ||
240 | struct sc2731_charger_info *info = power_supply_get_drvdata(psy); | ||
241 | int ret = 0; | ||
242 | u32 cur; | ||
243 | |||
244 | mutex_lock(&info->lock); | ||
245 | |||
246 | switch (psp) { | ||
247 | case POWER_SUPPLY_PROP_STATUS: | ||
248 | if (info->charging) | ||
249 | val->intval = sc2731_charger_get_status(info); | ||
250 | else | ||
251 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
252 | break; | ||
253 | |||
254 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
255 | if (!info->charging) { | ||
256 | val->intval = 0; | ||
257 | } else { | ||
258 | ret = sc2731_charger_get_current(info, &cur); | ||
259 | if (ret) | ||
260 | goto out; | ||
261 | |||
262 | val->intval = cur * 1000; | ||
263 | } | ||
264 | break; | ||
265 | |||
266 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
267 | if (!info->charging) { | ||
268 | val->intval = 0; | ||
269 | } else { | ||
270 | ret = sc2731_charger_get_current_limit(info, &cur); | ||
271 | if (ret) | ||
272 | goto out; | ||
273 | |||
274 | val->intval = cur * 1000; | ||
275 | } | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | ret = -EINVAL; | ||
280 | } | ||
281 | |||
282 | out: | ||
283 | mutex_unlock(&info->lock); | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static int sc2731_charger_property_is_writeable(struct power_supply *psy, | ||
288 | enum power_supply_property psp) | ||
289 | { | ||
290 | int ret; | ||
291 | |||
292 | switch (psp) { | ||
293 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
294 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
295 | ret = 1; | ||
296 | break; | ||
297 | |||
298 | default: | ||
299 | ret = 0; | ||
300 | } | ||
301 | |||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | static enum power_supply_property sc2731_usb_props[] = { | ||
306 | POWER_SUPPLY_PROP_STATUS, | ||
307 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
308 | POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, | ||
309 | }; | ||
310 | |||
311 | static const struct power_supply_desc sc2731_charger_desc = { | ||
312 | .name = "sc2731_charger", | ||
313 | .type = POWER_SUPPLY_TYPE_USB, | ||
314 | .properties = sc2731_usb_props, | ||
315 | .num_properties = ARRAY_SIZE(sc2731_usb_props), | ||
316 | .get_property = sc2731_charger_usb_get_property, | ||
317 | .set_property = sc2731_charger_usb_set_property, | ||
318 | .property_is_writeable = sc2731_charger_property_is_writeable, | ||
319 | }; | ||
320 | |||
321 | static int sc2731_charger_usb_change(struct notifier_block *nb, | ||
322 | unsigned long limit, void *data) | ||
323 | { | ||
324 | struct sc2731_charger_info *info = | ||
325 | container_of(nb, struct sc2731_charger_info, usb_notify); | ||
326 | int ret = 0; | ||
327 | |||
328 | mutex_lock(&info->lock); | ||
329 | |||
330 | if (limit > 0) { | ||
331 | /* set current limitation and start to charge */ | ||
332 | ret = sc2731_charger_set_current_limit(info, limit); | ||
333 | if (ret) | ||
334 | goto out; | ||
335 | |||
336 | ret = sc2731_charger_set_current(info, limit); | ||
337 | if (ret) | ||
338 | goto out; | ||
339 | |||
340 | ret = sc2731_charger_start_charge(info); | ||
341 | if (ret) | ||
342 | goto out; | ||
343 | |||
344 | info->charging = true; | ||
345 | } else { | ||
346 | /* Stop charging */ | ||
347 | info->charging = false; | ||
348 | sc2731_charger_stop_charge(info); | ||
349 | } | ||
350 | |||
351 | out: | ||
352 | mutex_unlock(&info->lock); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | static int sc2731_charger_hw_init(struct sc2731_charger_info *info) | ||
357 | { | ||
358 | struct power_supply_battery_info bat_info = { }; | ||
359 | u32 term_currrent, term_voltage, cur_val, vol_val; | ||
360 | int ret; | ||
361 | |||
362 | /* Enable charger module */ | ||
363 | ret = regmap_update_bits(info->regmap, SC2731_MODULE_EN1, | ||
364 | SC2731_CHARGE_EN, SC2731_CHARGE_EN); | ||
365 | if (ret) | ||
366 | return ret; | ||
367 | |||
368 | ret = power_supply_get_battery_info(info->psy_usb, &bat_info); | ||
369 | if (ret) { | ||
370 | dev_warn(info->dev, "no battery information is supplied\n"); | ||
371 | |||
372 | /* | ||
373 | * If no battery information is supplied, we should set | ||
374 | * default charge termination current to 120 mA, and default | ||
375 | * charge termination voltage to 4.35V. | ||
376 | */ | ||
377 | cur_val = 0x2; | ||
378 | vol_val = 0x1; | ||
379 | } else { | ||
380 | term_currrent = bat_info.charge_term_current_ua / 1000; | ||
381 | |||
382 | if (term_currrent <= 90) | ||
383 | cur_val = 0; | ||
384 | else if (term_currrent >= 265) | ||
385 | cur_val = 0x7; | ||
386 | else | ||
387 | cur_val = ((term_currrent - 90) / 25) + 1; | ||
388 | |||
389 | term_voltage = bat_info.constant_charge_voltage_max_uv / 1000; | ||
390 | |||
391 | if (term_voltage > 4500) | ||
392 | term_voltage = 4500; | ||
393 | |||
394 | if (term_voltage > 4200) | ||
395 | vol_val = (term_voltage - 4200) / 100; | ||
396 | else | ||
397 | vol_val = 0; | ||
398 | } | ||
399 | |||
400 | /* Set charge termination current */ | ||
401 | ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG2, | ||
402 | SC2731_TERMINATION_CUR_MASK, cur_val); | ||
403 | if (ret) | ||
404 | goto error; | ||
405 | |||
406 | /* Set charge termination voltage */ | ||
407 | ret = regmap_update_bits(info->regmap, info->base + SC2731_CHG_CFG0, | ||
408 | SC2731_TERMINATION_VOL_MASK | | ||
409 | SC2731_TERMINATION_VOL_CAL_MASK, | ||
410 | (vol_val << SC2731_TERMINATION_VOL_SHIFT) | | ||
411 | (0x6 << SC2731_TERMINATION_VOL_CAL_SHIFT)); | ||
412 | if (ret) | ||
413 | goto error; | ||
414 | |||
415 | return 0; | ||
416 | |||
417 | error: | ||
418 | regmap_update_bits(info->regmap, SC2731_MODULE_EN1, SC2731_CHARGE_EN, 0); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | static int sc2731_charger_probe(struct platform_device *pdev) | ||
423 | { | ||
424 | struct device_node *np = pdev->dev.of_node; | ||
425 | struct sc2731_charger_info *info; | ||
426 | struct power_supply_config charger_cfg = { }; | ||
427 | int ret; | ||
428 | |||
429 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
430 | if (!info) | ||
431 | return -ENOMEM; | ||
432 | |||
433 | mutex_init(&info->lock); | ||
434 | info->dev = &pdev->dev; | ||
435 | |||
436 | info->regmap = dev_get_regmap(pdev->dev.parent, NULL); | ||
437 | if (!info->regmap) { | ||
438 | dev_err(&pdev->dev, "failed to get charger regmap\n"); | ||
439 | return -ENODEV; | ||
440 | } | ||
441 | |||
442 | ret = of_property_read_u32(np, "reg", &info->base); | ||
443 | if (ret) { | ||
444 | dev_err(&pdev->dev, "failed to get register address\n"); | ||
445 | return -ENODEV; | ||
446 | } | ||
447 | |||
448 | charger_cfg.drv_data = info; | ||
449 | charger_cfg.of_node = np; | ||
450 | info->psy_usb = devm_power_supply_register(&pdev->dev, | ||
451 | &sc2731_charger_desc, | ||
452 | &charger_cfg); | ||
453 | if (IS_ERR(info->psy_usb)) { | ||
454 | dev_err(&pdev->dev, "failed to register power supply\n"); | ||
455 | return PTR_ERR(info->psy_usb); | ||
456 | } | ||
457 | |||
458 | ret = sc2731_charger_hw_init(info); | ||
459 | if (ret) | ||
460 | return ret; | ||
461 | |||
462 | info->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "phys", 0); | ||
463 | if (IS_ERR(info->usb_phy)) { | ||
464 | dev_err(&pdev->dev, "failed to find USB phy\n"); | ||
465 | return PTR_ERR(info->usb_phy); | ||
466 | } | ||
467 | |||
468 | info->usb_notify.notifier_call = sc2731_charger_usb_change; | ||
469 | ret = usb_register_notifier(info->usb_phy, &info->usb_notify); | ||
470 | if (ret) { | ||
471 | dev_err(&pdev->dev, "failed to register notifier: %d\n", ret); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int sc2731_charger_remove(struct platform_device *pdev) | ||
479 | { | ||
480 | struct sc2731_charger_info *info = platform_get_drvdata(pdev); | ||
481 | |||
482 | usb_unregister_notifier(info->usb_phy, &info->usb_notify); | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static const struct of_device_id sc2731_charger_of_match[] = { | ||
488 | { .compatible = "sprd,sc2731-charger", }, | ||
489 | { } | ||
490 | }; | ||
491 | |||
492 | static struct platform_driver sc2731_charger_driver = { | ||
493 | .driver = { | ||
494 | .name = "sc2731-charger", | ||
495 | .of_match_table = sc2731_charger_of_match, | ||
496 | }, | ||
497 | .probe = sc2731_charger_probe, | ||
498 | .remove = sc2731_charger_remove, | ||
499 | }; | ||
500 | |||
501 | module_platform_driver(sc2731_charger_driver); | ||
502 | |||
503 | MODULE_DESCRIPTION("Spreadtrum SC2731 Charger Driver"); | ||
504 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c index bbcaee56db9d..80582c8f98fa 100644 --- a/drivers/power/supply/twl4030_charger.c +++ b/drivers/power/supply/twl4030_charger.c | |||
@@ -420,7 +420,8 @@ static void twl4030_current_worker(struct work_struct *data) | |||
420 | 420 | ||
421 | if (v < USB_MIN_VOLT) { | 421 | if (v < USB_MIN_VOLT) { |
422 | /* Back up and stop adjusting. */ | 422 | /* Back up and stop adjusting. */ |
423 | bci->usb_cur -= USB_CUR_STEP; | 423 | if (bci->usb_cur >= USB_CUR_STEP) |
424 | bci->usb_cur -= USB_CUR_STEP; | ||
424 | bci->usb_cur_target = bci->usb_cur; | 425 | bci->usb_cur_target = bci->usb_cur; |
425 | } else if (bci->usb_cur >= bci->usb_cur_target || | 426 | } else if (bci->usb_cur >= bci->usb_cur_target || |
426 | bci->usb_cur + USB_CUR_STEP > USB_MAX_CURRENT) { | 427 | bci->usb_cur + USB_CUR_STEP > USB_MAX_CURRENT) { |
@@ -439,6 +440,7 @@ static void twl4030_current_worker(struct work_struct *data) | |||
439 | static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | 440 | static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) |
440 | { | 441 | { |
441 | int ret; | 442 | int ret; |
443 | u32 reg; | ||
442 | 444 | ||
443 | if (bci->usb_mode == CHARGE_OFF) | 445 | if (bci->usb_mode == CHARGE_OFF) |
444 | enable = false; | 446 | enable = false; |
@@ -452,14 +454,38 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | |||
452 | bci->usb_enabled = 1; | 454 | bci->usb_enabled = 1; |
453 | } | 455 | } |
454 | 456 | ||
455 | if (bci->usb_mode == CHARGE_AUTO) | 457 | if (bci->usb_mode == CHARGE_AUTO) { |
458 | /* Enable interrupts now. */ | ||
459 | reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | | ||
460 | TWL4030_TBATOR2 | TWL4030_TBATOR1 | | ||
461 | TWL4030_BATSTS); | ||
462 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg, | ||
463 | TWL4030_INTERRUPTS_BCIIMR1A); | ||
464 | if (ret < 0) { | ||
465 | dev_err(bci->dev, | ||
466 | "failed to unmask interrupts: %d\n", | ||
467 | ret); | ||
468 | return ret; | ||
469 | } | ||
456 | /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ | 470 | /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ |
457 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); | 471 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); |
472 | } | ||
458 | 473 | ||
459 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ | 474 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ |
460 | ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0, | 475 | ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0, |
461 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); | 476 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); |
462 | if (bci->usb_mode == CHARGE_LINEAR) { | 477 | if (bci->usb_mode == CHARGE_LINEAR) { |
478 | /* Enable interrupts now. */ | ||
479 | reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_TBATOR2 | | ||
480 | TWL4030_TBATOR1 | TWL4030_BATSTS); | ||
481 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg, | ||
482 | TWL4030_INTERRUPTS_BCIIMR1A); | ||
483 | if (ret < 0) { | ||
484 | dev_err(bci->dev, | ||
485 | "failed to unmask interrupts: %d\n", | ||
486 | ret); | ||
487 | return ret; | ||
488 | } | ||
463 | twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0); | 489 | twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC|TWL4030_CVENAC, 0); |
464 | /* Watch dog key: WOVF acknowledge */ | 490 | /* Watch dog key: WOVF acknowledge */ |
465 | ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33, | 491 | ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0x33, |
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h index 7690f0793965..5fd0e429f472 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/mfd/cros_ec_commands.h | |||
@@ -3103,6 +3103,16 @@ struct ec_params_usb_pd_info_request { | |||
3103 | uint8_t port; | 3103 | uint8_t port; |
3104 | } __packed; | 3104 | } __packed; |
3105 | 3105 | ||
3106 | /* | ||
3107 | * This command will return the number of USB PD charge port + the number | ||
3108 | * of dedicated port present. | ||
3109 | * EC_CMD_USB_PD_PORTS does NOT include the dedicated ports | ||
3110 | */ | ||
3111 | #define EC_CMD_CHARGE_PORT_COUNT 0x0105 | ||
3112 | struct ec_response_charge_port_count { | ||
3113 | uint8_t port_count; | ||
3114 | } __packed; | ||
3115 | |||
3106 | /* Read USB-PD Device discovery info */ | 3116 | /* Read USB-PD Device discovery info */ |
3107 | #define EC_CMD_USB_PD_DISCOVERY 0x0113 | 3117 | #define EC_CMD_USB_PD_DISCOVERY 0x0113 |
3108 | struct ec_params_usb_pd_discovery_entry { | 3118 | struct ec_params_usb_pd_discovery_entry { |
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h index d6355f49fbae..507c5e214c42 100644 --- a/include/linux/power/bq27xxx_battery.h +++ b/include/linux/power/bq27xxx_battery.h | |||
@@ -24,6 +24,7 @@ enum bq27xxx_chip { | |||
24 | BQ27546, | 24 | BQ27546, |
25 | BQ27742, | 25 | BQ27742, |
26 | BQ27545, /* bq27545 */ | 26 | BQ27545, /* bq27545 */ |
27 | BQ27411, | ||
27 | BQ27421, /* bq27421, bq27441, bq27621 */ | 28 | BQ27421, /* bq27421, bq27441, bq27621 */ |
28 | BQ27425, | 29 | BQ27425, |
29 | BQ27426, | 30 | BQ27426, |