1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/device.h>
4 #include <linux/devm-helpers.h>
5 #include <linux/delay.h>
6 #include <linux/err.h>
7 #include <linux/extcon-provider.h>
8 #include <linux/i2c.h>
9 #include <linux/interrupt.h>
10 #include <linux/module.h>
11 #include <linux/pm.h>
12 #include <linux/regmap.h>
13
14 /* I2C addresses of MUIC internal registers */
15 #define MAX14526_DEVICE_ID 0x00
16 #define MAX14526_ID 0x02
17
18 /* CONTROL_1 register masks */
19 #define MAX14526_CONTROL_1 0x01
20 #define ID_2P2 BIT(6)
21 #define ID_620 BIT(5)
22 #define ID_200 BIT(4)
23 #define VLDO BIT(3)
24 #define SEMREN BIT(2)
25 #define ADC_EN BIT(1)
26 #define CP_EN BIT(0)
27
28 /* CONTROL_2 register masks */
29 #define MAX14526_CONTROL_2 0x02
30 #define INTPOL BIT(7)
31 #define INT_EN BIT(6)
32 #define MIC_LP BIT(5)
33 #define CP_AUD BIT(4)
34 #define CHG_TYPE BIT(1)
35 #define USB_DET_DIS BIT(0)
36
37 /* SW_CONTROL register masks */
38 #define MAX14526_SW_CONTROL 0x03
39 #define SW_DATA 0x00
40 #define SW_UART 0x01
41 #define SW_AUDIO 0x02
42 #define SW_OPEN 0x07
43
44 /* INT_STATUS register masks */
45 #define MAX14526_INT_STAT 0x04
46 #define CHGDET BIT(7)
47 #define MR_COMP BIT(6)
48 #define SENDEND BIT(5)
49 #define V_VBUS BIT(4)
50
51 /* STATUS register masks */
52 #define MAX14526_STATUS 0x05
53 #define CPORT BIT(7)
54 #define CHPORT BIT(6)
55 #define C1COMP BIT(0)
56
57 enum max14526_idno_resistance {
58 MAX14526_GND,
59 MAX14526_24KOHM,
60 MAX14526_56KOHM,
61 MAX14526_100KOHM,
62 MAX14526_130KOHM,
63 MAX14526_180KOHM,
64 MAX14526_240KOHM,
65 MAX14526_330KOHM,
66 MAX14526_430KOHM,
67 MAX14526_620KOHM,
68 MAX14526_910KOHM,
69 MAX14526_OPEN
70 };
71
72 enum max14526_field_idx {
73 VENDOR_ID, CHIP_REV, /* DEVID */
74 DM, DP, /* SW_CONTROL */
75 MAX14526_N_REGMAP_FIELDS
76 };
77
78 static const struct reg_field max14526_reg_field[MAX14526_N_REGMAP_FIELDS] = {
79 [VENDOR_ID] = REG_FIELD(MAX14526_DEVICE_ID, 4, 7),
80 [CHIP_REV] = REG_FIELD(MAX14526_DEVICE_ID, 0, 3),
81 [DM] = REG_FIELD(MAX14526_SW_CONTROL, 0, 2),
82 [DP] = REG_FIELD(MAX14526_SW_CONTROL, 3, 5),
83 };
84
85 struct max14526_data {
86 struct i2c_client *client;
87 struct extcon_dev *edev;
88
89 struct regmap *regmap;
90 struct regmap_field *rfield[MAX14526_N_REGMAP_FIELDS];
91
92 int last_state;
93 int cable;
94 };
95
96 enum max14526_muic_modes {
97 MAX14526_OTG = MAX14526_GND, /* no power */
98 MAX14526_MHL = MAX14526_56KOHM, /* no power */
99 MAX14526_OTG_Y = MAX14526_GND | V_VBUS,
100 MAX14526_MHL_CHG = MAX14526_GND | V_VBUS | CHGDET,
101 MAX14526_NONE = MAX14526_OPEN,
102 MAX14526_USB = MAX14526_OPEN | V_VBUS,
103 MAX14526_CHG = MAX14526_OPEN | V_VBUS | CHGDET,
104 };
105
106 static const unsigned int max14526_extcon_cable[] = {
107 EXTCON_USB,
108 EXTCON_USB_HOST,
109 EXTCON_CHG_USB_FAST,
110 EXTCON_DISP_MHL,
111 EXTCON_NONE,
112 };
113
max14526_ap_usb_mode(struct max14526_data * priv)114 static int max14526_ap_usb_mode(struct max14526_data *priv)
115 {
116 struct device *dev = &priv->client->dev;
117 int ret;
118
119 /* Enable USB Path */
120 ret = regmap_field_write(priv->rfield[DM], SW_DATA);
121 if (ret)
122 return ret;
123
124 ret = regmap_field_write(priv->rfield[DP], SW_DATA);
125 if (ret)
126 return ret;
127
128 /* Enable 200K, Charger Pump and ADC */
129 ret = regmap_write(priv->regmap, MAX14526_CONTROL_1,
130 ID_200 | ADC_EN | CP_EN);
131 if (ret)
132 return ret;
133
134 dev_dbg(dev, "AP USB mode set\n");
135
136 return 0;
137 }
138
max14526_interrupt(int irq,void * dev_id)139 static irqreturn_t max14526_interrupt(int irq, void *dev_id)
140 {
141 struct max14526_data *priv = dev_id;
142 struct device *dev = &priv->client->dev;
143 int state, ret;
144
145 /*
146 * Upon an MUIC IRQ (MUIC_INT_N falls), wait at least 70ms
147 * before reading INT_STAT and STATUS. After the reads,
148 * MUIC_INT_N returns to high (but the INT_STAT and STATUS
149 * contents will be held).
150 */
151 msleep(100);
152
153 ret = regmap_read(priv->regmap, MAX14526_INT_STAT, &state);
154 if (ret)
155 dev_err(dev, "failed to read MUIC state %d\n", ret);
156
157 if (state == priv->last_state)
158 return IRQ_HANDLED;
159
160 /* Detach previous device */
161 extcon_set_state_sync(priv->edev, priv->cable, false);
162
163 switch (state) {
164 case MAX14526_USB:
165 priv->cable = EXTCON_USB;
166 break;
167
168 case MAX14526_CHG:
169 priv->cable = EXTCON_CHG_USB_FAST;
170 break;
171
172 case MAX14526_OTG:
173 case MAX14526_OTG_Y:
174 priv->cable = EXTCON_USB_HOST;
175 break;
176
177 case MAX14526_MHL:
178 case MAX14526_MHL_CHG:
179 priv->cable = EXTCON_DISP_MHL;
180 break;
181
182 case MAX14526_NONE:
183 default:
184 priv->cable = EXTCON_NONE;
185 break;
186 }
187
188 extcon_set_state_sync(priv->edev, priv->cable, true);
189
190 priv->last_state = state;
191
192 return IRQ_HANDLED;
193 }
194
195 static const struct regmap_config max14526_regmap_config = {
196 .reg_bits = 8,
197 .val_bits = 8,
198 .max_register = MAX14526_STATUS,
199 };
200
max14526_probe(struct i2c_client * client)201 static int max14526_probe(struct i2c_client *client)
202 {
203 struct device *dev = &client->dev;
204 struct max14526_data *priv;
205 int ret, dev_id, rev, i;
206
207 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
208 if (!priv)
209 return -ENOMEM;
210
211 priv->client = client;
212 i2c_set_clientdata(client, priv);
213
214 priv->regmap = devm_regmap_init_i2c(client, &max14526_regmap_config);
215 if (IS_ERR(priv->regmap))
216 return dev_err_probe(dev, PTR_ERR(priv->regmap), "cannot allocate regmap\n");
217
218 for (i = 0; i < MAX14526_N_REGMAP_FIELDS; i++) {
219 priv->rfield[i] = devm_regmap_field_alloc(dev, priv->regmap,
220 max14526_reg_field[i]);
221 if (IS_ERR(priv->rfield[i]))
222 return dev_err_probe(dev, PTR_ERR(priv->rfield[i]),
223 "cannot allocate regmap field\n");
224 }
225
226 /* Detect if MUIC version is supported */
227 ret = regmap_field_read(priv->rfield[VENDOR_ID], &dev_id);
228 if (ret)
229 return dev_err_probe(dev, ret, "failed to read MUIC ID\n");
230
231 regmap_field_read(priv->rfield[CHIP_REV], &rev);
232
233 if (dev_id == MAX14526_ID)
234 dev_info(dev, "detected MAX14526 MUIC with id 0x%x, rev 0x%x\n", dev_id, rev);
235 else
236 dev_err_probe(dev, -EINVAL, "MUIC vendor id 0x%X is not recognized\n", dev_id);
237
238 priv->edev = devm_extcon_dev_allocate(dev, max14526_extcon_cable);
239 if (IS_ERR(priv->edev))
240 return dev_err_probe(dev, (IS_ERR(priv->edev)),
241 "failed to allocate extcon device\n");
242
243 ret = devm_extcon_dev_register(dev, priv->edev);
244 if (ret < 0)
245 return dev_err_probe(dev, ret, "failed to register extcon device\n");
246
247 ret = max14526_ap_usb_mode(priv);
248 if (ret < 0)
249 return dev_err_probe(dev, ret, "failed to set AP USB mode\n");
250
251 regmap_write_bits(priv->regmap, MAX14526_CONTROL_2, INT_EN, INT_EN);
252 regmap_write_bits(priv->regmap, MAX14526_CONTROL_2, USB_DET_DIS, (u32)~USB_DET_DIS);
253
254 ret = devm_request_threaded_irq(dev, client->irq, NULL, &max14526_interrupt,
255 IRQF_ONESHOT | IRQF_SHARED, client->name, priv);
256 if (ret)
257 return dev_err_probe(dev, ret, "failed to register IRQ\n");
258
259 irq_wake_thread(client->irq, priv);
260
261 return 0;
262 }
263
max14526_resume(struct device * dev)264 static int max14526_resume(struct device *dev)
265 {
266 struct i2c_client *client = to_i2c_client(dev);
267 struct max14526_data *priv = i2c_get_clientdata(client);
268
269 irq_wake_thread(client->irq, priv);
270
271 return 0;
272 }
273
274 static DEFINE_SIMPLE_DEV_PM_OPS(max14526_pm_ops, NULL, max14526_resume);
275
276 static const struct of_device_id max14526_match[] = {
277 { .compatible = "maxim,max14526" },
278 { /* sentinel */ }
279 };
280 MODULE_DEVICE_TABLE(of, max14526_match);
281
282 static const struct i2c_device_id max14526_id[] = {
283 { "max14526" },
284 { }
285 };
286 MODULE_DEVICE_TABLE(i2c, max14526_id);
287
288 static struct i2c_driver max14526_driver = {
289 .driver = {
290 .name = "max14526",
291 .of_match_table = max14526_match,
292 .pm = &max14526_pm_ops,
293 },
294 .probe = max14526_probe,
295 .id_table = max14526_id,
296 };
297 module_i2c_driver(max14526_driver);
298
299 MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
300 MODULE_DESCRIPTION("MAX14526 extcon driver to support MUIC");
301 MODULE_LICENSE("GPL");
302