1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * ti_fpc202.c - FPC202 Dual Port Controller driver
4 *
5 * Copyright (C) 2024 Bootlin
6 *
7 */
8
9 #include <linux/cleanup.h>
10 #include <linux/err.h>
11 #include <linux/i2c.h>
12 #include <linux/i2c-atr.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/gpio/driver.h>
15 #include <linux/module.h>
16
17 #define FPC202_NUM_PORTS 2
18 #define FPC202_ALIASES_PER_PORT 2
19
20 /*
21 * GPIO: port mapping
22 *
23 * 0: P0_S0_IN_A
24 * 1: P0_S1_IN_A
25 * 2: P1_S0_IN_A
26 * 3: P1_S1_IN_A
27 * 4: P0_S0_IN_B
28 * ...
29 * 8: P0_S0_IN_C
30 * ...
31 * 12: P0_S0_OUT_A
32 * ...
33 * 16: P0_S0_OUT_B
34 * ...
35 * 19: P1_S1_OUT_B
36 *
37 */
38
39 #define FPC202_GPIO_COUNT 20
40 #define FPC202_GPIO_P0_S0_IN_B 4
41 #define FPC202_GPIO_P0_S0_OUT_A 12
42
43 #define FPC202_REG_IN_A_INT 0x6
44 #define FPC202_REG_IN_C_IN_B 0x7
45 #define FPC202_REG_OUT_A_OUT_B 0x8
46
47 #define FPC202_REG_OUT_A_OUT_B_VAL 0xa
48
49 #define FPC202_REG_MOD_DEV(port, dev) (0xb4 + ((port) * 4) + (dev))
50 #define FPC202_REG_AUX_DEV(port, dev) (0xb6 + ((port) * 4) + (dev))
51
52 /*
53 * The FPC202 doesn't support turning off address translation on a single port.
54 * So just set an invalid I2C address as the translation target when no client
55 * address is attached.
56 */
57 #define FPC202_REG_DEV_INVALID 0
58
59 /* Even aliases are assigned to device 0 and odd aliases to device 1 */
60 #define fpc202_dev_num_from_alias(alias) ((alias) % 2)
61
62 struct fpc202_priv {
63 struct i2c_client *client;
64 struct i2c_atr *atr;
65 struct gpio_desc *en_gpio;
66 struct gpio_chip gpio;
67
68 /* Lock REG_MOD/AUX_DEV and addr_caches during attach/detach */
69 struct mutex reg_dev_lock;
70
71 /* Cached device addresses for both ports and their devices */
72 u8 addr_caches[2][2];
73
74 /* Keep track of which ports were probed */
75 DECLARE_BITMAP(probed_ports, FPC202_NUM_PORTS);
76 };
77
fpc202_fill_alias_table(struct i2c_client * client,u16 * aliases,int port_id)78 static void fpc202_fill_alias_table(struct i2c_client *client, u16 *aliases, int port_id)
79 {
80 u16 first_alias;
81 int i;
82
83 /*
84 * There is a predefined list of aliases for each FPC202 I2C
85 * self-address. This allows daisy-chained FPC202 units to
86 * automatically take on different sets of aliases.
87 * Each port of an FPC202 unit is assigned two aliases from this list.
88 */
89 first_alias = 0x10 + 4 * port_id + 8 * ((u16)client->addr - 2);
90
91 for (i = 0; i < FPC202_ALIASES_PER_PORT; i++)
92 aliases[i] = first_alias + i;
93 }
94
fpc202_gpio_get_dir(int offset)95 static int fpc202_gpio_get_dir(int offset)
96 {
97 return offset < FPC202_GPIO_P0_S0_OUT_A ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
98 }
99
fpc202_read(struct fpc202_priv * priv,u8 reg)100 static int fpc202_read(struct fpc202_priv *priv, u8 reg)
101 {
102 int val;
103
104 val = i2c_smbus_read_byte_data(priv->client, reg);
105 return val;
106 }
107
fpc202_write(struct fpc202_priv * priv,u8 reg,u8 value)108 static int fpc202_write(struct fpc202_priv *priv, u8 reg, u8 value)
109 {
110 return i2c_smbus_write_byte_data(priv->client, reg, value);
111 }
112
fpc202_set_enable(struct fpc202_priv * priv,int enable)113 static void fpc202_set_enable(struct fpc202_priv *priv, int enable)
114 {
115 if (!priv->en_gpio)
116 return;
117
118 gpiod_set_value(priv->en_gpio, enable);
119 }
120
fpc202_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)121 static void fpc202_gpio_set(struct gpio_chip *chip, unsigned int offset,
122 int value)
123 {
124 struct fpc202_priv *priv = gpiochip_get_data(chip);
125 int ret;
126 u8 val;
127
128 if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_IN)
129 return;
130
131 ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B_VAL);
132 if (ret < 0) {
133 dev_err(&priv->client->dev, "Failed to set GPIO %d value! err %d\n", offset, ret);
134 return;
135 }
136
137 val = (u8)ret;
138
139 if (value)
140 val |= BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
141 else
142 val &= ~BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
143
144 fpc202_write(priv, FPC202_REG_OUT_A_OUT_B_VAL, val);
145 }
146
fpc202_gpio_get(struct gpio_chip * chip,unsigned int offset)147 static int fpc202_gpio_get(struct gpio_chip *chip, unsigned int offset)
148 {
149 struct fpc202_priv *priv = gpiochip_get_data(chip);
150 u8 reg, bit;
151 int ret;
152
153 if (offset < FPC202_GPIO_P0_S0_IN_B) {
154 reg = FPC202_REG_IN_A_INT;
155 bit = BIT(4 + offset);
156 } else if (offset < FPC202_GPIO_P0_S0_OUT_A) {
157 reg = FPC202_REG_IN_C_IN_B;
158 bit = BIT(offset - FPC202_GPIO_P0_S0_IN_B);
159 } else {
160 reg = FPC202_REG_OUT_A_OUT_B_VAL;
161 bit = BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
162 }
163
164 ret = fpc202_read(priv, reg);
165 if (ret < 0)
166 return ret;
167
168 return !!(((u8)ret) & bit);
169 }
170
fpc202_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)171 static int fpc202_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
172 {
173 if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_OUT)
174 return -EINVAL;
175
176 return 0;
177 }
178
fpc202_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)179 static int fpc202_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
180 int value)
181 {
182 struct fpc202_priv *priv = gpiochip_get_data(chip);
183 int ret;
184 u8 val;
185
186 if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_IN)
187 return -EINVAL;
188
189 fpc202_gpio_set(chip, offset, value);
190
191 ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B);
192 if (ret < 0)
193 return ret;
194
195 val = (u8)ret | BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
196
197 return fpc202_write(priv, FPC202_REG_OUT_A_OUT_B, val);
198 }
199
200 /*
201 * Set the translation table entry associated with a port and device number.
202 *
203 * Each downstream port of the FPC202 has two fixed aliases corresponding to
204 * device numbers 0 and 1. If one of these aliases is found in an incoming I2C
205 * transfer, it will be translated to the address given by the corresponding
206 * translation table entry.
207 */
fpc202_write_dev_addr(struct fpc202_priv * priv,u32 port_id,int dev_num,u16 addr)208 static int fpc202_write_dev_addr(struct fpc202_priv *priv, u32 port_id, int dev_num, u16 addr)
209 {
210 int ret, reg_mod, reg_aux;
211 u8 val;
212
213 guard(mutex)(&priv->reg_dev_lock);
214
215 reg_mod = FPC202_REG_MOD_DEV(port_id, dev_num);
216 reg_aux = FPC202_REG_AUX_DEV(port_id, dev_num);
217 val = addr & 0x7f;
218
219 ret = fpc202_write(priv, reg_mod, val);
220 if (ret)
221 return ret;
222
223 /*
224 * The FPC202 datasheet is unclear about the role of the AUX registers.
225 * Empirically, writing to them as well seems to be necessary for
226 * address translation to function properly.
227 */
228 ret = fpc202_write(priv, reg_aux, val);
229
230 priv->addr_caches[port_id][dev_num] = val;
231
232 return ret;
233 }
234
fpc202_attach_addr(struct i2c_atr * atr,u32 chan_id,u16 addr,u16 alias)235 static int fpc202_attach_addr(struct i2c_atr *atr, u32 chan_id,
236 u16 addr, u16 alias)
237 {
238 struct fpc202_priv *priv = i2c_atr_get_driver_data(atr);
239
240 dev_dbg(&priv->client->dev, "attaching address 0x%02x to alias 0x%02x\n", addr, alias);
241
242 return fpc202_write_dev_addr(priv, chan_id, fpc202_dev_num_from_alias(alias), addr);
243 }
244
fpc202_detach_addr(struct i2c_atr * atr,u32 chan_id,u16 addr)245 static void fpc202_detach_addr(struct i2c_atr *atr, u32 chan_id,
246 u16 addr)
247 {
248 struct fpc202_priv *priv = i2c_atr_get_driver_data(atr);
249 int dev_num, reg_mod, val;
250
251 for (dev_num = 0; dev_num < 2; dev_num++) {
252 reg_mod = FPC202_REG_MOD_DEV(chan_id, dev_num);
253
254 mutex_lock(&priv->reg_dev_lock);
255
256 val = priv->addr_caches[chan_id][dev_num];
257
258 mutex_unlock(&priv->reg_dev_lock);
259
260 if (val < 0) {
261 dev_err(&priv->client->dev, "failed to read register 0x%x while detaching address 0x%02x\n",
262 reg_mod, addr);
263 return;
264 }
265
266 if (val == (addr & 0x7f)) {
267 fpc202_write_dev_addr(priv, chan_id, dev_num, FPC202_REG_DEV_INVALID);
268 return;
269 }
270 }
271 }
272
273 static const struct i2c_atr_ops fpc202_atr_ops = {
274 .attach_addr = fpc202_attach_addr,
275 .detach_addr = fpc202_detach_addr,
276 };
277
fpc202_probe_port(struct fpc202_priv * priv,struct device_node * i2c_handle,int port_id)278 static int fpc202_probe_port(struct fpc202_priv *priv, struct device_node *i2c_handle, int port_id)
279 {
280 u16 aliases[FPC202_ALIASES_PER_PORT] = { };
281 struct device *dev = &priv->client->dev;
282 struct i2c_atr_adap_desc desc = { };
283 int ret = 0;
284
285 desc.chan_id = port_id;
286 desc.parent = dev;
287 desc.bus_handle = of_node_to_fwnode(i2c_handle);
288 desc.num_aliases = FPC202_ALIASES_PER_PORT;
289
290 fpc202_fill_alias_table(priv->client, aliases, port_id);
291 desc.aliases = aliases;
292
293 ret = i2c_atr_add_adapter(priv->atr, &desc);
294 if (ret)
295 return ret;
296
297 set_bit(port_id, priv->probed_ports);
298
299 ret = fpc202_write_dev_addr(priv, port_id, 0, FPC202_REG_DEV_INVALID);
300 if (ret)
301 return ret;
302
303 return fpc202_write_dev_addr(priv, port_id, 1, FPC202_REG_DEV_INVALID);
304 }
305
fpc202_remove_port(struct fpc202_priv * priv,int port_id)306 static void fpc202_remove_port(struct fpc202_priv *priv, int port_id)
307 {
308 i2c_atr_del_adapter(priv->atr, port_id);
309 clear_bit(port_id, priv->probed_ports);
310 }
311
fpc202_probe(struct i2c_client * client)312 static int fpc202_probe(struct i2c_client *client)
313 {
314 struct device *dev = &client->dev;
315 struct device_node *i2c_handle;
316 struct fpc202_priv *priv;
317 int ret, port_id;
318
319 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
320 if (!priv)
321 return -ENOMEM;
322
323 mutex_init(&priv->reg_dev_lock);
324
325 priv->client = client;
326 i2c_set_clientdata(client, priv);
327
328 priv->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
329 if (IS_ERR(priv->en_gpio)) {
330 ret = PTR_ERR(priv->en_gpio);
331 dev_err(dev, "failed to fetch enable GPIO! err %d\n", ret);
332 goto destroy_mutex;
333 }
334
335 priv->gpio.label = "gpio-fpc202";
336 priv->gpio.base = -1;
337 priv->gpio.direction_input = fpc202_gpio_direction_input;
338 priv->gpio.direction_output = fpc202_gpio_direction_output;
339 priv->gpio.set = fpc202_gpio_set;
340 priv->gpio.get = fpc202_gpio_get;
341 priv->gpio.ngpio = FPC202_GPIO_COUNT;
342 priv->gpio.parent = dev;
343 priv->gpio.owner = THIS_MODULE;
344
345 ret = gpiochip_add_data(&priv->gpio, priv);
346 if (ret) {
347 priv->gpio.parent = NULL;
348 dev_err(dev, "failed to add gpiochip err %d\n", ret);
349 goto disable_gpio;
350 }
351
352 priv->atr = i2c_atr_new(client->adapter, dev, &fpc202_atr_ops, 2, 0);
353 if (IS_ERR(priv->atr)) {
354 ret = PTR_ERR(priv->atr);
355 dev_err(dev, "failed to create i2c atr err %d\n", ret);
356 goto disable_gpio;
357 }
358
359 i2c_atr_set_driver_data(priv->atr, priv);
360
361 bitmap_zero(priv->probed_ports, FPC202_NUM_PORTS);
362
363 for_each_child_of_node(dev->of_node, i2c_handle) {
364 ret = of_property_read_u32(i2c_handle, "reg", &port_id);
365 if (ret) {
366 if (ret == -EINVAL)
367 continue;
368
369 dev_err(dev, "failed to read 'reg' property of child node, err %d\n", ret);
370 goto unregister_chans;
371 }
372
373 if (port_id > FPC202_NUM_PORTS) {
374 dev_err(dev, "port ID %d is out of range!\n", port_id);
375 ret = -EINVAL;
376 goto unregister_chans;
377 }
378
379 ret = fpc202_probe_port(priv, i2c_handle, port_id);
380 if (ret) {
381 dev_err(dev, "Failed to probe port %d, err %d\n", port_id, ret);
382 goto unregister_chans;
383 }
384 }
385
386 goto out;
387
388 unregister_chans:
389 for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
390 fpc202_remove_port(priv, port_id);
391
392 i2c_atr_delete(priv->atr);
393 disable_gpio:
394 fpc202_set_enable(priv, 0);
395 gpiochip_remove(&priv->gpio);
396 destroy_mutex:
397 mutex_destroy(&priv->reg_dev_lock);
398 out:
399 return ret;
400 }
401
fpc202_remove(struct i2c_client * client)402 static void fpc202_remove(struct i2c_client *client)
403 {
404 struct fpc202_priv *priv = i2c_get_clientdata(client);
405 int port_id;
406
407 for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
408 fpc202_remove_port(priv, port_id);
409
410 mutex_destroy(&priv->reg_dev_lock);
411
412 i2c_atr_delete(priv->atr);
413
414 fpc202_set_enable(priv, 0);
415 gpiochip_remove(&priv->gpio);
416 }
417
418 static const struct of_device_id fpc202_of_match[] = {
419 { .compatible = "ti,fpc202" },
420 {}
421 };
422 MODULE_DEVICE_TABLE(of, fpc202_of_match);
423
424 static struct i2c_driver fpc202_driver = {
425 .driver = {
426 .name = "fpc202",
427 .of_match_table = fpc202_of_match,
428 },
429 .probe = fpc202_probe,
430 .remove = fpc202_remove,
431 };
432
433 module_i2c_driver(fpc202_driver);
434
435 MODULE_AUTHOR("Romain Gantois <romain.gantois@bootlin.com>");
436 MODULE_DESCRIPTION("TI FPC202 Dual Port Controller driver");
437 MODULE_LICENSE("GPL");
438 MODULE_IMPORT_NS("I2C_ATR");
439