From 821212c3df8e85b8934712b681158a7a669cb4d6 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Tue, 26 Jan 2016 12:04:38 -0200 Subject: [PATCH] drivers: gpio: Add support for AON GPIO to QMSI driver This adds support to the AON GPIO controller using the QMSI driver. In order to enable it, the following configuration options must be set: CONFIG_QMSI_DRIVERS=y CONFIG_QMSI_INSTALL_PATH="PATH TO LIBQMSI" CONFIG_GPIO_QMSI=y CONFIG_GPIO_QMSI_AON=y Change-Id: I5a1a232d97741ad7fdbf40d8aea5a835e5b4e724 Signed-off-by: Vinicius Costa Gomes --- arch/x86/soc/quark_se/Kconfig | 8 +++ drivers/gpio/Kconfig | 26 ++++++++ drivers/gpio/gpio_qmsi.c | 112 ++++++++++++++++++++++++++-------- 3 files changed, 121 insertions(+), 25 deletions(-) diff --git a/arch/x86/soc/quark_se/Kconfig b/arch/x86/soc/quark_se/Kconfig index 315abfd3391..20830bc277f 100644 --- a/arch/x86/soc/quark_se/Kconfig +++ b/arch/x86/soc/quark_se/Kconfig @@ -124,6 +124,14 @@ config GPIO_QMSI_0_IRQ default 8 config GPIO_QMSI_0_PRI default 2 +config GPIO_QMSI_AON + def_bool n +config GPIO_QMSI_AON_NAME + default "gpio_aon" +config GPIO_QMSI_AON_IRQ + default 31 +config GPIO_QMSI_AON_PRI + default 2 endif endif endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b82c027b5d3..4abb9b2e828 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -633,6 +633,32 @@ config GPIO_QMSI_0_PRI help IRQ priority +config GPIO_QMSI_AON + bool "QMSI GPIO block AON" + depends on GPIO_QMSI + default n + help + Include support for the GPIO AON (always on) port using QMSI. + +config GPIO_QMSI_AON_NAME + string "Driver name" + depends on GPIO_QMSI_AON + default "gpio_aon" + +config GPIO_QMSI_AON_IRQ + int "Controller interrupt number" + depends on GPIO_QMSI_AON + default 0 + help + IRQ number for the controller + +config GPIO_QMSI_AON_PRI + int "Controller interrupt priority" + depends on GPIO_QMSI_AON + default 2 + help + IRQ priority + config GPIO_SCH bool "SCH GPIO controller" depends on GPIO diff --git a/drivers/gpio/gpio_qmsi.c b/drivers/gpio/gpio_qmsi.c index 2f481a5459f..d8463aa6286 100644 --- a/drivers/gpio/gpio_qmsi.c +++ b/drivers/gpio/gpio_qmsi.c @@ -40,15 +40,46 @@ struct gpio_qmsi_runtime { uint32_t pin_callbacks; uint8_t port_callback; }; + +int gpio_qmsi_init(struct device *dev); + +#ifdef CONFIG_GPIO_QMSI_0 +static struct gpio_qmsi_config gpio_0_config = { + .gpio = QM_GPIO_0, + .addr = &QM_GPIO[0], + .num_pins = QM_NUM_GPIO_PINS, +}; + +static struct gpio_qmsi_runtime gpio_0_runtime; + +DEVICE_INIT(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init, + &gpio_0_runtime, &gpio_0_config, + SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#endif /* CONFIG_GPIO_QMSI_0 */ + +#ifdef CONFIG_GPIO_QMSI_AON +static struct gpio_qmsi_config gpio_aon_config = { + .gpio = QM_AON_GPIO_0, + .addr = (qm_gpio_reg_t *) QM_AON_GPIO_BASE, + .num_pins = QM_NUM_AON_GPIO_PINS, +}; + +static struct gpio_qmsi_runtime gpio_aon_runtime; + +DEVICE_INIT(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init, + &gpio_aon_runtime, &gpio_aon_config, + SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); + +#endif /* CONFIG_GPIO_QMSI_AON */ + /* * TODO: Zephyr's API is not clear about the behavior of the this * application callback. This topic is currently under * discussion, so this implementation will be fixed as soon as a * decision is made. */ -static void gpio_qmsi_0_int_callback(uint32_t status) +static void gpio_qmsi_callback(struct device *port, uint32_t status) { - struct device *port = device_get_binding(CONFIG_GPIO_QMSI_0_NAME); struct gpio_qmsi_config *config = port->config->config_info; struct gpio_qmsi_runtime *context = port->driver_data; const uint32_t enabled_mask = context->pin_callbacks & status; @@ -72,6 +103,28 @@ static void gpio_qmsi_0_int_callback(uint32_t status) } } +static void gpio_qmsi_0_int_callback(uint32_t status) +{ +#ifndef CONFIG_GPIO_QMSI_0 + return; +#else + struct device *port = DEVICE_GET(gpio_0); + + gpio_qmsi_callback(port, status); +#endif +} + +static void gpio_qmsi_aon_int_callback(uint32_t status) +{ +#ifndef CONFIG_GPIO_QMSI_AON + return; +#else + struct device *port = DEVICE_GET(gpio_aon); + + gpio_qmsi_callback(port, status); +#endif +} + static void qmsi_write_bit(uint32_t *target, uint8_t bit, uint8_t value) { if (value) { @@ -108,8 +161,17 @@ static inline void qmsi_pin_config(struct device *port, uint32_t pin, int flags) qmsi_write_bit(&cfg.int_en, pin, 1); } - /* FIXME: for multiple GPIO ports */ - cfg.callback = gpio_qmsi_0_int_callback; + switch (gpio) { + case QM_GPIO_0: + cfg.callback = gpio_qmsi_0_int_callback; + break; + case QM_AON_GPIO_0: + cfg.callback = gpio_qmsi_aon_int_callback; + break; + default: + return; + } + qm_gpio_set_config(gpio, &cfg); /* Recover the original interrupt mask for this port. */ @@ -250,33 +312,33 @@ int gpio_qmsi_init(struct device *port) struct gpio_qmsi_config *gpio_config = port->config->config_info; uint32_t reg = (uint32_t) gpio_config->addr; - clk_periph_enable(CLK_PERIPH_GPIO_REGISTER | - CLK_PERIPH_GPIO_INTERRUPT | CLK_PERIPH_GPIO_DB); + switch (gpio_config->gpio) { + case QM_GPIO_0: + clk_periph_enable(CLK_PERIPH_GPIO_REGISTER | + CLK_PERIPH_GPIO_INTERRUPT | + CLK_PERIPH_GPIO_DB); + IRQ_CONNECT(CONFIG_GPIO_QMSI_0_IRQ, + CONFIG_GPIO_QMSI_0_PRI, qm_gpio_isr_0, + 0, IOAPIC_LEVEL | IOAPIC_HIGH); + irq_enable(CONFIG_GPIO_QMSI_0_IRQ); + QM_SCSS_INT->int_gpio_mask &= ~BIT(0); + break; + case QM_AON_GPIO_0: + IRQ_CONNECT(CONFIG_GPIO_QMSI_AON_IRQ, + CONFIG_GPIO_QMSI_AON_PRI, qm_aon_gpio_isr_0, + 0, IOAPIC_LEVEL | IOAPIC_HIGH); + irq_enable(CONFIG_GPIO_QMSI_AON_IRQ); + QM_SCSS_INT->int_aon_gpio_mask &= ~BIT(0); + break; + default: + return DEV_FAIL; + } /* mask and disable interrupts */ sys_write32(~(0), reg + INTMASK); sys_write32(0, reg + INTEN); sys_write32(~(0), reg + PORTA_EOI); - IRQ_CONNECT(CONFIG_GPIO_QMSI_0_IRQ, CONFIG_GPIO_QMSI_0_PRI, qm_gpio_isr_0, - 0, IOAPIC_LEVEL | IOAPIC_HIGH); - - /* Enable GPIO IRQ and unmask interrupts for Lakemont. */ - sys_clear_bit(QM_SCSS_INT_BASE + INT_GPIO_MASK, 0); - irq_enable(CONFIG_GPIO_QMSI_0_IRQ); - port->driver_api = &api_funcs; return DEV_OK; } - -static struct gpio_qmsi_config gpio_0_config = { - .gpio = QM_GPIO_0, - .addr = &QM_GPIO[0], - .num_pins = QM_NUM_GPIO_PINS, -}; - -static struct gpio_qmsi_runtime gpio_0_runtime; - -DEVICE_INIT(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init, - &gpio_0_runtime, &gpio_0_config, - SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);