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:
Chekhov Ma
2023-12-13 11:40:51 +08:00
committed by Carles Cufí
parent ef867e4c7e
commit 734adf52c6

View File

@@ -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)); \
}