]> Git Repo - linux.git/blob - drivers/usb/typec/mux/fsa4480.c
crypto: akcipher - Drop sign/verify operations
[linux.git] / drivers / usb / typec / mux / fsa4480.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2021-2022 Linaro Ltd.
4  * Copyright (C) 2018-2020 The Linux Foundation
5  */
6
7 #include <linux/bits.h>
8 #include <linux/i2c.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/mutex.h>
12 #include <linux/regmap.h>
13 #include <linux/usb/typec_dp.h>
14 #include <linux/usb/typec_mux.h>
15
16 #define FSA4480_DEVICE_ID       0x00
17  #define FSA4480_DEVICE_ID_VENDOR_ID    GENMASK(7, 6)
18  #define FSA4480_DEVICE_ID_VERSION_ID   GENMASK(5, 3)
19  #define FSA4480_DEVICE_ID_REV_ID       GENMASK(2, 0)
20 #define FSA4480_SWITCH_ENABLE   0x04
21 #define FSA4480_SWITCH_SELECT   0x05
22 #define FSA4480_SWITCH_STATUS1  0x07
23 #define FSA4480_SLOW_L          0x08
24 #define FSA4480_SLOW_R          0x09
25 #define FSA4480_SLOW_MIC        0x0a
26 #define FSA4480_SLOW_SENSE      0x0b
27 #define FSA4480_SLOW_GND        0x0c
28 #define FSA4480_DELAY_L_R       0x0d
29 #define FSA4480_DELAY_L_MIC     0x0e
30 #define FSA4480_DELAY_L_SENSE   0x0f
31 #define FSA4480_DELAY_L_AGND    0x10
32 #define FSA4480_FUNCTION_ENABLE 0x12
33 #define FSA4480_RESET           0x1e
34 #define FSA4480_MAX_REGISTER    0x1f
35
36 #define FSA4480_ENABLE_DEVICE   BIT(7)
37 #define FSA4480_ENABLE_SBU      GENMASK(6, 5)
38 #define FSA4480_ENABLE_USB      GENMASK(4, 3)
39 #define FSA4480_ENABLE_SENSE    BIT(2)
40 #define FSA4480_ENABLE_MIC      BIT(1)
41 #define FSA4480_ENABLE_AGND     BIT(0)
42
43 #define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5)
44 #define FSA4480_SEL_USB         GENMASK(4, 3)
45 #define FSA4480_SEL_SENSE       BIT(2)
46 #define FSA4480_SEL_MIC         BIT(1)
47 #define FSA4480_SEL_AGND        BIT(0)
48
49 #define FSA4480_ENABLE_AUTO_JACK_DETECT BIT(0)
50
51 struct fsa4480 {
52         struct i2c_client *client;
53
54         /* used to serialize concurrent change requests */
55         struct mutex lock;
56
57         struct typec_switch_dev *sw;
58         struct typec_mux_dev *mux;
59
60         struct regmap *regmap;
61
62         enum typec_orientation orientation;
63         unsigned long mode;
64         unsigned int svid;
65
66         u8 cur_enable;
67         bool swap_sbu_lanes;
68 };
69
70 static const struct regmap_config fsa4480_regmap_config = {
71         .reg_bits = 8,
72         .val_bits = 8,
73         .max_register = FSA4480_MAX_REGISTER,
74         /* Accesses only done under fsa4480->lock */
75         .disable_locking = true,
76 };
77
78 static int fsa4480_set(struct fsa4480 *fsa)
79 {
80         bool reverse = (fsa->orientation == TYPEC_ORIENTATION_REVERSE);
81         u8 enable = FSA4480_ENABLE_DEVICE;
82         u8 sel = 0;
83
84         if (fsa->swap_sbu_lanes)
85                 reverse = !reverse;
86
87         /* USB Mode */
88         if (fsa->mode < TYPEC_STATE_MODAL ||
89             (!fsa->svid && (fsa->mode == TYPEC_MODE_USB2 ||
90                             fsa->mode == TYPEC_MODE_USB3))) {
91                 enable |= FSA4480_ENABLE_USB;
92                 sel = FSA4480_SEL_USB;
93         } else if (fsa->svid) {
94                 switch (fsa->mode) {
95                 /* DP Only */
96                 case TYPEC_DP_STATE_C:
97                 case TYPEC_DP_STATE_E:
98                         enable |= FSA4480_ENABLE_SBU;
99                         if (reverse)
100                                 sel = FSA4480_SEL_SBU_REVERSE;
101                         break;
102
103                 /* DP + USB */
104                 case TYPEC_DP_STATE_D:
105                 case TYPEC_DP_STATE_F:
106                         enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_SBU;
107                         sel = FSA4480_SEL_USB;
108                         if (reverse)
109                                 sel |= FSA4480_SEL_SBU_REVERSE;
110                         break;
111
112                 default:
113                         return -EOPNOTSUPP;
114                 }
115         } else if (fsa->mode == TYPEC_MODE_AUDIO) {
116                 /* Audio Accessory Mode, setup to auto Jack Detection */
117                 enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_AGND;
118         } else
119                 return -EOPNOTSUPP;
120
121         if (fsa->cur_enable & FSA4480_ENABLE_SBU) {
122                 /* Disable SBU output while re-configuring the switch */
123                 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE,
124                              fsa->cur_enable & ~FSA4480_ENABLE_SBU);
125
126                 /* 35us to allow the SBU switch to turn off */
127                 usleep_range(35, 1000);
128         }
129
130         regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, sel);
131         regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, enable);
132
133         /* Start AUDIO JACK DETECTION to setup MIC, AGND & Sense muxes */
134         if (enable & FSA4480_ENABLE_AGND)
135                 regmap_write(fsa->regmap, FSA4480_FUNCTION_ENABLE,
136                              FSA4480_ENABLE_AUTO_JACK_DETECT);
137
138         if (enable & FSA4480_ENABLE_SBU) {
139                 /* 15us to allow the SBU switch to turn on again */
140                 usleep_range(15, 1000);
141         }
142
143         fsa->cur_enable = enable;
144
145         return 0;
146 }
147
148 static int fsa4480_switch_set(struct typec_switch_dev *sw,
149                               enum typec_orientation orientation)
150 {
151         struct fsa4480 *fsa = typec_switch_get_drvdata(sw);
152         int ret = 0;
153
154         mutex_lock(&fsa->lock);
155
156         if (fsa->orientation != orientation) {
157                 fsa->orientation = orientation;
158
159                 ret = fsa4480_set(fsa);
160         }
161
162         mutex_unlock(&fsa->lock);
163
164         return ret;
165 }
166
167 static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
168 {
169         struct fsa4480 *fsa = typec_mux_get_drvdata(mux);
170         int ret = 0;
171
172         mutex_lock(&fsa->lock);
173
174         if (fsa->mode != state->mode) {
175                 fsa->mode = state->mode;
176
177                 if (state->alt)
178                         fsa->svid = state->alt->svid;
179                 else
180                         fsa->svid = 0; // No SVID
181
182                 ret = fsa4480_set(fsa);
183         }
184
185         mutex_unlock(&fsa->lock);
186
187         return ret;
188 }
189
190 enum {
191         NORMAL_LANE_MAPPING,
192         INVERT_LANE_MAPPING,
193 };
194
195 #define DATA_LANES_COUNT        2
196
197 static const int supported_data_lane_mapping[][DATA_LANES_COUNT] = {
198         [NORMAL_LANE_MAPPING] = { 0, 1 },
199         [INVERT_LANE_MAPPING] = { 1, 0 },
200 };
201
202 static int fsa4480_parse_data_lanes_mapping(struct fsa4480 *fsa)
203 {
204         struct fwnode_handle *ep;
205         u32 data_lanes[DATA_LANES_COUNT];
206         int ret, i, j;
207
208         ep = fwnode_graph_get_next_endpoint(dev_fwnode(&fsa->client->dev), NULL);
209         if (!ep)
210                 return 0;
211
212         ret = fwnode_property_read_u32_array(ep, "data-lanes", data_lanes, DATA_LANES_COUNT);
213         if (ret == -EINVAL)
214                 /* Property isn't here, consider default mapping */
215                 goto out_done;
216         if (ret) {
217                 dev_err(&fsa->client->dev, "invalid data-lanes property: %d\n", ret);
218                 goto out_error;
219         }
220
221         for (i = 0; i < ARRAY_SIZE(supported_data_lane_mapping); i++) {
222                 for (j = 0; j < DATA_LANES_COUNT; j++) {
223                         if (data_lanes[j] != supported_data_lane_mapping[i][j])
224                                 break;
225                 }
226
227                 if (j == DATA_LANES_COUNT)
228                         break;
229         }
230
231         switch (i) {
232         case NORMAL_LANE_MAPPING:
233                 break;
234         case INVERT_LANE_MAPPING:
235                 fsa->swap_sbu_lanes = true;
236                 break;
237         default:
238                 dev_err(&fsa->client->dev, "invalid data-lanes mapping\n");
239                 ret = -EINVAL;
240                 goto out_error;
241         }
242
243 out_done:
244         ret = 0;
245
246 out_error:
247         fwnode_handle_put(ep);
248
249         return ret;
250 }
251
252 static int fsa4480_probe(struct i2c_client *client)
253 {
254         struct device *dev = &client->dev;
255         struct typec_switch_desc sw_desc = { };
256         struct typec_mux_desc mux_desc = { };
257         struct fsa4480 *fsa;
258         int val = 0;
259         int ret;
260
261         fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL);
262         if (!fsa)
263                 return -ENOMEM;
264
265         fsa->client = client;
266         mutex_init(&fsa->lock);
267
268         ret = fsa4480_parse_data_lanes_mapping(fsa);
269         if (ret)
270                 return ret;
271
272         fsa->regmap = devm_regmap_init_i2c(client, &fsa4480_regmap_config);
273         if (IS_ERR(fsa->regmap))
274                 return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n");
275
276         ret = regmap_read(fsa->regmap, FSA4480_DEVICE_ID, &val);
277         if (ret)
278                 return dev_err_probe(dev, -ENODEV, "FSA4480 not found\n");
279
280         dev_dbg(dev, "Found FSA4480 v%lu.%lu (Vendor ID = %lu)\n",
281                 FIELD_GET(FSA4480_DEVICE_ID_VERSION_ID, val),
282                 FIELD_GET(FSA4480_DEVICE_ID_REV_ID, val),
283                 FIELD_GET(FSA4480_DEVICE_ID_VENDOR_ID, val));
284
285         /* Safe mode */
286         fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB;
287         fsa->mode = TYPEC_STATE_SAFE;
288         fsa->orientation = TYPEC_ORIENTATION_NONE;
289
290         /* set default settings */
291         regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00);
292         regmap_write(fsa->regmap, FSA4480_SLOW_R, 0x00);
293         regmap_write(fsa->regmap, FSA4480_SLOW_MIC, 0x00);
294         regmap_write(fsa->regmap, FSA4480_SLOW_SENSE, 0x00);
295         regmap_write(fsa->regmap, FSA4480_SLOW_GND, 0x00);
296         regmap_write(fsa->regmap, FSA4480_DELAY_L_R, 0x00);
297         regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00);
298         regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00);
299         regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09);
300         regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, FSA4480_SEL_USB);
301         regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable);
302
303         sw_desc.drvdata = fsa;
304         sw_desc.fwnode = dev_fwnode(dev);
305         sw_desc.set = fsa4480_switch_set;
306
307         fsa->sw = typec_switch_register(dev, &sw_desc);
308         if (IS_ERR(fsa->sw))
309                 return dev_err_probe(dev, PTR_ERR(fsa->sw), "failed to register typec switch\n");
310
311         mux_desc.drvdata = fsa;
312         mux_desc.fwnode = dev_fwnode(dev);
313         mux_desc.set = fsa4480_mux_set;
314
315         fsa->mux = typec_mux_register(dev, &mux_desc);
316         if (IS_ERR(fsa->mux)) {
317                 typec_switch_unregister(fsa->sw);
318                 return dev_err_probe(dev, PTR_ERR(fsa->mux), "failed to register typec mux\n");
319         }
320
321         i2c_set_clientdata(client, fsa);
322         return 0;
323 }
324
325 static void fsa4480_remove(struct i2c_client *client)
326 {
327         struct fsa4480 *fsa = i2c_get_clientdata(client);
328
329         typec_mux_unregister(fsa->mux);
330         typec_switch_unregister(fsa->sw);
331 }
332
333 static const struct i2c_device_id fsa4480_table[] = {
334         { "fsa4480" },
335         { }
336 };
337 MODULE_DEVICE_TABLE(i2c, fsa4480_table);
338
339 static const struct of_device_id fsa4480_of_table[] = {
340         { .compatible = "fcs,fsa4480" },
341         { }
342 };
343 MODULE_DEVICE_TABLE(of, fsa4480_of_table);
344
345 static struct i2c_driver fsa4480_driver = {
346         .driver = {
347                 .name = "fsa4480",
348                 .of_match_table = fsa4480_of_table,
349         },
350         .probe          = fsa4480_probe,
351         .remove         = fsa4480_remove,
352         .id_table       = fsa4480_table,
353 };
354 module_i2c_driver(fsa4480_driver);
355
356 MODULE_DESCRIPTION("ON Semiconductor FSA4480 driver");
357 MODULE_LICENSE("GPL v2");
This page took 0.053024 seconds and 4 git commands to generate.