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 <vinicius.gomes@intel.com>
This commit is contained in:
parent
fb84242956
commit
821212c3df
3 changed files with 121 additions and 25 deletions
|
@ -124,6 +124,14 @@ config GPIO_QMSI_0_IRQ
|
||||||
default 8
|
default 8
|
||||||
config GPIO_QMSI_0_PRI
|
config GPIO_QMSI_0_PRI
|
||||||
default 2
|
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
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -633,6 +633,32 @@ config GPIO_QMSI_0_PRI
|
||||||
help
|
help
|
||||||
IRQ priority
|
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
|
config GPIO_SCH
|
||||||
bool "SCH GPIO controller"
|
bool "SCH GPIO controller"
|
||||||
depends on GPIO
|
depends on GPIO
|
||||||
|
|
|
@ -40,15 +40,46 @@ struct gpio_qmsi_runtime {
|
||||||
uint32_t pin_callbacks;
|
uint32_t pin_callbacks;
|
||||||
uint8_t port_callback;
|
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
|
* TODO: Zephyr's API is not clear about the behavior of the this
|
||||||
* application callback. This topic is currently under
|
* application callback. This topic is currently under
|
||||||
* discussion, so this implementation will be fixed as soon as a
|
* discussion, so this implementation will be fixed as soon as a
|
||||||
* decision is made.
|
* 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_config *config = port->config->config_info;
|
||||||
struct gpio_qmsi_runtime *context = port->driver_data;
|
struct gpio_qmsi_runtime *context = port->driver_data;
|
||||||
const uint32_t enabled_mask = context->pin_callbacks & status;
|
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)
|
static void qmsi_write_bit(uint32_t *target, uint8_t bit, uint8_t value)
|
||||||
{
|
{
|
||||||
if (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);
|
qmsi_write_bit(&cfg.int_en, pin, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: for multiple GPIO ports */
|
switch (gpio) {
|
||||||
cfg.callback = gpio_qmsi_0_int_callback;
|
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);
|
qm_gpio_set_config(gpio, &cfg);
|
||||||
|
|
||||||
/* Recover the original interrupt mask for this port. */
|
/* 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;
|
struct gpio_qmsi_config *gpio_config = port->config->config_info;
|
||||||
uint32_t reg = (uint32_t) gpio_config->addr;
|
uint32_t reg = (uint32_t) gpio_config->addr;
|
||||||
|
|
||||||
clk_periph_enable(CLK_PERIPH_GPIO_REGISTER |
|
switch (gpio_config->gpio) {
|
||||||
CLK_PERIPH_GPIO_INTERRUPT | CLK_PERIPH_GPIO_DB);
|
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 */
|
/* mask and disable interrupts */
|
||||||
sys_write32(~(0), reg + INTMASK);
|
sys_write32(~(0), reg + INTMASK);
|
||||||
sys_write32(0, reg + INTEN);
|
sys_write32(0, reg + INTEN);
|
||||||
sys_write32(~(0), reg + PORTA_EOI);
|
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;
|
port->driver_api = &api_funcs;
|
||||||
return DEV_OK;
|
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);
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue