drivers: i2c: Add support for LPC11U6X I2C controllers
This commit adds a driver for the LPC11U6X I2C controllers Signed-off-by: Maxime Bittan <maxime.bittan@seagate.com>
This commit is contained in:
parent
adb5dd920b
commit
9ca6b704a7
6 changed files with 529 additions and 0 deletions
|
@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_CC32XX i2c_cc32xx.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_I2C_ESP32 i2c_esp32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_GPIO i2c_gpio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_IMX i2c_imx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_LPC11U6X i2c_lpc11u6x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_XEC i2c_mchp_xec.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_MCUX i2c_mcux.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_MCUX_FLEXCOMM i2c_mcux_flexcomm.c)
|
||||
|
|
|
@ -37,6 +37,7 @@ source "drivers/i2c/Kconfig.sifive"
|
|||
source "drivers/i2c/Kconfig.stm32"
|
||||
source "drivers/i2c/Kconfig.sam0"
|
||||
source "drivers/i2c/Kconfig.litex"
|
||||
source "drivers/i2c/Kconfig.lpc11u6x"
|
||||
|
||||
config I2C_INIT_PRIORITY
|
||||
int "Init priority"
|
||||
|
|
8
drivers/i2c/Kconfig.lpc11u6x
Normal file
8
drivers/i2c/Kconfig.lpc11u6x
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2020 Seagate Technology LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config I2C_LPC11U6X
|
||||
bool "LPC11U6X I2C driver"
|
||||
depends on SOC_SERIES_LPC11U6X
|
||||
help
|
||||
Enable I2C support on the LPC11U6X SoCs
|
417
drivers/i2c/i2c_lpc11u6x.c
Normal file
417
drivers/i2c/i2c_lpc11u6x.c
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Seagate Technology LLC
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nxp_lpc11u6x_i2c
|
||||
|
||||
#include <kernel.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <drivers/pinmux.h>
|
||||
#include <drivers/clock_control.h>
|
||||
#include <dt-bindings/pinctrl/lpc11u6x-pinctrl.h>
|
||||
#include "i2c_lpc11u6x.h"
|
||||
|
||||
#define DEV_CFG(dev) ((dev)->config_info)
|
||||
#define DEV_BASE(dev) (((struct lpc11u6x_i2c_config *) DEV_CFG((dev)))->base)
|
||||
#define DEV_DATA(dev) ((dev)->driver_data)
|
||||
|
||||
static void lpc11u6x_i2c_set_bus_speed(const struct lpc11u6x_i2c_config *cfg,
|
||||
struct device *clk_dev,
|
||||
uint32_t speed)
|
||||
{
|
||||
uint32_t clk, div;
|
||||
|
||||
clock_control_get_rate(clk_dev, (clock_control_subsys_t) cfg->clkid,
|
||||
&clk);
|
||||
div = clk / speed;
|
||||
|
||||
cfg->base->sclh = div / 2;
|
||||
cfg->base->scll = div - (div / 2);
|
||||
}
|
||||
|
||||
static int lpc11u6x_i2c_configure(struct device *dev, uint32_t dev_config)
|
||||
{
|
||||
const struct lpc11u6x_i2c_config *cfg = DEV_CFG(dev);
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA(dev);
|
||||
struct device *clk_dev, *pinmux_dev;
|
||||
uint32_t speed, flags = 0;
|
||||
|
||||
switch (I2C_SPEED_GET(dev_config)) {
|
||||
case I2C_SPEED_STANDARD:
|
||||
speed = 100000;
|
||||
break;
|
||||
case I2C_SPEED_FAST:
|
||||
speed = 400000;
|
||||
break;
|
||||
case I2C_SPEED_FAST_PLUS:
|
||||
flags |= IOCON_FASTI2C_EN;
|
||||
speed = 1000000;
|
||||
break;
|
||||
case I2C_SPEED_HIGH:
|
||||
case I2C_SPEED_ULTRA:
|
||||
return -ENOTSUP;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev_config & I2C_ADDR_10_BITS) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
clk_dev = device_get_binding(cfg->clock_drv);
|
||||
if (!clk_dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
lpc11u6x_i2c_set_bus_speed(cfg, clk_dev, speed);
|
||||
|
||||
if (!flags) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pinmux_dev = device_get_binding(cfg->scl_pinmux_drv);
|
||||
if (!pinmux_dev) {
|
||||
goto err;
|
||||
}
|
||||
pinmux_pin_set(pinmux_dev, cfg->scl_pin, cfg->scl_flags | flags);
|
||||
|
||||
pinmux_dev = device_get_binding(cfg->sda_pinmux_drv);
|
||||
if (!pinmux_dev) {
|
||||
goto err;
|
||||
}
|
||||
pinmux_pin_set(pinmux_dev, cfg->sda_pin, cfg->sda_flags | flags);
|
||||
|
||||
exit:
|
||||
k_mutex_unlock(&data->mutex);
|
||||
return 0;
|
||||
err:
|
||||
k_mutex_unlock(&data->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int lpc11u6x_i2c_transfer(struct device *dev, struct i2c_msg *msgs,
|
||||
uint8_t num_msgs, uint16_t addr)
|
||||
{
|
||||
const struct lpc11u6x_i2c_config *cfg = DEV_CFG(dev);
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (!num_msgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
|
||||
data->transfer.msgs = msgs;
|
||||
data->transfer.curr_buf = msgs->buf;
|
||||
data->transfer.curr_len = msgs->len;
|
||||
data->transfer.nr_msgs = num_msgs;
|
||||
data->transfer.addr = addr;
|
||||
|
||||
/* Reset all control bits */
|
||||
cfg->base->con_clr = LPC11U6X_I2C_CONTROL_SI |
|
||||
LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_START;
|
||||
|
||||
/* Send start and wait for completion */
|
||||
data->transfer.status = LPC11U6X_I2C_STATUS_BUSY;
|
||||
cfg->base->con_set = LPC11U6X_I2C_CONTROL_START;
|
||||
|
||||
k_sem_take(&data->completion, K_FOREVER);
|
||||
|
||||
if (data->transfer.status != LPC11U6X_I2C_STATUS_OK) {
|
||||
ret = -EIO;
|
||||
}
|
||||
data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
|
||||
|
||||
/* If a slave is registered, put the controller in slave mode */
|
||||
if (data->slave) {
|
||||
cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpc11u6x_i2c_slave_register(struct device *dev,
|
||||
struct i2c_slave_config *cfg)
|
||||
{
|
||||
const struct lpc11u6x_i2c_config *dev_cfg = DEV_CFG(dev);
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (!cfg) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cfg->flags & I2C_SLAVE_FLAGS_ADDR_10_BITS) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
if (data->slave) {
|
||||
ret = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data->slave = cfg;
|
||||
/* Configure controller to act as slave */
|
||||
dev_cfg->base->addr0 = (cfg->address << 1);
|
||||
dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_START |
|
||||
LPC11U6X_I2C_CONTROL_STOP | LPC11U6X_I2C_CONTROL_SI;
|
||||
dev_cfg->base->con_set = LPC11U6X_I2C_CONTROL_AA;
|
||||
|
||||
exit:
|
||||
k_mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int lpc11u6x_i2c_slave_unregister(struct device *dev,
|
||||
struct i2c_slave_config *cfg)
|
||||
{
|
||||
const struct lpc11u6x_i2c_config *dev_cfg = DEV_CFG(dev);
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA(dev);
|
||||
|
||||
if (!cfg) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (data->slave != cfg) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
data->slave = NULL;
|
||||
dev_cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA;
|
||||
k_mutex_unlock(&data->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpc11u6x_i2c_isr(void *arg)
|
||||
{
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA((struct device *)arg);
|
||||
struct lpc11u6x_i2c_regs *i2c = DEV_BASE((struct device *) arg);
|
||||
struct lpc11u6x_i2c_current_transfer *transfer = &data->transfer;
|
||||
uint32_t clear = LPC11U6X_I2C_CONTROL_SI;
|
||||
uint32_t set = 0;
|
||||
uint8_t val;
|
||||
|
||||
switch (i2c->stat) {
|
||||
/* Master TX states */
|
||||
case LPC11U6X_I2C_MASTER_TX_START:
|
||||
case LPC11U6X_I2C_MASTER_TX_RESTART:
|
||||
i2c->dat = (transfer->addr << 1) |
|
||||
(transfer->msgs->flags & I2C_MSG_READ);
|
||||
clear |= LPC11U6X_I2C_CONTROL_START;
|
||||
transfer->curr_buf = transfer->msgs->buf;
|
||||
transfer->curr_len = transfer->msgs->len;
|
||||
break;
|
||||
|
||||
case LPC11U6X_I2C_MASTER_TX_ADR_ACK:
|
||||
case LPC11U6X_I2C_MASTER_TX_DAT_ACK:
|
||||
if (!transfer->curr_len) {
|
||||
transfer->msgs++;
|
||||
transfer->nr_msgs--;
|
||||
if (!transfer->nr_msgs) {
|
||||
transfer->status = LPC11U6X_I2C_STATUS_OK;
|
||||
set |= LPC11U6X_I2C_CONTROL_STOP;
|
||||
} else {
|
||||
set |= LPC11U6X_I2C_CONTROL_START;
|
||||
}
|
||||
} else {
|
||||
i2c->dat = transfer->curr_buf[0];
|
||||
transfer->curr_buf++;
|
||||
transfer->curr_len--;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Master RX states */
|
||||
case LPC11U6X_I2C_MASTER_RX_DAT_NACK:
|
||||
transfer->msgs++;
|
||||
transfer->nr_msgs--;
|
||||
set |= (transfer->nr_msgs ? LPC11U6X_I2C_CONTROL_START :
|
||||
LPC11U6X_I2C_CONTROL_STOP);
|
||||
if (!transfer->nr_msgs) {
|
||||
transfer->status = LPC11U6X_I2C_STATUS_OK;
|
||||
}
|
||||
/* fallthrough */
|
||||
case LPC11U6X_I2C_MASTER_RX_DAT_ACK:
|
||||
transfer->curr_buf[0] = i2c->dat;
|
||||
transfer->curr_buf++;
|
||||
transfer->curr_len--;
|
||||
/* fallthrough */
|
||||
case LPC11U6X_I2C_MASTER_RX_ADR_ACK:
|
||||
if (transfer->curr_len <= 1) {
|
||||
clear |= LPC11U6X_I2C_CONTROL_AA;
|
||||
} else {
|
||||
set |= LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Slave States */
|
||||
case LPC11U6X_I2C_SLAVE_RX_ADR_ACK:
|
||||
case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_ADR_ACK:
|
||||
case LPC11U6X_I2C_SLAVE_RX_GC_ACK:
|
||||
case LPC11U6X_I2C_SLAVE_RX_ARB_LOST_GC_ACK:
|
||||
if (data->slave->callbacks->write_requested(data->slave)) {
|
||||
clear |= LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
break;
|
||||
|
||||
case LPC11U6X_I2C_SLAVE_RX_DAT_ACK:
|
||||
case LPC11U6X_I2C_SLAVE_RX_GC_DAT_ACK:
|
||||
val = i2c->dat;
|
||||
if (data->slave->callbacks->write_received(data->slave, val)) {
|
||||
clear |= LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
break;
|
||||
|
||||
case LPC11U6X_I2C_SLAVE_RX_DAT_NACK:
|
||||
case LPC11U6X_I2C_SLAVE_RX_GC_DAT_NACK:
|
||||
val = i2c->dat;
|
||||
data->slave->callbacks->write_received(data->slave, val);
|
||||
data->slave->callbacks->stop(data->slave);
|
||||
set |= LPC11U6X_I2C_CONTROL_AA;
|
||||
break;
|
||||
|
||||
case LPC11U6X_I2C_SLAVE_RX_STOP:
|
||||
data->slave->callbacks->stop(data->slave);
|
||||
set |= LPC11U6X_I2C_CONTROL_AA;
|
||||
break;
|
||||
|
||||
case LPC11U6X_I2C_SLAVE_TX_ADR_ACK:
|
||||
case LPC11U6X_I2C_SLAVE_TX_ARB_LOST_ADR_ACK:
|
||||
if (data->slave->callbacks->read_requested(data->slave, &val)) {
|
||||
clear |= LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
i2c->dat = val;
|
||||
break;
|
||||
case LPC11U6X_I2C_SLAVE_TX_DAT_ACK:
|
||||
if (data->slave->callbacks->read_processed(data->slave, &val)) {
|
||||
clear |= LPC11U6X_I2C_CONTROL_AA;
|
||||
}
|
||||
i2c->dat = val;
|
||||
break;
|
||||
case LPC11U6X_I2C_SLAVE_TX_DAT_NACK:
|
||||
case LPC11U6X_I2C_SLAVE_TX_LAST_BYTE:
|
||||
data->slave->callbacks->stop(data->slave);
|
||||
set |= LPC11U6X_I2C_CONTROL_AA;
|
||||
break;
|
||||
|
||||
/* Error cases */
|
||||
case LPC11U6X_I2C_MASTER_TX_ADR_NACK:
|
||||
case LPC11U6X_I2C_MASTER_RX_ADR_NACK:
|
||||
case LPC11U6X_I2C_MASTER_TX_DAT_NACK:
|
||||
case LPC11U6X_I2C_MASTER_TX_ARB_LOST:
|
||||
transfer->status = LPC11U6X_I2C_STATUS_FAIL;
|
||||
set = LPC11U6X_I2C_CONTROL_STOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
set = LPC11U6X_I2C_CONTROL_STOP;
|
||||
break;
|
||||
}
|
||||
|
||||
i2c->con_clr = clear;
|
||||
i2c->con_set = set;
|
||||
if ((transfer->status != LPC11U6X_I2C_STATUS_BUSY) &&
|
||||
(transfer->status != LPC11U6X_I2C_STATUS_INACTIVE)) {
|
||||
k_sem_give(&data->completion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int lpc11u6x_i2c_init(struct device *dev)
|
||||
{
|
||||
const struct lpc11u6x_i2c_config *cfg = DEV_CFG(dev);
|
||||
struct lpc11u6x_i2c_data *data = DEV_DATA(dev);
|
||||
struct device *pinmux_dev, *clk_dev;
|
||||
|
||||
/* Configure SCL and SDA pins */
|
||||
pinmux_dev = device_get_binding(cfg->scl_pinmux_drv);
|
||||
if (!pinmux_dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
pinmux_pin_set(pinmux_dev, cfg->scl_pin, cfg->scl_flags);
|
||||
|
||||
pinmux_dev = device_get_binding(cfg->sda_pinmux_drv);
|
||||
if (!pinmux_dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
pinmux_pin_set(pinmux_dev, cfg->sda_pin, cfg->sda_flags);
|
||||
|
||||
/* Configure clock and de-assert reset for I2Cx */
|
||||
clk_dev = device_get_binding(cfg->clock_drv);
|
||||
if (!clk_dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
clock_control_on(clk_dev, (clock_control_subsys_t) cfg->clkid);
|
||||
|
||||
/* Configure bus speed. Default is 100KHz */
|
||||
lpc11u6x_i2c_set_bus_speed(cfg, clk_dev, 100000);
|
||||
|
||||
/* Clear all control bytes and enable I2C interface */
|
||||
cfg->base->con_clr = LPC11U6X_I2C_CONTROL_AA | LPC11U6X_I2C_CONTROL_SI |
|
||||
LPC11U6X_I2C_CONTROL_START | LPC11U6X_I2C_CONTROL_I2C_EN;
|
||||
cfg->base->con_set = LPC11U6X_I2C_CONTROL_I2C_EN;
|
||||
|
||||
/* Initialize mutex and semaphore */
|
||||
k_mutex_init(&data->mutex);
|
||||
k_sem_init(&data->completion, 0, 1);
|
||||
|
||||
data->transfer.status = LPC11U6X_I2C_STATUS_INACTIVE;
|
||||
/* Configure IRQ */
|
||||
cfg->irq_config_func(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_driver_api i2c_api = {
|
||||
.configure = lpc11u6x_i2c_configure,
|
||||
.transfer = lpc11u6x_i2c_transfer,
|
||||
.slave_register = lpc11u6x_i2c_slave_register,
|
||||
.slave_unregister = lpc11u6x_i2c_slave_unregister,
|
||||
};
|
||||
|
||||
#define LPC11U6X_I2C_INIT(idx) \
|
||||
\
|
||||
static void lpc11u6x_i2c_isr_config_##idx(struct device *dev); \
|
||||
\
|
||||
static const struct lpc11u6x_i2c_config i2c_cfg_##idx = { \
|
||||
.base = \
|
||||
(struct lpc11u6x_i2c_regs *) DT_INST_REG_ADDR(idx), \
|
||||
.clock_drv = DT_LABEL(DT_INST_PHANDLE(idx, clocks)), \
|
||||
.scl_pinmux_drv = \
|
||||
DT_LABEL(DT_INST_PHANDLE_BY_NAME(idx, pinmuxs, scl)), \
|
||||
.sda_pinmux_drv = \
|
||||
DT_LABEL(DT_INST_PHANDLE_BY_NAME(idx, pinmuxs, sda)), \
|
||||
.irq_config_func = lpc11u6x_i2c_isr_config_##idx, \
|
||||
.scl_flags = \
|
||||
DT_INST_PHA_BY_NAME(idx, pinmuxs, scl, function), \
|
||||
.sda_flags = \
|
||||
DT_INST_PHA_BY_NAME(idx, pinmuxs, sda, function), \
|
||||
.scl_pin = DT_INST_PHA_BY_NAME(idx, pinmuxs, scl, pin), \
|
||||
.sda_pin = DT_INST_PHA_BY_NAME(idx, pinmuxs, sda, pin), \
|
||||
.clkid = DT_INST_PHA_BY_IDX(idx, clocks, 0, clkid), \
|
||||
}; \
|
||||
\
|
||||
static struct lpc11u6x_i2c_data i2c_data_##idx; \
|
||||
\
|
||||
DEVICE_AND_API_INIT(lpc11u6x_i2c_##idx, DT_INST_LABEL(idx), \
|
||||
&lpc11u6x_i2c_init, \
|
||||
&i2c_data_##idx, &i2c_cfg_##idx, \
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, \
|
||||
&i2c_api); \
|
||||
\
|
||||
static void lpc11u6x_i2c_isr_config_##idx(struct device *dev) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQN(idx), \
|
||||
DT_INST_IRQ(idx, priority), \
|
||||
lpc11u6x_i2c_isr, DEVICE_GET(lpc11u6x_i2c_##idx), 0); \
|
||||
\
|
||||
irq_enable(DT_INST_IRQN(idx)); \
|
||||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LPC11U6X_I2C_INIT);
|
95
drivers/i2c/i2c_lpc11u6x.h
Normal file
95
drivers/i2c/i2c_lpc11u6x.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Seagate Technology LLC
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_I2C_I2C_LPC11U6X_H_
|
||||
#define ZEPHYR_DRIVERS_I2C_I2C_LPC11U6X_H_
|
||||
|
||||
#define LPC11U6X_I2C_CONTROL_AA (1 << 2)
|
||||
#define LPC11U6X_I2C_CONTROL_SI (1 << 3)
|
||||
#define LPC11U6X_I2C_CONTROL_STOP (1 << 4)
|
||||
#define LPC11U6X_I2C_CONTROL_START (1 << 5)
|
||||
#define LPC11U6X_I2C_CONTROL_I2C_EN (1 << 6)
|
||||
|
||||
/* I2C controller states */
|
||||
#define LPC11U6X_I2C_MASTER_TX_START 0x08
|
||||
#define LPC11U6X_I2C_MASTER_TX_RESTART 0x10
|
||||
#define LPC11U6X_I2C_MASTER_TX_ADR_ACK 0x18
|
||||
#define LPC11U6X_I2C_MASTER_TX_ADR_NACK 0x20
|
||||
#define LPC11U6X_I2C_MASTER_TX_DAT_ACK 0x28
|
||||
#define LPC11U6X_I2C_MASTER_TX_DAT_NACK 0x30
|
||||
#define LPC11U6X_I2C_MASTER_TX_ARB_LOST 0x38
|
||||
|
||||
#define LPC11U6X_I2C_MASTER_RX_ADR_ACK 0x40
|
||||
#define LPC11U6X_I2C_MASTER_RX_ADR_NACK 0x48
|
||||
#define LPC11U6X_I2C_MASTER_RX_DAT_ACK 0x50
|
||||
#define LPC11U6X_I2C_MASTER_RX_DAT_NACK 0x58
|
||||
|
||||
#define LPC11U6X_I2C_SLAVE_RX_ADR_ACK 0x60
|
||||
#define LPC11U6X_I2C_SLAVE_RX_ARB_LOST_ADR_ACK 0x68
|
||||
#define LPC11U6X_I2C_SLAVE_RX_GC_ACK 0x70
|
||||
#define LPC11U6X_I2C_SLAVE_RX_ARB_LOST_GC_ACK 0x78
|
||||
#define LPC11U6X_I2C_SLAVE_RX_DAT_ACK 0x80
|
||||
#define LPC11U6X_I2C_SLAVE_RX_DAT_NACK 0x88
|
||||
#define LPC11U6X_I2C_SLAVE_RX_GC_DAT_ACK 0x90
|
||||
#define LPC11U6X_I2C_SLAVE_RX_GC_DAT_NACK 0x98
|
||||
#define LPC11U6X_I2C_SLAVE_RX_STOP 0xA0
|
||||
|
||||
#define LPC11U6X_I2C_SLAVE_TX_ADR_ACK 0xA8
|
||||
#define LPC11U6X_I2C_SLAVE_TX_ARB_LOST_ADR_ACK 0xB0
|
||||
#define LPC11U6X_I2C_SLAVE_TX_DAT_ACK 0xB8
|
||||
#define LPC11U6X_I2C_SLAVE_TX_DAT_NACK 0xC0
|
||||
#define LPC11U6X_I2C_SLAVE_TX_LAST_BYTE 0xC8
|
||||
|
||||
/* Transfer Status */
|
||||
#define LPC11U6X_I2C_STATUS_BUSY 0x01
|
||||
#define LPC11U6X_I2C_STATUS_OK 0x02
|
||||
#define LPC11U6X_I2C_STATUS_FAIL 0x03
|
||||
#define LPC11U6X_I2C_STATUS_INACTIVE 0x04
|
||||
|
||||
struct lpc11u6x_i2c_regs {
|
||||
volatile uint32_t con_set; /* Control set */
|
||||
volatile const uint32_t stat; /* Status */
|
||||
volatile uint32_t dat; /* Data */
|
||||
volatile uint32_t addr0; /* Slave address 0 */
|
||||
volatile uint32_t sclh; /* SCL Duty Cycle */
|
||||
volatile uint32_t scll; /* SCL Duty Cycle */
|
||||
volatile uint32_t con_clr; /* Control clear */
|
||||
volatile uint32_t mm_ctrl; /* Monitor mode control */
|
||||
volatile uint32_t addr[3]; /* Slave address {1,2,3} */
|
||||
volatile const uint32_t data_buffer; /* Data buffer */
|
||||
volatile uint32_t mask[4]; /* Slave address mask */
|
||||
};
|
||||
|
||||
struct lpc11u6x_i2c_config {
|
||||
struct lpc11u6x_i2c_regs *base;
|
||||
char *clock_drv;
|
||||
char *scl_pinmux_drv;
|
||||
char *sda_pinmux_drv;
|
||||
void (*irq_config_func)(struct device *dev);
|
||||
uint32_t clkid;
|
||||
uint32_t scl_flags;
|
||||
uint32_t sda_flags;
|
||||
uint8_t scl_pin;
|
||||
uint8_t sda_pin;
|
||||
};
|
||||
|
||||
struct lpc11u6x_i2c_current_transfer {
|
||||
struct i2c_msg *msgs;
|
||||
uint8_t *curr_buf;
|
||||
uint8_t curr_len;
|
||||
uint8_t nr_msgs;
|
||||
uint8_t addr;
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
struct lpc11u6x_i2c_data {
|
||||
struct lpc11u6x_i2c_current_transfer transfer;
|
||||
struct i2c_slave_config *slave;
|
||||
struct k_sem completion;
|
||||
struct k_mutex mutex;
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_I2C_I2C_LPC11U6X_H_ */
|
|
@ -28,4 +28,11 @@ config UART_LPC11U6X
|
|||
|
||||
endif # SERIAL
|
||||
|
||||
if I2C
|
||||
|
||||
config I2C_LPC11U6X
|
||||
default y
|
||||
|
||||
endif # I2C
|
||||
|
||||
endif # SOC_SERIES_LPC11U6X
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue