xref: /linux/drivers/misc/ti_fpc202.c (revision 0227b49b50276657243e54f5609e65c4f0eaaf4d)
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 int 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 	ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B_VAL);
129 	if (ret < 0) {
130 		dev_err(&priv->client->dev, "Failed to set GPIO %d value! err %d\n", offset, ret);
131 		return ret;
132 	}
133 
134 	val = (u8)ret;
135 
136 	if (value)
137 		val |= BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
138 	else
139 		val &= ~BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
140 
141 	return fpc202_write(priv, FPC202_REG_OUT_A_OUT_B_VAL, val);
142 }
143 
fpc202_gpio_get(struct gpio_chip * chip,unsigned int offset)144 static int fpc202_gpio_get(struct gpio_chip *chip, unsigned int offset)
145 {
146 	struct fpc202_priv *priv = gpiochip_get_data(chip);
147 	u8 reg, bit;
148 	int ret;
149 
150 	if (offset < FPC202_GPIO_P0_S0_IN_B) {
151 		reg = FPC202_REG_IN_A_INT;
152 		bit = BIT(4 + offset);
153 	} else if (offset < FPC202_GPIO_P0_S0_OUT_A) {
154 		reg = FPC202_REG_IN_C_IN_B;
155 		bit = BIT(offset - FPC202_GPIO_P0_S0_IN_B);
156 	} else {
157 		reg = FPC202_REG_OUT_A_OUT_B_VAL;
158 		bit = BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
159 	}
160 
161 	ret = fpc202_read(priv, reg);
162 	if (ret < 0)
163 		return ret;
164 
165 	return !!(((u8)ret) & bit);
166 }
167 
fpc202_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)168 static int fpc202_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
169 {
170 	if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_OUT)
171 		return -EINVAL;
172 
173 	return 0;
174 }
175 
fpc202_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)176 static int fpc202_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
177 					int value)
178 {
179 	struct fpc202_priv *priv = gpiochip_get_data(chip);
180 	int ret;
181 	u8 val;
182 
183 	if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_IN)
184 		return -EINVAL;
185 
186 	fpc202_gpio_set(chip, offset, value);
187 
188 	ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B);
189 	if (ret < 0)
190 		return ret;
191 
192 	val = (u8)ret | BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
193 
194 	return fpc202_write(priv, FPC202_REG_OUT_A_OUT_B, val);
195 }
196 
197 /*
198  * Set the translation table entry associated with a port and device number.
199  *
200  * Each downstream port of the FPC202 has two fixed aliases corresponding to
201  * device numbers 0 and 1. If one of these aliases is found in an incoming I2C
202  * transfer, it will be translated to the address given by the corresponding
203  * translation table entry.
204  */
fpc202_write_dev_addr(struct fpc202_priv * priv,u32 port_id,int dev_num,u16 addr)205 static int fpc202_write_dev_addr(struct fpc202_priv *priv, u32 port_id, int dev_num, u16 addr)
206 {
207 	int ret, reg_mod, reg_aux;
208 	u8 val;
209 
210 	guard(mutex)(&priv->reg_dev_lock);
211 
212 	reg_mod = FPC202_REG_MOD_DEV(port_id, dev_num);
213 	reg_aux = FPC202_REG_AUX_DEV(port_id, dev_num);
214 	val = addr & 0x7f;
215 
216 	ret = fpc202_write(priv, reg_mod, val);
217 	if (ret)
218 		return ret;
219 
220 	/*
221 	 * The FPC202 datasheet is unclear about the role of the AUX registers.
222 	 * Empirically, writing to them as well seems to be necessary for
223 	 * address translation to function properly.
224 	 */
225 	ret = fpc202_write(priv, reg_aux, val);
226 
227 	priv->addr_caches[port_id][dev_num] = val;
228 
229 	return ret;
230 }
231 
fpc202_attach_addr(struct i2c_atr * atr,u32 chan_id,u16 addr,u16 alias)232 static int fpc202_attach_addr(struct i2c_atr *atr, u32 chan_id,
233 			      u16 addr, u16 alias)
234 {
235 	struct fpc202_priv *priv = i2c_atr_get_driver_data(atr);
236 
237 	dev_dbg(&priv->client->dev, "attaching address 0x%02x to alias 0x%02x\n", addr, alias);
238 
239 	return fpc202_write_dev_addr(priv, chan_id, fpc202_dev_num_from_alias(alias), addr);
240 }
241 
fpc202_detach_addr(struct i2c_atr * atr,u32 chan_id,u16 addr)242 static void fpc202_detach_addr(struct i2c_atr *atr, u32 chan_id,
243 			       u16 addr)
244 {
245 	struct fpc202_priv *priv = i2c_atr_get_driver_data(atr);
246 	int dev_num, reg_mod, val;
247 
248 	for (dev_num = 0; dev_num < 2; dev_num++) {
249 		reg_mod = FPC202_REG_MOD_DEV(chan_id, dev_num);
250 
251 		mutex_lock(&priv->reg_dev_lock);
252 
253 		val = priv->addr_caches[chan_id][dev_num];
254 
255 		mutex_unlock(&priv->reg_dev_lock);
256 
257 		if (val < 0) {
258 			dev_err(&priv->client->dev, "failed to read register 0x%x while detaching address 0x%02x\n",
259 				reg_mod, addr);
260 			return;
261 		}
262 
263 		if (val == (addr & 0x7f)) {
264 			fpc202_write_dev_addr(priv, chan_id, dev_num, FPC202_REG_DEV_INVALID);
265 			return;
266 		}
267 	}
268 }
269 
270 static const struct i2c_atr_ops fpc202_atr_ops = {
271 	.attach_addr = fpc202_attach_addr,
272 	.detach_addr = fpc202_detach_addr,
273 };
274 
fpc202_probe_port(struct fpc202_priv * priv,struct device_node * i2c_handle,int port_id)275 static int fpc202_probe_port(struct fpc202_priv *priv, struct device_node *i2c_handle, int port_id)
276 {
277 	u16 aliases[FPC202_ALIASES_PER_PORT] = { };
278 	struct device *dev = &priv->client->dev;
279 	struct i2c_atr_adap_desc desc = { };
280 	int ret = 0;
281 
282 	desc.chan_id = port_id;
283 	desc.parent = dev;
284 	desc.bus_handle = of_fwnode_handle(i2c_handle);
285 	desc.num_aliases = FPC202_ALIASES_PER_PORT;
286 
287 	fpc202_fill_alias_table(priv->client, aliases, port_id);
288 	desc.aliases = aliases;
289 
290 	ret = i2c_atr_add_adapter(priv->atr, &desc);
291 	if (ret)
292 		return ret;
293 
294 	set_bit(port_id, priv->probed_ports);
295 
296 	ret = fpc202_write_dev_addr(priv, port_id, 0, FPC202_REG_DEV_INVALID);
297 	if (ret)
298 		return ret;
299 
300 	return fpc202_write_dev_addr(priv, port_id, 1, FPC202_REG_DEV_INVALID);
301 }
302 
fpc202_remove_port(struct fpc202_priv * priv,int port_id)303 static void fpc202_remove_port(struct fpc202_priv *priv, int port_id)
304 {
305 	i2c_atr_del_adapter(priv->atr, port_id);
306 	clear_bit(port_id, priv->probed_ports);
307 }
308 
fpc202_probe(struct i2c_client * client)309 static int fpc202_probe(struct i2c_client *client)
310 {
311 	struct device *dev = &client->dev;
312 	struct device_node *i2c_handle;
313 	struct fpc202_priv *priv;
314 	int ret, port_id;
315 
316 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
317 	if (!priv)
318 		return -ENOMEM;
319 
320 	mutex_init(&priv->reg_dev_lock);
321 
322 	priv->client = client;
323 	i2c_set_clientdata(client, priv);
324 
325 	priv->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
326 	if (IS_ERR(priv->en_gpio)) {
327 		ret = PTR_ERR(priv->en_gpio);
328 		dev_err(dev, "failed to fetch enable GPIO! err %d\n", ret);
329 		goto destroy_mutex;
330 	}
331 
332 	priv->gpio.label = "gpio-fpc202";
333 	priv->gpio.base = -1;
334 	priv->gpio.direction_input = fpc202_gpio_direction_input;
335 	priv->gpio.direction_output = fpc202_gpio_direction_output;
336 	priv->gpio.set = fpc202_gpio_set;
337 	priv->gpio.get = fpc202_gpio_get;
338 	priv->gpio.ngpio = FPC202_GPIO_COUNT;
339 	priv->gpio.parent = dev;
340 	priv->gpio.owner = THIS_MODULE;
341 
342 	ret = gpiochip_add_data(&priv->gpio, priv);
343 	if (ret) {
344 		priv->gpio.parent = NULL;
345 		dev_err(dev, "failed to add gpiochip err %d\n", ret);
346 		goto disable_gpio;
347 	}
348 
349 	priv->atr = i2c_atr_new(client->adapter, dev, &fpc202_atr_ops, 2, 0);
350 	if (IS_ERR(priv->atr)) {
351 		ret = PTR_ERR(priv->atr);
352 		dev_err(dev, "failed to create i2c atr err %d\n", ret);
353 		goto disable_gpio;
354 	}
355 
356 	i2c_atr_set_driver_data(priv->atr, priv);
357 
358 	bitmap_zero(priv->probed_ports, FPC202_NUM_PORTS);
359 
360 	for_each_child_of_node(dev->of_node, i2c_handle) {
361 		ret = of_property_read_u32(i2c_handle, "reg", &port_id);
362 		if (ret) {
363 			if (ret == -EINVAL)
364 				continue;
365 
366 			dev_err(dev, "failed to read 'reg' property of child node, err %d\n", ret);
367 			goto unregister_chans;
368 		}
369 
370 		if (port_id > FPC202_NUM_PORTS) {
371 			dev_err(dev, "port ID %d is out of range!\n", port_id);
372 			ret = -EINVAL;
373 			goto unregister_chans;
374 		}
375 
376 		ret = fpc202_probe_port(priv, i2c_handle, port_id);
377 		if (ret) {
378 			dev_err(dev, "Failed to probe port %d, err %d\n", port_id, ret);
379 			goto unregister_chans;
380 		}
381 	}
382 
383 	goto out;
384 
385 unregister_chans:
386 	for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
387 		fpc202_remove_port(priv, port_id);
388 
389 	i2c_atr_delete(priv->atr);
390 disable_gpio:
391 	fpc202_set_enable(priv, 0);
392 	gpiochip_remove(&priv->gpio);
393 destroy_mutex:
394 	mutex_destroy(&priv->reg_dev_lock);
395 out:
396 	return ret;
397 }
398 
fpc202_remove(struct i2c_client * client)399 static void fpc202_remove(struct i2c_client *client)
400 {
401 	struct fpc202_priv *priv = i2c_get_clientdata(client);
402 	int port_id;
403 
404 	for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
405 		fpc202_remove_port(priv, port_id);
406 
407 	mutex_destroy(&priv->reg_dev_lock);
408 
409 	i2c_atr_delete(priv->atr);
410 
411 	fpc202_set_enable(priv, 0);
412 	gpiochip_remove(&priv->gpio);
413 }
414 
415 static const struct of_device_id fpc202_of_match[] = {
416 	{ .compatible = "ti,fpc202" },
417 	{}
418 };
419 MODULE_DEVICE_TABLE(of, fpc202_of_match);
420 
421 static struct i2c_driver fpc202_driver = {
422 	.driver = {
423 		.name = "fpc202",
424 		.of_match_table = fpc202_of_match,
425 	},
426 	.probe = fpc202_probe,
427 	.remove = fpc202_remove,
428 };
429 
430 module_i2c_driver(fpc202_driver);
431 
432 MODULE_AUTHOR("Romain Gantois <romain.gantois@bootlin.com>");
433 MODULE_DESCRIPTION("TI FPC202 Dual Port Controller driver");
434 MODULE_LICENSE("GPL");
435 MODULE_IMPORT_NS("I2C_ATR");
436