GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / usb / typec / hd3ss3220.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * TI HD3SS3220 Type-C DRP Port Controller Driver
4  *
5  * Copyright (C) 2019 Renesas Electronics Corp.
6  */
7
8 #include <linux/module.h>
9 #include <linux/i2c.h>
10 #include <linux/usb/role.h>
11 #include <linux/irqreturn.h>
12 #include <linux/interrupt.h>
13 #include <linux/regmap.h>
14 #include <linux/slab.h>
15 #include <linux/usb/typec.h>
16 #include <linux/delay.h>
17 #include <linux/workqueue.h>
18
19 #define HD3SS3220_REG_CN_STAT_CTRL      0x09
20 #define HD3SS3220_REG_GEN_CTRL          0x0A
21 #define HD3SS3220_REG_DEV_REV           0xA0
22
23 /* Register HD3SS3220_REG_CN_STAT_CTRL*/
24 #define HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK  (BIT(7) | BIT(6))
25 #define HD3SS3220_REG_CN_STAT_CTRL_AS_DFP               BIT(6)
26 #define HD3SS3220_REG_CN_STAT_CTRL_AS_UFP               BIT(7)
27 #define HD3SS3220_REG_CN_STAT_CTRL_TO_ACCESSORY         (BIT(7) | BIT(6))
28 #define HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS           BIT(4)
29
30 /* Register HD3SS3220_REG_GEN_CTRL*/
31 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK            (BIT(2) | BIT(1))
32 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT     0x00
33 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK     BIT(1)
34 #define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC     (BIT(2) | BIT(1))
35
36 struct hd3ss3220 {
37         struct device *dev;
38         struct regmap *regmap;
39         struct usb_role_switch  *role_sw;
40         struct typec_port *port;
41         struct delayed_work output_poll_work;
42         enum usb_role role_state;
43         bool poll;
44 };
45
46 static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int src_pref)
47 {
48         return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL,
49                                   HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK,
50                                   src_pref);
51 }
52
53 static enum usb_role hd3ss3220_get_attached_state(struct hd3ss3220 *hd3ss3220)
54 {
55         unsigned int reg_val;
56         enum usb_role attached_state;
57         int ret;
58
59         ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
60                           &reg_val);
61         if (ret < 0)
62                 return ret;
63
64         switch (reg_val & HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK) {
65         case HD3SS3220_REG_CN_STAT_CTRL_AS_DFP:
66                 attached_state = USB_ROLE_HOST;
67                 break;
68         case HD3SS3220_REG_CN_STAT_CTRL_AS_UFP:
69                 attached_state = USB_ROLE_DEVICE;
70                 break;
71         default:
72                 attached_state = USB_ROLE_NONE;
73                 break;
74         }
75
76         return attached_state;
77 }
78
79 static int hd3ss3220_dr_set(struct typec_port *port, enum typec_data_role role)
80 {
81         struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port);
82         enum usb_role role_val;
83         int pref, ret = 0;
84
85         if (role == TYPEC_HOST) {
86                 role_val = USB_ROLE_HOST;
87                 pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC;
88         } else {
89                 role_val = USB_ROLE_DEVICE;
90                 pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK;
91         }
92
93         ret = hd3ss3220_set_source_pref(hd3ss3220, pref);
94         usleep_range(10, 100);
95
96         usb_role_switch_set_role(hd3ss3220->role_sw, role_val);
97         typec_set_data_role(hd3ss3220->port, role);
98
99         return ret;
100 }
101
102 static const struct typec_operations hd3ss3220_ops = {
103         .dr_set = hd3ss3220_dr_set
104 };
105
106 static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
107 {
108         enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
109
110         usb_role_switch_set_role(hd3ss3220->role_sw, role_state);
111         if (role_state == USB_ROLE_NONE)
112                 hd3ss3220_set_source_pref(hd3ss3220,
113                                 HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT);
114
115         switch (role_state) {
116         case USB_ROLE_HOST:
117                 typec_set_data_role(hd3ss3220->port, TYPEC_HOST);
118                 break;
119         case USB_ROLE_DEVICE:
120                 typec_set_data_role(hd3ss3220->port, TYPEC_DEVICE);
121                 break;
122         default:
123                 break;
124         }
125
126         hd3ss3220->role_state = role_state;
127 }
128
129 static void output_poll_execute(struct work_struct *work)
130 {
131         struct delayed_work *delayed_work = to_delayed_work(work);
132         struct hd3ss3220 *hd3ss3220 = container_of(delayed_work,
133                                                    struct hd3ss3220,
134                                                    output_poll_work);
135         enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
136
137         if (hd3ss3220->role_state != role_state)
138                 hd3ss3220_set_role(hd3ss3220);
139
140         schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
141 }
142
143 static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220)
144 {
145         int err;
146
147         hd3ss3220_set_role(hd3ss3220);
148         err = regmap_write_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL,
149                                 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS,
150                                 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS);
151         if (err < 0)
152                 return IRQ_NONE;
153
154         return IRQ_HANDLED;
155 }
156
157 static irqreturn_t hd3ss3220_irq_handler(int irq, void *data)
158 {
159         struct i2c_client *client = to_i2c_client(data);
160         struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
161
162         return hd3ss3220_irq(hd3ss3220);
163 }
164
165 static const struct regmap_config config = {
166         .reg_bits = 8,
167         .val_bits = 8,
168         .max_register = 0x0A,
169 };
170
171 static int hd3ss3220_probe(struct i2c_client *client)
172 {
173         struct typec_capability typec_cap = { };
174         struct hd3ss3220 *hd3ss3220;
175         struct fwnode_handle *connector, *ep;
176         int ret;
177         unsigned int data;
178
179         hd3ss3220 = devm_kzalloc(&client->dev, sizeof(struct hd3ss3220),
180                                  GFP_KERNEL);
181         if (!hd3ss3220)
182                 return -ENOMEM;
183
184         i2c_set_clientdata(client, hd3ss3220);
185
186         hd3ss3220->dev = &client->dev;
187         hd3ss3220->regmap = devm_regmap_init_i2c(client, &config);
188         if (IS_ERR(hd3ss3220->regmap))
189                 return PTR_ERR(hd3ss3220->regmap);
190
191         hd3ss3220_set_source_pref(hd3ss3220,
192                                   HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT);
193         /* For backward compatibility check the connector child node first */
194         connector = device_get_named_child_node(hd3ss3220->dev, "connector");
195         if (connector) {
196                 hd3ss3220->role_sw = fwnode_usb_role_switch_get(connector);
197         } else {
198                 ep = fwnode_graph_get_next_endpoint(dev_fwnode(hd3ss3220->dev), NULL);
199                 if (!ep)
200                         return -ENODEV;
201                 connector = fwnode_graph_get_remote_port_parent(ep);
202                 fwnode_handle_put(ep);
203                 if (!connector)
204                         return -ENODEV;
205                 hd3ss3220->role_sw = usb_role_switch_get(hd3ss3220->dev);
206         }
207
208         if (IS_ERR(hd3ss3220->role_sw)) {
209                 ret = PTR_ERR(hd3ss3220->role_sw);
210                 goto err_put_fwnode;
211         }
212
213         typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
214         typec_cap.driver_data = hd3ss3220;
215         typec_cap.type = TYPEC_PORT_DRP;
216         typec_cap.data = TYPEC_PORT_DRD;
217         typec_cap.ops = &hd3ss3220_ops;
218         typec_cap.fwnode = connector;
219
220         hd3ss3220->port = typec_register_port(&client->dev, &typec_cap);
221         if (IS_ERR(hd3ss3220->port)) {
222                 ret = PTR_ERR(hd3ss3220->port);
223                 goto err_put_role;
224         }
225
226         hd3ss3220_set_role(hd3ss3220);
227         ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, &data);
228         if (ret < 0)
229                 goto err_unreg_port;
230
231         if (data & HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS) {
232                 ret = regmap_write(hd3ss3220->regmap,
233                                 HD3SS3220_REG_CN_STAT_CTRL,
234                                 data | HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS);
235                 if (ret < 0)
236                         goto err_unreg_port;
237         }
238
239         if (client->irq > 0) {
240                 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
241                                         hd3ss3220_irq_handler,
242                                         IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
243                                         "hd3ss3220", &client->dev);
244                 if (ret)
245                         goto err_unreg_port;
246         } else {
247                 INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute);
248                 hd3ss3220->poll = true;
249         }
250
251         ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV);
252         if (ret < 0)
253                 goto err_unreg_port;
254
255         fwnode_handle_put(connector);
256
257         if (hd3ss3220->poll)
258                 schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
259
260         dev_info(&client->dev, "probed revision=0x%x\n", ret);
261
262         return 0;
263 err_unreg_port:
264         typec_unregister_port(hd3ss3220->port);
265 err_put_role:
266         usb_role_switch_put(hd3ss3220->role_sw);
267 err_put_fwnode:
268         fwnode_handle_put(connector);
269
270         return ret;
271 }
272
273 static void hd3ss3220_remove(struct i2c_client *client)
274 {
275         struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
276
277         if (hd3ss3220->poll)
278                 cancel_delayed_work_sync(&hd3ss3220->output_poll_work);
279
280         typec_unregister_port(hd3ss3220->port);
281         usb_role_switch_put(hd3ss3220->role_sw);
282 }
283
284 static const struct of_device_id dev_ids[] = {
285         { .compatible = "ti,hd3ss3220"},
286         {}
287 };
288 MODULE_DEVICE_TABLE(of, dev_ids);
289
290 static struct i2c_driver hd3ss3220_driver = {
291         .driver = {
292                 .name = "hd3ss3220",
293                 .of_match_table = dev_ids,
294         },
295         .probe = hd3ss3220_probe,
296         .remove = hd3ss3220_remove,
297 };
298
299 module_i2c_driver(hd3ss3220_driver);
300
301 MODULE_AUTHOR("Biju Das <biju.das@bp.renesas.com>");
302 MODULE_DESCRIPTION("TI HD3SS3220 DRP Port Controller Driver");
303 MODULE_LICENSE("GPL");