Skip to content

Commit

Permalink
drivers: gpio: xlnx_ps: switch driver over to DEVICE_MMIO mapping
Browse files Browse the repository at this point in the history
Set up a named device MMIO memory mapping in the GPIO controller's
parent device, map the virtual memory in the init function of the
parent device.

Once the controller's register space has been successfully mapped,
propagate the mapped virtual address to all child (= GPIO bank)
devices. While it is possible to add a named mapping to every
single GPIO bank device and initialize it in the respective bank
device's init function, this would result in multiple virtual
address mappings all pointing to the same 4k of physical memory.
I assume that, although all those mappings having the same attri-
butes, such a setup is at least discouraged.

Signed-off-by: Immo Birnbaum <[email protected]>
  • Loading branch information
ibirnbaum committed Sep 21, 2024
1 parent 3f2790b commit 977ce26
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 32 deletions.
28 changes: 24 additions & 4 deletions drivers/gpio/gpio_xlnx_ps.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#define DT_DRV_COMPAT xlnx_ps_gpio

#define DEV_CFG(_dev) ((const struct gpio_xlnx_ps_dev_cfg *)(_dev)->config)
#define DEV_DATA(_dev) ((struct gpio_xlnx_ps_dev_data *const)(_dev)->data)

/*
* An API is required for this driver, but as no pin access is provided at
* this level, use the default API contents provided by the driver subsystem.
Expand All @@ -41,7 +44,22 @@ static const struct gpio_driver_api gpio_xlnx_ps_default_apis;
*/
static int gpio_xlnx_ps_init(const struct device *dev)
{
const struct gpio_xlnx_ps_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_dev_data *dev_data = DEV_DATA(dev);
uint32_t bank;

/* Perform the actual memory map operation in the parent device */
DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE);
dev_data->base = DEVICE_MMIO_NAMED_GET(dev, reg_base);
__ASSERT(dev_data->base != 0, "%s map register space failed", dev->name);

/* Propagate the virtual base address to the bank devices */
for (bank = 0; bank < dev_conf->num_banks; bank++) {
struct gpio_xlnx_ps_bank_dev_data *bank_data =
dev_conf->bank_devices[bank]->data;
__ASSERT(bank_data != NULL, "%s bank %u data unresolved", dev->name, bank);
bank_data->base = dev_data->base;
}

/* Initialize the device's interrupt */
dev_conf->config_func(dev);
Expand All @@ -63,7 +81,7 @@ static int gpio_xlnx_ps_init(const struct device *dev)
*/
static void gpio_xlnx_ps_isr(const struct device *dev)
{
const struct gpio_xlnx_ps_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_dev_cfg *dev_conf = DEV_CFG(dev);

const struct gpio_driver_api *api;
struct gpio_xlnx_ps_bank_dev_data *bank_data;
Expand Down Expand Up @@ -102,11 +120,13 @@ static const struct device *const gpio_xlnx_ps##idx##_banks[] = {\

/* Device config & run-time data struct creation macros */
#define GPIO_XLNX_PS_DEV_DATA(idx)\
static struct gpio_xlnx_ps_dev_data gpio_xlnx_ps##idx##_data;
static struct gpio_xlnx_ps_dev_data gpio_xlnx_ps##idx##_data = {\
.base = 0x0,\
};

#define GPIO_XLNX_PS_DEV_CONFIG(idx)\
static const struct gpio_xlnx_ps_dev_cfg gpio_xlnx_ps##idx##_cfg = {\
.base_addr = DT_INST_REG_ADDR(idx),\
DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(idx)),\
.bank_devices = gpio_xlnx_ps##idx##_banks,\
.num_banks = ARRAY_SIZE(gpio_xlnx_ps##idx##_banks),\
.config_func = gpio_xlnx_ps##idx##_irq_config\
Expand Down
6 changes: 5 additions & 1 deletion drivers/gpio/gpio_xlnx_ps.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ typedef void (*gpio_xlnx_ps_config_irq_t)(const struct device *dev);
*/
struct gpio_xlnx_ps_dev_data {
struct gpio_driver_data common;

DEVICE_MMIO_NAMED_RAM(reg_base);
mem_addr_t base;
};

/**
Expand All @@ -36,7 +39,8 @@ struct gpio_xlnx_ps_dev_data {
struct gpio_xlnx_ps_dev_cfg {
struct gpio_driver_config common;

uint32_t base_addr;
DEVICE_MMIO_NAMED_ROM(reg_base);

const struct device *const *bank_devices;
uint32_t num_banks;
gpio_xlnx_ps_config_irq_t config_func;
Expand Down
43 changes: 31 additions & 12 deletions drivers/gpio/gpio_xlnx_ps_bank.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#define DT_DRV_COMPAT xlnx_ps_gpio_bank

#define DEV_CFG(_dev) ((const struct gpio_xlnx_ps_bank_dev_cfg *)(_dev)->config)
#define DEV_DATA(_dev) ((struct gpio_xlnx_ps_bank_dev_data *const)(_dev)->data)

/**
* @brief GPIO bank pin configuration function
*
Expand All @@ -47,7 +50,8 @@ static int gpio_xlnx_ps_pin_configure(const struct device *dev,
gpio_pin_t pin,
gpio_flags_t flags)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t pin_mask = BIT(pin);
uint32_t bank_data;
uint32_t dirm_data;
Expand Down Expand Up @@ -127,7 +131,8 @@ static int gpio_xlnx_ps_pin_configure(const struct device *dev,
static int gpio_xlnx_ps_bank_get(const struct device *dev,
gpio_port_value_t *value)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);

*value = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
return 0;
Expand Down Expand Up @@ -159,7 +164,8 @@ static int gpio_xlnx_ps_bank_set_masked(const struct device *dev,
gpio_port_pins_t mask,
gpio_port_value_t value)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t bank_data;

bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
Expand Down Expand Up @@ -187,7 +193,8 @@ static int gpio_xlnx_ps_bank_set_masked(const struct device *dev,
static int gpio_xlnx_ps_bank_set_bits(const struct device *dev,
gpio_port_pins_t pins)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t bank_data;

bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
Expand Down Expand Up @@ -215,7 +222,8 @@ static int gpio_xlnx_ps_bank_set_bits(const struct device *dev,
static int gpio_xlnx_ps_bank_clear_bits(const struct device *dev,
gpio_port_pins_t pins)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t bank_data;

bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
Expand Down Expand Up @@ -243,7 +251,8 @@ static int gpio_xlnx_ps_bank_clear_bits(const struct device *dev,
static int gpio_xlnx_ps_bank_toggle_bits(const struct device *dev,
gpio_port_pins_t pins)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t bank_data;

bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
Expand Down Expand Up @@ -282,7 +291,8 @@ static int gpio_xlnx_ps_bank_pin_irq_configure(const struct device *dev,
enum gpio_int_mode mode,
enum gpio_int_trig trig)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t pin_mask = BIT(pin);
uint32_t int_type_data;
uint32_t int_polarity_data;
Expand Down Expand Up @@ -358,7 +368,8 @@ static int gpio_xlnx_ps_bank_pin_irq_configure(const struct device *dev,
*/
static uint32_t gpio_xlnx_ps_bank_get_int_status(const struct device *dev)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);
uint32_t int_status;

int_status = sys_read32(GPIO_XLNX_PS_BANK_INT_STAT_REG);
Expand Down Expand Up @@ -387,7 +398,7 @@ static int gpio_xlnx_ps_bank_manage_callback(const struct device *dev,
struct gpio_callback *callback,
bool set)
{
struct gpio_xlnx_ps_bank_dev_data *dev_data = dev->data;
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);

return gpio_manage_callback(&dev_data->callbacks, callback, set);
}
Expand Down Expand Up @@ -419,7 +430,14 @@ static const struct gpio_driver_api gpio_xlnx_ps_bank_apis = {
*/
static int gpio_xlnx_ps_bank_init(const struct device *dev)
{
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = DEV_CFG(dev);
struct gpio_xlnx_ps_bank_dev_data *dev_data = DEV_DATA(dev);

__ASSERT(dev_data->base != 0, "%s mapped base address missing", dev->name);
if (dev_data->base == 0) {
LOG_ERR("%s mapped base address missing", dev->name);
return -EIO;
}

sys_write32(~0x0, GPIO_XLNX_PS_BANK_INT_DIS_REG); /* Disable all interrupts */
sys_write32(~0x0, GPIO_XLNX_PS_BANK_INT_STAT_REG); /* Clear all interrupts */
Expand All @@ -436,10 +454,11 @@ static const struct gpio_xlnx_ps_bank_dev_cfg gpio_xlnx_ps_bank##idx##_cfg = {\
.common = {\
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx),\
},\
.base_addr = DT_REG_ADDR(DT_PARENT(DT_INST(idx, DT_DRV_COMPAT))),\
.bank_index = idx,\
};\
static struct gpio_xlnx_ps_bank_dev_data gpio_xlnx_ps_bank##idx##_data;\
static struct gpio_xlnx_ps_bank_dev_data gpio_xlnx_ps_bank##idx##_data = {\
.base = 0,\
};\
DEVICE_DT_INST_DEFINE(idx, gpio_xlnx_ps_bank_init, NULL,\
&gpio_xlnx_ps_bank##idx##_data, &gpio_xlnx_ps_bank##idx##_cfg,\
PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_xlnx_ps_bank_apis);
Expand Down
29 changes: 14 additions & 15 deletions drivers/gpio/gpio_xlnx_ps_bank.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,31 @@
* Register address calculation macros
* Register address offsets: comp. Zynq-7000 TRM, ug585, chap. B.19
*/
#define GPIO_XLNX_PS_BANK_MASK_DATA_LSW_REG (dev_conf->base_addr\
#define GPIO_XLNX_PS_BANK_MASK_DATA_LSW_REG (dev_data->base\
+ ((uint32_t)dev_conf->bank_index * 0x8))
#define GPIO_XLNX_PS_BANK_MASK_DATA_MSW_REG ((dev_conf->base_addr + 0x04)\
#define GPIO_XLNX_PS_BANK_MASK_DATA_MSW_REG ((dev_data->base + 0x04)\
+ ((uint32_t)dev_conf->bank_index * 0x8))
#define GPIO_XLNX_PS_BANK_DATA_REG ((dev_conf->base_addr + 0x40)\
#define GPIO_XLNX_PS_BANK_DATA_REG ((dev_data->base + 0x40)\
+ ((uint32_t)dev_conf->bank_index * 0x4))
#define GPIO_XLNX_PS_BANK_DATA_RO_REG ((dev_conf->base_addr + 0x60)\
#define GPIO_XLNX_PS_BANK_DATA_RO_REG ((dev_data->base + 0x60)\
+ ((uint32_t)dev_conf->bank_index * 0x4))
#define GPIO_XLNX_PS_BANK_DIRM_REG ((dev_conf->base_addr + 0x204)\
#define GPIO_XLNX_PS_BANK_DIRM_REG ((dev_data->base + 0x204)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_OEN_REG ((dev_conf->base_addr + 0x208)\
#define GPIO_XLNX_PS_BANK_OEN_REG ((dev_data->base + 0x208)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_MASK_REG ((dev_conf->base_addr + 0x20C)\
#define GPIO_XLNX_PS_BANK_INT_MASK_REG ((dev_data->base + 0x20C)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_EN_REG ((dev_conf->base_addr + 0x210)\
#define GPIO_XLNX_PS_BANK_INT_EN_REG ((dev_data->base + 0x210)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_DIS_REG ((dev_conf->base_addr + 0x214)\
#define GPIO_XLNX_PS_BANK_INT_DIS_REG ((dev_data->base + 0x214)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_STAT_REG ((dev_conf->base_addr + 0x218)\
#define GPIO_XLNX_PS_BANK_INT_STAT_REG ((dev_data->base + 0x218)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_TYPE_REG ((dev_conf->base_addr + 0x21C)\
#define GPIO_XLNX_PS_BANK_INT_TYPE_REG ((dev_data->base + 0x21C)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_POLARITY_REG ((dev_conf->base_addr + 0x220)\
#define GPIO_XLNX_PS_BANK_INT_POLARITY_REG ((dev_data->base + 0x220)\
+ ((uint32_t)dev_conf->bank_index * 0x40))
#define GPIO_XLNX_PS_BANK_INT_ANY_REG ((dev_conf->base_addr + 0x224)\
#define GPIO_XLNX_PS_BANK_INT_ANY_REG ((dev_data->base + 0x224)\
+ ((uint32_t)dev_conf->bank_index * 0x40))

/**
Expand All @@ -51,6 +51,7 @@
*/
struct gpio_xlnx_ps_bank_dev_data {
struct gpio_driver_data common;
mem_addr_t base;
sys_slist_t callbacks;
};

Expand All @@ -64,8 +65,6 @@ struct gpio_xlnx_ps_bank_dev_data {
*/
struct gpio_xlnx_ps_bank_dev_cfg {
struct gpio_driver_config common;

uint32_t base_addr;
uint8_t bank_index;
};

Expand Down

0 comments on commit 977ce26

Please sign in to comment.