1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver 4 * 5 * Copyright (C) 2011 Samsung Electronics 6 * MyungJoo Ham <myungjoo.ham@samsung.com> 7 */ 8 9 #include <linux/gpio.h> 10 #include <linux/interrupt.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_device.h> 14 #include <linux/of_gpio.h> 15 #include <linux/slab.h> 16 #include <linux/power_supply.h> 17 #include <linux/platform_device.h> 18 #include <linux/power/max8903_charger.h> 19 20 struct max8903_data { 21 struct max8903_pdata *pdata; 22 struct device *dev; 23 struct power_supply *psy; 24 struct power_supply_desc psy_desc; 25 bool fault; 26 bool usb_in; 27 bool ta_in; 28 }; 29 30 static enum power_supply_property max8903_charger_props[] = { 31 POWER_SUPPLY_PROP_STATUS, /* Charger status output */ 32 POWER_SUPPLY_PROP_ONLINE, /* External power source */ 33 POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */ 34 }; 35 36 static int max8903_get_property(struct power_supply *psy, 37 enum power_supply_property psp, 38 union power_supply_propval *val) 39 { 40 struct max8903_data *data = power_supply_get_drvdata(psy); 41 42 switch (psp) { 43 case POWER_SUPPLY_PROP_STATUS: 44 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 45 if (gpio_is_valid(data->pdata->chg)) { 46 if (gpio_get_value(data->pdata->chg) == 0) 47 val->intval = POWER_SUPPLY_STATUS_CHARGING; 48 else if (data->usb_in || data->ta_in) 49 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 50 else 51 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 52 } 53 break; 54 case POWER_SUPPLY_PROP_ONLINE: 55 val->intval = 0; 56 if (data->usb_in || data->ta_in) 57 val->intval = 1; 58 break; 59 case POWER_SUPPLY_PROP_HEALTH: 60 val->intval = POWER_SUPPLY_HEALTH_GOOD; 61 if (data->fault) 62 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 63 break; 64 default: 65 return -EINVAL; 66 } 67 68 return 0; 69 } 70 71 static irqreturn_t max8903_dcin(int irq, void *_data) 72 { 73 struct max8903_data *data = _data; 74 struct max8903_pdata *pdata = data->pdata; 75 bool ta_in; 76 enum power_supply_type old_type; 77 78 ta_in = gpio_get_value(pdata->dok) ? false : true; 79 80 if (ta_in == data->ta_in) 81 return IRQ_HANDLED; 82 83 data->ta_in = ta_in; 84 85 /* Set Current-Limit-Mode 1:DC 0:USB */ 86 if (gpio_is_valid(pdata->dcm)) 87 gpio_set_value(pdata->dcm, ta_in ? 1 : 0); 88 89 /* Charger Enable / Disable (cen is negated) */ 90 if (gpio_is_valid(pdata->cen)) 91 gpio_set_value(pdata->cen, ta_in ? 0 : 92 (data->usb_in ? 0 : 1)); 93 94 dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? 95 "Connected" : "Disconnected"); 96 97 old_type = data->psy_desc.type; 98 99 if (data->ta_in) 100 data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS; 101 else if (data->usb_in) 102 data->psy_desc.type = POWER_SUPPLY_TYPE_USB; 103 else 104 data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY; 105 106 if (old_type != data->psy_desc.type) 107 power_supply_changed(data->psy); 108 109 return IRQ_HANDLED; 110 } 111 112 static irqreturn_t max8903_usbin(int irq, void *_data) 113 { 114 struct max8903_data *data = _data; 115 struct max8903_pdata *pdata = data->pdata; 116 bool usb_in; 117 enum power_supply_type old_type; 118 119 usb_in = gpio_get_value(pdata->uok) ? false : true; 120 121 if (usb_in == data->usb_in) 122 return IRQ_HANDLED; 123 124 data->usb_in = usb_in; 125 126 /* Do not touch Current-Limit-Mode */ 127 128 /* Charger Enable / Disable (cen is negated) */ 129 if (gpio_is_valid(pdata->cen)) 130 gpio_set_value(pdata->cen, usb_in ? 0 : 131 (data->ta_in ? 0 : 1)); 132 133 dev_dbg(data->dev, "USB Charger %s.\n", usb_in ? 134 "Connected" : "Disconnected"); 135 136 old_type = data->psy_desc.type; 137 138 if (data->ta_in) 139 data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS; 140 else if (data->usb_in) 141 data->psy_desc.type = POWER_SUPPLY_TYPE_USB; 142 else 143 data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY; 144 145 if (old_type != data->psy_desc.type) 146 power_supply_changed(data->psy); 147 148 return IRQ_HANDLED; 149 } 150 151 static irqreturn_t max8903_fault(int irq, void *_data) 152 { 153 struct max8903_data *data = _data; 154 struct max8903_pdata *pdata = data->pdata; 155 bool fault; 156 157 fault = gpio_get_value(pdata->flt) ? false : true; 158 159 if (fault == data->fault) 160 return IRQ_HANDLED; 161 162 data->fault = fault; 163 164 if (fault) 165 dev_err(data->dev, "Charger suffers a fault and stops.\n"); 166 else 167 dev_err(data->dev, "Charger recovered from a fault.\n"); 168 169 return IRQ_HANDLED; 170 } 171 172 static struct max8903_pdata *max8903_parse_dt_data(struct device *dev) 173 { 174 struct device_node *np = dev->of_node; 175 struct max8903_pdata *pdata = NULL; 176 177 if (!np) 178 return NULL; 179 180 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 181 if (!pdata) 182 return NULL; 183 184 pdata->dc_valid = false; 185 pdata->usb_valid = false; 186 187 pdata->cen = of_get_named_gpio(np, "cen-gpios", 0); 188 if (!gpio_is_valid(pdata->cen)) 189 pdata->cen = -EINVAL; 190 191 pdata->chg = of_get_named_gpio(np, "chg-gpios", 0); 192 if (!gpio_is_valid(pdata->chg)) 193 pdata->chg = -EINVAL; 194 195 pdata->flt = of_get_named_gpio(np, "flt-gpios", 0); 196 if (!gpio_is_valid(pdata->flt)) 197 pdata->flt = -EINVAL; 198 199 pdata->usus = of_get_named_gpio(np, "usus-gpios", 0); 200 if (!gpio_is_valid(pdata->usus)) 201 pdata->usus = -EINVAL; 202 203 pdata->dcm = of_get_named_gpio(np, "dcm-gpios", 0); 204 if (!gpio_is_valid(pdata->dcm)) 205 pdata->dcm = -EINVAL; 206 207 pdata->dok = of_get_named_gpio(np, "dok-gpios", 0); 208 if (!gpio_is_valid(pdata->dok)) 209 pdata->dok = -EINVAL; 210 else 211 pdata->dc_valid = true; 212 213 pdata->uok = of_get_named_gpio(np, "uok-gpios", 0); 214 if (!gpio_is_valid(pdata->uok)) 215 pdata->uok = -EINVAL; 216 else 217 pdata->usb_valid = true; 218 219 return pdata; 220 } 221 222 static int max8903_setup_gpios(struct platform_device *pdev) 223 { 224 struct max8903_data *data = platform_get_drvdata(pdev); 225 struct device *dev = &pdev->dev; 226 struct max8903_pdata *pdata = pdev->dev.platform_data; 227 int ret = 0; 228 int gpio; 229 int ta_in = 0; 230 int usb_in = 0; 231 232 if (pdata->dc_valid) { 233 if (gpio_is_valid(pdata->dok)) { 234 ret = devm_gpio_request(dev, pdata->dok, 235 data->psy_desc.name); 236 if (ret) { 237 dev_err(dev, 238 "Failed GPIO request for dok: %d err %d\n", 239 pdata->dok, ret); 240 return ret; 241 } 242 243 gpio = pdata->dok; /* PULL_UPed Interrupt */ 244 ta_in = gpio_get_value(gpio) ? 0 : 1; 245 } else { 246 dev_err(dev, "When DC is wired, DOK should be wired as well.\n"); 247 return -EINVAL; 248 } 249 } 250 251 if (gpio_is_valid(pdata->dcm)) { 252 ret = devm_gpio_request(dev, pdata->dcm, data->psy_desc.name); 253 if (ret) { 254 dev_err(dev, 255 "Failed GPIO request for dcm: %d err %d\n", 256 pdata->dcm, ret); 257 return ret; 258 } 259 260 gpio = pdata->dcm; /* Output */ 261 gpio_set_value(gpio, ta_in); 262 } 263 264 if (pdata->usb_valid) { 265 if (gpio_is_valid(pdata->uok)) { 266 ret = devm_gpio_request(dev, pdata->uok, 267 data->psy_desc.name); 268 if (ret) { 269 dev_err(dev, 270 "Failed GPIO request for uok: %d err %d\n", 271 pdata->uok, ret); 272 return ret; 273 } 274 275 gpio = pdata->uok; 276 usb_in = gpio_get_value(gpio) ? 0 : 1; 277 } else { 278 dev_err(dev, "When USB is wired, UOK should be wired." 279 "as well.\n"); 280 return -EINVAL; 281 } 282 } 283 284 if (gpio_is_valid(pdata->cen)) { 285 ret = devm_gpio_request(dev, pdata->cen, data->psy_desc.name); 286 if (ret) { 287 dev_err(dev, 288 "Failed GPIO request for cen: %d err %d\n", 289 pdata->cen, ret); 290 return ret; 291 } 292 293 gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); 294 } 295 296 if (gpio_is_valid(pdata->chg)) { 297 ret = devm_gpio_request(dev, pdata->chg, data->psy_desc.name); 298 if (ret) { 299 dev_err(dev, 300 "Failed GPIO request for chg: %d err %d\n", 301 pdata->chg, ret); 302 return ret; 303 } 304 } 305 306 if (gpio_is_valid(pdata->flt)) { 307 ret = devm_gpio_request(dev, pdata->flt, data->psy_desc.name); 308 if (ret) { 309 dev_err(dev, 310 "Failed GPIO request for flt: %d err %d\n", 311 pdata->flt, ret); 312 return ret; 313 } 314 } 315 316 if (gpio_is_valid(pdata->usus)) { 317 ret = devm_gpio_request(dev, pdata->usus, data->psy_desc.name); 318 if (ret) { 319 dev_err(dev, 320 "Failed GPIO request for usus: %d err %d\n", 321 pdata->usus, ret); 322 return ret; 323 } 324 } 325 326 data->fault = false; 327 data->ta_in = ta_in; 328 data->usb_in = usb_in; 329 330 return 0; 331 } 332 333 static int max8903_probe(struct platform_device *pdev) 334 { 335 struct max8903_data *data; 336 struct device *dev = &pdev->dev; 337 struct max8903_pdata *pdata = pdev->dev.platform_data; 338 struct power_supply_config psy_cfg = {}; 339 int ret = 0; 340 341 data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL); 342 if (!data) 343 return -ENOMEM; 344 345 if (IS_ENABLED(CONFIG_OF) && !pdata && dev->of_node) 346 pdata = max8903_parse_dt_data(dev); 347 348 if (!pdata) { 349 dev_err(dev, "No platform data.\n"); 350 return -EINVAL; 351 } 352 353 pdev->dev.platform_data = pdata; 354 data->pdata = pdata; 355 data->dev = dev; 356 platform_set_drvdata(pdev, data); 357 358 if (pdata->dc_valid == false && pdata->usb_valid == false) { 359 dev_err(dev, "No valid power sources.\n"); 360 return -EINVAL; 361 } 362 363 ret = max8903_setup_gpios(pdev); 364 if (ret) 365 return ret; 366 367 data->psy_desc.name = "max8903_charger"; 368 data->psy_desc.type = (data->ta_in) ? POWER_SUPPLY_TYPE_MAINS : 369 ((data->usb_in) ? POWER_SUPPLY_TYPE_USB : 370 POWER_SUPPLY_TYPE_BATTERY); 371 data->psy_desc.get_property = max8903_get_property; 372 data->psy_desc.properties = max8903_charger_props; 373 data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props); 374 375 psy_cfg.of_node = dev->of_node; 376 psy_cfg.drv_data = data; 377 378 data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg); 379 if (IS_ERR(data->psy)) { 380 dev_err(dev, "failed: power supply register.\n"); 381 return PTR_ERR(data->psy); 382 } 383 384 if (pdata->dc_valid) { 385 ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok), 386 NULL, max8903_dcin, 387 IRQF_TRIGGER_FALLING | 388 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 389 "MAX8903 DC IN", data); 390 if (ret) { 391 dev_err(dev, "Cannot request irq %d for DC (%d)\n", 392 gpio_to_irq(pdata->dok), ret); 393 return ret; 394 } 395 } 396 397 if (pdata->usb_valid) { 398 ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok), 399 NULL, max8903_usbin, 400 IRQF_TRIGGER_FALLING | 401 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 402 "MAX8903 USB IN", data); 403 if (ret) { 404 dev_err(dev, "Cannot request irq %d for USB (%d)\n", 405 gpio_to_irq(pdata->uok), ret); 406 return ret; 407 } 408 } 409 410 if (gpio_is_valid(pdata->flt)) { 411 ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt), 412 NULL, max8903_fault, 413 IRQF_TRIGGER_FALLING | 414 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 415 "MAX8903 Fault", data); 416 if (ret) { 417 dev_err(dev, "Cannot request irq %d for Fault (%d)\n", 418 gpio_to_irq(pdata->flt), ret); 419 return ret; 420 } 421 } 422 423 return 0; 424 } 425 426 static const struct of_device_id max8903_match_ids[] = { 427 { .compatible = "maxim,max8903", }, 428 { /* sentinel */ } 429 }; 430 MODULE_DEVICE_TABLE(of, max8903_match_ids); 431 432 static struct platform_driver max8903_driver = { 433 .probe = max8903_probe, 434 .driver = { 435 .name = "max8903-charger", 436 .of_match_table = max8903_match_ids 437 }, 438 }; 439 440 module_platform_driver(max8903_driver); 441 442 MODULE_LICENSE("GPL"); 443 MODULE_DESCRIPTION("MAX8903 Charger Driver"); 444 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 445 MODULE_ALIAS("platform:max8903-charger"); 446