Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / power / supply / max8997_charger.c
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // max8997_charger.c - Power supply consumer driver for the Maxim 8997/8966
4 //
5 //  Copyright (C) 2011 Samsung Electronics
6 //  MyungJoo Ham <myungjoo.ham@samsung.com>
7
8 #include <linux/err.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/platform_device.h>
12 #include <linux/power_supply.h>
13 #include <linux/mfd/max8997.h>
14 #include <linux/mfd/max8997-private.h>
15
16 struct charger_data {
17         struct device *dev;
18         struct max8997_dev *iodev;
19         struct power_supply *battery;
20 };
21
22 static enum power_supply_property max8997_battery_props[] = {
23         POWER_SUPPLY_PROP_STATUS, /* "FULL" or "NOT FULL" only. */
24         POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
25         POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
26 };
27
28 /* Note that the charger control is done by a current regulator "CHARGER" */
29 static int max8997_battery_get_property(struct power_supply *psy,
30                 enum power_supply_property psp,
31                 union power_supply_propval *val)
32 {
33         struct charger_data *charger = power_supply_get_drvdata(psy);
34         struct i2c_client *i2c = charger->iodev->i2c;
35         int ret;
36         u8 reg;
37
38         switch (psp) {
39         case POWER_SUPPLY_PROP_STATUS:
40                 val->intval = 0;
41                 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
42                 if (ret)
43                         return ret;
44                 if ((reg & (1 << 0)) == 0x1)
45                         val->intval = POWER_SUPPLY_STATUS_FULL;
46
47                 break;
48         case POWER_SUPPLY_PROP_PRESENT:
49                 val->intval = 0;
50                 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
51                 if (ret)
52                         return ret;
53                 if ((reg & (1 << 2)) == 0x0)
54                         val->intval = 1;
55
56                 break;
57         case POWER_SUPPLY_PROP_ONLINE:
58                 val->intval = 0;
59                 ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
60                 if (ret)
61                         return ret;
62                 /* DCINOK */
63                 if (reg & (1 << 1))
64                         val->intval = 1;
65
66                 break;
67         default:
68                 return -EINVAL;
69         }
70
71         return 0;
72 }
73
74 static const struct power_supply_desc max8997_battery_desc = {
75         .name           = "max8997_pmic",
76         .type           = POWER_SUPPLY_TYPE_BATTERY,
77         .get_property   = max8997_battery_get_property,
78         .properties     = max8997_battery_props,
79         .num_properties = ARRAY_SIZE(max8997_battery_props),
80 };
81
82 static int max8997_battery_probe(struct platform_device *pdev)
83 {
84         int ret = 0;
85         struct charger_data *charger;
86         struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
87         struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
88         struct power_supply_config psy_cfg = {};
89
90         if (!pdata)
91                 return -EINVAL;
92
93         if (pdata->eoc_mA) {
94                 int val = (pdata->eoc_mA - 50) / 10;
95                 if (val < 0)
96                         val = 0;
97                 if (val > 0xf)
98                         val = 0xf;
99
100                 ret = max8997_update_reg(iodev->i2c,
101                                 MAX8997_REG_MBCCTRL5, val, 0xf);
102                 if (ret < 0) {
103                         dev_err(&pdev->dev, "Cannot use i2c bus.\n");
104                         return ret;
105                 }
106         }
107
108         switch (pdata->timeout) {
109         case 5:
110                 ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
111                                 0x2 << 4, 0x7 << 4);
112                 break;
113         case 6:
114                 ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
115                                 0x3 << 4, 0x7 << 4);
116                 break;
117         case 7:
118                 ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
119                                 0x4 << 4, 0x7 << 4);
120                 break;
121         case 0:
122                 ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
123                                 0x7 << 4, 0x7 << 4);
124                 break;
125         default:
126                 dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
127                                 pdata->timeout);
128                 return -EINVAL;
129         }
130         if (ret < 0) {
131                 dev_err(&pdev->dev, "Cannot use i2c bus.\n");
132                 return ret;
133         }
134
135         charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
136         if (!charger)
137                 return -ENOMEM;
138
139         platform_set_drvdata(pdev, charger);
140
141
142         charger->dev = &pdev->dev;
143         charger->iodev = iodev;
144
145         psy_cfg.drv_data = charger;
146
147         charger->battery = devm_power_supply_register(&pdev->dev,
148                                                  &max8997_battery_desc,
149                                                  &psy_cfg);
150         if (IS_ERR(charger->battery)) {
151                 dev_err(&pdev->dev, "failed: power supply register\n");
152                 return PTR_ERR(charger->battery);
153         }
154
155         return 0;
156 }
157
158 static const struct platform_device_id max8997_battery_id[] = {
159         { "max8997-battery", 0 },
160         { }
161 };
162 MODULE_DEVICE_TABLE(platform, max8997_battery_id);
163
164 static struct platform_driver max8997_battery_driver = {
165         .driver = {
166                 .name = "max8997-battery",
167         },
168         .probe = max8997_battery_probe,
169         .id_table = max8997_battery_id,
170 };
171
172 static int __init max8997_battery_init(void)
173 {
174         return platform_driver_register(&max8997_battery_driver);
175 }
176 subsys_initcall(max8997_battery_init);
177
178 static void __exit max8997_battery_cleanup(void)
179 {
180         platform_driver_unregister(&max8997_battery_driver);
181 }
182 module_exit(max8997_battery_cleanup);
183
184 MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver");
185 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
186 MODULE_LICENSE("GPL");