Merge tag 'hwmon-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck...
[linux-2.6-microblaze.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_SWITCH_ENABLE   0x04
17 #define FSA4480_SWITCH_SELECT   0x05
18 #define FSA4480_SWITCH_STATUS1  0x07
19 #define FSA4480_SLOW_L          0x08
20 #define FSA4480_SLOW_R          0x09
21 #define FSA4480_SLOW_MIC        0x0a
22 #define FSA4480_SLOW_SENSE      0x0b
23 #define FSA4480_SLOW_GND        0x0c
24 #define FSA4480_DELAY_L_R       0x0d
25 #define FSA4480_DELAY_L_MIC     0x0e
26 #define FSA4480_DELAY_L_SENSE   0x0f
27 #define FSA4480_DELAY_L_AGND    0x10
28 #define FSA4480_FUNCTION_ENABLE 0x12
29 #define FSA4480_RESET           0x1e
30 #define FSA4480_MAX_REGISTER    0x1f
31
32 #define FSA4480_ENABLE_DEVICE   BIT(7)
33 #define FSA4480_ENABLE_SBU      GENMASK(6, 5)
34 #define FSA4480_ENABLE_USB      GENMASK(4, 3)
35 #define FSA4480_ENABLE_SENSE    BIT(2)
36 #define FSA4480_ENABLE_MIC      BIT(1)
37 #define FSA4480_ENABLE_AGND     BIT(0)
38
39 #define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5)
40 #define FSA4480_SEL_USB         GENMASK(4, 3)
41 #define FSA4480_SEL_SENSE       BIT(2)
42 #define FSA4480_SEL_MIC         BIT(1)
43 #define FSA4480_SEL_AGND        BIT(0)
44
45 #define FSA4480_ENABLE_AUTO_JACK_DETECT BIT(0)
46
47 struct fsa4480 {
48         struct i2c_client *client;
49
50         /* used to serialize concurrent change requests */
51         struct mutex lock;
52
53         struct typec_switch_dev *sw;
54         struct typec_mux_dev *mux;
55
56         struct regmap *regmap;
57
58         enum typec_orientation orientation;
59         unsigned long mode;
60         unsigned int svid;
61
62         u8 cur_enable;
63 };
64
65 static const struct regmap_config fsa4480_regmap_config = {
66         .reg_bits = 8,
67         .val_bits = 8,
68         .max_register = FSA4480_MAX_REGISTER,
69         /* Accesses only done under fsa4480->lock */
70         .disable_locking = true,
71 };
72
73 static int fsa4480_set(struct fsa4480 *fsa)
74 {
75         bool reverse = (fsa->orientation == TYPEC_ORIENTATION_REVERSE);
76         u8 enable = FSA4480_ENABLE_DEVICE;
77         u8 sel = 0;
78
79         /* USB Mode */
80         if (fsa->mode < TYPEC_STATE_MODAL ||
81             (!fsa->svid && (fsa->mode == TYPEC_MODE_USB2 ||
82                             fsa->mode == TYPEC_MODE_USB3))) {
83                 enable |= FSA4480_ENABLE_USB;
84                 sel = FSA4480_SEL_USB;
85         } else if (fsa->svid) {
86                 switch (fsa->mode) {
87                 /* DP Only */
88                 case TYPEC_DP_STATE_C:
89                 case TYPEC_DP_STATE_E:
90                         enable |= FSA4480_ENABLE_SBU;
91                         if (reverse)
92                                 sel = FSA4480_SEL_SBU_REVERSE;
93                         break;
94
95                 /* DP + USB */
96                 case TYPEC_DP_STATE_D:
97                 case TYPEC_DP_STATE_F:
98                         enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_SBU;
99                         sel = FSA4480_SEL_USB;
100                         if (reverse)
101                                 sel |= FSA4480_SEL_SBU_REVERSE;
102                         break;
103
104                 default:
105                         return -EOPNOTSUPP;
106                 }
107         } else if (fsa->mode == TYPEC_MODE_AUDIO) {
108                 /* Audio Accessory Mode, setup to auto Jack Detection */
109                 enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_AGND;
110         } else
111                 return -EOPNOTSUPP;
112
113         if (fsa->cur_enable & FSA4480_ENABLE_SBU) {
114                 /* Disable SBU output while re-configuring the switch */
115                 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE,
116                              fsa->cur_enable & ~FSA4480_ENABLE_SBU);
117
118                 /* 35us to allow the SBU switch to turn off */
119                 usleep_range(35, 1000);
120         }
121
122         regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, sel);
123         regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, enable);
124
125         /* Start AUDIO JACK DETECTION to setup MIC, AGND & Sense muxes */
126         if (enable & FSA4480_ENABLE_AGND)
127                 regmap_write(fsa->regmap, FSA4480_FUNCTION_ENABLE,
128                              FSA4480_ENABLE_AUTO_JACK_DETECT);
129
130         if (enable & FSA4480_ENABLE_SBU) {
131                 /* 15us to allow the SBU switch to turn on again */
132                 usleep_range(15, 1000);
133         }
134
135         fsa->cur_enable = enable;
136
137         return 0;
138 }
139
140 static int fsa4480_switch_set(struct typec_switch_dev *sw,
141                               enum typec_orientation orientation)
142 {
143         struct fsa4480 *fsa = typec_switch_get_drvdata(sw);
144         int ret = 0;
145
146         mutex_lock(&fsa->lock);
147
148         if (fsa->orientation != orientation) {
149                 fsa->orientation = orientation;
150
151                 ret = fsa4480_set(fsa);
152         }
153
154         mutex_unlock(&fsa->lock);
155
156         return ret;
157 }
158
159 static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
160 {
161         struct fsa4480 *fsa = typec_mux_get_drvdata(mux);
162         int ret = 0;
163
164         mutex_lock(&fsa->lock);
165
166         if (fsa->mode != state->mode) {
167                 fsa->mode = state->mode;
168
169                 if (state->alt)
170                         fsa->svid = state->alt->svid;
171                 else
172                         fsa->svid = 0; // No SVID
173
174                 ret = fsa4480_set(fsa);
175         }
176
177         mutex_unlock(&fsa->lock);
178
179         return ret;
180 }
181
182 static int fsa4480_probe(struct i2c_client *client)
183 {
184         struct device *dev = &client->dev;
185         struct typec_switch_desc sw_desc = { };
186         struct typec_mux_desc mux_desc = { };
187         struct fsa4480 *fsa;
188
189         fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL);
190         if (!fsa)
191                 return -ENOMEM;
192
193         fsa->client = client;
194         mutex_init(&fsa->lock);
195
196         fsa->regmap = devm_regmap_init_i2c(client, &fsa4480_regmap_config);
197         if (IS_ERR(fsa->regmap))
198                 return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n");
199
200         /* Safe mode */
201         fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB;
202         fsa->mode = TYPEC_STATE_SAFE;
203         fsa->orientation = TYPEC_ORIENTATION_NONE;
204
205         /* set default settings */
206         regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00);
207         regmap_write(fsa->regmap, FSA4480_SLOW_R, 0x00);
208         regmap_write(fsa->regmap, FSA4480_SLOW_MIC, 0x00);
209         regmap_write(fsa->regmap, FSA4480_SLOW_SENSE, 0x00);
210         regmap_write(fsa->regmap, FSA4480_SLOW_GND, 0x00);
211         regmap_write(fsa->regmap, FSA4480_DELAY_L_R, 0x00);
212         regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00);
213         regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00);
214         regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09);
215         regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, FSA4480_SEL_USB);
216         regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable);
217
218         sw_desc.drvdata = fsa;
219         sw_desc.fwnode = dev_fwnode(dev);
220         sw_desc.set = fsa4480_switch_set;
221
222         fsa->sw = typec_switch_register(dev, &sw_desc);
223         if (IS_ERR(fsa->sw))
224                 return dev_err_probe(dev, PTR_ERR(fsa->sw), "failed to register typec switch\n");
225
226         mux_desc.drvdata = fsa;
227         mux_desc.fwnode = dev_fwnode(dev);
228         mux_desc.set = fsa4480_mux_set;
229
230         fsa->mux = typec_mux_register(dev, &mux_desc);
231         if (IS_ERR(fsa->mux)) {
232                 typec_switch_unregister(fsa->sw);
233                 return dev_err_probe(dev, PTR_ERR(fsa->mux), "failed to register typec mux\n");
234         }
235
236         i2c_set_clientdata(client, fsa);
237         return 0;
238 }
239
240 static void fsa4480_remove(struct i2c_client *client)
241 {
242         struct fsa4480 *fsa = i2c_get_clientdata(client);
243
244         typec_mux_unregister(fsa->mux);
245         typec_switch_unregister(fsa->sw);
246 }
247
248 static const struct i2c_device_id fsa4480_table[] = {
249         { "fsa4480" },
250         { }
251 };
252 MODULE_DEVICE_TABLE(i2c, fsa4480_table);
253
254 static const struct of_device_id fsa4480_of_table[] = {
255         { .compatible = "fcs,fsa4480" },
256         { }
257 };
258 MODULE_DEVICE_TABLE(of, fsa4480_of_table);
259
260 static struct i2c_driver fsa4480_driver = {
261         .driver = {
262                 .name = "fsa4480",
263                 .of_match_table = fsa4480_of_table,
264         },
265         .probe          = fsa4480_probe,
266         .remove         = fsa4480_remove,
267         .id_table       = fsa4480_table,
268 };
269 module_i2c_driver(fsa4480_driver);
270
271 MODULE_DESCRIPTION("ON Semiconductor FSA4480 driver");
272 MODULE_LICENSE("GPL v2");