1 /*
2  * Copyright (c) 2020 Innoseis BV
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/logging/log.h>
13 #include <stdint.h>
14 
15 LOG_MODULE_REGISTER(tca954x, CONFIG_I2C_LOG_LEVEL);
16 
17 struct tca954x_root_config {
18 	struct i2c_dt_spec i2c;
19 	uint8_t nchans;
20 	const struct gpio_dt_spec reset_gpios;
21 };
22 
23 struct tca954x_root_data {
24 	struct k_mutex lock;
25 	uint8_t selected_chan;
26 };
27 
28 struct tca954x_channel_config {
29 	const struct device *root;
30 	uint8_t chan_mask;
31 };
32 
33 static inline struct tca954x_root_data *
get_root_data_from_channel(const struct device * dev)34 get_root_data_from_channel(const struct device *dev)
35 {
36 	const struct tca954x_channel_config *channel_config = dev->config;
37 
38 	return channel_config->root->data;
39 }
40 
41 static inline const struct tca954x_root_config *
get_root_config_from_channel(const struct device * dev)42 get_root_config_from_channel(const struct device *dev)
43 {
44 	const struct tca954x_channel_config *channel_config = dev->config;
45 
46 	return channel_config->root->config;
47 }
48 
tca954x_configure(const struct device * dev,uint32_t dev_config)49 static int tca954x_configure(const struct device *dev, uint32_t dev_config)
50 {
51 	const struct tca954x_root_config *cfg =
52 			get_root_config_from_channel(dev);
53 
54 	return i2c_configure(cfg->i2c.bus, dev_config);
55 }
56 
tca954x_set_channel(const struct device * dev,uint8_t select_mask)57 static int tca954x_set_channel(const struct device *dev, uint8_t select_mask)
58 {
59 	int res = 0;
60 	struct tca954x_root_data *data = dev->data;
61 	const struct tca954x_root_config *cfg = dev->config;
62 
63 	/* Only select the channel if its different from the last channel */
64 	if (data->selected_chan != select_mask) {
65 		res = i2c_write_dt(&cfg->i2c, &select_mask, 1);
66 		if (res == 0) {
67 			data->selected_chan = select_mask;
68 		} else {
69 			LOG_DBG("tca954x: failed to set channel");
70 		}
71 	}
72 	return res;
73 }
74 
tca954x_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)75 static int tca954x_transfer(const struct device *dev,
76 			     struct i2c_msg *msgs,
77 			     uint8_t num_msgs,
78 			     uint16_t addr)
79 {
80 	struct tca954x_root_data *data = get_root_data_from_channel(dev);
81 	const struct tca954x_root_config *config =
82 			get_root_config_from_channel(dev);
83 	const struct tca954x_channel_config *down_cfg = dev->config;
84 	int res;
85 
86 	res = k_mutex_lock(&data->lock, K_MSEC(5000));
87 	if (res != 0) {
88 		return res;
89 	}
90 
91 	res = tca954x_set_channel(down_cfg->root, down_cfg->chan_mask);
92 	if (res != 0) {
93 		goto end_trans;
94 	}
95 
96 	res = i2c_transfer(config->i2c.bus, msgs, num_msgs, addr);
97 
98 end_trans:
99 	k_mutex_unlock(&data->lock);
100 	return res;
101 }
102 
tca954x_root_init(const struct device * dev)103 static int tca954x_root_init(const struct device *dev)
104 {
105 	struct tca954x_root_data *i2c_tca954x = dev->data;
106 	const struct tca954x_root_config *config = dev->config;
107 
108 	if (!device_is_ready(config->i2c.bus)) {
109 		LOG_ERR("I2C bus %s not ready", config->i2c.bus->name);
110 		return -ENODEV;
111 	}
112 
113 	/* If the RESET line is available, configure it. */
114 	if (config->reset_gpios.port) {
115 		if (!device_is_ready(config->reset_gpios.port)) {
116 			LOG_ERR("%s is not ready",
117 				config->reset_gpios.port->name);
118 			return -ENODEV;
119 		}
120 
121 		if (gpio_pin_configure_dt(&config->reset_gpios, GPIO_OUTPUT)) {
122 			LOG_ERR("%s: failed to configure RESET line", dev->name);
123 			return -EIO;
124 		}
125 
126 		/* Deassert reset line */
127 		gpio_pin_set_dt(&config->reset_gpios, 0);
128 	}
129 
130 	i2c_tca954x->selected_chan = 0;
131 
132 	return 0;
133 }
134 
tca954x_channel_init(const struct device * dev)135 static int tca954x_channel_init(const struct device *dev)
136 {
137 	const struct tca954x_channel_config *chan_cfg = dev->config;
138 	const struct tca954x_root_config *root_cfg =
139 			get_root_config_from_channel(dev);
140 
141 	if (!device_is_ready(chan_cfg->root)) {
142 		LOG_ERR("I2C mux root %s not ready", chan_cfg->root->name);
143 		return -ENODEV;
144 	}
145 
146 	if (chan_cfg->chan_mask >= BIT(root_cfg->nchans)) {
147 		LOG_ERR("Wrong DTS address provided for %s", dev->name);
148 		return -EINVAL;
149 	}
150 
151 	return 0;
152 }
153 
154 const struct i2c_driver_api tca954x_api_funcs = {
155 	.configure = tca954x_configure,
156 	.transfer = tca954x_transfer,
157 };
158 
159 #define TCA954x_CHILD_DEFINE(node_id, n)				    \
160 	static const struct tca954x_channel_config			    \
161 		tca##n##a_down_config_##node_id = {			    \
162 		.chan_mask = BIT(DT_REG_ADDR(node_id)),			    \
163 		.root = DEVICE_DT_GET(DT_PARENT(node_id)),		    \
164 	};								    \
165 	DEVICE_DT_DEFINE(node_id,					    \
166 			 tca954x_channel_init,				    \
167 			 NULL,						    \
168 			 NULL,						    \
169 			 &tca##n##a_down_config_##node_id,		    \
170 			 POST_KERNEL, CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO, \
171 			 &tca954x_api_funcs);
172 
173 #define TCA954x_ROOT_DEFINE(n, inst, ch)				          \
174 	static const struct tca954x_root_config tca##n##a_cfg_##inst = {          \
175 		.i2c = I2C_DT_SPEC_INST_GET(inst),				  \
176 		.nchans = ch,							  \
177 		.reset_gpios = GPIO_DT_SPEC_GET_OR(			          \
178 				DT_INST(inst, ti_tca##n##a), reset_gpios, {0}),	  \
179 	};								          \
180 	static struct tca954x_root_data tca##n##a_data_##inst = {		  \
181 		.lock = Z_MUTEX_INITIALIZER(tca##n##a_data_##inst.lock),	  \
182 	};									  \
183 	I2C_DEVICE_DT_DEFINE(DT_INST(inst, ti_tca##n##a),			  \
184 			      tca954x_root_init, NULL,				  \
185 			      &tca##n##a_data_##inst, &tca##n##a_cfg_##inst,	  \
186 			      POST_KERNEL, CONFIG_I2C_TCA954X_ROOT_INIT_PRIO,	  \
187 			      NULL);						  \
188 	DT_FOREACH_CHILD_VARGS(DT_INST(inst, ti_tca##n##a), TCA954x_CHILD_DEFINE, n);
189 
190 /*
191  * TCA9546A: 4 channels
192  */
193 #define TCA9546A_INIT(n) TCA954x_ROOT_DEFINE(9546, n, 4)
194 #undef DT_DRV_COMPAT
195 #define DT_DRV_COMPAT ti_tca9546a
196 DT_INST_FOREACH_STATUS_OKAY(TCA9546A_INIT)
197 
198 /*
199  * TCA9548A: 8 channels
200  */
201 #define TCA9548A_INIT(n) TCA954x_ROOT_DEFINE(9548, n, 8)
202 #undef DT_DRV_COMPAT
203 #define DT_DRV_COMPAT ti_tca9548a
204 DT_INST_FOREACH_STATUS_OKAY(TCA9548A_INIT)
205