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