0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/err.h>
0009 #include <linux/extcon.h>
0010 #include <linux/module.h>
0011 #include <linux/slab.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/power_supply.h>
0014 #include <linux/mfd/max8997.h>
0015 #include <linux/mfd/max8997-private.h>
0016 #include <linux/regulator/consumer.h>
0017 #include <linux/devm-helpers.h>
0018
0019
0020 #define DCINOK_SHIFT 1
0021 #define DCINOK_MASK (1 << DCINOK_SHIFT)
0022 #define DETBAT_SHIFT 2
0023 #define DETBAT_MASK (1 << DETBAT_SHIFT)
0024
0025
0026 #define TFCH_SHIFT 4
0027 #define TFCH_MASK (7 << TFCH_SHIFT)
0028
0029
0030 #define ITOPOFF_SHIFT 0
0031 #define ITOPOFF_MASK (0xF << ITOPOFF_SHIFT)
0032
0033 struct charger_data {
0034 struct device *dev;
0035 struct max8997_dev *iodev;
0036 struct power_supply *battery;
0037 struct regulator *reg;
0038 struct extcon_dev *edev;
0039 struct notifier_block extcon_nb;
0040 struct work_struct extcon_work;
0041 };
0042
0043 static enum power_supply_property max8997_battery_props[] = {
0044 POWER_SUPPLY_PROP_STATUS,
0045 POWER_SUPPLY_PROP_PRESENT,
0046 POWER_SUPPLY_PROP_ONLINE,
0047 };
0048
0049
0050 static int max8997_battery_get_property(struct power_supply *psy,
0051 enum power_supply_property psp,
0052 union power_supply_propval *val)
0053 {
0054 struct charger_data *charger = power_supply_get_drvdata(psy);
0055 struct i2c_client *i2c = charger->iodev->i2c;
0056 int ret;
0057 u8 reg;
0058
0059 switch (psp) {
0060 case POWER_SUPPLY_PROP_STATUS:
0061 val->intval = 0;
0062 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
0063 if (ret)
0064 return ret;
0065 if ((reg & (1 << 0)) == 0x1)
0066 val->intval = POWER_SUPPLY_STATUS_FULL;
0067 else if ((reg & DCINOK_MASK))
0068 val->intval = POWER_SUPPLY_STATUS_CHARGING;
0069 else
0070 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
0071
0072 break;
0073 case POWER_SUPPLY_PROP_PRESENT:
0074 val->intval = 0;
0075 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
0076 if (ret)
0077 return ret;
0078 if ((reg & DETBAT_MASK) == 0x0)
0079 val->intval = 1;
0080
0081 break;
0082 case POWER_SUPPLY_PROP_ONLINE:
0083 val->intval = 0;
0084 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®);
0085 if (ret)
0086 return ret;
0087 if (reg & DCINOK_MASK)
0088 val->intval = 1;
0089
0090 break;
0091 default:
0092 return -EINVAL;
0093 }
0094
0095 return 0;
0096 }
0097
0098 static void max8997_battery_extcon_evt_worker(struct work_struct *work)
0099 {
0100 struct charger_data *charger =
0101 container_of(work, struct charger_data, extcon_work);
0102 struct extcon_dev *edev = charger->edev;
0103 int current_limit;
0104
0105 if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
0106 dev_dbg(charger->dev, "USB SDP charger is connected\n");
0107 current_limit = 450000;
0108 } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
0109 dev_dbg(charger->dev, "USB DCP charger is connected\n");
0110 current_limit = 650000;
0111 } else if (extcon_get_state(edev, EXTCON_CHG_USB_FAST) > 0) {
0112 dev_dbg(charger->dev, "USB FAST charger is connected\n");
0113 current_limit = 650000;
0114 } else if (extcon_get_state(edev, EXTCON_CHG_USB_SLOW) > 0) {
0115 dev_dbg(charger->dev, "USB SLOW charger is connected\n");
0116 current_limit = 650000;
0117 } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
0118 dev_dbg(charger->dev, "USB CDP charger is connected\n");
0119 current_limit = 650000;
0120 } else {
0121 dev_dbg(charger->dev, "USB charger is disconnected\n");
0122 current_limit = -1;
0123 }
0124
0125 if (current_limit > 0) {
0126 int ret = regulator_set_current_limit(charger->reg, current_limit, current_limit);
0127
0128 if (ret) {
0129 dev_err(charger->dev, "failed to set current limit: %d\n", ret);
0130 return;
0131 }
0132 ret = regulator_enable(charger->reg);
0133 if (ret)
0134 dev_err(charger->dev, "failed to enable regulator: %d\n", ret);
0135 } else {
0136 int ret = regulator_disable(charger->reg);
0137
0138 if (ret)
0139 dev_err(charger->dev, "failed to disable regulator: %d\n", ret);
0140 }
0141 }
0142
0143 static int max8997_battery_extcon_evt(struct notifier_block *nb,
0144 unsigned long event, void *param)
0145 {
0146 struct charger_data *charger =
0147 container_of(nb, struct charger_data, extcon_nb);
0148 schedule_work(&charger->extcon_work);
0149 return NOTIFY_OK;
0150 }
0151
0152 static const struct power_supply_desc max8997_battery_desc = {
0153 .name = "max8997_pmic",
0154 .type = POWER_SUPPLY_TYPE_BATTERY,
0155 .get_property = max8997_battery_get_property,
0156 .properties = max8997_battery_props,
0157 .num_properties = ARRAY_SIZE(max8997_battery_props),
0158 };
0159
0160 static int max8997_battery_probe(struct platform_device *pdev)
0161 {
0162 int ret = 0;
0163 struct charger_data *charger;
0164 struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
0165 struct device_node *np = pdev->dev.of_node;
0166 struct i2c_client *i2c = iodev->i2c;
0167 struct max8997_platform_data *pdata = iodev->pdata;
0168 struct power_supply_config psy_cfg = {};
0169
0170 if (!pdata) {
0171 dev_err(&pdev->dev, "No platform data supplied.\n");
0172 return -EINVAL;
0173 }
0174
0175 if (pdata->eoc_mA) {
0176 int val = (pdata->eoc_mA - 50) / 10;
0177 if (val < 0)
0178 val = 0;
0179 if (val > 0xf)
0180 val = 0xf;
0181
0182 ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL5,
0183 val << ITOPOFF_SHIFT, ITOPOFF_MASK);
0184 if (ret < 0) {
0185 dev_err(&pdev->dev, "Cannot use i2c bus.\n");
0186 return ret;
0187 }
0188 }
0189 switch (pdata->timeout) {
0190 case 5:
0191 ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1,
0192 0x2 << TFCH_SHIFT, TFCH_MASK);
0193 break;
0194 case 6:
0195 ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1,
0196 0x3 << TFCH_SHIFT, TFCH_MASK);
0197 break;
0198 case 7:
0199 ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1,
0200 0x4 << TFCH_SHIFT, TFCH_MASK);
0201 break;
0202 case 0:
0203 ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1,
0204 0x7 << TFCH_SHIFT, TFCH_MASK);
0205 break;
0206 default:
0207 dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
0208 pdata->timeout);
0209 return -EINVAL;
0210 }
0211 if (ret < 0) {
0212 dev_err(&pdev->dev, "Cannot use i2c bus.\n");
0213 return ret;
0214 }
0215
0216 charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
0217 if (!charger)
0218 return -ENOMEM;
0219
0220 platform_set_drvdata(pdev, charger);
0221
0222 charger->dev = &pdev->dev;
0223 charger->iodev = iodev;
0224
0225 psy_cfg.drv_data = charger;
0226
0227 charger->battery = devm_power_supply_register(&pdev->dev,
0228 &max8997_battery_desc,
0229 &psy_cfg);
0230 if (IS_ERR(charger->battery)) {
0231 dev_err(&pdev->dev, "failed: power supply register\n");
0232 return PTR_ERR(charger->battery);
0233 }
0234
0235
0236 pdev->dev.of_node = iodev->dev->of_node;
0237 charger->reg = devm_regulator_get_optional(&pdev->dev, "charger");
0238 pdev->dev.of_node = np;
0239 if (IS_ERR(charger->reg)) {
0240 if (PTR_ERR(charger->reg) == -EPROBE_DEFER)
0241 return -EPROBE_DEFER;
0242 dev_info(&pdev->dev, "couldn't get charger regulator\n");
0243 }
0244 charger->edev = extcon_get_extcon_dev("max8997-muic");
0245 if (IS_ERR(charger->edev)) {
0246 dev_err_probe(charger->dev, PTR_ERR(charger->edev),
0247 "couldn't get extcon device: max8997-muic\n");
0248 return PTR_ERR(charger->edev);
0249 }
0250
0251 if (!IS_ERR(charger->reg) && !IS_ERR_OR_NULL(charger->edev)) {
0252 ret = devm_work_autocancel(&pdev->dev, &charger->extcon_work,
0253 max8997_battery_extcon_evt_worker);
0254 if (ret) {
0255 dev_err(&pdev->dev, "failed to add extcon evt stop action: %d\n", ret);
0256 return ret;
0257 }
0258 charger->extcon_nb.notifier_call = max8997_battery_extcon_evt;
0259 ret = devm_extcon_register_notifier_all(&pdev->dev, charger->edev,
0260 &charger->extcon_nb);
0261 if (ret) {
0262 dev_err(&pdev->dev, "failed to register extcon notifier\n");
0263 return ret;
0264 }
0265 }
0266
0267 return 0;
0268 }
0269
0270 static const struct platform_device_id max8997_battery_id[] = {
0271 { "max8997-battery", 0 },
0272 { }
0273 };
0274 MODULE_DEVICE_TABLE(platform, max8997_battery_id);
0275
0276 static struct platform_driver max8997_battery_driver = {
0277 .driver = {
0278 .name = "max8997-battery",
0279 },
0280 .probe = max8997_battery_probe,
0281 .id_table = max8997_battery_id,
0282 };
0283 module_platform_driver(max8997_battery_driver);
0284
0285 MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver");
0286 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
0287 MODULE_LICENSE("GPL");