0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/gpio/consumer.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/slab.h>
0015 #include <linux/power_supply.h>
0016 #include <linux/platform_device.h>
0017
0018 struct max8903_data {
0019 struct device *dev;
0020 struct power_supply *psy;
0021 struct power_supply_desc psy_desc;
0022
0023
0024
0025
0026
0027
0028 struct gpio_desc *cen;
0029 struct gpio_desc *dok;
0030 struct gpio_desc *uok;
0031 struct gpio_desc *chg;
0032 struct gpio_desc *flt;
0033 struct gpio_desc *dcm;
0034 struct gpio_desc *usus;
0035 bool fault;
0036 bool usb_in;
0037 bool ta_in;
0038 };
0039
0040 static enum power_supply_property max8903_charger_props[] = {
0041 POWER_SUPPLY_PROP_STATUS,
0042 POWER_SUPPLY_PROP_ONLINE,
0043 POWER_SUPPLY_PROP_HEALTH,
0044 };
0045
0046 static int max8903_get_property(struct power_supply *psy,
0047 enum power_supply_property psp,
0048 union power_supply_propval *val)
0049 {
0050 struct max8903_data *data = power_supply_get_drvdata(psy);
0051
0052 switch (psp) {
0053 case POWER_SUPPLY_PROP_STATUS:
0054 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
0055 if (data->chg) {
0056 if (gpiod_get_value(data->chg))
0057
0058 val->intval = POWER_SUPPLY_STATUS_CHARGING;
0059 else if (data->usb_in || data->ta_in)
0060 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
0061 else
0062 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
0063 }
0064 break;
0065 case POWER_SUPPLY_PROP_ONLINE:
0066 val->intval = 0;
0067 if (data->usb_in || data->ta_in)
0068 val->intval = 1;
0069 break;
0070 case POWER_SUPPLY_PROP_HEALTH:
0071 val->intval = POWER_SUPPLY_HEALTH_GOOD;
0072 if (data->fault)
0073 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
0074 break;
0075 default:
0076 return -EINVAL;
0077 }
0078
0079 return 0;
0080 }
0081
0082 static irqreturn_t max8903_dcin(int irq, void *_data)
0083 {
0084 struct max8903_data *data = _data;
0085 bool ta_in;
0086 enum power_supply_type old_type;
0087
0088
0089
0090
0091
0092
0093
0094
0095 ta_in = gpiod_get_value(data->dok);
0096
0097 if (ta_in == data->ta_in)
0098 return IRQ_HANDLED;
0099
0100 data->ta_in = ta_in;
0101
0102
0103 if (data->dcm)
0104 gpiod_set_value(data->dcm, ta_in);
0105
0106
0107 if (data->cen) {
0108 int val;
0109
0110 if (ta_in)
0111
0112 val = 1;
0113 else if (data->usb_in)
0114
0115 val = 1;
0116 else
0117
0118 val = 0;
0119
0120 gpiod_set_value(data->cen, val);
0121 }
0122
0123 dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
0124 "Connected" : "Disconnected");
0125
0126 old_type = data->psy_desc.type;
0127
0128 if (data->ta_in)
0129 data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
0130 else if (data->usb_in)
0131 data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
0132 else
0133 data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
0134
0135 if (old_type != data->psy_desc.type)
0136 power_supply_changed(data->psy);
0137
0138 return IRQ_HANDLED;
0139 }
0140
0141 static irqreturn_t max8903_usbin(int irq, void *_data)
0142 {
0143 struct max8903_data *data = _data;
0144 bool usb_in;
0145 enum power_supply_type old_type;
0146
0147
0148
0149
0150
0151
0152
0153
0154 usb_in = gpiod_get_value(data->uok);
0155
0156 if (usb_in == data->usb_in)
0157 return IRQ_HANDLED;
0158
0159 data->usb_in = usb_in;
0160
0161
0162
0163
0164 if (data->cen) {
0165 int val;
0166
0167 if (usb_in)
0168
0169 val = 1;
0170 else if (data->ta_in)
0171
0172 val = 1;
0173 else
0174
0175 val = 0;
0176
0177 gpiod_set_value(data->cen, val);
0178 }
0179
0180 dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
0181 "Connected" : "Disconnected");
0182
0183 old_type = data->psy_desc.type;
0184
0185 if (data->ta_in)
0186 data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
0187 else if (data->usb_in)
0188 data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
0189 else
0190 data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
0191
0192 if (old_type != data->psy_desc.type)
0193 power_supply_changed(data->psy);
0194
0195 return IRQ_HANDLED;
0196 }
0197
0198 static irqreturn_t max8903_fault(int irq, void *_data)
0199 {
0200 struct max8903_data *data = _data;
0201 bool fault;
0202
0203
0204
0205
0206
0207
0208
0209
0210 fault = gpiod_get_value(data->flt);
0211
0212 if (fault == data->fault)
0213 return IRQ_HANDLED;
0214
0215 data->fault = fault;
0216
0217 if (fault)
0218 dev_err(data->dev, "Charger suffers a fault and stops.\n");
0219 else
0220 dev_err(data->dev, "Charger recovered from a fault.\n");
0221
0222 return IRQ_HANDLED;
0223 }
0224
0225 static int max8903_setup_gpios(struct platform_device *pdev)
0226 {
0227 struct max8903_data *data = platform_get_drvdata(pdev);
0228 struct device *dev = &pdev->dev;
0229 bool ta_in = false;
0230 bool usb_in = false;
0231 enum gpiod_flags flags;
0232
0233 data->dok = devm_gpiod_get_optional(dev, "dok", GPIOD_IN);
0234 if (IS_ERR(data->dok))
0235 return dev_err_probe(dev, PTR_ERR(data->dok),
0236 "failed to get DOK GPIO");
0237 if (data->dok) {
0238 gpiod_set_consumer_name(data->dok, data->psy_desc.name);
0239
0240
0241
0242
0243
0244
0245 ta_in = gpiod_get_value(data->dok);
0246 }
0247
0248 data->uok = devm_gpiod_get_optional(dev, "uok", GPIOD_IN);
0249 if (IS_ERR(data->uok))
0250 return dev_err_probe(dev, PTR_ERR(data->uok),
0251 "failed to get UOK GPIO");
0252 if (data->uok) {
0253 gpiod_set_consumer_name(data->uok, data->psy_desc.name);
0254
0255
0256
0257
0258
0259
0260 usb_in = gpiod_get_value(data->uok);
0261 }
0262
0263
0264 if (!data->dok && !data->uok) {
0265 dev_err(dev, "no valid power source\n");
0266 return -EINVAL;
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 flags = (ta_in || usb_in) ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
0278
0279
0280
0281
0282 data->cen = devm_gpiod_get(dev, "cen", flags);
0283 if (IS_ERR(data->cen))
0284 return dev_err_probe(dev, PTR_ERR(data->cen),
0285 "failed to get CEN GPIO");
0286 gpiod_set_consumer_name(data->cen, data->psy_desc.name);
0287
0288
0289
0290
0291
0292
0293
0294
0295 flags = ta_in ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
0296 data->dcm = devm_gpiod_get_optional(dev, "dcm", flags);
0297 if (IS_ERR(data->dcm))
0298 return dev_err_probe(dev, PTR_ERR(data->dcm),
0299 "failed to get DCM GPIO");
0300 gpiod_set_consumer_name(data->dcm, data->psy_desc.name);
0301
0302 data->chg = devm_gpiod_get_optional(dev, "chg", GPIOD_IN);
0303 if (IS_ERR(data->chg))
0304 return dev_err_probe(dev, PTR_ERR(data->chg),
0305 "failed to get CHG GPIO");
0306 gpiod_set_consumer_name(data->chg, data->psy_desc.name);
0307
0308 data->flt = devm_gpiod_get_optional(dev, "flt", GPIOD_IN);
0309 if (IS_ERR(data->flt))
0310 return dev_err_probe(dev, PTR_ERR(data->flt),
0311 "failed to get FLT GPIO");
0312 gpiod_set_consumer_name(data->flt, data->psy_desc.name);
0313
0314 data->usus = devm_gpiod_get_optional(dev, "usus", GPIOD_IN);
0315 if (IS_ERR(data->usus))
0316 return dev_err_probe(dev, PTR_ERR(data->usus),
0317 "failed to get USUS GPIO");
0318 gpiod_set_consumer_name(data->usus, data->psy_desc.name);
0319
0320 data->fault = false;
0321 data->ta_in = ta_in;
0322 data->usb_in = usb_in;
0323
0324 return 0;
0325 }
0326
0327 static int max8903_probe(struct platform_device *pdev)
0328 {
0329 struct max8903_data *data;
0330 struct device *dev = &pdev->dev;
0331 struct power_supply_config psy_cfg = {};
0332 int ret = 0;
0333
0334 data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
0335 if (!data)
0336 return -ENOMEM;
0337
0338 data->dev = dev;
0339 platform_set_drvdata(pdev, data);
0340
0341 ret = max8903_setup_gpios(pdev);
0342 if (ret)
0343 return ret;
0344
0345 data->psy_desc.name = "max8903_charger";
0346 data->psy_desc.type = (data->ta_in) ? POWER_SUPPLY_TYPE_MAINS :
0347 ((data->usb_in) ? POWER_SUPPLY_TYPE_USB :
0348 POWER_SUPPLY_TYPE_BATTERY);
0349 data->psy_desc.get_property = max8903_get_property;
0350 data->psy_desc.properties = max8903_charger_props;
0351 data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);
0352
0353 psy_cfg.of_node = dev->of_node;
0354 psy_cfg.drv_data = data;
0355
0356 data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
0357 if (IS_ERR(data->psy)) {
0358 dev_err(dev, "failed: power supply register.\n");
0359 return PTR_ERR(data->psy);
0360 }
0361
0362 if (data->dok) {
0363 ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->dok),
0364 NULL, max8903_dcin,
0365 IRQF_TRIGGER_FALLING |
0366 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0367 "MAX8903 DC IN", data);
0368 if (ret) {
0369 dev_err(dev, "Cannot request irq %d for DC (%d)\n",
0370 gpiod_to_irq(data->dok), ret);
0371 return ret;
0372 }
0373 }
0374
0375 if (data->uok) {
0376 ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->uok),
0377 NULL, max8903_usbin,
0378 IRQF_TRIGGER_FALLING |
0379 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0380 "MAX8903 USB IN", data);
0381 if (ret) {
0382 dev_err(dev, "Cannot request irq %d for USB (%d)\n",
0383 gpiod_to_irq(data->uok), ret);
0384 return ret;
0385 }
0386 }
0387
0388 if (data->flt) {
0389 ret = devm_request_threaded_irq(dev, gpiod_to_irq(data->flt),
0390 NULL, max8903_fault,
0391 IRQF_TRIGGER_FALLING |
0392 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0393 "MAX8903 Fault", data);
0394 if (ret) {
0395 dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
0396 gpiod_to_irq(data->flt), ret);
0397 return ret;
0398 }
0399 }
0400
0401 return 0;
0402 }
0403
0404 static const struct of_device_id max8903_match_ids[] = {
0405 { .compatible = "maxim,max8903", },
0406 { }
0407 };
0408 MODULE_DEVICE_TABLE(of, max8903_match_ids);
0409
0410 static struct platform_driver max8903_driver = {
0411 .probe = max8903_probe,
0412 .driver = {
0413 .name = "max8903-charger",
0414 .of_match_table = max8903_match_ids
0415 },
0416 };
0417
0418 module_platform_driver(max8903_driver);
0419
0420 MODULE_LICENSE("GPL");
0421 MODULE_DESCRIPTION("MAX8903 Charger Driver");
0422 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
0423 MODULE_ALIAS("platform:max8903-charger");