1 /*
2  * Copyright (c) 2020 Vestas Wind Systems A/S
3  * Copyright (c) 2017 Linaro Ltd.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT gpio_i2c
9 
10 /**
11  * @file
12  * @brief Driver for software driven I2C using GPIO lines
13  *
14  * This driver implements an I2C interface by driving two GPIO lines under
15  * software control.
16  *
17  * The GPIO pins used must be configured (through devicetree and pinmux) with
18  * suitable flags, i.e. the SDA pin as open-collector/open-drain with a pull-up
19  * resistor (possibly as an external component attached to the pin).
20  *
21  * When the SDA pin is read it must return the state of the physical hardware
22  * line, not just the last state written to it for output.
23  *
24  * The SCL pin should be configured in the same manner as SDA, or, if it is
25  * known that the hardware attached to pin doesn't attempt clock stretching,
26  * then the SCL pin may be a push/pull output.
27  */
28 
29 #include <zephyr/device.h>
30 #include <errno.h>
31 #include <zephyr/drivers/gpio.h>
32 #include <zephyr/drivers/i2c.h>
33 
34 #include <zephyr/logging/log.h>
35 LOG_MODULE_REGISTER(i2c_gpio);
36 
37 #include "i2c-priv.h"
38 #include "i2c_bitbang.h"
39 
40 /* Driver config */
41 struct i2c_gpio_config {
42 	struct gpio_dt_spec scl_gpio;
43 	struct gpio_dt_spec sda_gpio;
44 	uint32_t bitrate;
45 };
46 
47 /* Driver instance data */
48 struct i2c_gpio_context {
49 	struct i2c_bitbang bitbang;	/* Bit-bang library data */
50 	struct k_mutex mutex;
51 };
52 
i2c_gpio_set_scl(void * io_context,int state)53 static void i2c_gpio_set_scl(void *io_context, int state)
54 {
55 	const struct i2c_gpio_config *config = io_context;
56 
57 	gpio_pin_set_dt(&config->scl_gpio, state);
58 }
59 
i2c_gpio_set_sda(void * io_context,int state)60 static void i2c_gpio_set_sda(void *io_context, int state)
61 {
62 	const struct i2c_gpio_config *config = io_context;
63 
64 	gpio_pin_set_dt(&config->sda_gpio, state);
65 }
66 
i2c_gpio_get_sda(void * io_context)67 static int i2c_gpio_get_sda(void *io_context)
68 {
69 	const struct i2c_gpio_config *config = io_context;
70 	int rc = gpio_pin_get_dt(&config->sda_gpio);
71 
72 	/* Default high as that would be a NACK */
73 	return rc != 0;
74 }
75 
76 static const struct i2c_bitbang_io io_fns = {
77 	.set_scl = &i2c_gpio_set_scl,
78 	.set_sda = &i2c_gpio_set_sda,
79 	.get_sda = &i2c_gpio_get_sda,
80 };
81 
i2c_gpio_configure(const struct device * dev,uint32_t dev_config)82 static int i2c_gpio_configure(const struct device *dev, uint32_t dev_config)
83 {
84 	struct i2c_gpio_context *context = dev->data;
85 	int rc;
86 
87 	k_mutex_lock(&context->mutex, K_FOREVER);
88 
89 	rc = i2c_bitbang_configure(&context->bitbang, dev_config);
90 
91 	k_mutex_unlock(&context->mutex);
92 
93 	return rc;
94 }
95 
i2c_gpio_get_config(const struct device * dev,uint32_t * config)96 static int i2c_gpio_get_config(const struct device *dev, uint32_t *config)
97 {
98 	struct i2c_gpio_context *context = dev->data;
99 	int rc;
100 
101 	k_mutex_lock(&context->mutex, K_FOREVER);
102 
103 	rc = i2c_bitbang_get_config(&context->bitbang, config);
104 	if (rc < 0) {
105 		LOG_ERR("I2C controller not configured: %d", rc);
106 	}
107 
108 	k_mutex_unlock(&context->mutex);
109 
110 	return rc;
111 }
112 
i2c_gpio_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t slave_address)113 static int i2c_gpio_transfer(const struct device *dev, struct i2c_msg *msgs,
114 				uint8_t num_msgs, uint16_t slave_address)
115 {
116 	struct i2c_gpio_context *context = dev->data;
117 	int rc;
118 
119 	k_mutex_lock(&context->mutex, K_FOREVER);
120 
121 	rc = i2c_bitbang_transfer(&context->bitbang, msgs, num_msgs,
122 				    slave_address);
123 
124 	k_mutex_unlock(&context->mutex);
125 
126 	return rc;
127 }
128 
i2c_gpio_recover_bus(const struct device * dev)129 static int i2c_gpio_recover_bus(const struct device *dev)
130 {
131 	struct i2c_gpio_context *context = dev->data;
132 	int rc;
133 
134 	k_mutex_lock(&context->mutex, K_FOREVER);
135 
136 	rc = i2c_bitbang_recover_bus(&context->bitbang);
137 
138 	k_mutex_unlock(&context->mutex);
139 
140 	return rc;
141 }
142 
143 static DEVICE_API(i2c, api) = {
144 	.configure = i2c_gpio_configure,
145 	.get_config = i2c_gpio_get_config,
146 	.transfer = i2c_gpio_transfer,
147 	.recover_bus = i2c_gpio_recover_bus,
148 #ifdef CONFIG_I2C_RTIO
149 	.iodev_submit = i2c_iodev_submit_fallback,
150 #endif
151 };
152 
i2c_gpio_init(const struct device * dev)153 static int i2c_gpio_init(const struct device *dev)
154 {
155 	struct i2c_gpio_context *context = dev->data;
156 	const struct i2c_gpio_config *config = dev->config;
157 	uint32_t bitrate_cfg;
158 	int err;
159 
160 	if (!gpio_is_ready_dt(&config->scl_gpio)) {
161 		LOG_ERR("SCL GPIO device not ready");
162 		return -ENODEV;
163 	}
164 
165 	err = gpio_pin_configure_dt(&config->scl_gpio, GPIO_OUTPUT_HIGH);
166 	if (err) {
167 		LOG_ERR("failed to configure SCL GPIO pin (err %d)", err);
168 		return err;
169 	}
170 
171 	if (!gpio_is_ready_dt(&config->sda_gpio)) {
172 		LOG_ERR("SDA GPIO device not ready");
173 		return -ENODEV;
174 	}
175 
176 	err = gpio_pin_configure_dt(&config->sda_gpio,
177 				    GPIO_INPUT | GPIO_OUTPUT_HIGH);
178 	if (err == -ENOTSUP) {
179 		err = gpio_pin_configure_dt(&config->sda_gpio,
180 					    GPIO_OUTPUT_HIGH);
181 	}
182 	if (err) {
183 		LOG_ERR("failed to configure SDA GPIO pin (err %d)", err);
184 		return err;
185 	}
186 
187 	i2c_bitbang_init(&context->bitbang, &io_fns, (void *)config);
188 
189 	bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
190 	err = i2c_bitbang_configure(&context->bitbang,
191 				    I2C_MODE_CONTROLLER | bitrate_cfg);
192 	if (err) {
193 		LOG_ERR("failed to configure I2C bitbang (err %d)", err);
194 		return err;
195 	}
196 
197 	err = k_mutex_init(&context->mutex);
198 	if (err) {
199 		LOG_ERR("Failed to create the i2c lock mutex : %d", err);
200 		return err;
201 	}
202 
203 	return 0;
204 }
205 
206 #define	DEFINE_I2C_GPIO(_num)						\
207 									\
208 static struct i2c_gpio_context i2c_gpio_dev_data_##_num;		\
209 									\
210 static const struct i2c_gpio_config i2c_gpio_dev_cfg_##_num = {		\
211 	.scl_gpio	= GPIO_DT_SPEC_INST_GET(_num, scl_gpios),	\
212 	.sda_gpio	= GPIO_DT_SPEC_INST_GET(_num, sda_gpios),	\
213 	.bitrate	= DT_INST_PROP(_num, clock_frequency),		\
214 };									\
215 									\
216 I2C_DEVICE_DT_INST_DEFINE(_num,						\
217 	    i2c_gpio_init,						\
218 	    NULL,							\
219 	    &i2c_gpio_dev_data_##_num,					\
220 	    &i2c_gpio_dev_cfg_##_num,					\
221 	    POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, &api);
222 
223 DT_INST_FOREACH_STATUS_OKAY(DEFINE_I2C_GPIO)
224