You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
708 lines
18 KiB
708 lines
18 KiB
/* |
|
* Copyright (c) 2015 Intel Corporation. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
/** |
|
* @file Driver for PCAL9535A I2C-based GPIO driver. |
|
*/ |
|
|
|
#include <nanokernel.h> |
|
|
|
#include <gpio.h> |
|
#include <i2c.h> |
|
|
|
#include "gpio_pcal9535a.h" |
|
|
|
#ifndef CONFIG_GPIO_PCAL9535A_DEBUG |
|
#define DBG(...) { ; } |
|
#else |
|
#if defined(CONFIG_STDOUT_CONSOLE) |
|
#include <stdio.h> |
|
#define DBG printf |
|
#else |
|
#include <misc/printk.h> |
|
#define DBG printk |
|
#endif /* CONFIG_STDOUT_CONSOLE */ |
|
#endif /* CONFIG_GPIO_PCAL9535A_DEBUG */ |
|
|
|
/* Register definitions */ |
|
#define REG_INPUT_PORT0 0x00 |
|
#define REG_INPUT_PORT1 0x01 |
|
#define REG_OUTPUT_PORT0 0x02 |
|
#define REG_OUTPUT_PORT1 0x03 |
|
#define REG_POL_INV_PORT0 0x04 |
|
#define REG_POL_INV_PORT1 0x05 |
|
#define REG_CONF_PORT0 0x06 |
|
#define REG_CONG_PORT1 0x07 |
|
#define REG_OUT_DRV_STRENGTH_PORT0_L 0x40 |
|
#define REG_OUT_DRV_STRENGTH_PORT0_H 0x41 |
|
#define REG_OUT_DRV_STRENGTH_PORT1_L 0x42 |
|
#define REG_OUT_DRV_STRENGTH_PORT1_H 0x43 |
|
#define REG_INPUT_LATCH_PORT0 0x44 |
|
#define REG_INPUT_LATCH_PORT1 0x45 |
|
#define REG_PUD_EN_PORT0 0x46 |
|
#define REG_PUD_EN_PORT1 0x47 |
|
#define REG_PUD_SEL_PORT0 0x48 |
|
#define REG_PUD_SEL_PORT1 0x49 |
|
#define REG_INT_MASK_PORT0 0x4A |
|
#define REG_INT_MASK_PORT1 0x4B |
|
#define REG_INT_STATUS_PORT0 0x4C |
|
#define REG_INT_STATUS_PORT1 0x4D |
|
#define REG_OUTPUT_PORT_CONF 0x4F |
|
|
|
/** |
|
* @brief Check to see if a I2C master is identified for communication. |
|
* |
|
* @param dev Device struct. |
|
* @return 1 if I2C master is identified, 0 if not. |
|
*/ |
|
static inline int _has_i2c_master(struct device *dev) |
|
{ |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
struct device * const i2c_master = drv_data->i2c_master; |
|
|
|
if (i2c_master) |
|
return 1; |
|
else |
|
return 0; |
|
} |
|
|
|
/** |
|
* @brief Read both port 0 and port 1 registers of certain register function. |
|
* |
|
* Given the register in reg, read the pair of port 0 and port 1. |
|
* |
|
* @param dev Device struct of the PCAL9535A. |
|
* @param reg Register to read (the PORT0 of the pair of registers). |
|
* @param buf Buffer to read data into. |
|
* |
|
* @return DEV_OK if successful, failed otherwise. |
|
*/ |
|
static int _read_port_regs(struct device *dev, uint8_t reg, |
|
union gpio_pcal9535a_port_data *buf) |
|
{ |
|
const struct gpio_pcal9535a_config * const config = |
|
dev->config->config_info; |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
struct device * const i2c_master = drv_data->i2c_master; |
|
uint16_t i2c_addr = config->i2c_slave_addr; |
|
int ret; |
|
uint8_t cmd[] = { reg }; |
|
struct i2c_msg msgs[2]; |
|
|
|
msgs[0].buf = cmd; |
|
msgs[0].len = 1; |
|
msgs[0].flags = I2C_MSG_WRITE; |
|
|
|
msgs[1].buf = buf->byte; |
|
msgs[1].len = 2; |
|
msgs[1].flags = I2C_MSG_READ | I2C_MSG_RESTART; |
|
|
|
ret = i2c_transfer(i2c_master, msgs, 2, i2c_addr); |
|
if (ret) { |
|
DBG("PCAL9535A[0x%X]: error reading register 0x%X (%d)\n", |
|
i2c_addr, reg, ret); |
|
goto error; |
|
} |
|
|
|
DBG("PCAL9535A[0x%X]: Read: REG[0x%X] = 0x%X, REG[0x%X] = 0x%X\n", |
|
i2c_addr, reg, buf->byte[0], (reg + 1), buf->byte[1]); |
|
|
|
error: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Write both port 0 and port 1 registers of certain register function. |
|
* |
|
* Given the register in reg, write the pair of port 0 and port 1. |
|
* |
|
* @param dev Device struct of the PCAL9535A. |
|
* @param reg Register to write into (the PORT0 of the pair of registers). |
|
* @param buf Buffer to write data from. |
|
* |
|
* @return DEV_OK if successful, failed otherwise. |
|
*/ |
|
static int _write_port_regs(struct device *dev, uint8_t reg, |
|
union gpio_pcal9535a_port_data *buf) |
|
{ |
|
const struct gpio_pcal9535a_config * const config = |
|
dev->config->config_info; |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
struct device * const i2c_master = drv_data->i2c_master; |
|
uint16_t i2c_addr = config->i2c_slave_addr; |
|
uint8_t cmd[] = {reg, buf->byte[0], buf->byte[1]}; |
|
int ret; |
|
|
|
DBG("PCAL9535A[0x%X]: Write: REG[0x%X] = 0x%X, REG[0x%X] = 0x%X\n", |
|
i2c_addr, reg, buf->byte[0], (reg + 1), buf->byte[1]); |
|
|
|
ret = i2c_write(i2c_master, cmd, sizeof(cmd), i2c_addr); |
|
if (ret) { |
|
DBG("PCAL9535A[0x%X]: error writing from register 0x%X (%d)\n", |
|
i2c_addr, reg, ret); |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Setup the pin direction (input or output) |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param flags Flags of pin or port |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int _setup_pin_dir(struct device *dev, int access_op, |
|
uint32_t pin, int flags) |
|
{ |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
union gpio_pcal9535a_port_data *port = &drv_data->reg_cache.dir; |
|
uint16_t bit_mask; |
|
uint16_t new_value = 0; |
|
int ret; |
|
|
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
bit_mask = 1 << pin; |
|
|
|
/* Config 0 == output, 1 == input */ |
|
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { |
|
new_value = 1 << pin; |
|
} |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
/* Config 0 == output, 1 == input */ |
|
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) { |
|
port->all = 0xFFFF; |
|
} else { |
|
port->all = 0x0; |
|
} |
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
goto done; |
|
} |
|
|
|
ret = _write_port_regs(dev, REG_CONF_PORT0, port); |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Setup the pin pull up/pull down status |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param flags Flags of pin or port |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int _setup_pin_pullupdown(struct device *dev, int access_op, |
|
uint32_t pin, int flags) |
|
{ |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
union gpio_pcal9535a_port_data *port; |
|
uint16_t bit_mask; |
|
uint16_t new_value = 0; |
|
int ret; |
|
|
|
/* If disabling pull up/down, there is no need to set the selection |
|
* register. Just go straight to disabling. |
|
*/ |
|
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_NORMAL) { |
|
goto en_dis; |
|
} |
|
|
|
/* Setup pin pull up or pull down */ |
|
port = &drv_data->reg_cache.pud_sel; |
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
bit_mask = 1 << pin; |
|
|
|
/* pull down == 0, pull up == 1*/ |
|
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { |
|
new_value = 1 << pin; |
|
} |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
/* pull down == 0, pull up == 1*/ |
|
if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { |
|
port->all = 0xFFFF; |
|
} else { |
|
port->all = 0x0; |
|
} |
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
goto done; |
|
} |
|
|
|
ret = _write_port_regs(dev, REG_PUD_SEL_PORT0, port); |
|
if (ret) { |
|
goto done; |
|
} |
|
|
|
en_dis: |
|
/* enable/disable pull up/down */ |
|
port = &drv_data->reg_cache.pud_en; |
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
bit_mask = 1 << pin; |
|
|
|
if ((flags & GPIO_PUD_MASK) != GPIO_PUD_NORMAL) { |
|
new_value = 1 << pin; |
|
} |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
if ((flags & GPIO_PUD_MASK) != GPIO_PUD_NORMAL) { |
|
port->all = 0xFFFF; |
|
} else { |
|
port->all = 0x0; |
|
} |
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
goto done; |
|
} |
|
|
|
ret = _write_port_regs(dev, REG_PUD_EN_PORT0, port); |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Setup the polarity of pin or port |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param flags Flags of pin or port |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int _setup_pin_polarity(struct device *dev, int access_op, |
|
uint32_t pin, int flags) |
|
{ |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
union gpio_pcal9535a_port_data *port = &drv_data->reg_cache.pol_inv; |
|
uint16_t bit_mask; |
|
uint16_t new_value = 0; |
|
int ret; |
|
|
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
bit_mask = 1 << pin; |
|
|
|
/* normal == 0, invert == 1 */ |
|
if ((flags & GPIO_POL_MASK) == GPIO_POL_INV) { |
|
new_value = 1 << pin; |
|
} |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
/* normal == 0, invert == 1 */ |
|
if ((flags & GPIO_POL_MASK) == GPIO_POL_INV) { |
|
port->all = 0xFFFF; |
|
} else { |
|
port->all = 0x0; |
|
} |
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
goto done; |
|
} |
|
|
|
ret = _write_port_regs(dev, REG_POL_INV_PORT0, port); |
|
if (!ret) { |
|
drv_data->out_pol_inv = port->all; |
|
} |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Configurate pin or port |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param flags Flags of pin or port |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int gpio_pcal9535a_config(struct device *dev, int access_op, |
|
uint32_t pin, int flags) |
|
{ |
|
int ret; |
|
|
|
#ifdef CONFIG_GPIO_PCAL9535A_DEBUG |
|
const struct gpio_pcal9535a_config * const config = |
|
dev->config->config_info; |
|
uint16_t i2c_addr = config->i2c_slave_addr; |
|
#endif |
|
|
|
if (!_has_i2c_master(dev)) { |
|
return DEV_INVALID_CONF; |
|
} |
|
|
|
ret = _setup_pin_dir(dev, access_op, pin, flags); |
|
if (ret) { |
|
DBG("PCAL9535A[0x%X]: error setting pin direction (%d)\n", |
|
i2c_addr, ret); |
|
goto done; |
|
} |
|
|
|
ret = _setup_pin_polarity(dev, access_op, pin, flags); |
|
if (ret) { |
|
DBG("PCAL9535A[0x%X]: error setting pin polarity (%d)\n", |
|
i2c_addr, ret); |
|
goto done; |
|
} |
|
|
|
ret = _setup_pin_pullupdown(dev, access_op, pin, flags); |
|
if (ret) { |
|
DBG("PCAL9535A[0x%X]: error setting pin pull up/down (%d)\n", |
|
i2c_addr, ret); |
|
goto done; |
|
} |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Set the pin or port output |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param value Value to set (0 or 1) |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int gpio_pcal9535a_write(struct device *dev, int access_op, |
|
uint32_t pin, uint32_t value) |
|
{ |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
union gpio_pcal9535a_port_data *port = &drv_data->reg_cache.output; |
|
uint16_t bit_mask; |
|
uint16_t new_value; |
|
int ret; |
|
|
|
if (!_has_i2c_master(dev)) { |
|
return DEV_INVALID_CONF; |
|
} |
|
|
|
/* Invert input value for pins configurated as active low. */ |
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
bit_mask = 1 << pin; |
|
|
|
new_value = (value << pin) & bit_mask; |
|
new_value ^= (drv_data->out_pol_inv & bit_mask); |
|
new_value &= bit_mask; |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
port->all = value; |
|
bit_mask = drv_data->out_pol_inv; |
|
|
|
new_value = value & bit_mask; |
|
new_value ^= drv_data->out_pol_inv; |
|
new_value &= bit_mask; |
|
|
|
port->all &= ~bit_mask; |
|
port->all |= new_value; |
|
|
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
goto done; |
|
} |
|
|
|
ret = _write_port_regs(dev, REG_OUTPUT_PORT0, port); |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
/** |
|
* @brief Read the pin or port status |
|
* |
|
* @param dev Device struct of the PCAL9535A |
|
* @param access_op Access operation (pin or port) |
|
* @param pin The pin number |
|
* @param value Value of input pin(s) |
|
* |
|
* @return DEV_OK if successful, failed otherwise |
|
*/ |
|
static int gpio_pcal9535a_read(struct device *dev, int access_op, |
|
uint32_t pin, uint32_t *value) |
|
{ |
|
union gpio_pcal9535a_port_data buf; |
|
int ret; |
|
|
|
if (!_has_i2c_master(dev)) { |
|
return DEV_INVALID_CONF; |
|
} |
|
|
|
ret = _read_port_regs(dev, REG_INPUT_PORT0, &buf); |
|
if (ret != DEV_OK) { |
|
goto done; |
|
} |
|
|
|
switch (access_op) { |
|
case GPIO_ACCESS_BY_PIN: |
|
*value = (buf.all >> pin) & 0x01; |
|
break; |
|
case GPIO_ACCESS_BY_PORT: |
|
*value = buf.all; |
|
break; |
|
default: |
|
ret = DEV_INVALID_OP; |
|
break; |
|
} |
|
|
|
done: |
|
return ret; |
|
} |
|
|
|
static int gpio_pcal9535a_set_callback(struct device *dev, |
|
gpio_callback_t callback) |
|
{ |
|
ARG_UNUSED(dev); |
|
ARG_UNUSED(callback); |
|
|
|
return DEV_INVALID_OP; |
|
} |
|
|
|
static int gpio_pcal9535a_enable_callback(struct device *dev, |
|
int access_op, uint32_t pin) |
|
{ |
|
ARG_UNUSED(dev); |
|
ARG_UNUSED(access_op); |
|
ARG_UNUSED(pin); |
|
|
|
return DEV_INVALID_OP; |
|
} |
|
|
|
static int gpio_pcal9535a_disable_callback(struct device *dev, |
|
int access_op, uint32_t pin) |
|
{ |
|
ARG_UNUSED(dev); |
|
ARG_UNUSED(access_op); |
|
ARG_UNUSED(pin); |
|
|
|
return DEV_INVALID_OP; |
|
} |
|
|
|
static int gpio_pcal9535a_suspend_port(struct device *dev) |
|
{ |
|
if (!_has_i2c_master(dev)) { |
|
return DEV_INVALID_CONF; |
|
} |
|
|
|
return DEV_INVALID_OP; |
|
} |
|
|
|
static int gpio_pcal9535a_resume_port(struct device *dev) |
|
{ |
|
if (!_has_i2c_master(dev)) { |
|
return DEV_INVALID_CONF; |
|
} |
|
|
|
return DEV_INVALID_OP; |
|
} |
|
|
|
static struct gpio_driver_api gpio_pcal9535a_drv_api_funcs = { |
|
.config = gpio_pcal9535a_config, |
|
.write = gpio_pcal9535a_write, |
|
.read = gpio_pcal9535a_read, |
|
.set_callback = gpio_pcal9535a_set_callback, |
|
.enable_callback = gpio_pcal9535a_enable_callback, |
|
.disable_callback = gpio_pcal9535a_disable_callback, |
|
.suspend = gpio_pcal9535a_suspend_port, |
|
.resume = gpio_pcal9535a_resume_port, |
|
}; |
|
|
|
/** |
|
* @brief Initialization function of PCAL9535A |
|
* |
|
* @param dev Device struct |
|
* @return DEV_OK if successful, failed otherwise. |
|
*/ |
|
int gpio_pcal9535a_init(struct device *dev) |
|
{ |
|
const struct gpio_pcal9535a_config * const config = |
|
dev->config->config_info; |
|
struct gpio_pcal9535a_drv_data * const drv_data = |
|
(struct gpio_pcal9535a_drv_data * const)dev->driver_data; |
|
struct device *i2c_master; |
|
|
|
dev->driver_api = &gpio_pcal9535a_drv_api_funcs; |
|
|
|
/* Find out the device struct of the I2C master */ |
|
i2c_master = device_get_binding((char *)config->i2c_master_dev_name); |
|
if (!i2c_master) { |
|
return DEV_INVALID_CONF; |
|
} |
|
drv_data->i2c_master = i2c_master; |
|
|
|
nano_timer_init(&drv_data->timer, (void *) 0); |
|
|
|
return DEV_OK; |
|
} |
|
|
|
/* Initialization for PCAL9535A_0 */ |
|
#ifdef CONFIG_GPIO_PCAL9535A_0 |
|
#include <device.h> |
|
#include <init.h> |
|
|
|
static struct gpio_pcal9535a_config gpio_pcal9535a_0_cfg = { |
|
.i2c_master_dev_name = CONFIG_GPIO_PCAL9535A_0_I2C_MASTER_DEV_NAME, |
|
.i2c_slave_addr = CONFIG_GPIO_PCAL9535A_0_I2C_ADDR, |
|
}; |
|
|
|
static struct gpio_pcal9535a_drv_data gpio_pcal9535a_0_drvdata = { |
|
/* Default for registers according to datasheet */ |
|
.reg_cache.output = { .all = 0xFFFF }, |
|
.reg_cache.pol_inv = { .all = 0x0 }, |
|
.reg_cache.dir = { .all = 0xFFFF }, |
|
.reg_cache.pud_en = { .all = 0x0 }, |
|
.reg_cache.pud_sel = { .all = 0xFFFF }, |
|
}; |
|
|
|
/* This has to init after I2C master */ |
|
DEVICE_INIT(gpio_pcal9535a_0, CONFIG_GPIO_PCAL9535A_0_DEV_NAME, |
|
gpio_pcal9535a_init, |
|
&gpio_pcal9535a_0_drvdata, &gpio_pcal9535a_0_cfg, |
|
SECONDARY, CONFIG_GPIO_PCAL9535A_INIT_PRIORITY); |
|
|
|
#endif /* CONFIG_GPIO_PCAL9535A_0 */ |
|
|
|
/* Initialization for PCAL9535A_1 */ |
|
#ifdef CONFIG_GPIO_PCAL9535A_1 |
|
#include <device.h> |
|
#include <init.h> |
|
|
|
static struct gpio_pcal9535a_config gpio_pcal9535a_1_cfg = { |
|
.i2c_master_dev_name = CONFIG_GPIO_PCAL9535A_1_I2C_MASTER_DEV_NAME, |
|
.i2c_slave_addr = CONFIG_GPIO_PCAL9535A_1_I2C_ADDR, |
|
}; |
|
|
|
static struct gpio_pcal9535a_drv_data gpio_pcal9535a_1_drvdata = { |
|
/* Default for registers according to datasheet */ |
|
.reg_cache.output = { .all = 0xFFFF }, |
|
.reg_cache.pol_inv = { .all = 0x0 }, |
|
.reg_cache.dir = { .all = 0xFFFF }, |
|
.reg_cache.pud_en = { .all = 0x0 }, |
|
.reg_cache.pud_sel = { .all = 0xFFFF }, |
|
}; |
|
|
|
/* This has to init after I2C master */ |
|
DEVICE_INIT(gpio_pcal9535a_1, CONFIG_GPIO_PCAL9535A_1_DEV_NAME, |
|
gpio_pcal9535a_init, |
|
&gpio_pcal9535a_1_drvdata, &gpio_pcal9535a_1_cfg, |
|
SECONDARY, CONFIG_GPIO_PCAL9535A_INIT_PRIORITY); |
|
|
|
#endif /* CONFIG_GPIO_PCAL9535A_1 */ |
|
|
|
/* Initialization for PCAL9535A_2 */ |
|
#ifdef CONFIG_GPIO_PCAL9535A_2 |
|
#include <device.h> |
|
#include <init.h> |
|
|
|
static struct gpio_pcal9535a_config gpio_pcal9535a_2_cfg = { |
|
.i2c_master_dev_name = CONFIG_GPIO_PCAL9535A_2_I2C_MASTER_DEV_NAME, |
|
.i2c_slave_addr = CONFIG_GPIO_PCAL9535A_2_I2C_ADDR, |
|
}; |
|
|
|
static struct gpio_pcal9535a_drv_data gpio_pcal9535a_2_drvdata = { |
|
/* Default for registers according to datasheet */ |
|
.reg_cache.output = { .all = 0xFFFF }, |
|
.reg_cache.pol_inv = { .all = 0x0 }, |
|
.reg_cache.dir = { .all = 0xFFFF }, |
|
.reg_cache.pud_en = { .all = 0x0 }, |
|
.reg_cache.pud_sel = { .all = 0xFFFF }, |
|
}; |
|
|
|
/* This has to init after I2C master */ |
|
DEVICE_INIT(gpio_pcal9535a_2, CONFIG_GPIO_PCAL9535A_2_DEV_NAME, |
|
gpio_pcal9535a_init, |
|
&gpio_pcal9535a_2_drvdata, &gpio_pcal9535a_2_cfg, |
|
SECONDARY, CONFIG_GPIO_PCAL9535A_INIT_PRIORITY); |
|
|
|
#endif /* CONFIG_GPIO_PCAL9535A_2 */ |
|
|
|
/* Initialization for PCAL9535A_3 */ |
|
#ifdef CONFIG_GPIO_PCAL9535A_3 |
|
#include <device.h> |
|
#include <init.h> |
|
|
|
static struct gpio_pcal9535a_config gpio_pcal9535a_3_cfg = { |
|
.i2c_master_dev_name = CONFIG_GPIO_PCAL9535A_3_I2C_MASTER_DEV_NAME, |
|
.i2c_slave_addr = CONFIG_GPIO_PCAL9535A_3_I2C_ADDR, |
|
}; |
|
|
|
static struct gpio_pcal9535a_drv_data gpio_pcal9535a_3_drvdata = { |
|
/* Default for registers according to datasheet */ |
|
.reg_cache.output = { .all = 0xFFFF }, |
|
.reg_cache.pol_inv = { .all = 0x0 }, |
|
.reg_cache.dir = { .all = 0xFFFF }, |
|
.reg_cache.pud_en = { .all = 0x0 }, |
|
.reg_cache.pud_sel = { .all = 0xFFFF }, |
|
}; |
|
|
|
/* This has to init after I2C master */ |
|
DEVICE_INIT(gpio_pcal9535a_3, CONFIG_GPIO_PCAL9535A_3_DEV_NAME, |
|
gpio_pcal9535a_init, |
|
&gpio_pcal9535a_3_drvdata, &gpio_pcal9535a_3_cfg, |
|
SECONDARY, CONFIG_GPIO_PCAL9535A_INIT_PRIORITY); |
|
|
|
|
|
#endif /* CONFIG_GPIO_PCAL9535A_3 */
|
|
|