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
fsa4480_set(struct fsa4480 * fsa)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
fsa4480_switch_set(struct typec_switch_dev * sw,enum typec_orientation orientation)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
fsa4480_mux_set(struct typec_mux_dev * mux,struct typec_mux_state * state)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
fsa4480_probe(struct i2c_client * client)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
fsa4480_remove(struct i2c_client * client)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");
273