Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:

- alternative reset driver for new at91 SoCs

- misc fixes

* tag 'for-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply:
sbs-battery: fix power status when battery charging near dry
power: ipaq-micro-battery: freeing the wrong variable
power/max8925: freeing wrong variable
power: reset: at91-shdwc: add new shutdown controller driver
ARM: dts: at91: shdwc binding: add new shutdown controller documentation

+361 -10
+59
Documentation/devicetree/bindings/arm/atmel-at91.txt
··· 151 151 clocks = <&clk32k>; 152 152 }; 153 153 154 + SHDWC SAMA5D2-Compatible Shutdown Controller 155 + 156 + 1) shdwc node 157 + 158 + required properties: 159 + - compatible: should be "atmel,sama5d2-shdwc". 160 + - reg: should contain registers location and length 161 + - clocks: phandle to input clock. 162 + - #address-cells: should be one. The cell is the wake-up input index. 163 + - #size-cells: should be zero. 164 + 165 + optional properties: 166 + 167 + - debounce-delay-us: minimum wake-up inputs debouncer period in 168 + microseconds. It's usually a board-related property. 169 + - atmel,wakeup-rtc-timer: boolean to enable Real-Time Clock wake-up. 170 + 171 + The node contains child nodes for each wake-up input that the platform uses. 172 + 173 + 2) input nodes 174 + 175 + Wake-up input nodes are usually described in the "board" part of the Device 176 + Tree. Note also that input 0 is linked to the wake-up pin and is frequently 177 + used. 178 + 179 + Required properties: 180 + - reg: should contain the wake-up input index [0 - 15]. 181 + 182 + Optional properties: 183 + - atmel,wakeup-active-high: boolean, the corresponding wake-up input described 184 + by the child, forces the wake-up of the core power supply on a high level. 185 + The default is to be active low. 186 + 187 + Example: 188 + 189 + On the SoC side: 190 + shdwc@f8048010 { 191 + compatible = "atmel,sama5d2-shdwc"; 192 + reg = <0xf8048010 0x10>; 193 + clocks = <&clk32k>; 194 + #address-cells = <1>; 195 + #size-cells = <0>; 196 + atmel,wakeup-rtc-timer; 197 + }; 198 + 199 + On the board side: 200 + shdwc@f8048010 { 201 + debounce-delay-us = <976>; 202 + 203 + input@0 { 204 + reg = <0>; 205 + }; 206 + 207 + input@1 { 208 + reg = <1>; 209 + atmel,wakeup-active-high; 210 + }; 211 + }; 212 + 154 213 Special Function Registers (SFR) 155 214 156 215 Special Function Registers (SFR) manage specific aspects of the integrated
+5
MAINTAINERS
··· 2048 2048 S: Supported 2049 2049 F: drivers/tty/serial/atmel_serial.c 2050 2050 2051 + ATMEL AT91 SAMA5D2-Compatible Shutdown Controller 2052 + M: Nicolas Ferre <nicolas.ferre@atmel.com> 2053 + S: Supported 2054 + F: drivers/power/reset/at91-sama5d2_shdwc.c 2055 + 2051 2056 ATMEL SAMA5D2 ADC DRIVER 2052 2057 M: Ludovic Desroches <ludovic.desroches@atmel.com> 2053 2058 L: linux-iio@vger.kernel.org
+1 -1
drivers/power/ipaq_micro_battery.c
··· 261 261 return 0; 262 262 263 263 ac_err: 264 - power_supply_unregister(micro_ac_power); 264 + power_supply_unregister(micro_batt_power); 265 265 batt_err: 266 266 cancel_delayed_work_sync(&mb->update); 267 267 destroy_workqueue(mb->wq);
+5 -5
drivers/power/max8925_power.c
··· 540 540 info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg); 541 541 if (IS_ERR(info->usb)) { 542 542 ret = PTR_ERR(info->usb); 543 - goto out_usb; 543 + goto out_unregister_ac; 544 544 } 545 545 info->usb->dev.parent = &pdev->dev; 546 546 547 547 info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL); 548 548 if (IS_ERR(info->battery)) { 549 549 ret = PTR_ERR(info->battery); 550 - goto out_battery; 550 + goto out_unregister_usb; 551 551 } 552 552 info->battery->dev.parent = &pdev->dev; 553 553 ··· 560 560 561 561 max8925_init_charger(chip, info); 562 562 return 0; 563 - out_battery: 564 - power_supply_unregister(info->battery); 565 - out_usb: 563 + out_unregister_usb: 564 + power_supply_unregister(info->usb); 565 + out_unregister_ac: 566 566 power_supply_unregister(info->ac); 567 567 out: 568 568 return ret;
+8
drivers/power/reset/Kconfig
··· 30 30 This driver supports restart for Atmel AT91SAM9 and SAMA5 31 31 SoCs 32 32 33 + config POWER_RESET_AT91_SAMA5D2_SHDWC 34 + tristate "Atmel AT91 SAMA5D2-Compatible shutdown controller driver" 35 + depends on ARCH_AT91 || COMPILE_TEST 36 + default SOC_SAMA5 37 + help 38 + This driver supports the alternate shutdown controller for some Atmel 39 + SAMA5 SoCs. It is present for example on SAMA5D2 SoC. 40 + 33 41 config POWER_RESET_AXXIA 34 42 bool "LSI Axxia reset driver" 35 43 depends on ARCH_AXXIA
+1
drivers/power/reset/Makefile
··· 1 1 obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o 2 2 obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o 3 3 obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o 4 + obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o 4 5 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 5 6 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o 6 7 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
+282
drivers/power/reset/at91-sama5d2_shdwc.c
··· 1 + /* 2 + * Atmel SAMA5D2-Compatible Shutdown Controller (SHDWC) driver. 3 + * Found on some SoCs as the sama5d2 (obviously). 4 + * 5 + * Copyright (C) 2015 Atmel Corporation, 6 + * Nicolas Ferre <nicolas.ferre@atmel.com> 7 + * 8 + * Evolved from driver at91-poweroff.c. 9 + * 10 + * This file is licensed under the terms of the GNU General Public 11 + * License version 2. This program is licensed "as is" without any 12 + * warranty of any kind, whether express or implied. 13 + * 14 + * TODO: 15 + * - addition to status of other wake-up inputs [1 - 15] 16 + * - Analog Comparator wake-up alarm 17 + * - Serial RX wake-up alarm 18 + * - low power debouncer 19 + */ 20 + 21 + #include <linux/clk.h> 22 + #include <linux/io.h> 23 + #include <linux/module.h> 24 + #include <linux/of.h> 25 + #include <linux/platform_device.h> 26 + #include <linux/printk.h> 27 + 28 + #define SLOW_CLOCK_FREQ 32768 29 + 30 + #define AT91_SHDW_CR 0x00 /* Shut Down Control Register */ 31 + #define AT91_SHDW_SHDW BIT(0) /* Shut Down command */ 32 + #define AT91_SHDW_KEY (0xa5UL << 24) /* KEY Password */ 33 + 34 + #define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */ 35 + #define AT91_SHDW_WKUPDBC_SHIFT 24 36 + #define AT91_SHDW_WKUPDBC_MASK GENMASK(31, 16) 37 + #define AT91_SHDW_WKUPDBC(x) (((x) << AT91_SHDW_WKUPDBC_SHIFT) \ 38 + & AT91_SHDW_WKUPDBC_MASK) 39 + 40 + #define AT91_SHDW_SR 0x08 /* Shut Down Status Register */ 41 + #define AT91_SHDW_WKUPIS_SHIFT 16 42 + #define AT91_SHDW_WKUPIS_MASK GENMASK(31, 16) 43 + #define AT91_SHDW_WKUPIS(x) ((1 << (x)) << AT91_SHDW_WKUPIS_SHIFT \ 44 + & AT91_SHDW_WKUPIS_MASK) 45 + 46 + #define AT91_SHDW_WUIR 0x0c /* Shutdown Wake-up Inputs Register */ 47 + #define AT91_SHDW_WKUPEN_MASK GENMASK(15, 0) 48 + #define AT91_SHDW_WKUPEN(x) ((1 << (x)) & AT91_SHDW_WKUPEN_MASK) 49 + #define AT91_SHDW_WKUPT_SHIFT 16 50 + #define AT91_SHDW_WKUPT_MASK GENMASK(31, 16) 51 + #define AT91_SHDW_WKUPT(x) ((1 << (x)) << AT91_SHDW_WKUPT_SHIFT \ 52 + & AT91_SHDW_WKUPT_MASK) 53 + 54 + #define SHDW_WK_PIN(reg, cfg) ((reg) & AT91_SHDW_WKUPIS((cfg)->wkup_pin_input)) 55 + #define SHDW_RTCWK(reg, cfg) (((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1) 56 + #define SHDW_RTCWKEN(cfg) (1 << ((cfg)->mr_rtcwk_shift)) 57 + 58 + #define DBC_PERIOD_US(x) DIV_ROUND_UP_ULL((1000000 * (x)), \ 59 + SLOW_CLOCK_FREQ) 60 + 61 + struct shdwc_config { 62 + u8 wkup_pin_input; 63 + u8 mr_rtcwk_shift; 64 + u8 sr_rtcwk_shift; 65 + }; 66 + 67 + struct shdwc { 68 + struct shdwc_config *cfg; 69 + void __iomem *at91_shdwc_base; 70 + }; 71 + 72 + /* 73 + * Hold configuration here, cannot be more than one instance of the driver 74 + * since pm_power_off itself is global. 75 + */ 76 + static struct shdwc *at91_shdwc; 77 + static struct clk *sclk; 78 + 79 + static const unsigned long long sdwc_dbc_period[] = { 80 + 0, 3, 32, 512, 4096, 32768, 81 + }; 82 + 83 + static void __init at91_wakeup_status(struct platform_device *pdev) 84 + { 85 + struct shdwc *shdw = platform_get_drvdata(pdev); 86 + u32 reg; 87 + char *reason = "unknown"; 88 + 89 + reg = readl(shdw->at91_shdwc_base + AT91_SHDW_SR); 90 + 91 + dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg); 92 + 93 + /* Simple power-on, just bail out */ 94 + if (!reg) 95 + return; 96 + 97 + if (SHDW_WK_PIN(reg, shdw->cfg)) 98 + reason = "WKUP pin"; 99 + else if (SHDW_RTCWK(reg, shdw->cfg)) 100 + reason = "RTC"; 101 + 102 + pr_info("AT91: Wake-Up source: %s\n", reason); 103 + } 104 + 105 + static void at91_poweroff(void) 106 + { 107 + writel(AT91_SHDW_KEY | AT91_SHDW_SHDW, 108 + at91_shdwc->at91_shdwc_base + AT91_SHDW_CR); 109 + } 110 + 111 + static u32 at91_shdwc_debouncer_value(struct platform_device *pdev, 112 + u32 in_period_us) 113 + { 114 + int i; 115 + int max_idx = ARRAY_SIZE(sdwc_dbc_period) - 1; 116 + unsigned long long period_us; 117 + unsigned long long max_period_us = DBC_PERIOD_US(sdwc_dbc_period[max_idx]); 118 + 119 + if (in_period_us > max_period_us) { 120 + dev_warn(&pdev->dev, 121 + "debouncer period %u too big, reduced to %llu us\n", 122 + in_period_us, max_period_us); 123 + return max_idx; 124 + } 125 + 126 + for (i = max_idx - 1; i > 0; i--) { 127 + period_us = DBC_PERIOD_US(sdwc_dbc_period[i]); 128 + dev_dbg(&pdev->dev, "%s: ref[%d] = %llu\n", 129 + __func__, i, period_us); 130 + if (in_period_us > period_us) 131 + break; 132 + } 133 + 134 + return i + 1; 135 + } 136 + 137 + static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev, 138 + struct device_node *np) 139 + { 140 + struct device_node *cnp; 141 + u32 wk_input_mask; 142 + u32 wuir = 0; 143 + u32 wk_input; 144 + 145 + for_each_child_of_node(np, cnp) { 146 + if (of_property_read_u32(cnp, "reg", &wk_input)) { 147 + dev_warn(&pdev->dev, "reg property is missing for %s\n", 148 + cnp->full_name); 149 + continue; 150 + } 151 + 152 + wk_input_mask = 1 << wk_input; 153 + if (!(wk_input_mask & AT91_SHDW_WKUPEN_MASK)) { 154 + dev_warn(&pdev->dev, 155 + "wake-up input %d out of bounds ignore\n", 156 + wk_input); 157 + continue; 158 + } 159 + wuir |= wk_input_mask; 160 + 161 + if (of_property_read_bool(cnp, "atmel,wakeup-active-high")) 162 + wuir |= AT91_SHDW_WKUPT(wk_input); 163 + 164 + dev_dbg(&pdev->dev, "%s: (child %d) wuir = %#x\n", 165 + __func__, wk_input, wuir); 166 + } 167 + 168 + return wuir; 169 + } 170 + 171 + static void at91_shdwc_dt_configure(struct platform_device *pdev) 172 + { 173 + struct shdwc *shdw = platform_get_drvdata(pdev); 174 + struct device_node *np = pdev->dev.of_node; 175 + u32 mode = 0, tmp, input; 176 + 177 + if (!np) { 178 + dev_err(&pdev->dev, "device node not found\n"); 179 + return; 180 + } 181 + 182 + if (!of_property_read_u32(np, "debounce-delay-us", &tmp)) 183 + mode |= AT91_SHDW_WKUPDBC(at91_shdwc_debouncer_value(pdev, tmp)); 184 + 185 + if (of_property_read_bool(np, "atmel,wakeup-rtc-timer")) 186 + mode |= SHDW_RTCWKEN(shdw->cfg); 187 + 188 + dev_dbg(&pdev->dev, "%s: mode = %#x\n", __func__, mode); 189 + writel(mode, shdw->at91_shdwc_base + AT91_SHDW_MR); 190 + 191 + input = at91_shdwc_get_wakeup_input(pdev, np); 192 + writel(input, shdw->at91_shdwc_base + AT91_SHDW_WUIR); 193 + } 194 + 195 + static const struct shdwc_config sama5d2_shdwc_config = { 196 + .wkup_pin_input = 0, 197 + .mr_rtcwk_shift = 17, 198 + .sr_rtcwk_shift = 5, 199 + }; 200 + 201 + static const struct of_device_id at91_shdwc_of_match[] = { 202 + { 203 + .compatible = "atmel,sama5d2-shdwc", 204 + .data = &sama5d2_shdwc_config, 205 + }, { 206 + /*sentinel*/ 207 + } 208 + }; 209 + MODULE_DEVICE_TABLE(of, at91_shdwc_of_match); 210 + 211 + static int __init at91_shdwc_probe(struct platform_device *pdev) 212 + { 213 + struct resource *res; 214 + const struct of_device_id *match; 215 + int ret; 216 + 217 + if (!pdev->dev.of_node) 218 + return -ENODEV; 219 + 220 + at91_shdwc = devm_kzalloc(&pdev->dev, sizeof(*at91_shdwc), GFP_KERNEL); 221 + if (!at91_shdwc) 222 + return -ENOMEM; 223 + 224 + platform_set_drvdata(pdev, at91_shdwc); 225 + 226 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 227 + at91_shdwc->at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); 228 + if (IS_ERR(at91_shdwc->at91_shdwc_base)) { 229 + dev_err(&pdev->dev, "Could not map reset controller address\n"); 230 + return PTR_ERR(at91_shdwc->at91_shdwc_base); 231 + } 232 + 233 + match = of_match_node(at91_shdwc_of_match, pdev->dev.of_node); 234 + at91_shdwc->cfg = (struct shdwc_config *)(match->data); 235 + 236 + sclk = devm_clk_get(&pdev->dev, NULL); 237 + if (IS_ERR(sclk)) 238 + return PTR_ERR(sclk); 239 + 240 + ret = clk_prepare_enable(sclk); 241 + if (ret) { 242 + dev_err(&pdev->dev, "Could not enable slow clock\n"); 243 + return ret; 244 + } 245 + 246 + at91_wakeup_status(pdev); 247 + 248 + at91_shdwc_dt_configure(pdev); 249 + 250 + pm_power_off = at91_poweroff; 251 + 252 + return 0; 253 + } 254 + 255 + static int __exit at91_shdwc_remove(struct platform_device *pdev) 256 + { 257 + struct shdwc *shdw = platform_get_drvdata(pdev); 258 + 259 + if (pm_power_off == at91_poweroff) 260 + pm_power_off = NULL; 261 + 262 + /* Reset values to disable wake-up features */ 263 + writel(0, shdw->at91_shdwc_base + AT91_SHDW_MR); 264 + writel(0, shdw->at91_shdwc_base + AT91_SHDW_WUIR); 265 + 266 + clk_disable_unprepare(sclk); 267 + 268 + return 0; 269 + } 270 + 271 + static struct platform_driver at91_shdwc_driver = { 272 + .remove = __exit_p(at91_shdwc_remove), 273 + .driver = { 274 + .name = "at91-shdwc", 275 + .of_match_table = at91_shdwc_of_match, 276 + }, 277 + }; 278 + module_platform_driver_probe(at91_shdwc_driver, at91_shdwc_probe); 279 + 280 + MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>"); 281 + MODULE_DESCRIPTION("Atmel shutdown controller driver"); 282 + MODULE_LICENSE("GPL v2");
-4
drivers/power/sbs-battery.c
··· 382 382 383 383 if (ret & BATTERY_FULL_CHARGED) 384 384 val->intval = POWER_SUPPLY_STATUS_FULL; 385 - else if (ret & BATTERY_FULL_DISCHARGED) 386 - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 387 385 else if (ret & BATTERY_DISCHARGING) 388 386 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 389 387 else ··· 700 702 701 703 if (ret & BATTERY_FULL_CHARGED) 702 704 ret = POWER_SUPPLY_STATUS_FULL; 703 - else if (ret & BATTERY_FULL_DISCHARGED) 704 - ret = POWER_SUPPLY_STATUS_NOT_CHARGING; 705 705 else if (ret & BATTERY_DISCHARGING) 706 706 ret = POWER_SUPPLY_STATUS_DISCHARGING; 707 707 else