driver: mucx_lpi2c: enable runtime mmio configuration
Enable runtime mmio configuration in mcux_lpi2c driver. The fsl_lpi2c driver relies on physical address to determine instance number. So mmap flag 'K_MEM_DIRECT_MAP' is required. Signed-off-by: Chekhov Ma <chekhov.ma@nxp.com>
This commit is contained in:
@@ -32,8 +32,13 @@ LOG_MODULE_REGISTER(mcux_lpi2c);
|
||||
*/
|
||||
#define SCAN_DELAY_US(baudrate) (12 * USEC_PER_SEC / baudrate)
|
||||
|
||||
/* Required by DEVICE_MMIO_NAMED_* macros */
|
||||
#define DEV_CFG(_dev) \
|
||||
((const struct mcux_lpi2c_config *)(_dev)->config)
|
||||
#define DEV_DATA(_dev) ((struct mcux_lpi2c_data *)(_dev)->data)
|
||||
|
||||
struct mcux_lpi2c_config {
|
||||
LPI2C_Type *base;
|
||||
DEVICE_MMIO_NAMED_ROM(reg_base);
|
||||
const struct device *clock_dev;
|
||||
clock_control_subsys_t clock_subsys;
|
||||
void (*irq_config_func)(const struct device *dev);
|
||||
@@ -47,6 +52,7 @@ struct mcux_lpi2c_config {
|
||||
};
|
||||
|
||||
struct mcux_lpi2c_data {
|
||||
DEVICE_MMIO_NAMED_RAM(reg_base);
|
||||
lpi2c_master_handle_t handle;
|
||||
struct k_sem lock;
|
||||
struct k_sem device_sync_sem;
|
||||
@@ -66,7 +72,7 @@ static int mcux_lpi2c_configure(const struct device *dev,
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = config->base;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
uint32_t clock_freq;
|
||||
uint32_t baudrate;
|
||||
int ret;
|
||||
@@ -138,11 +144,11 @@ static uint32_t mcux_lpi2c_convert_flags(int msg_flags)
|
||||
}
|
||||
|
||||
static int mcux_lpi2c_transfer(const struct device *dev, struct i2c_msg *msgs,
|
||||
uint8_t num_msgs, uint16_t addr)
|
||||
uint8_t num_msgs, uint16_t addr)
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = config->base;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
lpi2c_master_transfer_t transfer;
|
||||
status_t status;
|
||||
int ret = 0;
|
||||
@@ -306,6 +312,7 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev)
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks;
|
||||
int ret;
|
||||
uint32_t flags;
|
||||
@@ -319,11 +326,11 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev)
|
||||
* every byte. For these reason, we handle the LPI2C IRQ
|
||||
* directly.
|
||||
*/
|
||||
flags = LPI2C_SlaveGetStatusFlags(config->base);
|
||||
flags = LPI2C_SlaveGetStatusFlags(base);
|
||||
|
||||
if (flags & kLPI2C_SlaveAddressValidFlag) {
|
||||
/* Read Slave address to clear flag */
|
||||
LPI2C_SlaveGetReceivedAddress(config->base);
|
||||
LPI2C_SlaveGetReceivedAddress(base);
|
||||
data->first_tx = true;
|
||||
/* Reset to sending ACK, in case we NAK'ed before */
|
||||
data->send_ack = true;
|
||||
@@ -384,26 +391,27 @@ static void mcux_lpi2c_slave_irq_handler(const struct device *dev)
|
||||
}
|
||||
|
||||
if (flags & kLPI2C_SlaveStopDetectFlag) {
|
||||
LPI2C_SlaveClearStatusFlags(config->base, flags);
|
||||
LPI2C_SlaveClearStatusFlags(base, flags);
|
||||
if (target_cb->stop) {
|
||||
target_cb->stop(data->target_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & kLPI2C_SlaveTransmitAckFlag) {
|
||||
LPI2C_SlaveTransmitAck(config->base, data->send_ack);
|
||||
LPI2C_SlaveTransmitAck(base, data->send_ack);
|
||||
}
|
||||
}
|
||||
|
||||
static int mcux_lpi2c_target_register(const struct device *dev,
|
||||
struct i2c_target_config *target_config)
|
||||
struct i2c_target_config *target_config)
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
lpi2c_slave_config_t slave_config;
|
||||
uint32_t clock_freq;
|
||||
|
||||
LPI2C_MasterDeinit(config->base);
|
||||
LPI2C_MasterDeinit(base);
|
||||
|
||||
/* Get the clock frequency */
|
||||
if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
|
||||
@@ -430,11 +438,11 @@ static int mcux_lpi2c_target_register(const struct device *dev,
|
||||
* this behavior may cause issues with some I2C controllers.
|
||||
*/
|
||||
slave_config.sclStall.enableAck = true;
|
||||
LPI2C_SlaveInit(config->base, &slave_config, clock_freq);
|
||||
LPI2C_SlaveInit(base, &slave_config, clock_freq);
|
||||
/* Clear all flags. */
|
||||
LPI2C_SlaveClearStatusFlags(config->base, (uint32_t)kLPI2C_SlaveClearFlags);
|
||||
LPI2C_SlaveClearStatusFlags(base, (uint32_t)kLPI2C_SlaveClearFlags);
|
||||
/* Enable interrupt */
|
||||
LPI2C_SlaveEnableInterrupts(config->base,
|
||||
LPI2C_SlaveEnableInterrupts(base,
|
||||
(kLPI2C_SlaveTxReadyFlag |
|
||||
kLPI2C_SlaveRxReadyFlag |
|
||||
kLPI2C_SlaveStopDetectFlag |
|
||||
@@ -448,6 +456,7 @@ static int mcux_lpi2c_target_unregister(const struct device *dev,
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
|
||||
if (!data->target_attached) {
|
||||
return -EINVAL;
|
||||
@@ -456,7 +465,7 @@ static int mcux_lpi2c_target_unregister(const struct device *dev,
|
||||
data->target_cfg = NULL;
|
||||
data->target_attached = false;
|
||||
|
||||
LPI2C_SlaveDeinit(config->base);
|
||||
LPI2C_SlaveDeinit(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -464,9 +473,8 @@ static int mcux_lpi2c_target_unregister(const struct device *dev,
|
||||
|
||||
static void mcux_lpi2c_isr(const struct device *dev)
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = config->base;
|
||||
LPI2C_Type *base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
|
||||
#ifdef CONFIG_I2C_TARGET
|
||||
if (data->target_attached) {
|
||||
@@ -481,11 +489,15 @@ static int mcux_lpi2c_init(const struct device *dev)
|
||||
{
|
||||
const struct mcux_lpi2c_config *config = dev->config;
|
||||
struct mcux_lpi2c_data *data = dev->data;
|
||||
LPI2C_Type *base = config->base;
|
||||
LPI2C_Type *base;
|
||||
uint32_t clock_freq, bitrate_cfg;
|
||||
lpi2c_master_config_t master_config;
|
||||
int error;
|
||||
|
||||
DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP);
|
||||
|
||||
base = (LPI2C_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
|
||||
|
||||
k_sem_init(&data->lock, 1, 1);
|
||||
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
@@ -549,7 +561,7 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = {
|
||||
static void mcux_lpi2c_config_func_##n(const struct device *dev); \
|
||||
\
|
||||
static const struct mcux_lpi2c_config mcux_lpi2c_config_##n = { \
|
||||
.base = (LPI2C_Type *)DT_INST_REG_ADDR(n), \
|
||||
DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \
|
||||
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
||||
.clock_subsys = \
|
||||
(clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
|
||||
@@ -566,17 +578,17 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = {
|
||||
static struct mcux_lpi2c_data mcux_lpi2c_data_##n; \
|
||||
\
|
||||
I2C_DEVICE_DT_INST_DEFINE(n, mcux_lpi2c_init, NULL, \
|
||||
&mcux_lpi2c_data_##n, \
|
||||
&mcux_lpi2c_config_##n, POST_KERNEL, \
|
||||
CONFIG_I2C_INIT_PRIORITY, \
|
||||
&mcux_lpi2c_driver_api); \
|
||||
&mcux_lpi2c_data_##n, \
|
||||
&mcux_lpi2c_config_##n, POST_KERNEL, \
|
||||
CONFIG_I2C_INIT_PRIORITY, \
|
||||
&mcux_lpi2c_driver_api); \
|
||||
\
|
||||
static void mcux_lpi2c_config_func_##n(const struct device *dev) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), \
|
||||
DT_INST_IRQ(n, priority), \
|
||||
mcux_lpi2c_isr, \
|
||||
DEVICE_DT_INST_GET(n), 0); \
|
||||
DT_INST_IRQ(n, priority), \
|
||||
mcux_lpi2c_isr, \
|
||||
DEVICE_DT_INST_GET(n), 0); \
|
||||
\
|
||||
irq_enable(DT_INST_IRQN(n)); \
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user