GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / extcon / extcon-ptn5150.c
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // extcon-ptn5150.c - PTN5150 CC logic extcon driver to support USB detection
4 //
5 // Based on extcon-sm5502.c driver
6 // Copyright (c) 2018-2019 by Vijai Kumar K
7 // Author: Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>
8 // Copyright (c) 2020 Krzysztof Kozlowski <krzk@kernel.org>
9
10 #include <linux/bitfield.h>
11 #include <linux/err.h>
12 #include <linux/i2c.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17 #include <linux/slab.h>
18 #include <linux/extcon-provider.h>
19 #include <linux/gpio/consumer.h>
20 #include <linux/usb/role.h>
21
22 /* PTN5150 registers */
23 #define PTN5150_REG_DEVICE_ID                   0x01
24 #define PTN5150_REG_CONTROL                     0x02
25 #define PTN5150_REG_INT_STATUS                  0x03
26 #define PTN5150_REG_CC_STATUS                   0x04
27 #define PTN5150_REG_CON_DET                     0x09
28 #define PTN5150_REG_VCONN_STATUS                0x0a
29 #define PTN5150_REG_RESET                       0x0b
30 #define PTN5150_REG_INT_MASK                    0x18
31 #define PTN5150_REG_INT_REG_STATUS              0x19
32 #define PTN5150_REG_END                         PTN5150_REG_INT_REG_STATUS
33
34 #define PTN5150_DFP_ATTACHED                    0x1
35 #define PTN5150_UFP_ATTACHED                    0x2
36
37 /* Define PTN5150 MASK/SHIFT constant */
38 #define PTN5150_REG_DEVICE_ID_VERSION           GENMASK(7, 3)
39 #define PTN5150_REG_DEVICE_ID_VENDOR            GENMASK(2, 0)
40
41 #define PTN5150_REG_CC_PORT_ATTACHMENT          GENMASK(4, 2)
42 #define PTN5150_REG_CC_VBUS_DETECTION           BIT(7)
43 #define PTN5150_REG_INT_CABLE_ATTACH_MASK       BIT(0)
44 #define PTN5150_REG_INT_CABLE_DETACH_MASK       BIT(1)
45
46 struct ptn5150_info {
47         struct device *dev;
48         struct extcon_dev *edev;
49         struct i2c_client *i2c;
50         struct regmap *regmap;
51         struct gpio_desc *int_gpiod;
52         struct gpio_desc *vbus_gpiod;
53         int irq;
54         struct work_struct irq_work;
55         struct mutex mutex;
56         struct usb_role_switch *role_sw;
57 };
58
59 /* List of detectable cables */
60 static const unsigned int ptn5150_extcon_cable[] = {
61         EXTCON_USB,
62         EXTCON_USB_HOST,
63         EXTCON_NONE,
64 };
65
66 static const struct regmap_config ptn5150_regmap_config = {
67         .reg_bits       = 8,
68         .val_bits       = 8,
69         .max_register   = PTN5150_REG_END,
70 };
71
72 static void ptn5150_check_state(struct ptn5150_info *info)
73 {
74         unsigned int port_status, reg_data, vbus;
75         enum usb_role usb_role = USB_ROLE_NONE;
76         int ret;
77
78         ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
79         if (ret) {
80                 dev_err(info->dev, "failed to read CC STATUS %d\n", ret);
81                 return;
82         }
83
84         port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data);
85
86         switch (port_status) {
87         case PTN5150_DFP_ATTACHED:
88                 extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
89                 gpiod_set_value_cansleep(info->vbus_gpiod, 0);
90                 extcon_set_state_sync(info->edev, EXTCON_USB, true);
91                 usb_role = USB_ROLE_DEVICE;
92                 break;
93         case PTN5150_UFP_ATTACHED:
94                 extcon_set_state_sync(info->edev, EXTCON_USB, false);
95                 vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data);
96                 if (vbus)
97                         gpiod_set_value_cansleep(info->vbus_gpiod, 0);
98                 else
99                         gpiod_set_value_cansleep(info->vbus_gpiod, 1);
100
101                 extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
102                 usb_role = USB_ROLE_HOST;
103                 break;
104         default:
105                 break;
106         }
107
108         if (usb_role) {
109                 ret = usb_role_switch_set_role(info->role_sw, usb_role);
110                 if (ret)
111                         dev_err(info->dev, "failed to set %s role: %d\n",
112                                 usb_role_string(usb_role), ret);
113         }
114 }
115
116 static void ptn5150_irq_work(struct work_struct *work)
117 {
118         struct ptn5150_info *info = container_of(work,
119                         struct ptn5150_info, irq_work);
120         int ret = 0;
121         unsigned int int_status;
122
123         if (!info->edev)
124                 return;
125
126         mutex_lock(&info->mutex);
127
128         /* Clear interrupt. Read would clear the register */
129         ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
130         if (ret) {
131                 dev_err(info->dev, "failed to read INT STATUS %d\n", ret);
132                 mutex_unlock(&info->mutex);
133                 return;
134         }
135
136         if (int_status) {
137                 unsigned int cable_attach;
138
139                 cable_attach = int_status & PTN5150_REG_INT_CABLE_ATTACH_MASK;
140                 if (cable_attach) {
141                         ptn5150_check_state(info);
142                 } else {
143                         extcon_set_state_sync(info->edev,
144                                         EXTCON_USB_HOST, false);
145                         extcon_set_state_sync(info->edev,
146                                         EXTCON_USB, false);
147                         gpiod_set_value_cansleep(info->vbus_gpiod, 0);
148
149                         ret = usb_role_switch_set_role(info->role_sw,
150                                                        USB_ROLE_NONE);
151                         if (ret)
152                                 dev_err(info->dev,
153                                         "failed to set none role: %d\n",
154                                         ret);
155                 }
156         }
157
158         /* Clear interrupt. Read would clear the register */
159         ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS,
160                         &int_status);
161         if (ret) {
162                 dev_err(info->dev,
163                         "failed to read INT REG STATUS %d\n", ret);
164                 mutex_unlock(&info->mutex);
165                 return;
166         }
167
168         mutex_unlock(&info->mutex);
169 }
170
171
172 static irqreturn_t ptn5150_irq_handler(int irq, void *data)
173 {
174         struct ptn5150_info *info = data;
175
176         schedule_work(&info->irq_work);
177
178         return IRQ_HANDLED;
179 }
180
181 static int ptn5150_init_dev_type(struct ptn5150_info *info)
182 {
183         unsigned int reg_data, vendor_id, version_id;
184         int ret;
185
186         ret = regmap_read(info->regmap, PTN5150_REG_DEVICE_ID, &reg_data);
187         if (ret) {
188                 dev_err(info->dev, "failed to read DEVICE_ID %d\n", ret);
189                 return -EINVAL;
190         }
191
192         vendor_id = FIELD_GET(PTN5150_REG_DEVICE_ID_VENDOR, reg_data);
193         version_id = FIELD_GET(PTN5150_REG_DEVICE_ID_VERSION, reg_data);
194         dev_dbg(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
195                 version_id, vendor_id);
196
197         /* Clear any existing interrupts */
198         ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &reg_data);
199         if (ret) {
200                 dev_err(info->dev,
201                         "failed to read PTN5150_REG_INT_STATUS %d\n",
202                         ret);
203                 return -EINVAL;
204         }
205
206         ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS, &reg_data);
207         if (ret) {
208                 dev_err(info->dev,
209                         "failed to read PTN5150_REG_INT_REG_STATUS %d\n", ret);
210                 return -EINVAL;
211         }
212
213         return 0;
214 }
215
216 static void ptn5150_work_sync_and_put(void *data)
217 {
218         struct ptn5150_info *info = data;
219
220         cancel_work_sync(&info->irq_work);
221         usb_role_switch_put(info->role_sw);
222 }
223
224 static int ptn5150_i2c_probe(struct i2c_client *i2c)
225 {
226         struct device *dev = &i2c->dev;
227         struct device_node *np = i2c->dev.of_node;
228         struct ptn5150_info *info;
229         int ret;
230
231         if (!np)
232                 return -EINVAL;
233
234         info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
235         if (!info)
236                 return -ENOMEM;
237         i2c_set_clientdata(i2c, info);
238
239         info->dev = &i2c->dev;
240         info->i2c = i2c;
241         info->vbus_gpiod = devm_gpiod_get(&i2c->dev, "vbus", GPIOD_OUT_LOW);
242         if (IS_ERR(info->vbus_gpiod)) {
243                 ret = PTR_ERR(info->vbus_gpiod);
244                 if (ret == -ENOENT) {
245                         dev_info(dev, "No VBUS GPIO, ignoring VBUS control\n");
246                         info->vbus_gpiod = NULL;
247                 } else {
248                         return dev_err_probe(dev, ret, "failed to get VBUS GPIO\n");
249                 }
250         }
251
252         mutex_init(&info->mutex);
253
254         INIT_WORK(&info->irq_work, ptn5150_irq_work);
255
256         info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
257         if (IS_ERR(info->regmap)) {
258                 return dev_err_probe(info->dev, PTR_ERR(info->regmap),
259                                      "failed to allocate register map\n");
260         }
261
262         if (i2c->irq > 0) {
263                 info->irq = i2c->irq;
264         } else {
265                 info->int_gpiod = devm_gpiod_get(&i2c->dev, "int", GPIOD_IN);
266                 if (IS_ERR(info->int_gpiod)) {
267                         return dev_err_probe(dev, PTR_ERR(info->int_gpiod),
268                                              "failed to get INT GPIO\n");
269                 }
270
271                 info->irq = gpiod_to_irq(info->int_gpiod);
272                 if (info->irq < 0) {
273                         dev_err(dev, "failed to get INTB IRQ\n");
274                         return info->irq;
275                 }
276         }
277
278         ret = devm_request_threaded_irq(dev, info->irq, NULL,
279                                         ptn5150_irq_handler,
280                                         IRQF_TRIGGER_FALLING |
281                                         IRQF_ONESHOT,
282                                         i2c->name, info);
283         if (ret < 0) {
284                 dev_err(dev, "failed to request handler for INTB IRQ\n");
285                 return ret;
286         }
287
288         /* Allocate extcon device */
289         info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
290         if (IS_ERR(info->edev)) {
291                 dev_err(info->dev, "failed to allocate memory for extcon\n");
292                 return -ENOMEM;
293         }
294
295         /* Register extcon device */
296         ret = devm_extcon_dev_register(info->dev, info->edev);
297         if (ret) {
298                 dev_err(info->dev, "failed to register extcon device\n");
299                 return ret;
300         }
301
302         extcon_set_property_capability(info->edev, EXTCON_USB,
303                                         EXTCON_PROP_USB_VBUS);
304         extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
305                                         EXTCON_PROP_USB_VBUS);
306         extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
307                                         EXTCON_PROP_USB_TYPEC_POLARITY);
308
309         /* Initialize PTN5150 device and print vendor id and version id */
310         ret = ptn5150_init_dev_type(info);
311         if (ret)
312                 return -EINVAL;
313
314         info->role_sw = usb_role_switch_get(info->dev);
315         if (IS_ERR(info->role_sw))
316                 return dev_err_probe(info->dev, PTR_ERR(info->role_sw),
317                                      "failed to get role switch\n");
318
319         ret = devm_add_action_or_reset(dev, ptn5150_work_sync_and_put, info);
320         if (ret)
321                 return ret;
322
323         /*
324          * Update current extcon state if for example OTG connection was there
325          * before the probe
326          */
327         mutex_lock(&info->mutex);
328         ptn5150_check_state(info);
329         mutex_unlock(&info->mutex);
330
331         return 0;
332 }
333
334 static const struct of_device_id ptn5150_dt_match[] = {
335         { .compatible = "nxp,ptn5150" },
336         { },
337 };
338 MODULE_DEVICE_TABLE(of, ptn5150_dt_match);
339
340 static const struct i2c_device_id ptn5150_i2c_id[] = {
341         { "ptn5150", 0 },
342         { }
343 };
344 MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id);
345
346 static struct i2c_driver ptn5150_i2c_driver = {
347         .driver         = {
348                 .name   = "ptn5150",
349                 .of_match_table = ptn5150_dt_match,
350         },
351         .probe_new      = ptn5150_i2c_probe,
352         .id_table = ptn5150_i2c_id,
353 };
354 module_i2c_driver(ptn5150_i2c_driver);
355
356 MODULE_DESCRIPTION("NXP PTN5150 CC logic Extcon driver");
357 MODULE_AUTHOR("Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>");
358 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
359 MODULE_LICENSE("GPL v2");