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

power: supply: max8903: Convert to GPIO descriptors

The MAX8903 uses up to 5 different GPIO lines to control and
monitor charging.

When converting to use GPIO descriptors instead of the old
GPIO numbers the following side-refactorings were done:

- Decomission the platform data container struct as all
GPIO descriptors are now "live" members of the driver
state container. The "dc_valid" and "usb_valid" just
indicate the presence of a DC or USB charger detection
line, and this can be handled by just checking if
the optional GPIO descriptor for each is != NULL.

- The gpiolib will now respect the GPIO_ACTIVE_LOW flag
for each of the lines, meaning gpiod_get_value() for example
will return 1 (asserted) if a line is flagged as
active low and is also physically low. The same applies
to output lines, vice versa mutatis mutandis. The code
has been augmented to account for this in all sites.

- The terse parenthesis such as this:
gpio_set_value(pdata->cen, ta_in ? 0 :
(data->usb_in ? 0 : 1));
have been expanded to more readable if / else if / else
statements that are easier for humans to read.

- Comments were inserted to underscore polarity in each
case where it could be confusing to users of the old code.

One thing is notable: the device tree bindings does not show
an example of polarity assigned for the line "dcm-gpios"
DC current monitor, is assumed to be flagged GPIO_ACTIVE_HIGH
and driving it high (asserted) will achieve DC charger current
limits and driving it low will achieve USB charger current
limits. Device trees with this (optional) GPIO line defined
should definately be flagged as GPIO_ACTIVE_HIGH.

Cc: Chris Lapa <chris@lapa.com.au>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Linus Walleij and committed by
Sebastian Reichel
50da8d04 3188677d

+163 -215
+163 -215
drivers/power/supply/max8903_charger.c
··· 6 6 * MyungJoo Ham <myungjoo.ham@samsung.com> 7 7 */ 8 8 9 - #include <linux/gpio.h> 9 + #include <linux/gpio/consumer.h> 10 10 #include <linux/interrupt.h> 11 11 #include <linux/module.h> 12 12 #include <linux/of.h> 13 13 #include <linux/of_device.h> 14 - #include <linux/of_gpio.h> 15 14 #include <linux/slab.h> 16 15 #include <linux/power_supply.h> 17 16 #include <linux/platform_device.h> 18 17 19 - struct max8903_pdata { 20 - /* 21 - * GPIOs 22 - * cen, chg, flt, dcm and usus are optional. 23 - * dok and uok are not optional depending on the status of 24 - * dc_valid and usb_valid. 25 - */ 26 - int cen; /* Charger Enable input */ 27 - int dok; /* DC(Adapter) Power OK output */ 28 - int uok; /* USB Power OK output */ 29 - int chg; /* Charger status output */ 30 - int flt; /* Fault output */ 31 - int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */ 32 - int usus; /* USB Suspend Input (1: suspended) */ 33 - 34 - /* 35 - * DC(Adapter/TA) is wired 36 - * When dc_valid is true, 37 - * dok should be valid. 38 - * 39 - * At least one of dc_valid or usb_valid should be true. 40 - */ 41 - bool dc_valid; 42 - /* 43 - * USB is wired 44 - * When usb_valid is true, 45 - * uok should be valid. 46 - */ 47 - bool usb_valid; 48 - }; 49 - 50 18 struct max8903_data { 51 - struct max8903_pdata *pdata; 52 19 struct device *dev; 53 20 struct power_supply *psy; 54 21 struct power_supply_desc psy_desc; 22 + /* 23 + * GPIOs 24 + * chg, flt, dcm and usus are optional. 25 + * dok or uok must be present. 26 + * If dok is present, cen must be present. 27 + */ 28 + struct gpio_desc *cen; /* Charger Enable input */ 29 + struct gpio_desc *dok; /* DC (Adapter) Power OK output */ 30 + struct gpio_desc *uok; /* USB Power OK output */ 31 + struct gpio_desc *chg; /* Charger status output */ 32 + struct gpio_desc *flt; /* Fault output */ 33 + struct gpio_desc *dcm; /* Current-Limit Mode input (1: DC, 2: USB) */ 34 + struct gpio_desc *usus; /* USB Suspend Input (1: suspended) */ 55 35 bool fault; 56 36 bool usb_in; 57 37 bool ta_in; ··· 52 72 switch (psp) { 53 73 case POWER_SUPPLY_PROP_STATUS: 54 74 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 55 - if (gpio_is_valid(data->pdata->chg)) { 56 - if (gpio_get_value(data->pdata->chg) == 0) 75 + if (data->chg) { 76 + if (gpiod_get_value(data->chg)) 77 + /* CHG asserted */ 57 78 val->intval = POWER_SUPPLY_STATUS_CHARGING; 58 79 else if (data->usb_in || data->ta_in) 59 80 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; ··· 82 101 static irqreturn_t max8903_dcin(int irq, void *_data) 83 102 { 84 103 struct max8903_data *data = _data; 85 - struct max8903_pdata *pdata = data->pdata; 86 104 bool ta_in; 87 105 enum power_supply_type old_type; 88 106 89 - ta_in = gpio_get_value(pdata->dok) ? false : true; 107 + /* 108 + * This means the line is asserted. 109 + * 110 + * The signal is active low, but the inversion is handled in the GPIO 111 + * library as the line should be flagged GPIO_ACTIVE_LOW in the device 112 + * tree. 113 + */ 114 + ta_in = gpiod_get_value(data->dok); 90 115 91 116 if (ta_in == data->ta_in) 92 117 return IRQ_HANDLED; ··· 100 113 data->ta_in = ta_in; 101 114 102 115 /* Set Current-Limit-Mode 1:DC 0:USB */ 103 - if (gpio_is_valid(pdata->dcm)) 104 - gpio_set_value(pdata->dcm, ta_in ? 1 : 0); 116 + if (data->dcm) 117 + gpiod_set_value(data->dcm, ta_in); 105 118 106 - /* Charger Enable / Disable (cen is negated) */ 107 - if (gpio_is_valid(pdata->cen)) 108 - gpio_set_value(pdata->cen, ta_in ? 0 : 109 - (data->usb_in ? 0 : 1)); 119 + /* Charger Enable / Disable */ 120 + if (data->cen) { 121 + int val; 122 + 123 + if (ta_in) 124 + /* Certainly enable if DOK is asserted */ 125 + val = 1; 126 + else if (data->usb_in) 127 + /* Enable if the USB charger is enabled */ 128 + val = 1; 129 + else 130 + /* Else default-disable */ 131 + val = 0; 132 + 133 + gpiod_set_value(data->cen, val); 134 + } 110 135 111 136 dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? 112 137 "Connected" : "Disconnected"); ··· 141 142 static irqreturn_t max8903_usbin(int irq, void *_data) 142 143 { 143 144 struct max8903_data *data = _data; 144 - struct max8903_pdata *pdata = data->pdata; 145 145 bool usb_in; 146 146 enum power_supply_type old_type; 147 147 148 - usb_in = gpio_get_value(pdata->uok) ? false : true; 148 + /* 149 + * This means the line is asserted. 150 + * 151 + * The signal is active low, but the inversion is handled in the GPIO 152 + * library as the line should be flagged GPIO_ACTIVE_LOW in the device 153 + * tree. 154 + */ 155 + usb_in = gpiod_get_value(data->uok); 149 156 150 157 if (usb_in == data->usb_in) 151 158 return IRQ_HANDLED; ··· 160 155 161 156 /* Do not touch Current-Limit-Mode */ 162 157 163 - /* Charger Enable / Disable (cen is negated) */ 164 - if (gpio_is_valid(pdata->cen)) 165 - gpio_set_value(pdata->cen, usb_in ? 0 : 166 - (data->ta_in ? 0 : 1)); 158 + /* Charger Enable / Disable */ 159 + if (data->cen) { 160 + int val; 161 + 162 + if (usb_in) 163 + /* Certainly enable if UOK is asserted */ 164 + val = 1; 165 + else if (data->ta_in) 166 + /* Enable if the DC charger is enabled */ 167 + val = 1; 168 + else 169 + /* Else default-disable */ 170 + val = 0; 171 + 172 + gpiod_set_value(data->cen, val); 173 + } 167 174 168 175 dev_dbg(data->dev, "USB Charger %s.\n", usb_in ? 169 176 "Connected" : "Disconnected"); ··· 198 181 static irqreturn_t max8903_fault(int irq, void *_data) 199 182 { 200 183 struct max8903_data *data = _data; 201 - struct max8903_pdata *pdata = data->pdata; 202 184 bool fault; 203 185 204 - fault = gpio_get_value(pdata->flt) ? false : true; 186 + /* 187 + * This means the line is asserted. 188 + * 189 + * The signal is active low, but the inversion is handled in the GPIO 190 + * library as the line should be flagged GPIO_ACTIVE_LOW in the device 191 + * tree. 192 + */ 193 + fault = gpiod_get_value(data->flt); 205 194 206 195 if (fault == data->fault) 207 196 return IRQ_HANDLED; ··· 222 199 return IRQ_HANDLED; 223 200 } 224 201 225 - static struct max8903_pdata *max8903_parse_dt_data(struct device *dev) 226 - { 227 - struct device_node *np = dev->of_node; 228 - struct max8903_pdata *pdata = NULL; 229 - 230 - if (!np) 231 - return NULL; 232 - 233 - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 234 - if (!pdata) 235 - return NULL; 236 - 237 - pdata->dc_valid = false; 238 - pdata->usb_valid = false; 239 - 240 - pdata->cen = of_get_named_gpio(np, "cen-gpios", 0); 241 - if (!gpio_is_valid(pdata->cen)) 242 - pdata->cen = -EINVAL; 243 - 244 - pdata->chg = of_get_named_gpio(np, "chg-gpios", 0); 245 - if (!gpio_is_valid(pdata->chg)) 246 - pdata->chg = -EINVAL; 247 - 248 - pdata->flt = of_get_named_gpio(np, "flt-gpios", 0); 249 - if (!gpio_is_valid(pdata->flt)) 250 - pdata->flt = -EINVAL; 251 - 252 - pdata->usus = of_get_named_gpio(np, "usus-gpios", 0); 253 - if (!gpio_is_valid(pdata->usus)) 254 - pdata->usus = -EINVAL; 255 - 256 - pdata->dcm = of_get_named_gpio(np, "dcm-gpios", 0); 257 - if (!gpio_is_valid(pdata->dcm)) 258 - pdata->dcm = -EINVAL; 259 - 260 - pdata->dok = of_get_named_gpio(np, "dok-gpios", 0); 261 - if (!gpio_is_valid(pdata->dok)) 262 - pdata->dok = -EINVAL; 263 - else 264 - pdata->dc_valid = true; 265 - 266 - pdata->uok = of_get_named_gpio(np, "uok-gpios", 0); 267 - if (!gpio_is_valid(pdata->uok)) 268 - pdata->uok = -EINVAL; 269 - else 270 - pdata->usb_valid = true; 271 - 272 - return pdata; 273 - } 274 - 275 202 static int max8903_setup_gpios(struct platform_device *pdev) 276 203 { 277 204 struct max8903_data *data = platform_get_drvdata(pdev); 278 205 struct device *dev = &pdev->dev; 279 - struct max8903_pdata *pdata = pdev->dev.platform_data; 280 - int ret = 0; 281 - int gpio; 282 - int ta_in = 0; 283 - int usb_in = 0; 206 + bool ta_in = false; 207 + bool usb_in = false; 208 + enum gpiod_flags flags; 284 209 285 - if (pdata->dc_valid) { 286 - if (gpio_is_valid(pdata->dok)) { 287 - ret = devm_gpio_request(dev, pdata->dok, 288 - data->psy_desc.name); 289 - if (ret) { 290 - dev_err(dev, 291 - "Failed GPIO request for dok: %d err %d\n", 292 - pdata->dok, ret); 293 - return ret; 294 - } 295 - 296 - gpio = pdata->dok; /* PULL_UPed Interrupt */ 297 - ta_in = gpio_get_value(gpio) ? 0 : 1; 298 - } else { 299 - dev_err(dev, "When DC is wired, DOK should be wired as well.\n"); 300 - return -EINVAL; 301 - } 210 + data->dok = devm_gpiod_get_optional(dev, "dok", GPIOD_IN); 211 + if (IS_ERR(data->dok)) 212 + return dev_err_probe(dev, PTR_ERR(data->dok), 213 + "failed to get DOK GPIO"); 214 + if (data->dok) { 215 + gpiod_set_consumer_name(data->dok, data->psy_desc.name); 216 + /* 217 + * The DC OK is pulled up to 1 and goes low when a charger 218 + * is plugged in (active low) but in the device tree the 219 + * line is marked as GPIO_ACTIVE_LOW so we get a 1 (asserted) 220 + * here if the DC charger is plugged in. 221 + */ 222 + ta_in = gpiod_get_value(data->dok); 302 223 } 303 224 304 - if (gpio_is_valid(pdata->dcm)) { 305 - ret = devm_gpio_request(dev, pdata->dcm, data->psy_desc.name); 306 - if (ret) { 307 - dev_err(dev, 308 - "Failed GPIO request for dcm: %d err %d\n", 309 - pdata->dcm, ret); 310 - return ret; 311 - } 312 - 313 - gpio = pdata->dcm; /* Output */ 314 - gpio_set_value(gpio, ta_in); 225 + data->uok = devm_gpiod_get_optional(dev, "uok", GPIOD_IN); 226 + if (IS_ERR(data->uok)) 227 + return dev_err_probe(dev, PTR_ERR(data->uok), 228 + "failed to get UOK GPIO"); 229 + if (data->uok) { 230 + gpiod_set_consumer_name(data->uok, data->psy_desc.name); 231 + /* 232 + * The USB OK is pulled up to 1 and goes low when a USB charger 233 + * is plugged in (active low) but in the device tree the 234 + * line is marked as GPIO_ACTIVE_LOW so we get a 1 (asserted) 235 + * here if the USB charger is plugged in. 236 + */ 237 + usb_in = gpiod_get_value(data->uok); 315 238 } 316 239 317 - if (pdata->usb_valid) { 318 - if (gpio_is_valid(pdata->uok)) { 319 - ret = devm_gpio_request(dev, pdata->uok, 320 - data->psy_desc.name); 321 - if (ret) { 322 - dev_err(dev, 323 - "Failed GPIO request for uok: %d err %d\n", 324 - pdata->uok, ret); 325 - return ret; 326 - } 327 - 328 - gpio = pdata->uok; 329 - usb_in = gpio_get_value(gpio) ? 0 : 1; 330 - } else { 331 - dev_err(dev, "When USB is wired, UOK should be wired." 332 - "as well.\n"); 333 - return -EINVAL; 334 - } 240 + /* Either DC OK or USB OK must be provided */ 241 + if (!data->dok && !data->uok) { 242 + dev_err(dev, "no valid power source\n"); 243 + return -EINVAL; 335 244 } 336 245 337 - if (gpio_is_valid(pdata->cen)) { 338 - ret = devm_gpio_request(dev, pdata->cen, data->psy_desc.name); 339 - if (ret) { 340 - dev_err(dev, 341 - "Failed GPIO request for cen: %d err %d\n", 342 - pdata->cen, ret); 343 - return ret; 344 - } 246 + /* 247 + * If either charger is already connected at this point, 248 + * assert the CEN line and enable charging from the start. 249 + * 250 + * The line is active low but also marked with GPIO_ACTIVE_LOW 251 + * in the device tree, so when we assert the line with 252 + * GPIOD_OUT_HIGH the line will be driven low. 253 + */ 254 + flags = (ta_in || usb_in) ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; 255 + /* 256 + * If DC OK is provided, Charger Enable CEN is compulsory 257 + * so this is not optional here. 258 + */ 259 + data->cen = devm_gpiod_get(dev, "cen", flags); 260 + if (IS_ERR(data->cen)) 261 + return dev_err_probe(dev, PTR_ERR(data->cen), 262 + "failed to get CEN GPIO"); 263 + gpiod_set_consumer_name(data->cen, data->psy_desc.name); 345 264 346 - gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); 347 - } 265 + /* 266 + * If the DC charger is connected, then select it. 267 + * 268 + * The DCM line should be marked GPIO_ACTIVE_HIGH in the 269 + * device tree. Driving it high will enable the DC charger 270 + * input over the USB charger input. 271 + */ 272 + flags = ta_in ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; 273 + data->dcm = devm_gpiod_get_optional(dev, "dcm", flags); 274 + if (IS_ERR(data->dcm)) 275 + return dev_err_probe(dev, PTR_ERR(data->dcm), 276 + "failed to get DCM GPIO"); 277 + gpiod_set_consumer_name(data->dcm, data->psy_desc.name); 348 278 349 - if (gpio_is_valid(pdata->chg)) { 350 - ret = devm_gpio_request(dev, pdata->chg, data->psy_desc.name); 351 - if (ret) { 352 - dev_err(dev, 353 - "Failed GPIO request for chg: %d err %d\n", 354 - pdata->chg, ret); 355 - return ret; 356 - } 357 - } 279 + data->chg = devm_gpiod_get_optional(dev, "chg", GPIOD_IN); 280 + if (IS_ERR(data->chg)) 281 + return dev_err_probe(dev, PTR_ERR(data->chg), 282 + "failed to get CHG GPIO"); 283 + gpiod_set_consumer_name(data->chg, data->psy_desc.name); 358 284 359 - if (gpio_is_valid(pdata->flt)) { 360 - ret = devm_gpio_request(dev, pdata->flt, data->psy_desc.name); 361 - if (ret) { 362 - dev_err(dev, 363 - "Failed GPIO request for flt: %d err %d\n", 364 - pdata->flt, ret); 365 - return ret; 366 - } 367 - } 285 + data->flt = devm_gpiod_get_optional(dev, "flt", GPIOD_IN); 286 + if (IS_ERR(data->flt)) 287 + return dev_err_probe(dev, PTR_ERR(data->flt), 288 + "failed to get FLT GPIO"); 289 + gpiod_set_consumer_name(data->flt, data->psy_desc.name); 368 290 369 - if (gpio_is_valid(pdata->usus)) { 370 - ret = devm_gpio_request(dev, pdata->usus, data->psy_desc.name); 371 - if (ret) { 372 - dev_err(dev, 373 - "Failed GPIO request for usus: %d err %d\n", 374 - pdata->usus, ret); 375 - return ret; 376 - } 377 - } 291 + data->usus = devm_gpiod_get_optional(dev, "usus", GPIOD_IN); 292 + if (IS_ERR(data->usus)) 293 + return dev_err_probe(dev, PTR_ERR(data->usus), 294 + "failed to get USUS GPIO"); 295 + gpiod_set_consumer_name(data->usus, data->psy_desc.name); 378 296 379 297 data->fault = false; 380 298 data->ta_in = ta_in; ··· 328 364 { 329 365 struct max8903_data *data; 330 366 struct device *dev = &pdev->dev; 331 - struct max8903_pdata *pdata = pdev->dev.platform_data; 332 367 struct power_supply_config psy_cfg = {}; 333 368 int ret = 0; 334 369 ··· 335 372 if (!data) 336 373 return -ENOMEM; 337 374 338 - if (IS_ENABLED(CONFIG_OF) && !pdata && dev->of_node) 339 - pdata = max8903_parse_dt_data(dev); 340 - 341 - if (!pdata) { 342 - dev_err(dev, "No platform data.\n"); 343 - return -EINVAL; 344 - } 345 - 346 - pdev->dev.platform_data = pdata; 347 - data->pdata = pdata; 348 375 data->dev = dev; 349 376 platform_set_drvdata(pdev, data); 350 - 351 - if (pdata->dc_valid == false && pdata->usb_valid == false) { 352 - dev_err(dev, "No valid power sources.\n"); 353 - return -EINVAL; 354 - } 355 377 356 378 ret = max8903_setup_gpios(pdev); 357 379 if (ret) ··· 359 411 return PTR_ERR(data->psy); 360 412 } 361 413 362 - if (pdata->dc_valid) { 363 - ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok), 414 + if (data->dok) { 415 + ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->dok), 364 416 NULL, max8903_dcin, 365 417 IRQF_TRIGGER_FALLING | 366 418 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 367 419 "MAX8903 DC IN", data); 368 420 if (ret) { 369 421 dev_err(dev, "Cannot request irq %d for DC (%d)\n", 370 - gpio_to_irq(pdata->dok), ret); 422 + gpiod_to_irq(data->dok), ret); 371 423 return ret; 372 424 } 373 425 } 374 426 375 - if (pdata->usb_valid) { 376 - ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok), 427 + if (data->uok) { 428 + ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->uok), 377 429 NULL, max8903_usbin, 378 430 IRQF_TRIGGER_FALLING | 379 431 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 380 432 "MAX8903 USB IN", data); 381 433 if (ret) { 382 434 dev_err(dev, "Cannot request irq %d for USB (%d)\n", 383 - gpio_to_irq(pdata->uok), ret); 435 + gpiod_to_irq(data->uok), ret); 384 436 return ret; 385 437 } 386 438 } 387 439 388 - if (gpio_is_valid(pdata->flt)) { 389 - ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt), 440 + if (data->flt) { 441 + ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->flt), 390 442 NULL, max8903_fault, 391 443 IRQF_TRIGGER_FALLING | 392 444 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 393 445 "MAX8903 Fault", data); 394 446 if (ret) { 395 447 dev_err(dev, "Cannot request irq %d for Fault (%d)\n", 396 - gpio_to_irq(pdata->flt), ret); 448 + gpiod_to_irq(data->flt), ret); 397 449 return ret; 398 450 } 399 451 }