Microchip: MEC172x GPIO driver version 2
Create version 2 of the MEC GPIO driver to support MEC172x to not interfere with MEC152x. When the MEC172x ECIA interrupt aggregator driver is ready, this driver will use ECIA for registering GPIO interrupt callbacks instead of maintaining its own interrupt table. Add V2 DT binding. Add the Kconfig configuration settings for the MEC172x GPIO V2 driver at the SoC and board level. Add port id to DT allowing use of DT FOR EACH macro in the driver. Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
parent
1382d64ed5
commit
6976800cf0
9 changed files with 594 additions and 1 deletions
|
@ -17,6 +17,29 @@
|
|||
zephyr,flash = &flash0;
|
||||
zephyr,console = &uart1;
|
||||
};
|
||||
|
||||
aliases {
|
||||
led0 = &led4;
|
||||
led1 = &led3;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led4: led_0 {
|
||||
/* GPIO241/CMP_VOUT0/PWM0_ALT on schematic,
|
||||
* LED4 on silkscreen.
|
||||
*/
|
||||
gpios = <&gpio_240_276 1 GPIO_ACTIVE_HIGH>;
|
||||
label = "LED 4";
|
||||
};
|
||||
led3: led_1 {
|
||||
/* GPIO175/CMP_VOUT1/PWM8_ALT on schematic,
|
||||
* LED5 on silkscreen.
|
||||
*/
|
||||
gpios = <&gpio_140_176 29 GPIO_ACTIVE_HIGH>;
|
||||
label = "LED 5";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cpu0 {
|
||||
|
|
|
@ -10,6 +10,7 @@ CONFIG_BOARD_MEC172XEVB_ASSY6906=y
|
|||
CONFIG_RTOS_TIMER=y
|
||||
|
||||
CONFIG_CLOCK_CONTROL=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
|
|
@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_RCAR gpio_rcar.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_GPIO_CY8C95XX gpio_cy8c95xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_SNPS_CREG gpio_creg_gpio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_STMPE1600 gpio_stmpe1600.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_XEC_V2 gpio_mchp_xec_v2.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_SHELL gpio_shell.c)
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
config GPIO_XEC
|
||||
bool "XEC Microchip GPIO driver"
|
||||
depends on SOC_FAMILY_MEC
|
||||
depends on SOC_SERIES_MEC1501X
|
||||
help
|
||||
Enable the Microchip XEC gpio driver.
|
||||
|
||||
config GPIO_XEC_V2
|
||||
bool "XEC Microchip GPIO driver V2"
|
||||
depends on SOC_SERIES_MEC172X
|
||||
help
|
||||
Enable the Microchip XEC gpio V2 driver.
|
||||
|
|
424
drivers/gpio/gpio_mchp_xec_v2.c
Normal file
424
drivers/gpio/gpio_mchp_xec_v2.c
Normal file
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT microchip_xec_gpio_v2
|
||||
|
||||
#include <errno.h>
|
||||
#include <device.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <soc.h>
|
||||
#include <arch/arm/aarch32/cortex_m/cmsis.h>
|
||||
|
||||
#include "gpio_utils.h"
|
||||
|
||||
#define XEC_ECIA_REGS ((struct ecia_regs *)(DT_REG_ADDR(DT_NODELABEL(ecia))))
|
||||
|
||||
static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = {
|
||||
(MCHP_GPIO_PORT_A_BITMAP),
|
||||
(MCHP_GPIO_PORT_B_BITMAP),
|
||||
(MCHP_GPIO_PORT_C_BITMAP),
|
||||
(MCHP_GPIO_PORT_D_BITMAP),
|
||||
(MCHP_GPIO_PORT_E_BITMAP),
|
||||
(MCHP_GPIO_PORT_F_BITMAP),
|
||||
};
|
||||
|
||||
struct gpio_xec_data {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_data common;
|
||||
/* port ISR callback routine address */
|
||||
sys_slist_t callbacks;
|
||||
};
|
||||
|
||||
struct gpio_xec_config {
|
||||
/* gpio_driver_config needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
uintptr_t pcr1_base;
|
||||
uintptr_t parin_addr;
|
||||
uintptr_t parout_addr;
|
||||
uint8_t girq_id;
|
||||
uint8_t port_num;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* Each GPIO pin 32-bit control register located consecutively in memory */
|
||||
static inline uintptr_t pin_ctrl_addr(const struct device *dev, gpio_pin_t pin)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
|
||||
return config->pcr1_base + ((uintptr_t)pin * 4u);
|
||||
}
|
||||
|
||||
/* GPIO Parallel input is a single 32-bit register per bank of 32 pins */
|
||||
static inline uintptr_t pin_parin_addr(const struct device *dev)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
|
||||
return config->parin_addr;
|
||||
}
|
||||
|
||||
/* GPIO Parallel output is a single 32-bit register per bank of 32 pins */
|
||||
static inline uintptr_t pin_parout_addr(const struct device *dev)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
|
||||
return config->parout_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use Zephyr system API to implement
|
||||
* reg32(addr) = (reg32(addr) & ~mask) | (val & mask)
|
||||
*/
|
||||
static inline void xec_mask_write32(uintptr_t addr, uint32_t mask, uint32_t val)
|
||||
{
|
||||
uint32_t r = (sys_read32(addr) & ~mask) | (val & mask);
|
||||
|
||||
sys_write32(r, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* notes: The GPIO parallel output bits are read-only until the
|
||||
* Alternate-Output-Disable (AOD) bit is set in the pin's control
|
||||
* register. To preload a parallel output value to prevent certain
|
||||
* classes of glitching for output pins we must:
|
||||
* Set GPIO control AOD=1 with the pin direction set to input.
|
||||
* Program the new pin value in the respective GPIO parallel output
|
||||
* register.
|
||||
* Program other GPIO control bits except direction.
|
||||
* Last step set the GPIO control register direction bit to output.
|
||||
*/
|
||||
static int gpio_xec_configure(const struct device *dev,
|
||||
gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
uintptr_t pcr1_addr = pin_ctrl_addr(dev, pin);
|
||||
uintptr_t pout_addr = pin_parout_addr(dev);
|
||||
uint32_t pcr1 = 0U;
|
||||
uint32_t mask = 0U;
|
||||
|
||||
/* Validate pin number range in terms of current port */
|
||||
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0U) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Don't support "open source" mode */
|
||||
if (((flags & GPIO_SINGLE_ENDED) != 0U) &&
|
||||
((flags & GPIO_LINE_OPEN_DRAIN) == 0U)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* The flags contain options that require touching registers in the
|
||||
* PCRs for a given GPIO. There are no GPIO modules in Microchip SOCs!
|
||||
* Keep direction as input until last.
|
||||
* Clear input pad disable allowing input pad to operate.
|
||||
* Clear Power gate to allow pads to operate.
|
||||
*/
|
||||
mask |= MCHP_GPIO_CTRL_DIR_MASK;
|
||||
mask |= MCHP_GPIO_CTRL_INPAD_DIS_MASK;
|
||||
mask |= MCHP_GPIO_CTRL_PWRG_MASK;
|
||||
pcr1 |= MCHP_GPIO_CTRL_DIR_INPUT;
|
||||
|
||||
/* Figure out the pullup/pulldown configuration and keep it in the
|
||||
* pcr1 variable
|
||||
*/
|
||||
mask |= MCHP_GPIO_CTRL_PUD_MASK;
|
||||
|
||||
if ((flags & GPIO_PULL_UP) != 0U) {
|
||||
/* Enable the pull and select the pullup resistor. */
|
||||
pcr1 |= MCHP_GPIO_CTRL_PUD_PU;
|
||||
} else if ((flags & GPIO_PULL_DOWN) != 0U) {
|
||||
/* Enable the pull and select the pulldown resistor */
|
||||
pcr1 |= MCHP_GPIO_CTRL_PUD_PD;
|
||||
}
|
||||
|
||||
/* Push-pull or open drain */
|
||||
mask |= MCHP_GPIO_CTRL_BUFT_MASK;
|
||||
|
||||
if ((flags & GPIO_OPEN_DRAIN) != 0U) {
|
||||
/* Open drain */
|
||||
pcr1 |= MCHP_GPIO_CTRL_BUFT_OPENDRAIN;
|
||||
} else {
|
||||
/* Push-pull */
|
||||
pcr1 |= MCHP_GPIO_CTRL_BUFT_PUSHPULL;
|
||||
}
|
||||
|
||||
/* Use GPIO output register to control pin output, instead of
|
||||
* using the control register (=> alternate output disable).
|
||||
*/
|
||||
mask |= MCHP_GPIO_CTRL_AOD_MASK;
|
||||
pcr1 |= MCHP_GPIO_CTRL_AOD_DIS;
|
||||
|
||||
/* Make sure disconnected on first control register write */
|
||||
if (flags == GPIO_DISCONNECTED) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_PWRG_OFF;
|
||||
}
|
||||
|
||||
/* Now write contents of pcr1 variable to the PCR1 register that
|
||||
* corresponds to the GPIO being configured.
|
||||
* AOD is 1 and direction is input. HW will allow use to set the
|
||||
* GPIO parallel output bit for this pin and with the pin direction
|
||||
* as input no glitch will occur.
|
||||
*/
|
||||
xec_mask_write32(pcr1_addr, mask, pcr1);
|
||||
|
||||
if ((flags & GPIO_OUTPUT) != 0U) {
|
||||
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
|
||||
sys_set_bit(pout_addr, pin);
|
||||
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
|
||||
sys_clear_bit(pout_addr, pin);
|
||||
}
|
||||
|
||||
mask = MCHP_GPIO_CTRL_DIR_MASK;
|
||||
pcr1 = MCHP_GPIO_CTRL_DIR_OUTPUT;
|
||||
xec_mask_write32(pcr1_addr, mask, pcr1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gen_gpio_ctrl_icfg(enum gpio_int_mode mode, enum gpio_int_trig trig,
|
||||
uint32_t *pin_ctr1)
|
||||
{
|
||||
if (!pin_ctr1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_DISABLE;
|
||||
} else {
|
||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||
if (trig == GPIO_INT_TRIG_HIGH) {
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_LVL_HI;
|
||||
} else {
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_LVL_LO;
|
||||
}
|
||||
} else {
|
||||
switch (trig) {
|
||||
case GPIO_INT_TRIG_LOW:
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_FEDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_HIGH:
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_REDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_BOTH:
|
||||
*pin_ctr1 = MCHP_GPIO_CTRL_IDET_BEDGE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_xec_intr_en(gpio_pin_t pin, enum gpio_int_mode mode,
|
||||
uint8_t girq_id)
|
||||
{
|
||||
if (mode != GPIO_INT_MODE_DISABLED) {
|
||||
/* Enable interrupt to propagate via its GIRQ to the NVIC */
|
||||
mchp_soc_ecia_girq_src_en(girq_id, pin);
|
||||
}
|
||||
}
|
||||
|
||||
static int gpio_xec_pin_interrupt_configure(const struct device *dev,
|
||||
gpio_pin_t pin,
|
||||
enum gpio_int_mode mode,
|
||||
enum gpio_int_trig trig)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
uintptr_t pcr1_addr = pin_ctrl_addr(dev, pin);
|
||||
uint32_t pcr1 = 0u;
|
||||
uint32_t pcr1_req = 0u;
|
||||
|
||||
/* Validate pin number range in terms of current port */
|
||||
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0U) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check if GPIO port supports interrupts */
|
||||
if ((mode != GPIO_INT_MODE_DISABLED) &&
|
||||
((config->flags & GPIO_INT_ENABLE) == 0)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
pcr1_req = MCHP_GPIO_CTRL_IDET_DISABLE;
|
||||
if (gen_gpio_ctrl_icfg(mode, trig, &pcr1_req)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable interrupt in the EC aggregator */
|
||||
mchp_soc_ecia_girq_src_dis(config->girq_id, pin);
|
||||
|
||||
/* pin configuration matches requested detection mode? */
|
||||
pcr1 = sys_read32(pcr1_addr);
|
||||
|
||||
if ((pcr1 & MCHP_GPIO_CTRL_IDET_MASK) == pcr1_req) {
|
||||
gpio_xec_intr_en(pin, mode, config->girq_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcr1 &= ~MCHP_GPIO_CTRL_IDET_MASK;
|
||||
|
||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||
if (trig == GPIO_INT_TRIG_HIGH) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_LVL_HI;
|
||||
} else {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_LVL_LO;
|
||||
}
|
||||
sys_write32(pcr1, pcr1_addr);
|
||||
} else if (mode == GPIO_INT_MODE_EDGE) {
|
||||
if (trig == GPIO_INT_TRIG_LOW) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_FEDGE;
|
||||
} else if (trig == GPIO_INT_TRIG_HIGH) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_REDGE;
|
||||
} else if (trig == GPIO_INT_TRIG_BOTH) {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_BEDGE;
|
||||
}
|
||||
sys_write32(pcr1, pcr1_addr);
|
||||
__DMB(); /* insure write completes */
|
||||
} else {
|
||||
pcr1 |= MCHP_GPIO_CTRL_IDET_DISABLE;
|
||||
sys_write32(pcr1, pcr1_addr);
|
||||
}
|
||||
|
||||
mchp_soc_ecia_girq_src_clr(config->girq_id, pin);
|
||||
|
||||
gpio_xec_intr_en(pin, mode, config->girq_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_port_set_masked_raw(const struct device *dev,
|
||||
uint32_t mask,
|
||||
uint32_t value)
|
||||
{
|
||||
uintptr_t pout_addr = pin_parout_addr(dev);
|
||||
|
||||
xec_mask_write32(pout_addr, mask, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_port_set_bits_raw(const struct device *dev, uint32_t mask)
|
||||
{
|
||||
uintptr_t pout_addr = pin_parout_addr(dev);
|
||||
|
||||
sys_write32(sys_read32(pout_addr) | mask, pout_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_port_clear_bits_raw(const struct device *dev,
|
||||
uint32_t mask)
|
||||
{
|
||||
uintptr_t pout_addr = pin_parout_addr(dev);
|
||||
|
||||
sys_write32(sys_read32(pout_addr) & ~mask, pout_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_port_toggle_bits(const struct device *dev, uint32_t mask)
|
||||
{
|
||||
uintptr_t pout_addr = pin_parout_addr(dev);
|
||||
|
||||
sys_write32(sys_read32(pout_addr) ^ mask, pout_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_port_get_raw(const struct device *dev, uint32_t *value)
|
||||
{
|
||||
uintptr_t pin_addr = pin_parin_addr(dev);
|
||||
|
||||
*value = sys_read32(pin_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_xec_manage_callback(const struct device *dev,
|
||||
struct gpio_callback *callback, bool set)
|
||||
{
|
||||
struct gpio_xec_data *data = dev->data;
|
||||
|
||||
gpio_manage_callback(&data->callbacks, callback, set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_gpio_xec_port_isr(const struct device *dev)
|
||||
{
|
||||
const struct gpio_xec_config *config = dev->config;
|
||||
struct gpio_xec_data *data = dev->data;
|
||||
uint32_t girq_result;
|
||||
|
||||
/* Figure out which interrupts have been triggered from the EC
|
||||
* aggregator result register
|
||||
*/
|
||||
girq_result = mchp_soc_ecia_girq_result(config->girq_id);
|
||||
|
||||
/* Clear source register in aggregator before firing callbacks */
|
||||
mchp_soc_ecia_girq_src_clr_bitmap(config->girq_id, girq_result);
|
||||
|
||||
gpio_fire_callbacks(&data->callbacks, dev, girq_result);
|
||||
}
|
||||
|
||||
static const struct gpio_driver_api gpio_xec_driver_api = {
|
||||
.pin_configure = gpio_xec_configure,
|
||||
.port_get_raw = gpio_xec_port_get_raw,
|
||||
.port_set_masked_raw = gpio_xec_port_set_masked_raw,
|
||||
.port_set_bits_raw = gpio_xec_port_set_bits_raw,
|
||||
.port_clear_bits_raw = gpio_xec_port_clear_bits_raw,
|
||||
.port_toggle_bits = gpio_xec_port_toggle_bits,
|
||||
.pin_interrupt_configure = gpio_xec_pin_interrupt_configure,
|
||||
.manage_callback = gpio_xec_manage_callback,
|
||||
};
|
||||
|
||||
#define XEC_GPIO_PORT_FLAGS(n) \
|
||||
((DT_IRQ_HAS_CELL(DT_DRV_INST(n), irq)) ? GPIO_INT_ENABLE : 0)
|
||||
|
||||
#define XEC_GPIO_PORT(n) \
|
||||
static int gpio_xec_port_init_##n(const struct device *dev) \
|
||||
{ \
|
||||
if (!(DT_IRQ_HAS_CELL(DT_DRV_INST(n), irq))) { \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
const struct gpio_xec_config *config = dev->config; \
|
||||
\
|
||||
mchp_soc_ecia_girq_aggr_en(config->girq_id, 1); \
|
||||
\
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), \
|
||||
DT_INST_IRQ(n, priority), \
|
||||
gpio_gpio_xec_port_isr, \
|
||||
DEVICE_DT_INST_GET(n), 0U); \
|
||||
\
|
||||
irq_enable(DT_INST_IRQN(n)); \
|
||||
\
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static struct gpio_xec_data gpio_xec_port_data_##n; \
|
||||
\
|
||||
static const struct gpio_xec_config xec_gpio_config_##n = { \
|
||||
.common = { \
|
||||
.port_pin_mask = \
|
||||
GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
|
||||
}, \
|
||||
.pcr1_base = (uintptr_t)DT_INST_REG_ADDR_BY_IDX(n, 0), \
|
||||
.parin_addr = (uintptr_t)DT_INST_REG_ADDR_BY_IDX(n, 1), \
|
||||
.parout_addr = (uintptr_t)DT_INST_REG_ADDR_BY_IDX(n, 2),\
|
||||
.port_num = DT_INST_PROP(n, port_id), \
|
||||
.girq_id = DT_INST_PROP_OR(n, girq_id, 0), \
|
||||
.flags = XEC_GPIO_PORT_FLAGS(n), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, gpio_xec_port_init_##n, NULL, \
|
||||
&gpio_xec_port_data_##n, &xec_gpio_config_##n, \
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&gpio_xec_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(XEC_GPIO_PORT)
|
|
@ -257,51 +257,69 @@
|
|||
};
|
||||
};
|
||||
gpio_000_036: gpio@40081000 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081000 0x80 0x40081300 0x04
|
||||
0x40081380 0x04 0x400813fc 0x04>;
|
||||
interrupts = <3 2>;
|
||||
gpio-controller;
|
||||
label="GPIO000_036";
|
||||
port-id = <0>;
|
||||
girq-id = <11>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
gpio_040_076: gpio@40081080 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081080 0x80 0x40081304 0x04
|
||||
0x40081384 0x04 0x400813f8 0x4>;
|
||||
interrupts = <2 2>;
|
||||
gpio-controller;
|
||||
label="GPIO040_076";
|
||||
port-id = <1>;
|
||||
girq-id = <10>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
gpio_100_136: gpio@40081100 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081100 0x80 0x40081308 0x04
|
||||
0x40081388 0x04 0x400813f4 0x04>;
|
||||
gpio-controller;
|
||||
interrupts = <1 2>;
|
||||
label="GPIO100_136";
|
||||
port-id = <2>;
|
||||
girq-id = <9>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
gpio_140_176: gpio@40081180 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081180 0x80 0x4008130c 0x04
|
||||
0x4008138c 0x04 0x400813f0 0x04>;
|
||||
gpio-controller;
|
||||
interrupts = <0 2>;
|
||||
label="GPIO140_176";
|
||||
port-id = <3>;
|
||||
girq-id = <8>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
gpio_200_236: gpio@40081200 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081200 0x80 0x40081310 0x04
|
||||
0x40081390 0x04 0x400813ec 0x04>;
|
||||
gpio-controller;
|
||||
interrupts = <4 2>;
|
||||
label="GPIO200_236";
|
||||
port-id = <4>;
|
||||
girq-id = <12>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
gpio_240_276: gpio@40081280 {
|
||||
compatible = "microchip,xec-gpio-v2";
|
||||
reg = < 0x40081280 0x80 0x40081314 0x04
|
||||
0x40081394 0x04 0x400813e8 0x04>;
|
||||
gpio-controller;
|
||||
interrupts = <17 2>;
|
||||
label="GPIO240_276";
|
||||
port-id = <5>;
|
||||
girq-id = <26>;
|
||||
#gpio-cells=<2>;
|
||||
};
|
||||
wdog: watchdog@40000400 {
|
||||
|
|
35
dts/bindings/gpio/microchip,xec-gpio-v2.yaml
Normal file
35
dts/bindings/gpio/microchip,xec-gpio-v2.yaml
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Copyright (c) 2019, Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Microchip CEC/MEC GPIO V2 node
|
||||
|
||||
compatible: "microchip,xec-gpio-v2"
|
||||
|
||||
include: [gpio-controller.yaml, base.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: false
|
||||
|
||||
label:
|
||||
required: true
|
||||
|
||||
port-id:
|
||||
type: int
|
||||
required: true
|
||||
description: Zero based GPIO port number
|
||||
|
||||
girq-id:
|
||||
type: int
|
||||
required: true
|
||||
description: Aggregated GIRQ number for this bank of 32 GPIO pins.
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
|
@ -12,4 +12,11 @@ config UART_NS16550
|
|||
default y
|
||||
depends on SERIAL
|
||||
|
||||
config GPIO
|
||||
default y
|
||||
|
||||
config GPIO_XEC_V2
|
||||
default y
|
||||
depends on GPIO
|
||||
|
||||
endif # SOC_MEC172X_NSZ
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <devicetree.h>
|
||||
|
||||
#define ECIA_BASE_ADDR DT_REG_ADDR(DT_NODELABEL(ecia))
|
||||
|
||||
#define MCHP_FIRST_GIRQ_NOS 8u
|
||||
#define MCHP_LAST_GIRQ_NOS 26u
|
||||
|
@ -1156,4 +1159,79 @@ struct ecia_regs {
|
|||
volatile uint32_t BLK_ACTIVE;
|
||||
};
|
||||
|
||||
/* Until XEC ECIA driver is available we define these locally */
|
||||
static inline void mchp_soc_ecia_girq_aggr_en(uint8_t girq, uint8_t en)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
if (en) {
|
||||
ecia->BLK_EN_SET = BIT(girq);
|
||||
} else {
|
||||
ecia->BLK_EN_CLR = BIT(girq);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mchp_soc_ecia_girq_src_clr(uint8_t girq, uint8_t pin)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS) ||
|
||||
(pin > 31)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
ecia->GIRQ[girq - 8u].SRC = BIT(pin);
|
||||
}
|
||||
|
||||
static inline void mchp_soc_ecia_girq_src_clr_bitmap(uint8_t girq,
|
||||
uint32_t bitmap)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
ecia->GIRQ[girq - 8u].SRC = bitmap;
|
||||
}
|
||||
|
||||
static inline void mchp_soc_ecia_girq_src_dis(uint8_t girq, uint8_t pin)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS) ||
|
||||
(pin > 31)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
ecia->GIRQ[girq - 8u].EN_CLR = BIT(pin);
|
||||
}
|
||||
|
||||
static inline void mchp_soc_ecia_girq_src_en(uint8_t girq, uint8_t pin)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS) ||
|
||||
(pin > 31)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
ecia->GIRQ[girq - 8u].EN_SET = BIT(pin);
|
||||
}
|
||||
|
||||
static inline uint32_t mchp_soc_ecia_girq_result(uint8_t girq)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ_NOS) || (girq > MCHP_LAST_GIRQ_NOS)) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR);
|
||||
|
||||
return ecia->GIRQ[girq - 8u].RESULT;
|
||||
}
|
||||
|
||||
#endif /* #ifndef _MEC172X_ECIA_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue