diff --git a/drivers/i2c/Kconfig.gpio b/drivers/i2c/Kconfig.gpio index edc0a640ad9..95be9acadc3 100644 --- a/drivers/i2c/Kconfig.gpio +++ b/drivers/i2c/Kconfig.gpio @@ -6,143 +6,3 @@ config I2C_GPIO select I2C_BITBANG help Enable software driven (bit banging) I2C support using GPIO pins - -# ---------- Port 0 ---------- - -config I2C_GPIO_0 - bool "Enable GPIO Bit Bang I2C device 0" - depends on I2C_GPIO - help - This tells the driver to configure the I2C device at boot, depending - on the additional configuration options below. - -if I2C_GPIO_0 - -config I2C_GPIO_0_NAME - string "GPIO Bit Bang I2C device 0 device name" - default "I2C_0" - help - This is the device name for the I2C device, and is included in the - device struct. - -config I2C_GPIO_0_GPIO - string "Bit Bang I2C device 0 GPIO name" - help - This is the name of the GPIO device that controls the I2C lines. - -config I2C_GPIO_0_SCL_PIN - int "Bit Bang I2C device 0 GPIO pin number for SCL" - help - This is the GPIO pin number for the I2S SCL line - -config I2C_GPIO_0_SDA_PIN - int "Bit Bang I2C device 0 GPIO pin number for SDA" - help - This is the GPIO pin number for the I2S SDA line - -endif # I2C_GPIO_0 - -# ---------- Port 1 ---------- - -config I2C_GPIO_1 - bool "Enable GPIO Bit Bang I2C device 1" - depends on I2C_GPIO - help - This tells the driver to configure the I2C device at boot, depending - on the additional configuration options below. - -if I2C_GPIO_1 - -config I2C_GPIO_1_NAME - string "Bit Bang I2C device 1 device name" - default "I2C_1" - help - This is the device name for the I2C device, and is included in the - device struct. - -config I2C_GPIO_1_GPIO - string "Bit Bang I2C device 1 GPIO name" - help - This is the name of the GPIO device that controls the I2C lines. - -config I2C_GPIO_1_SCL_PIN - int "Bit Bang I2C device 1 GPIO pin number for SCL" - help - This is the GPIO pin number for the I2S SCL line - -config I2C_GPIO_1_SDA_PIN - int "Bit Bang I2C device 1 GPIO pin number for SDA" - help - This is the GPIO pin number for the I2S SDA line - -endif # I2C_GPIO_1 - -# ---------- Port 2 ---------- - -config I2C_GPIO_2 - bool "Enable GPIO Bit Bang I2C device 2" - depends on I2C_GPIO - help - This tells the driver to configure the I2C device at boot, depending - on the additional configuration options below. - -if I2C_GPIO_2 - -config I2C_GPIO_2_NAME - string "Bit Bang I2C device 2 device name" - default "I2C_2" - help - This is the device name for the I2C device, and is included in the - device struct. - -config I2C_GPIO_2_GPIO - string "Bit Bang I2C device 2 GPIO name" - help - This is the name of the GPIO device that controls the I2C lines. - -config I2C_GPIO_2_SCL_PIN - int "Bit Bang I2C device 2 GPIO pin number for SCL" - help - This is the GPIO pin number for the I2S SCL line - -config I2C_GPIO_2_SDA_PIN - int "Bit Bang I2C device 2 GPIO pin number for SDA" - help - This is the GPIO pin number for the I2S SDA line - -endif # I2C_GPIO_2 - -# ---------- Port 3 ---------- - -config I2C_GPIO_3 - bool "Enable GPIO Bit Bang I2C device 3" - depends on I2C_GPIO - help - This tells the driver to configure the I2C device at boot, depending - on the additional configuration options below. - -if I2C_GPIO_3 - -config I2C_GPIO_3_NAME - string "Bit Bang I2C device 3 device name" - default "I2C_3" - help - This is the device name for the I2C device, and is included in the - device struct. - -config I2C_GPIO_3_GPIO - string "Bit Bang I2C device 3 GPIO name" - help - This is the name of the GPIO device that controls the I2C lines. - -config I2C_GPIO_3_SCL_PIN - int "Bit Bang I2C device 3 GPIO pin number for SCL" - help - This is the GPIO pin number for the I2C SCL line - -config I2C_GPIO_3_SDA_PIN - int "Bit Bang I2C device 3 GPIO pin number for SDA" - help - This is the GPIO pin number for the I2C SDA line - -endif # I2C_GPIO_3 diff --git a/drivers/i2c/i2c_gpio.c b/drivers/i2c/i2c_gpio.c index 01c6dea920d..36a35d77629 100644 --- a/drivers/i2c/i2c_gpio.c +++ b/drivers/i2c/i2c_gpio.c @@ -1,16 +1,19 @@ /* + * Copyright (c) 2020 Vestas Wind Systems A/S * Copyright (c) 2017 Linaro Ltd. * * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT gpio_i2c + /** * @file * @brief Driver for software driven I2C using GPIO lines * * This driver implements an I2C interface by driving two GPIO lines under - * software control. The GPIO pins used must be preconfigured to to a suitable - * state, i.e. the SDA pin as open-colector/open-drain with a pull-up resistor + * software control. The GPIO pins used must be configured (through devicetree and pinmux) with suitable + * flags, i.e. the SDA pin as open-colector/open-drain with a pull-up resistor * (possibly as an external component attached to the pin). When the SDA pin * is read it must return the state of the physical hardware line, not just the * last state written to it for output. @@ -24,41 +27,51 @@ #include #include #include + +#include +LOG_MODULE_REGISTER(i2c_gpio); + +#include "i2c-priv.h" #include "i2c_bitbang.h" /* Driver config */ struct i2c_gpio_config { - char *gpio_name; - u8_t scl_pin; - u8_t sda_pin; + const char *scl_gpio_name; + const char *sda_gpio_name; + gpio_pin_t scl_pin; + gpio_pin_t sda_pin; + gpio_dt_flags_t scl_flags; + gpio_dt_flags_t sda_flags; + u32_t bitrate; }; /* Driver instance data */ struct i2c_gpio_context { struct i2c_bitbang bitbang; /* Bit-bang library data */ - struct device *gpio; /* GPIO used for I2C lines */ - u8_t scl_pin; /* Pin on gpio used for SCL line */ - u8_t sda_pin; /* Pin on gpio used for SDA line */ + struct device *scl_gpio; /* GPIO used for I2C SCL line */ + struct device *sda_gpio; /* GPIO used for I2C SDA line */ + gpio_pin_t scl_pin; /* Pin on gpio used for SCL line */ + gpio_pin_t sda_pin; /* Pin on gpio used for SDA line */ }; static void i2c_gpio_set_scl(void *io_context, int state) { struct i2c_gpio_context *context = io_context; - gpio_pin_set(context->gpio, context->scl_pin, state); + gpio_pin_set(context->scl_gpio, context->scl_pin, state); } static void i2c_gpio_set_sda(void *io_context, int state) { struct i2c_gpio_context *context = io_context; - gpio_pin_set(context->gpio, context->sda_pin, state); + gpio_pin_set(context->sda_gpio, context->sda_pin, state); } static int i2c_gpio_get_sda(void *io_context) { struct i2c_gpio_context *context = io_context; - int rc = gpio_pin_get(context->gpio, context->sda_pin); + int rc = gpio_pin_get(context->sda_gpio, context->sda_pin); /* Default high as that would be a NACK */ return rc != 0; @@ -83,7 +96,7 @@ static int i2c_gpio_transfer(struct device *dev, struct i2c_msg *msgs, struct i2c_gpio_context *context = dev->driver_data; return i2c_bitbang_transfer(&context->bitbang, msgs, num_msgs, - slave_address); + slave_address); } static struct i2c_driver_api api = { @@ -95,16 +108,48 @@ static int i2c_gpio_init(struct device *dev) { struct i2c_gpio_context *context = dev->driver_data; const struct i2c_gpio_config *config = dev->config->config_info; + u32_t bitrate_cfg; + int err; - context->gpio = device_get_binding(config->gpio_name); - if (!context->gpio) { + context->scl_gpio = device_get_binding(config->scl_gpio_name); + if (!context->scl_gpio) { + LOG_ERR("failed to get SCL GPIO device"); return -EINVAL; } + + err = gpio_config(context->scl_gpio, config->scl_pin, + config->scl_flags | GPIO_OUTPUT_HIGH); + if (err) { + LOG_ERR("failed to configure SCL GPIO pin (err %d)", err); + return err; + } + + context->sda_gpio = device_get_binding(config->sda_gpio_name); + if (!context->sda_gpio) { + LOG_ERR("failed to get SCL GPIO device"); + return -EINVAL; + } + + err = gpio_config(context->sda_gpio, config->sda_pin, + config->sda_flags | GPIO_OUTPUT_HIGH); + if (err) { + LOG_ERR("failed to configure SDA GPIO pin (err %d)", err); + return err; + } + context->sda_pin = config->sda_pin; context->scl_pin = config->scl_pin; i2c_bitbang_init(&context->bitbang, &io_fns, context); + bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); + err = i2c_bitbang_configure(&context->bitbang, + I2C_MODE_MASTER | bitrate_cfg); + if (err) { + LOG_ERR("failed to configure I2C bitbang (err %d)", err); + return err; + } + return 0; } @@ -113,29 +158,19 @@ static int i2c_gpio_init(struct device *dev) static struct i2c_gpio_context i2c_gpio_dev_data_##_num; \ \ static const struct i2c_gpio_config i2c_gpio_dev_cfg_##_num = { \ - .gpio_name = CONFIG_I2C_GPIO_##_num##_GPIO, \ - .scl_pin = CONFIG_I2C_GPIO_##_num##_SCL_PIN, \ - .sda_pin = CONFIG_I2C_GPIO_##_num##_SDA_PIN, \ + .scl_gpio_name = DT_INST_GPIO_LABEL(_num, scl_gpios), \ + .sda_gpio_name = DT_INST_GPIO_LABEL(_num, sda_gpios), \ + .scl_pin = DT_INST_GPIO_PIN(_num, scl_gpios), \ + .sda_pin = DT_INST_GPIO_PIN(_num, sda_gpios), \ + .scl_flags = DT_INST_GPIO_FLAGS(_num, scl_gpios), \ + .sda_flags = DT_INST_GPIO_FLAGS(_num, sda_gpios), \ + .bitrate = DT_INST_PROP(_num, clock_frequency), \ }; \ \ -DEVICE_AND_API_INIT(i2c_gpio_##_num, CONFIG_I2C_GPIO_##_num##_NAME, \ +DEVICE_AND_API_INIT(i2c_gpio_##_num, DT_INST_LABEL(_num), \ i2c_gpio_init, \ &i2c_gpio_dev_data_##_num, \ &i2c_gpio_dev_cfg_##_num, \ PRE_KERNEL_2, CONFIG_I2C_INIT_PRIORITY, &api) -#ifdef CONFIG_I2C_GPIO_0 -DEFINE_I2C_GPIO(0); -#endif - -#ifdef CONFIG_I2C_GPIO_1 -DEFINE_I2C_GPIO(1); -#endif - -#ifdef CONFIG_I2C_GPIO_2 -DEFINE_I2C_GPIO(2); -#endif - -#ifdef CONFIG_I2C_GPIO_3 -DEFINE_I2C_GPIO(3); -#endif +DT_INST_FOREACH(DEFINE_I2C_GPIO)