Skip to content

Commit

Permalink
drivers: i2c: gpio: convert to using devicetree for instances
Browse files Browse the repository at this point in the history
Convert the GPIO bit banging I2C controller driver to use devicetree
bindings for configuring instances.

Signed-off-by: Henrik Brix Andersen <[email protected]>
  • Loading branch information
henrikbrixandersen authored and galak committed May 5, 2020
1 parent ea61a6e commit 911b6a0
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 173 deletions.
140 changes: 0 additions & 140 deletions drivers/i2c/Kconfig.gpio
Original file line number Diff line number Diff line change
Expand Up @@ -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
101 changes: 68 additions & 33 deletions drivers/i2c/i2c_gpio.c
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -24,41 +27,51 @@
#include <errno.h>
#include <drivers/gpio.h>
#include <drivers/i2c.h>

#include <logging/log.h>
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;
Expand All @@ -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 = {
Expand All @@ -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->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->gpio = device_get_binding(config->gpio_name);
if (!context->gpio) {
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;
}

Expand All @@ -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)

0 comments on commit 911b6a0

Please sign in to comment.