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 
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 
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 
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 
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 
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 
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 
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 
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 
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  */
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 
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 
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 
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 
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 
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 
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