drivers: gpio_rcar: add memory mapping to driver
Add memory mapping to driver in order to use driver with platforms based on Cortex A with enabled MMU. Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
This commit is contained in:
parent
07f2c7a1df
commit
0ef6454c6f
|
@ -20,10 +20,14 @@
|
||||||
|
|
||||||
typedef void (*init_func_t)(const struct device *dev);
|
typedef void (*init_func_t)(const struct device *dev);
|
||||||
|
|
||||||
|
/* Required by DEVICE_MMIO_NAMED_* macros */
|
||||||
|
#define DEV_CFG(_dev) \
|
||||||
|
((const struct gpio_rcar_cfg *)(_dev)->config)
|
||||||
|
#define DEV_DATA(_dev) ((struct gpio_rcar_data *)(_dev)->data)
|
||||||
|
|
||||||
struct gpio_rcar_cfg {
|
struct gpio_rcar_cfg {
|
||||||
struct gpio_driver_config common;
|
struct gpio_driver_config common;
|
||||||
uint32_t reg_addr;
|
DEVICE_MMIO_NAMED_ROM(reg_base);
|
||||||
int reg_size;
|
|
||||||
init_func_t init_func;
|
init_func_t init_func;
|
||||||
const struct device *clock_dev;
|
const struct device *clock_dev;
|
||||||
struct rcar_cpg_clk mod_clk;
|
struct rcar_cpg_clk mod_clk;
|
||||||
|
@ -31,6 +35,7 @@ struct gpio_rcar_cfg {
|
||||||
|
|
||||||
struct gpio_rcar_data {
|
struct gpio_rcar_data {
|
||||||
struct gpio_driver_data common;
|
struct gpio_driver_data common;
|
||||||
|
DEVICE_MMIO_NAMED_RAM(reg_base);
|
||||||
sys_slist_t cb;
|
sys_slist_t cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,22 +53,20 @@ struct gpio_rcar_data {
|
||||||
#define OUTDTSEL 0x40 /* Output Data Select Register */
|
#define OUTDTSEL 0x40 /* Output Data Select Register */
|
||||||
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
|
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
|
||||||
|
|
||||||
static inline uint32_t gpio_rcar_read(const struct gpio_rcar_cfg *config,
|
static inline uint32_t gpio_rcar_read(const struct device *dev, uint32_t offs)
|
||||||
uint32_t offs)
|
|
||||||
{
|
{
|
||||||
return sys_read32(config->reg_addr + offs);
|
return sys_read32(DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gpio_rcar_write(const struct gpio_rcar_cfg *config,
|
static inline void gpio_rcar_write(const struct device *dev, uint32_t offs, uint32_t value)
|
||||||
uint32_t offs, uint32_t value)
|
|
||||||
{
|
{
|
||||||
sys_write32(value, config->reg_addr + offs);
|
sys_write32(value, DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpio_rcar_modify_bit(const struct gpio_rcar_cfg *config,
|
static void gpio_rcar_modify_bit(const struct device *dev,
|
||||||
uint32_t offs, int bit, bool value)
|
uint32_t offs, int bit, bool value)
|
||||||
{
|
{
|
||||||
uint32_t tmp = gpio_rcar_read(config, offs);
|
uint32_t tmp = gpio_rcar_read(dev, offs);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
tmp |= BIT(bit);
|
tmp |= BIT(bit);
|
||||||
|
@ -71,28 +74,27 @@ static void gpio_rcar_modify_bit(const struct gpio_rcar_cfg *config,
|
||||||
tmp &= ~BIT(bit);
|
tmp &= ~BIT(bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_rcar_write(config, offs, tmp);
|
gpio_rcar_write(dev, offs, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpio_rcar_port_isr(const struct device *dev)
|
static void gpio_rcar_port_isr(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
struct gpio_rcar_data *data = dev->data;
|
struct gpio_rcar_data *data = dev->data;
|
||||||
uint32_t pending, fsb, mask;
|
uint32_t pending, fsb, mask;
|
||||||
|
|
||||||
pending = gpio_rcar_read(config, INTDT);
|
pending = gpio_rcar_read(dev, INTDT);
|
||||||
mask = gpio_rcar_read(config, INTMSK);
|
mask = gpio_rcar_read(dev, INTMSK);
|
||||||
|
|
||||||
while ((pending = gpio_rcar_read(config, INTDT) &
|
while ((pending = gpio_rcar_read(dev, INTDT) &
|
||||||
gpio_rcar_read(config, INTMSK))) {
|
gpio_rcar_read(dev, INTMSK))) {
|
||||||
fsb = find_lsb_set(pending) - 1;
|
fsb = find_lsb_set(pending) - 1;
|
||||||
gpio_fire_callbacks(&data->cb, dev, BIT(fsb));
|
gpio_fire_callbacks(&data->cb, dev, BIT(fsb));
|
||||||
gpio_rcar_write(config, INTCLR, BIT(fsb));
|
gpio_rcar_write(dev, INTCLR, BIT(fsb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpio_rcar_config_general_input_output_mode(
|
static void gpio_rcar_config_general_input_output_mode(
|
||||||
const struct gpio_rcar_cfg *config,
|
const struct device *dev,
|
||||||
uint32_t gpio,
|
uint32_t gpio,
|
||||||
bool output)
|
bool output)
|
||||||
{
|
{
|
||||||
|
@ -102,25 +104,23 @@ static void gpio_rcar_config_general_input_output_mode(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Configure positive logic in POSNEG */
|
/* Configure positive logic in POSNEG */
|
||||||
gpio_rcar_modify_bit(config, POSNEG, gpio, false);
|
gpio_rcar_modify_bit(dev, POSNEG, gpio, false);
|
||||||
|
|
||||||
/* Select "General Input/Output Mode" in IOINTSEL */
|
/* Select "General Input/Output Mode" in IOINTSEL */
|
||||||
gpio_rcar_modify_bit(config, IOINTSEL, gpio, false);
|
gpio_rcar_modify_bit(dev, IOINTSEL, gpio, false);
|
||||||
|
|
||||||
/* Select Input Mode or Output Mode in INOUTSEL */
|
/* Select Input Mode or Output Mode in INOUTSEL */
|
||||||
gpio_rcar_modify_bit(config, INOUTSEL, gpio, output);
|
gpio_rcar_modify_bit(dev, INOUTSEL, gpio, output);
|
||||||
|
|
||||||
/* Select General Output Register to output data in OUTDTSEL */
|
/* Select General Output Register to output data in OUTDTSEL */
|
||||||
if (output) {
|
if (output) {
|
||||||
gpio_rcar_modify_bit(config, OUTDTSEL, gpio, false);
|
gpio_rcar_modify_bit(dev, OUTDTSEL, gpio, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gpio_rcar_configure(const struct device *dev,
|
static int gpio_rcar_configure(const struct device *dev,
|
||||||
gpio_pin_t pin, gpio_flags_t flags)
|
gpio_pin_t pin, gpio_flags_t flags)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
|
|
||||||
if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) {
|
if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) {
|
||||||
/* Pin cannot be configured as input and output */
|
/* Pin cannot be configured as input and output */
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
@ -131,13 +131,13 @@ static int gpio_rcar_configure(const struct device *dev,
|
||||||
|
|
||||||
if (flags & GPIO_OUTPUT) {
|
if (flags & GPIO_OUTPUT) {
|
||||||
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||||
gpio_rcar_modify_bit(config, OUTDT, pin, true);
|
gpio_rcar_modify_bit(dev, OUTDT, pin, true);
|
||||||
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||||
gpio_rcar_modify_bit(config, OUTDT, pin, false);
|
gpio_rcar_modify_bit(dev, OUTDT, pin, false);
|
||||||
}
|
}
|
||||||
gpio_rcar_config_general_input_output_mode(config, pin, true);
|
gpio_rcar_config_general_input_output_mode(dev, pin, true);
|
||||||
} else {
|
} else {
|
||||||
gpio_rcar_config_general_input_output_mode(config, pin, false);
|
gpio_rcar_config_general_input_output_mode(dev, pin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -146,9 +146,7 @@ static int gpio_rcar_configure(const struct device *dev,
|
||||||
static int gpio_rcar_port_get_raw(const struct device *dev,
|
static int gpio_rcar_port_get_raw(const struct device *dev,
|
||||||
gpio_port_value_t *value)
|
gpio_port_value_t *value)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
*value = gpio_rcar_read(dev, INDT);
|
||||||
|
|
||||||
*value = gpio_rcar_read(config, INDT);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,12 +154,11 @@ static int gpio_rcar_port_set_masked_raw(const struct device *dev,
|
||||||
gpio_port_pins_t mask,
|
gpio_port_pins_t mask,
|
||||||
gpio_port_value_t value)
|
gpio_port_value_t value)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
uint32_t port_val;
|
uint32_t port_val;
|
||||||
|
|
||||||
port_val = gpio_rcar_read(config, OUTDT);
|
port_val = gpio_rcar_read(dev, OUTDT);
|
||||||
port_val = (port_val & ~mask) | (value & mask);
|
port_val = (port_val & ~mask) | (value & mask);
|
||||||
gpio_rcar_write(config, OUTDT, port_val);
|
gpio_rcar_write(dev, OUTDT, port_val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -169,12 +166,11 @@ static int gpio_rcar_port_set_masked_raw(const struct device *dev,
|
||||||
static int gpio_rcar_port_set_bits_raw(const struct device *dev,
|
static int gpio_rcar_port_set_bits_raw(const struct device *dev,
|
||||||
gpio_port_pins_t pins)
|
gpio_port_pins_t pins)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
uint32_t port_val;
|
uint32_t port_val;
|
||||||
|
|
||||||
port_val = gpio_rcar_read(config, OUTDT);
|
port_val = gpio_rcar_read(dev, OUTDT);
|
||||||
port_val |= pins;
|
port_val |= pins;
|
||||||
gpio_rcar_write(config, OUTDT, port_val);
|
gpio_rcar_write(dev, OUTDT, port_val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -182,12 +178,11 @@ static int gpio_rcar_port_set_bits_raw(const struct device *dev,
|
||||||
static int gpio_rcar_port_clear_bits_raw(const struct device *dev,
|
static int gpio_rcar_port_clear_bits_raw(const struct device *dev,
|
||||||
gpio_port_pins_t pins)
|
gpio_port_pins_t pins)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
uint32_t port_val;
|
uint32_t port_val;
|
||||||
|
|
||||||
port_val = gpio_rcar_read(config, OUTDT);
|
port_val = gpio_rcar_read(dev, OUTDT);
|
||||||
port_val &= ~pins;
|
port_val &= ~pins;
|
||||||
gpio_rcar_write(config, OUTDT, port_val);
|
gpio_rcar_write(dev, OUTDT, port_val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -195,12 +190,11 @@ static int gpio_rcar_port_clear_bits_raw(const struct device *dev,
|
||||||
static int gpio_rcar_port_toggle_bits(const struct device *dev,
|
static int gpio_rcar_port_toggle_bits(const struct device *dev,
|
||||||
gpio_port_pins_t pins)
|
gpio_port_pins_t pins)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
uint32_t port_val;
|
uint32_t port_val;
|
||||||
|
|
||||||
port_val = gpio_rcar_read(config, OUTDT);
|
port_val = gpio_rcar_read(dev, OUTDT);
|
||||||
port_val ^= pins;
|
port_val ^= pins;
|
||||||
gpio_rcar_write(config, OUTDT, port_val);
|
gpio_rcar_write(dev, OUTDT, port_val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -210,35 +204,33 @@ static int gpio_rcar_pin_interrupt_configure(const struct device *dev,
|
||||||
enum gpio_int_mode mode,
|
enum gpio_int_mode mode,
|
||||||
enum gpio_int_trig trig)
|
enum gpio_int_trig trig)
|
||||||
{
|
{
|
||||||
const struct gpio_rcar_cfg *config = dev->config;
|
|
||||||
|
|
||||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure positive or negative logic in POSNEG */
|
/* Configure positive or negative logic in POSNEG */
|
||||||
gpio_rcar_modify_bit(config, POSNEG, pin,
|
gpio_rcar_modify_bit(dev, POSNEG, pin,
|
||||||
(trig == GPIO_INT_TRIG_LOW));
|
(trig == GPIO_INT_TRIG_LOW));
|
||||||
|
|
||||||
/* Configure edge or level trigger in EDGLEVEL */
|
/* Configure edge or level trigger in EDGLEVEL */
|
||||||
if (mode == GPIO_INT_MODE_EDGE) {
|
if (mode == GPIO_INT_MODE_EDGE) {
|
||||||
gpio_rcar_modify_bit(config, EDGLEVEL, pin, true);
|
gpio_rcar_modify_bit(dev, EDGLEVEL, pin, true);
|
||||||
} else {
|
} else {
|
||||||
gpio_rcar_modify_bit(config, EDGLEVEL, pin, false);
|
gpio_rcar_modify_bit(dev, EDGLEVEL, pin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trig == GPIO_INT_TRIG_BOTH) {
|
if (trig == GPIO_INT_TRIG_BOTH) {
|
||||||
gpio_rcar_modify_bit(config, BOTHEDGE, pin, true);
|
gpio_rcar_modify_bit(dev, BOTHEDGE, pin, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_rcar_modify_bit(config, IOINTSEL, pin, true);
|
gpio_rcar_modify_bit(dev, IOINTSEL, pin, true);
|
||||||
|
|
||||||
if (mode == GPIO_INT_MODE_EDGE) {
|
if (mode == GPIO_INT_MODE_EDGE) {
|
||||||
/* Write INTCLR in case of edge trigger */
|
/* Write INTCLR in case of edge trigger */
|
||||||
gpio_rcar_write(config, INTCLR, BIT(pin));
|
gpio_rcar_write(dev, INTCLR, BIT(pin));
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_rcar_write(config, MSKCLR, BIT(pin));
|
gpio_rcar_write(dev, MSKCLR, BIT(pin));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -259,6 +251,7 @@ static int gpio_rcar_init(const struct device *dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE);
|
||||||
config->init_func(dev);
|
config->init_func(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -284,41 +277,40 @@ static const struct gpio_driver_api gpio_rcar_driver_api = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device Instantiation */
|
/* Device Instantiation */
|
||||||
#define GPIO_RCAR_INIT(n) \
|
#define GPIO_RCAR_INIT(n) \
|
||||||
static void gpio_rcar_##n##_init(const struct device *dev); \
|
static void gpio_rcar_##n##_init(const struct device *dev); \
|
||||||
static const struct gpio_rcar_cfg gpio_rcar_cfg_##n = { \
|
static const struct gpio_rcar_cfg gpio_rcar_cfg_##n = { \
|
||||||
.common = { \
|
DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \
|
||||||
.port_pin_mask = \
|
.common = { \
|
||||||
GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
|
.port_pin_mask = \
|
||||||
}, \
|
GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
|
||||||
.reg_addr = DT_INST_REG_ADDR(n), \
|
}, \
|
||||||
.reg_size = DT_INST_REG_SIZE(n), \
|
.init_func = gpio_rcar_##n##_init, \
|
||||||
.init_func = gpio_rcar_##n##_init, \
|
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
||||||
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
.mod_clk.module = \
|
||||||
.mod_clk.module = \
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \
|
||||||
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \
|
.mod_clk.domain = \
|
||||||
.mod_clk.domain = \
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \
|
||||||
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \
|
}; \
|
||||||
}; \
|
static struct gpio_rcar_data gpio_rcar_data_##n; \
|
||||||
static struct gpio_rcar_data gpio_rcar_data_##n; \
|
\
|
||||||
\
|
DEVICE_DT_INST_DEFINE(n, \
|
||||||
DEVICE_DT_INST_DEFINE(n, \
|
gpio_rcar_init, \
|
||||||
gpio_rcar_init, \
|
NULL, \
|
||||||
NULL, \
|
&gpio_rcar_data_##n, \
|
||||||
&gpio_rcar_data_##n, \
|
&gpio_rcar_cfg_##n, \
|
||||||
&gpio_rcar_cfg_##n, \
|
PRE_KERNEL_1, \
|
||||||
PRE_KERNEL_1, \
|
CONFIG_GPIO_INIT_PRIORITY, \
|
||||||
CONFIG_GPIO_INIT_PRIORITY, \
|
&gpio_rcar_driver_api \
|
||||||
&gpio_rcar_driver_api \
|
); \
|
||||||
); \
|
static void gpio_rcar_##n##_init(const struct device *dev) \
|
||||||
static void gpio_rcar_##n##_init(const struct device *dev) \
|
{ \
|
||||||
{ \
|
IRQ_CONNECT(DT_INST_IRQN(n), \
|
||||||
IRQ_CONNECT(DT_INST_IRQN(n), \
|
0, \
|
||||||
0, \
|
gpio_rcar_port_isr, \
|
||||||
gpio_rcar_port_isr, \
|
DEVICE_DT_INST_GET(n), 0); \
|
||||||
DEVICE_DT_INST_GET(n), 0); \
|
\
|
||||||
\
|
irq_enable(DT_INST_IRQN(n)); \
|
||||||
irq_enable(DT_INST_IRQN(n)); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_RCAR_INIT)
|
DT_INST_FOREACH_STATUS_OKAY(GPIO_RCAR_INIT)
|
||||||
|
|
Loading…
Reference in a new issue