drivers: gpio_sx1509b: update to use new GPIO API
Update driver code and board files to use new GPIO configuration flags such as GPIO_ACTIVE_LOW. Also add implementation of new port_* driver API. Tested on external SX1509B breakout board and Thingy:52. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
f8f1a91cf7
commit
dfa7ef2c4d
|
@ -148,6 +148,7 @@
|
|||
/drivers/gpio/*ht16k33* @henrikbrixandersen
|
||||
/drivers/gpio/*lmp90xxx* @henrikbrixandersen
|
||||
/drivers/gpio/*stm32* @rsalveti @idlethread
|
||||
/drivers/gpio/*sx1509b* @pabigot
|
||||
/drivers/hwinfo/ @alexanderwachter
|
||||
/drivers/i2c/*litex* @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/i2s/i2s_ll_stm32* @avisconti
|
||||
|
|
|
@ -34,15 +34,15 @@
|
|||
compatible = "gpio-leds";
|
||||
/* Lightwell RGB */
|
||||
led0: led_0 {
|
||||
gpios = <&sx1509b 5 0>;
|
||||
gpios = <&sx1509b 5 GPIO_ACTIVE_LOW>;
|
||||
label = "Green LED";
|
||||
};
|
||||
led1: led_1 {
|
||||
gpios = <&sx1509b 6 0>;
|
||||
gpios = <&sx1509b 6 GPIO_ACTIVE_LOW>;
|
||||
label = "Blue LED";
|
||||
};
|
||||
led2: led_2 {
|
||||
gpios = <&sx1509b 7 0>;
|
||||
gpios = <&sx1509b 7 GPIO_ACTIVE_LOW>;
|
||||
label = "Red LED";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Aapo Vienamo
|
||||
* Copyright (c) 2018 Peter Bigot Consulting, LLC
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -14,28 +16,42 @@
|
|||
#include <sys/byteorder.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
/** Cache of the output configuration and data of the pins */
|
||||
struct gpio_sx1509b_pin_state {
|
||||
u16_t input_disable;
|
||||
u16_t pull_up;
|
||||
u16_t pull_down;
|
||||
u16_t open_drain;
|
||||
u16_t polarity;
|
||||
u16_t dir;
|
||||
u16_t data;
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(sx1509b, CONFIG_GPIO_LOG_LEVEL);
|
||||
|
||||
/* Number of pins supported by the device */
|
||||
#define NUM_PINS 16
|
||||
|
||||
/* Max to select all pins supported on the device. */
|
||||
#define ALL_PINS ((u16_t)BIT_MASK(NUM_PINS))
|
||||
|
||||
/* Reset delay is 2.5 ms, round up for Zephyr resolution */
|
||||
#define RESET_DELAY_MS 3
|
||||
|
||||
/** Cache of the output configuration and data of the pins. */
|
||||
struct sx1509b_pin_state {
|
||||
u16_t input_disable; /* 0x00 */
|
||||
u16_t long_slew; /* 0x02 */
|
||||
u16_t low_drive; /* 0x04 */
|
||||
u16_t pull_up; /* 0x06 */
|
||||
u16_t pull_down; /* 0x08 */
|
||||
u16_t open_drain; /* 0x0A */
|
||||
u16_t polarity; /* 0x0C */
|
||||
u16_t dir; /* 0x0E */
|
||||
u16_t data; /* 0x10 */
|
||||
};
|
||||
|
||||
/** Runtime driver data */
|
||||
struct gpio_sx1509b_drv_data {
|
||||
struct sx1509b_drv_data {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_data common;
|
||||
struct device *i2c_master;
|
||||
struct gpio_sx1509b_pin_state pin_state;
|
||||
struct sx1509b_pin_state pin_state;
|
||||
struct k_sem lock;
|
||||
};
|
||||
|
||||
/** Configuration data */
|
||||
struct gpio_sx1509b_config {
|
||||
struct sx1509b_config {
|
||||
const char *i2c_master_dev_name;
|
||||
u16_t i2c_slave_addr;
|
||||
};
|
||||
|
@ -43,32 +59,32 @@ struct gpio_sx1509b_config {
|
|||
/* General configuration register addresses */
|
||||
enum {
|
||||
/* TODO: Add rest of the regs */
|
||||
SX1509B_REG_CLOCK = 0x1e,
|
||||
SX1509B_REG_RESET = 0x7d,
|
||||
SX1509B_REG_CLOCK = 0x1e,
|
||||
SX1509B_REG_RESET = 0x7d,
|
||||
};
|
||||
|
||||
/* Magic values for softreset */
|
||||
enum {
|
||||
SX1509B_REG_RESET_MAGIC0 = 0x12,
|
||||
SX1509B_REG_RESET_MAGIC1 = 0x34,
|
||||
SX1509B_REG_RESET_MAGIC0 = 0x12,
|
||||
SX1509B_REG_RESET_MAGIC1 = 0x34,
|
||||
};
|
||||
|
||||
/* Register bits for SX1509B_REG_CLOCK */
|
||||
enum {
|
||||
SX1509B_REG_CLOCK_FOSC_OFF = 0 << 5,
|
||||
SX1509B_REG_CLOCK_FOSC_EXT = 1 << 5,
|
||||
SX1509B_REG_CLOCK_FOSC_INT_2MHZ = 2 << 5,
|
||||
SX1509B_REG_CLOCK_FOSC_OFF = 0 << 5,
|
||||
SX1509B_REG_CLOCK_FOSC_EXT = 1 << 5,
|
||||
SX1509B_REG_CLOCK_FOSC_INT_2MHZ = 2 << 5,
|
||||
};
|
||||
|
||||
/* Pin configuration register addresses */
|
||||
enum {
|
||||
SX1509B_REG_INPUT_DISABLE = 0x00,
|
||||
SX1509B_REG_PULL_UP = 0x06,
|
||||
SX1509B_REG_PULL_DOWN = 0x08,
|
||||
SX1509B_REG_OPEN_DRAIN = 0x0a,
|
||||
SX1509B_REG_DIR = 0x0e,
|
||||
SX1509B_REG_DATA = 0x10,
|
||||
SX1509B_REG_LED_DRIVER_ENABLE = 0x20,
|
||||
SX1509B_REG_INPUT_DISABLE = 0x00,
|
||||
SX1509B_REG_PULL_UP = 0x06,
|
||||
SX1509B_REG_PULL_DOWN = 0x08,
|
||||
SX1509B_REG_OPEN_DRAIN = 0x0a,
|
||||
SX1509B_REG_DIR = 0x0e,
|
||||
SX1509B_REG_DATA = 0x10,
|
||||
SX1509B_REG_LED_DRIVER_ENABLE = 0x20,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -90,153 +106,241 @@ static inline int i2c_reg_write_word_be(struct device *dev, u16_t dev_addr,
|
|||
return i2c_write(dev, tx_buf, 3, dev_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure pin or port
|
||||
*
|
||||
* @param dev Device struct of the SX1509B
|
||||
* @param access_op Access operation (pin or port)
|
||||
* @param pin The pin number
|
||||
* @param flags Flags of pin or port
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int gpio_sx1509b_config(struct device *dev, int access_op, u32_t pin,
|
||||
int flags)
|
||||
static int sx1509b_config(struct device *dev,
|
||||
int access_op, /* unused */
|
||||
u32_t pin,
|
||||
int flags)
|
||||
{
|
||||
const struct gpio_sx1509b_config *cfg = dev->config->config_info;
|
||||
struct gpio_sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
struct gpio_sx1509b_pin_state *pins = &drv_data->pin_state;
|
||||
int ret = 0;
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
struct sx1509b_pin_state *pins = &drv_data->pin_state;
|
||||
|
||||
if (flags & GPIO_INT) {
|
||||
struct {
|
||||
u8_t reg;
|
||||
struct sx1509b_pin_state pins;
|
||||
} __packed outbuf;
|
||||
int rc = 0;
|
||||
bool data_first = false;
|
||||
|
||||
/* Can't do I2C bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
/* Zephyr currently defines drive strength support based on
|
||||
* the behavior and capabilities of the Nordic GPIO
|
||||
* peripheral: strength defaults to low but can be set high,
|
||||
* and is controlled independently for output levels.
|
||||
*
|
||||
* SX150x defaults to high strength, and does not support
|
||||
* different strengths for different levels.
|
||||
*
|
||||
* Until something more general is available reject any
|
||||
* attempt to set a non-default drive strength.
|
||||
*/
|
||||
if ((flags & (GPIO_DS_ALT_LOW | GPIO_DS_ALT_HIGH)) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
switch (access_op) {
|
||||
case GPIO_ACCESS_BY_PIN:
|
||||
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) {
|
||||
pins->dir |= BIT(pin);
|
||||
pins->input_disable &= ~BIT(pin);
|
||||
} else {
|
||||
pins->dir &= ~BIT(pin);
|
||||
pins->input_disable |= BIT(pin);
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) {
|
||||
pins->pull_up |= BIT(pin);
|
||||
} else {
|
||||
pins->pull_up &= ~BIT(pin);
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) {
|
||||
pins->pull_down |= BIT(pin);
|
||||
} else {
|
||||
pins->pull_down &= ~BIT(pin);
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_NORMAL) {
|
||||
pins->pull_up &= ~BIT(pin);
|
||||
pins->pull_down &= ~BIT(pin);
|
||||
}
|
||||
if (flags & GPIO_DS_DISCONNECT_HIGH) {
|
||||
pins->open_drain &= ~BIT(pin);
|
||||
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
||||
if ((flags & GPIO_LINE_OPEN_DRAIN) != 0) {
|
||||
pins->open_drain |= BIT(pin);
|
||||
} else {
|
||||
pins->open_drain &= ~BIT(pin);
|
||||
/* Open source not supported */
|
||||
rc = -ENOTSUP;
|
||||
goto out;
|
||||
}
|
||||
if (flags & GPIO_POL_INV) {
|
||||
pins->polarity |= BIT(pin);
|
||||
} else {
|
||||
pins->polarity &= ~BIT(pin);
|
||||
}
|
||||
break;
|
||||
case GPIO_ACCESS_BY_PORT:
|
||||
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) {
|
||||
pins->dir = 0xffff;
|
||||
pins->input_disable = 0x0000;
|
||||
} else {
|
||||
pins->dir = 0x0000;
|
||||
pins->input_disable = 0xffff;
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) {
|
||||
pins->pull_up = 0xffff;
|
||||
} else {
|
||||
pins->pull_up = 0x0000;
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) {
|
||||
pins->pull_down = 0xffff;
|
||||
} else {
|
||||
pins->pull_down = 0x0000;
|
||||
}
|
||||
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_NORMAL) {
|
||||
pins->pull_up = 0x0000;
|
||||
pins->pull_down = 0x0000;
|
||||
}
|
||||
if (flags & GPIO_DS_DISCONNECT_HIGH) {
|
||||
pins->open_drain = 0xffff;
|
||||
} else {
|
||||
pins->open_drain = 0x0000;
|
||||
}
|
||||
if (flags & GPIO_POL_INV) {
|
||||
pins->polarity = 0xffff;
|
||||
} else {
|
||||
pins->polarity = 0x0000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_DIR, pins->dir);
|
||||
if (ret) {
|
||||
goto out;
|
||||
if ((flags & GPIO_PULL_UP) != 0) {
|
||||
pins->pull_up |= BIT(pin);
|
||||
} else {
|
||||
pins->pull_up &= ~BIT(pin);
|
||||
}
|
||||
if ((flags & GPIO_PULL_DOWN) != 0) {
|
||||
pins->pull_down |= BIT(pin);
|
||||
} else {
|
||||
pins->pull_down &= ~BIT(pin);
|
||||
}
|
||||
|
||||
ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_INPUT_DISABLE,
|
||||
pins->input_disable);
|
||||
if (ret) {
|
||||
goto out;
|
||||
if ((flags & GPIO_INPUT) != 0) {
|
||||
pins->input_disable &= ~BIT(pin);
|
||||
} else {
|
||||
pins->input_disable |= BIT(pin);
|
||||
}
|
||||
|
||||
ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_PULL_UP,
|
||||
pins->pull_up);
|
||||
if (ret) {
|
||||
goto out;
|
||||
if ((flags & GPIO_OUTPUT) != 0) {
|
||||
pins->dir &= ~BIT(pin);
|
||||
if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
|
||||
pins->data &= ~BIT(pin);
|
||||
} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
|
||||
pins->data |= BIT(pin);
|
||||
}
|
||||
} else {
|
||||
pins->dir |= BIT(pin);
|
||||
}
|
||||
|
||||
ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_PULL_DOWN,
|
||||
pins->pull_down);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
outbuf.reg = SX1509B_REG_INPUT_DISABLE;
|
||||
outbuf.pins.input_disable = sys_cpu_to_be16(pins->input_disable);
|
||||
outbuf.pins.long_slew = sys_cpu_to_be16(pins->long_slew);
|
||||
outbuf.pins.low_drive = sys_cpu_to_be16(pins->low_drive);
|
||||
outbuf.pins.pull_up = sys_cpu_to_be16(pins->pull_up);
|
||||
outbuf.pins.pull_down = sys_cpu_to_be16(pins->pull_down);
|
||||
outbuf.pins.open_drain = sys_cpu_to_be16(pins->open_drain);
|
||||
outbuf.pins.polarity = sys_cpu_to_be16(pins->polarity);
|
||||
outbuf.pins.dir = sys_cpu_to_be16(pins->dir);
|
||||
outbuf.pins.data = sys_cpu_to_be16(pins->data);
|
||||
|
||||
ret = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_OPEN_DRAIN,
|
||||
pins->open_drain);
|
||||
LOG_DBG("CFG %u %x : ID %04x ; PU %04x ; PD %04x ; DIR %04x ; DAT %04x",
|
||||
pin, flags,
|
||||
pins->input_disable, pins->pull_up, pins->pull_down,
|
||||
pins->dir, pins->data);
|
||||
if (data_first) {
|
||||
rc = i2c_reg_write_word_be(drv_data->i2c_master,
|
||||
cfg->i2c_slave_addr,
|
||||
SX1509B_REG_DATA, pins->data);
|
||||
if (rc == 0) {
|
||||
rc = i2c_write(drv_data->i2c_master,
|
||||
&outbuf.reg,
|
||||
sizeof(outbuf) - sizeof(pins->data),
|
||||
cfg->i2c_slave_addr);
|
||||
}
|
||||
} else {
|
||||
rc = i2c_write(drv_data->i2c_master,
|
||||
&outbuf.reg,
|
||||
sizeof(outbuf),
|
||||
cfg->i2c_slave_addr);
|
||||
}
|
||||
|
||||
out:
|
||||
k_sem_give(&drv_data->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int port_get(struct device *dev,
|
||||
gpio_port_value_t *value)
|
||||
{
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
u16_t pin_data;
|
||||
int rc = 0;
|
||||
|
||||
/* Can't do I2C bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
u8_t cmd = SX1509B_REG_DATA;
|
||||
|
||||
rc = i2c_write_read(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
&cmd, sizeof(cmd),
|
||||
&pin_data, sizeof(pin_data));
|
||||
LOG_DBG("read %04x got %d", sys_be16_to_cpu(pin_data), rc);
|
||||
if (rc != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
*value = sys_be16_to_cpu(pin_data);
|
||||
|
||||
out:
|
||||
k_sem_give(&drv_data->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int port_write(struct device *dev,
|
||||
gpio_port_pins_t mask,
|
||||
gpio_port_value_t value)
|
||||
{
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
u16_t *outp = &drv_data->pin_state.data;
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
u16_t orig_out = *outp;
|
||||
u16_t out = (orig_out & ~mask) | (u16_t)(value & mask);
|
||||
int rc = i2c_reg_write_word_be(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_DATA, out);
|
||||
if (rc == 0) {
|
||||
*outp = out;
|
||||
}
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
|
||||
LOG_DBG("write %04x msk %04x val %04x => %04x: %d", orig_out, mask, value, out, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int port_set_masked(struct device *dev,
|
||||
gpio_port_pins_t mask,
|
||||
gpio_port_value_t value)
|
||||
{
|
||||
/* Can't do I2C bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
if (mask & ~(gpio_port_pins_t)ALL_PINS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return port_write(dev, mask, value);
|
||||
}
|
||||
|
||||
static int port_set_bits(struct device *dev,
|
||||
gpio_port_pins_t pins)
|
||||
{
|
||||
return port_set_masked(dev, pins, pins);
|
||||
}
|
||||
|
||||
static int port_clear_bits(struct device *dev,
|
||||
gpio_port_pins_t pins)
|
||||
{
|
||||
return port_set_masked(dev, pins, 0);
|
||||
}
|
||||
|
||||
static int port_toggle_bits(struct device *dev,
|
||||
gpio_port_pins_t pins)
|
||||
{
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
|
||||
/* Can't do I2C bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
if (pins & ~(gpio_port_pins_t)ALL_PINS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return port_write(dev, pins,
|
||||
drv_data->pin_state.data ^ pins);
|
||||
}
|
||||
|
||||
static int pin_interrupt_configure(struct device *dev,
|
||||
unsigned int pin,
|
||||
enum gpio_int_mode mode,
|
||||
enum gpio_int_trig trig)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (mode != GPIO_INT_MODE_DISABLED) {
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the pin or port output
|
||||
*
|
||||
* @param dev Device struct of the SX1509B
|
||||
* @param access_op Access operation (pin or port)
|
||||
* @param pin The pin number
|
||||
* @param value Value to set (0 or 1)
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int gpio_sx1509b_write(struct device *dev, int access_op, u32_t pin,
|
||||
u32_t value)
|
||||
static int sx1509b_write(struct device *dev, int access_op, u32_t pin,
|
||||
u32_t value)
|
||||
{
|
||||
const struct gpio_sx1509b_config *cfg = dev->config->config_info;
|
||||
struct gpio_sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
u16_t *pin_data = &drv_data->pin_state.data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -265,21 +369,11 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the pin or port data
|
||||
*
|
||||
* @param dev Device struct of the SX1509B
|
||||
* @param access_op Access operation (pin or port)
|
||||
* @param pin The pin number
|
||||
* @param value Value of input pin(s)
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int gpio_sx1509b_read(struct device *dev, int access_op, u32_t pin,
|
||||
u32_t *value)
|
||||
static int sx1509b_read(struct device *dev, int access_op, u32_t pin,
|
||||
u32_t *value)
|
||||
{
|
||||
const struct gpio_sx1509b_config *cfg = dev->config->config_info;
|
||||
struct gpio_sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
u16_t pin_data;
|
||||
int ret;
|
||||
|
||||
|
@ -316,68 +410,79 @@ out:
|
|||
* @param dev Device struct
|
||||
* @return 0 if successful, failed otherwise.
|
||||
*/
|
||||
static int gpio_sx1509b_init(struct device *dev)
|
||||
static int sx1509b_init(struct device *dev)
|
||||
{
|
||||
const struct gpio_sx1509b_config *cfg = dev->config->config_info;
|
||||
struct gpio_sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
int ret;
|
||||
const struct sx1509b_config *cfg = dev->config->config_info;
|
||||
struct sx1509b_drv_data *drv_data = dev->driver_data;
|
||||
int rc;
|
||||
|
||||
drv_data->i2c_master = device_get_binding(cfg->i2c_master_dev_name);
|
||||
if (!drv_data->i2c_master) {
|
||||
ret = -EINVAL;
|
||||
LOG_ERR("%s: no bus %s", dev->config->name,
|
||||
cfg->i2c_master_dev_name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Reset state */
|
||||
drv_data->pin_state = (struct gpio_sx1509b_pin_state) {
|
||||
.input_disable = 0x0000,
|
||||
.pull_up = 0x0000,
|
||||
.pull_down = 0x0000,
|
||||
.open_drain = 0x0000,
|
||||
.dir = 0xffff,
|
||||
.data = 0xffff,
|
||||
drv_data->pin_state = (struct sx1509b_pin_state) {
|
||||
.dir = ALL_PINS,
|
||||
.data = ALL_PINS,
|
||||
};
|
||||
|
||||
ret = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_RESET, SX1509B_REG_RESET_MAGIC0);
|
||||
if (ret) {
|
||||
rc = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_RESET, SX1509B_REG_RESET_MAGIC0);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("%s: reset m0 failed: %d\n", dev->config->name, rc);
|
||||
goto out;
|
||||
}
|
||||
rc = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_RESET, SX1509B_REG_RESET_MAGIC1);
|
||||
if (rc != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_RESET, SX1509B_REG_RESET_MAGIC1);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
k_sleep(K_MSEC(RESET_DELAY_MS));
|
||||
|
||||
ret = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_CLOCK,
|
||||
SX1509B_REG_CLOCK_FOSC_INT_2MHZ);
|
||||
if (ret) {
|
||||
rc = i2c_reg_write_byte(drv_data->i2c_master, cfg->i2c_slave_addr,
|
||||
SX1509B_REG_CLOCK,
|
||||
SX1509B_REG_CLOCK_FOSC_INT_2MHZ);
|
||||
if (rc != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (rc != 0) {
|
||||
LOG_ERR("%s init failed: %d", dev->config->name, rc);
|
||||
} else {
|
||||
LOG_INF("%s init ok", dev->config->name);
|
||||
}
|
||||
k_sem_give(&drv_data->lock);
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct gpio_sx1509b_config gpio_sx1509b_cfg = {
|
||||
static const struct gpio_driver_api api_table = {
|
||||
.config = sx1509b_config,
|
||||
.write = sx1509b_write,
|
||||
.read = sx1509b_read,
|
||||
.port_get_raw = port_get,
|
||||
.port_set_masked_raw = port_set_masked,
|
||||
.port_set_bits_raw = port_set_bits,
|
||||
.port_clear_bits_raw = port_clear_bits,
|
||||
.port_toggle_bits = port_toggle_bits,
|
||||
.pin_interrupt_configure = pin_interrupt_configure,
|
||||
};
|
||||
|
||||
static const struct sx1509b_config sx1509b_cfg = {
|
||||
.i2c_master_dev_name = DT_INST_0_SEMTECH_SX1509B_BUS_NAME,
|
||||
.i2c_slave_addr = DT_INST_0_SEMTECH_SX1509B_BASE_ADDRESS,
|
||||
.i2c_slave_addr = DT_INST_0_SEMTECH_SX1509B_BASE_ADDRESS,
|
||||
};
|
||||
|
||||
static struct gpio_sx1509b_drv_data gpio_sx1509b_drvdata = {
|
||||
.lock = Z_SEM_INITIALIZER(gpio_sx1509b_drvdata.lock, 1, 1),
|
||||
static struct sx1509b_drv_data sx1509b_drvdata = {
|
||||
.lock = Z_SEM_INITIALIZER(sx1509b_drvdata.lock, 1, 1),
|
||||
};
|
||||
|
||||
static const struct gpio_driver_api gpio_sx1509b_drv_api_funcs = {
|
||||
.config = gpio_sx1509b_config,
|
||||
.write = gpio_sx1509b_write,
|
||||
.read = gpio_sx1509b_read,
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(gpio_sx1509b, DT_INST_0_SEMTECH_SX1509B_LABEL,
|
||||
gpio_sx1509b_init, &gpio_sx1509b_drvdata, &gpio_sx1509b_cfg,
|
||||
DEVICE_AND_API_INIT(sx1509b, DT_INST_0_SEMTECH_SX1509B_LABEL,
|
||||
sx1509b_init, &sx1509b_drvdata, &sx1509b_cfg,
|
||||
POST_KERNEL, CONFIG_GPIO_SX1509B_INIT_PRIORITY,
|
||||
&gpio_sx1509b_drv_api_funcs);
|
||||
&api_table);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
resources {
|
||||
compatible = "test,gpio_basic_api";
|
||||
out-gpios = <&sx1509b 0 0>; /* EXT0 */
|
||||
in-gpios = <&sx1509b 1 0>; /* EXT1 */
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue