diff --git a/arch/arm/soc/atmel_sam/sam4s/dts.fixup b/arch/arm/soc/atmel_sam/sam4s/dts.fixup index ea664c6adbd..74962fd0369 100644 --- a/arch/arm/soc/atmel_sam/sam4s/dts.fixup +++ b/arch/arm/soc/atmel_sam/sam4s/dts.fixup @@ -8,6 +8,22 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS +#define CONFIG_GPIO_SAM_PORTA_LABEL ATMEL_SAM_GPIO_400E0E00_LABEL +#define CONFIG_GPIO_SAM_PORTA_BASE_ADDRESS ATMEL_SAM_GPIO_400E0E00_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTA_IRQ ATMEL_SAM_GPIO_400E0E00_IRQ_0 +#define CONFIG_GPIO_SAM_PORTA_IRQ_PRIO ATMEL_SAM_GPIO_400E0E00_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTA_PERIPHERAL_ID ATMEL_SAM_GPIO_400E0E00_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTB_LABEL ATMEL_SAM_GPIO_400E1000_LABEL +#define CONFIG_GPIO_SAM_PORTB_BASE_ADDRESS ATMEL_SAM_GPIO_400E1000_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTB_IRQ ATMEL_SAM_GPIO_400E1000_IRQ_0 +#define CONFIG_GPIO_SAM_PORTB_IRQ_PRIO ATMEL_SAM_GPIO_400E1000_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTB_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1000_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTC_LABEL ATMEL_SAM_GPIO_400E1200_LABEL +#define CONFIG_GPIO_SAM_PORTC_BASE_ADDRESS ATMEL_SAM_GPIO_400E1200_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTC_IRQ ATMEL_SAM_GPIO_400E1200_IRQ_0 +#define CONFIG_GPIO_SAM_PORTC_IRQ_PRIO ATMEL_SAM_GPIO_400E1200_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTC_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1200_PERIPHERAL_ID + #define CONFIG_I2C_0_BASE_ADDRESS ATMEL_SAM_I2C_TWI_40018000_BASE_ADDRESS #define CONFIG_I2C_0_NAME ATMEL_SAM_I2C_TWI_40018000_LABEL #define CONFIG_I2C_0_BITRATE ATMEL_SAM_I2C_TWI_40018000_CLOCK_FREQUENCY diff --git a/arch/arm/soc/atmel_sam/same70/dts.fixup b/arch/arm/soc/atmel_sam/same70/dts.fixup index be26f3895d2..efa2df8286d 100644 --- a/arch/arm/soc/atmel_sam/same70/dts.fixup +++ b/arch/arm/soc/atmel_sam/same70/dts.fixup @@ -8,6 +8,32 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS +#define CONFIG_GPIO_SAM_PORTA_LABEL ATMEL_SAM_GPIO_400E0E00_LABEL +#define CONFIG_GPIO_SAM_PORTA_BASE_ADDRESS ATMEL_SAM_GPIO_400E0E00_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTA_IRQ ATMEL_SAM_GPIO_400E0E00_IRQ_0 +#define CONFIG_GPIO_SAM_PORTA_IRQ_PRIO ATMEL_SAM_GPIO_400E0E00_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTA_PERIPHERAL_ID ATMEL_SAM_GPIO_400E0E00_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTB_LABEL ATMEL_SAM_GPIO_400E1000_LABEL +#define CONFIG_GPIO_SAM_PORTB_BASE_ADDRESS ATMEL_SAM_GPIO_400E1000_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTB_IRQ ATMEL_SAM_GPIO_400E1000_IRQ_0 +#define CONFIG_GPIO_SAM_PORTB_IRQ_PRIO ATMEL_SAM_GPIO_400E1000_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTB_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1000_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTC_LABEL ATMEL_SAM_GPIO_400E1200_LABEL +#define CONFIG_GPIO_SAM_PORTC_BASE_ADDRESS ATMEL_SAM_GPIO_400E1200_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTC_IRQ ATMEL_SAM_GPIO_400E1200_IRQ_0 +#define CONFIG_GPIO_SAM_PORTC_IRQ_PRIO ATMEL_SAM_GPIO_400E1200_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTC_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1200_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTD_LABEL ATMEL_SAM_GPIO_400E1400_LABEL +#define CONFIG_GPIO_SAM_PORTD_BASE_ADDRESS ATMEL_SAM_GPIO_400E1400_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTD_IRQ ATMEL_SAM_GPIO_400E1400_IRQ_0 +#define CONFIG_GPIO_SAM_PORTD_IRQ_PRIO ATMEL_SAM_GPIO_400E1400_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTD_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1400_PERIPHERAL_ID +#define CONFIG_GPIO_SAM_PORTE_LABEL ATMEL_SAM_GPIO_400E1600_LABEL +#define CONFIG_GPIO_SAM_PORTE_BASE_ADDRESS ATMEL_SAM_GPIO_400E1600_BASE_ADDRESS +#define CONFIG_GPIO_SAM_PORTE_IRQ ATMEL_SAM_GPIO_400E1600_IRQ_0 +#define CONFIG_GPIO_SAM_PORTE_IRQ_PRIO ATMEL_SAM_GPIO_400E1600_IRQ_0_PRIORITY +#define CONFIG_GPIO_SAM_PORTE_PERIPHERAL_ID ATMEL_SAM_GPIO_400E1600_PERIPHERAL_ID + #define CONFIG_I2C_0_BASE_ADDRESS ATMEL_SAM_I2C_TWIHS_40018000_BASE_ADDRESS #define CONFIG_I2C_0_NAME ATMEL_SAM_I2C_TWIHS_40018000_LABEL #define CONFIG_I2C_0_BITRATE ATMEL_SAM_I2C_TWIHS_40018000_CLOCK_FREQUENCY diff --git a/boards/arm/sam4s_xplained/board.h b/boards/arm/sam4s_xplained/board.h index 230ebf8b23a..d6f012897d5 100644 --- a/boards/arm/sam4s_xplained/board.h +++ b/boards/arm/sam4s_xplained/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Justin Watson 2017 + * Copyright (c) Justin Watson 2018 * SPDX-License-Identifier: Apache-2.0 */ @@ -8,4 +8,22 @@ #include +#define BOARD_YELLOW_LED1_GPIO_PORT CONFIG_GPIO_SAM_PORTC_LABEL +#define BOARD_YELLOW_LED1_GPIO_PIN 10 + +#define BOARD_YELLOW_LED2_GPIO_PORT CONFIG_GPIO_SAM_PORTC_LABEL +#define BOARD_YELLOW_LED2_GPIO_PIN 17 + +#define BOARD_USER_PB2_GPIO_PORT CONFIG_GPIO_SAM_PORTA_LABEL +#define BOARD_USER_PB2_GPIO_PIN 5 + +/* Aliases to make the basic samples work. */ +#define LED0_GPIO_PORT BOARD_YELLOW_LED1_GPIO_PORT +#define LED0_GPIO_PIN BOARD_YELLOW_LED1_GPIO_PIN +#define LED1_GPIO_PORT BOARD_YELLOW_LED2_GPIO_PORT +#define LED1_GPIO_PIN BOARD_YELLOW_LED2_GPIO_PIN +#define SW0_GPIO_NAME BOARD_USER_PB2_GPIO_PORT +#define SW0_GPIO_PIN BOARD_USER_PB2_GPIO_PIN +#define SW0_GPIO_PIN_PUD GPIO_PUD_PULL_UP + #endif /* __INC_BOARD_H */ diff --git a/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst b/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst index d8c4be634ed..238fcd2a8a8 100644 --- a/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst +++ b/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst @@ -45,6 +45,8 @@ features: +-----------+------------+-------------------------------------+ | I2C | on-chip | i2c | +-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ Other hardware features are not currently supported by Zephyr. diff --git a/boards/arm/sam4s_xplained/sam4s_xplained_defconfig b/boards/arm/sam4s_xplained/sam4s_xplained_defconfig index f5d2ac3353f..41af698dcf1 100644 --- a/boards/arm/sam4s_xplained/sam4s_xplained_defconfig +++ b/boards/arm/sam4s_xplained/sam4s_xplained_defconfig @@ -10,3 +10,4 @@ CONFIG_UART_SAM=y CONFIG_UART_SAM_PORT_0=y CONFIG_BOARD_SAM4S_XPLAINED=y CONFIG_SOC_ATMEL_SAM4S_EXT_MAINCK=y +CONFIG_GPIO_SAM=y diff --git a/boards/arm/sam_e70_xplained/board.h b/boards/arm/sam_e70_xplained/board.h index 144797bf1f3..3b6d8d91804 100644 --- a/boards/arm/sam_e70_xplained/board.h +++ b/boards/arm/sam_e70_xplained/board.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018 Justin Watson * Copyright (c) 2016 Piotr Mienkowski * SPDX-License-Identifier: Apache-2.0 */ @@ -8,4 +9,20 @@ #include +#define BOARD_GREEN_LED_GPIO_PORT CONFIG_GPIO_SAM_PORTC_LABEL +#define BOARD_GREEN_LED_GPIO_PIN 8 + +/* The switch is labeled SW300 in the schematic, and labeled SW0 on the + * board. + */ +#define BOARD_SW0_GPIO_PORT CONFIG_GPIO_SAM_PORTA_LABEL +#define BOARD_SW0_GPIO_PIN 11 + +/* Aliases to make the basic samples work. */ +#define LED0_GPIO_PORT BOARD_GREEN_LED_GPIO_PORT +#define LED0_GPIO_PIN BOARD_GREEN_LED_GPIO_PIN +#define SW0_GPIO_NAME BOARD_SW0_GPIO_PORT +#define SW0_GPIO_PIN BOARD_SW0_GPIO_PIN +#define SW0_GPIO_PIN_PUD GPIO_PUD_PULL_UP + #endif /* _INC_BOARD_H_ */ diff --git a/boards/arm/sam_e70_xplained/doc/sam_e70_xplained.rst b/boards/arm/sam_e70_xplained/doc/sam_e70_xplained.rst index 8de267d7f5f..c1bf6166b05 100644 --- a/boards/arm/sam_e70_xplained/doc/sam_e70_xplained.rst +++ b/boards/arm/sam_e70_xplained/doc/sam_e70_xplained.rst @@ -54,6 +54,8 @@ features: +-----------+------------+-------------------------------------+ | WATCHDOG | on-chip | watchdog | +-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ Other hardware features are not currently supported by Zephyr. diff --git a/boards/arm/sam_e70_xplained/sam_e70_xplained_defconfig b/boards/arm/sam_e70_xplained/sam_e70_xplained_defconfig index 72f33c8288a..3f76be3900f 100644 --- a/boards/arm/sam_e70_xplained/sam_e70_xplained_defconfig +++ b/boards/arm/sam_e70_xplained/sam_e70_xplained_defconfig @@ -13,3 +13,4 @@ CONFIG_SERIAL=y CONFIG_USART_SAM=y CONFIG_USART_SAM_PORT_1=y CONFIG_BOARD_SAM_E70_XPLAINED=y +CONFIG_GPIO_SAM=y diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 6a177a6a282..60bfcedb9c7 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -19,5 +19,6 @@ zephyr_sources_ifdef(CONFIG_GPIO_QMSI_SS gpio_qmsi_ss.c) zephyr_sources_ifdef(CONFIG_GPIO_SCH gpio_sch.c) zephyr_sources_ifdef(CONFIG_GPIO_STM32 gpio_stm32.c) zephyr_sources_ifdef(CONFIG_GPIO_SAM0 gpio_sam0.c) +zephyr_sources_ifdef(CONFIG_GPIO_SAM gpio_sam.c) zephyr_sources_ifdef(CONFIG_USERSPACE gpio_handlers.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8597eb29d25..8fde8c480ae 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -75,4 +75,6 @@ source "drivers/gpio/Kconfig.altera_nios2" source "drivers/gpio/Kconfig.sam0" +source "drivers/gpio/Kconfig.sam" + endif # GPIO diff --git a/drivers/gpio/Kconfig.sam b/drivers/gpio/Kconfig.sam new file mode 100644 index 00000000000..96ad50814cb --- /dev/null +++ b/drivers/gpio/Kconfig.sam @@ -0,0 +1,11 @@ +# Kconfig.sam - Atmel SAM GPIO configuration options +# +# Copyright (c) 2018 Justin Watson +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_SAM + bool "Atmel SAM GPIO (PORT) driver" + depends on GPIO && SOC_FAMILY_SAM + default n + help + Enable support for the Atmel SAM 'PORT' GPIO controllers. diff --git a/drivers/gpio/gpio_sam.c b/drivers/gpio/gpio_sam.c new file mode 100644 index 00000000000..43d78a06df2 --- /dev/null +++ b/drivers/gpio/gpio_sam.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2018 Justin Watson + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "gpio_utils.h" + +typedef void (*config_func_t)(struct device *dev); + +struct gpio_sam_config { + Pio *regs; + config_func_t config_func; + u32_t periph_id; +}; + +struct gpio_sam_runtime { + sys_slist_t cb; +}; + +#define DEV_CFG(dev) \ + ((const struct gpio_sam_config *const)(dev)->config->config_info) + +static int gpio_sam_config(struct device *dev, int access_op, u32_t pin, + int flags) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(dev); + Pio *const pio = cfg->regs; + u32_t mask = 1 << pin; + + if (access_op != GPIO_ACCESS_BY_PIN) { + return -ENOTSUP; + } + + /* Setup the pin direcion. */ + if ((flags & GPIO_DIR_MASK) == GPIO_DIR_OUT) { + pio->PIO_OER = mask; + } else { + pio->PIO_ODR = mask; + } + + /* Setup interrupt configuration. */ + if (flags & GPIO_INT) { + /* Enable the interrupt. */ + pio->PIO_IER = mask; + + /* Enable the additional interrupt modes. */ + pio->PIO_AIMER = mask; + + switch (flags) { + case GPIO_INT_LEVEL: + pio->PIO_LSR = mask; + break; + case GPIO_INT_EDGE: + pio->PIO_ESR = mask; + break; + case GPIO_INT_DOUBLE_EDGE: + return -ENOTSUP; + default: + return -ENOTSUP; + } + + if (flags & GPIO_INT_ACTIVE_HIGH) { + /* Set to high-level or rising edge. */ + pio->PIO_REHLSR = mask; + } else { + /* Set to low-level or falling edge. */ + pio->PIO_FELLSR = mask; + } + } else { + /* Disable the interrupt. */ + pio->PIO_IDR = mask; + + /* Disable ther additional interrupt modes. */ + pio->PIO_AIMDR = mask; + } + + /* Setup Pull-up resistor. */ + if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_UP) { + /* Enable pull-up. */ + pio->PIO_PUER = mask; + } else { + pio->PIO_PUDR = mask; + } + + /* Setup Pull-down resistor. */ + if ((flags & GPIO_PUD_MASK) == GPIO_PUD_PULL_DOWN) { + pio->PIO_PPDER = mask; + } else { + pio->PIO_PPDDR = mask; + } + +#if defined(SOC_SERIES_SAM3X) + /* Setup debounce. */ + if (flags & GPIO_INT_DEBOUNCE) { + pio->PIO_DIFSR = mask; + } else { + pio->PIO_SCIFSR = mask; + } +#elif defined(SOC_SERIES_SAM4S) || defined(SOC_SERIES_SAME70) + /* Setup debounce. */ + if (flags & GPIO_INT_DEBOUNCE) { + pio->PIO_IFSCER = mask; + } else { + pio->PIO_IFSCDR = mask; + } +#endif + + /* Enable the PIO to control the pin (instead of a peripheral). */ + pio->PIO_PER = mask; + + return 0; +} + +static int gpio_sam_write(struct device *dev, int access_op, u32_t pin, + u32_t value) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(dev); + Pio *const pio = cfg->regs; + u32_t mask = 1 << pin; + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + if (value) { + /* Set the pin. */ + pio->PIO_SODR = mask; + } else { + /* Clear the pin. */ + pio->PIO_CODR = mask; + } + break; + case GPIO_ACCESS_BY_PORT: + if (value) { + /* Set all pins. */ + pio->PIO_SODR = 0xffffffff; + } else { + /* Clear all pins. */ + pio->PIO_CODR = 0xffffffff; + } + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int gpio_sam_read(struct device *dev, int access_op, u32_t pin, + u32_t *value) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(dev); + Pio *const pio = cfg->regs; + + *value = pio->PIO_PDSR; + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + *value = (*value >> pin) & 1; + break; + case GPIO_ACCESS_BY_PORT: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static void gpio_sam_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct gpio_sam_config * const cfg = DEV_CFG(dev); + Pio *const pio = cfg->regs; + struct gpio_sam_runtime *context = dev->driver_data; + u32_t int_stat; + + int_stat = pio->PIO_ISR; + + _gpio_fire_callbacks(&context->cb, dev, int_stat); +} + +static int gpio_sam_manage_callback(struct device *port, + struct gpio_callback *callback, + bool set) +{ + struct gpio_sam_runtime *context = port->driver_data; + + _gpio_manage_callback(&context->cb, callback, set); + + return 0; +} + +static int gpio_sam_enable_callback(struct device *port, + int access_op, u32_t pin) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(port); + Pio *const pio = cfg->regs; + u32_t mask; + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + mask = BIT(pin); + break; + case GPIO_ACCESS_BY_PORT: + mask = 0xFFFFFFFF; + break; + default: + return -ENOTSUP; + } + + pio->PIO_IER |= mask; + + return 0; +} + +static int gpio_sam_disable_callback(struct device *port, + int access_op, u32_t pin) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(port); + Pio *const pio = cfg->regs; + u32_t mask; + + switch (access_op) { + case GPIO_ACCESS_BY_PIN: + mask = BIT(pin); + break; + case GPIO_ACCESS_BY_PORT: + mask = 0xFFFFFFFF; + break; + default: + return -ENOTSUP; + } + + pio->PIO_IDR |= mask; + + return 0; +} + +static const struct gpio_driver_api gpio_sam_api = { + .config = gpio_sam_config, + .write = gpio_sam_write, + .read = gpio_sam_read, + .manage_callback = gpio_sam_manage_callback, + .enable_callback = gpio_sam_enable_callback, + .disable_callback = gpio_sam_disable_callback, +}; + +int gpio_sam_init(struct device *dev) +{ + const struct gpio_sam_config * const cfg = DEV_CFG(dev); + + /* The peripheral clock must be enabled for the interrupts to work. */ + soc_pmc_peripheral_enable(cfg->periph_id); + + cfg->config_func(dev); + + return 0; +} + +/* PORT A */ +#ifdef CONFIG_GPIO_SAM_PORTA_BASE_ADDRESS +static void port_a_sam_config_func(struct device *dev); + +static const struct gpio_sam_config port_a_sam_config = { + .regs = (Pio *)CONFIG_GPIO_SAM_PORTA_BASE_ADDRESS, + .periph_id = CONFIG_GPIO_SAM_PORTA_PERIPHERAL_ID, + .config_func = port_a_sam_config_func, +}; + +static struct gpio_sam_runtime port_a_sam_runtime; + +DEVICE_AND_API_INIT(port_a_sam, CONFIG_GPIO_SAM_PORTA_LABEL, gpio_sam_init, + &port_a_sam_runtime, &port_a_sam_config, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam_api); + +static void port_a_sam_config_func(struct device *dev) +{ + IRQ_CONNECT(CONFIG_GPIO_SAM_PORTA_IRQ, CONFIG_GPIO_SAM_PORTA_IRQ_PRIO, + gpio_sam_isr, DEVICE_GET(port_a_sam), 0); + irq_enable(CONFIG_GPIO_SAM_PORTA_IRQ); +} + +#endif /* CONFIG_GPIO_SAM_PORTA_BASE_ADDRESS */ + +/* PORT B */ +#ifdef CONFIG_GPIO_SAM_PORTB_BASE_ADDRESS +static void port_b_sam_config_func(struct device *dev); + +static const struct gpio_sam_config port_b_sam_config = { + .regs = (Pio *)CONFIG_GPIO_SAM_PORTB_BASE_ADDRESS, + .periph_id = CONFIG_GPIO_SAM_PORTB_PERIPHERAL_ID, + .config_func = port_b_sam_config_func, +}; + +static struct gpio_sam_runtime port_b_sam_runtime; + +DEVICE_AND_API_INIT(port_b_sam, CONFIG_GPIO_SAM_PORTB_LABEL, gpio_sam_init, + &port_b_sam_runtime, &port_b_sam_config, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam_api); + +static void port_b_sam_config_func(struct device *dev) +{ + IRQ_CONNECT(CONFIG_GPIO_SAM_PORTB_IRQ, CONFIG_GPIO_SAM_PORTB_IRQ_PRIO, + gpio_sam_isr, DEVICE_GET(port_b_sam), 0); + irq_enable(CONFIG_GPIO_SAM_PORTB_IRQ); +} + +#endif /* CONFIG_GPIO_SAM_PORTB_BASE_ADDRESS */ + +/* PORT C */ +#ifdef CONFIG_GPIO_SAM_PORTC_BASE_ADDRESS +static void port_c_sam_config_func(struct device *dev); + +static const struct gpio_sam_config port_c_sam_config = { + .regs = (Pio *)CONFIG_GPIO_SAM_PORTC_BASE_ADDRESS, + .periph_id = CONFIG_GPIO_SAM_PORTC_PERIPHERAL_ID, + .config_func = port_c_sam_config_func, +}; + +static struct gpio_sam_runtime port_c_sam_runtime; + +DEVICE_AND_API_INIT(port_c_sam, CONFIG_GPIO_SAM_PORTC_LABEL, gpio_sam_init, + &port_c_sam_runtime, &port_c_sam_config, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam_api); + +static void port_c_sam_config_func(struct device *dev) +{ + IRQ_CONNECT(CONFIG_GPIO_SAM_PORTC_IRQ, CONFIG_GPIO_SAM_PORTC_IRQ_PRIO, + gpio_sam_isr, DEVICE_GET(port_c_sam), 0); + irq_enable(CONFIG_GPIO_SAM_PORTC_IRQ); +} + +#endif /* CONFIG_GPIO_SAM_PORTC_BASE_ADDRESS */ + +/* PORT D */ +#ifdef CONFIG_GPIO_SAM_PORTD_BASE_ADDRESS +static void port_d_sam_config_func(struct device *dev); + +static const struct gpio_sam_config port_d_sam_config = { + .regs = (Pio *)CONFIG_GPIO_SAM_PORTD_BASE_ADDRESS, + .periph_id = CONFIG_GPIO_SAM_PORTD_PERIPHERAL_ID, + .config_func = port_d_sam_config_func, +}; + +static struct gpio_sam_runtime port_d_sam_runtime; + +DEVICE_AND_API_INIT(port_d_sam, CONFIG_GPIO_SAM_PORTD_LABEL, gpio_sam_init, + &port_d_sam_runtime, &port_d_sam_config, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam_api); + +static void port_d_sam_config_func(struct device *dev) +{ + IRQ_CONNECT(CONFIG_GPIO_SAM_PORTD_IRQ, CONFIG_GPIO_SAM_PORTD_IRQ_PRIO, + gpio_sam_isr, DEVICE_GET(port_d_sam), 0); + irq_enable(CONFIG_GPIO_SAM_PORTD_IRQ); +} + +#endif /* CONFIG_GPIO_SAM_PORTD_BASE_ADDRESS */ + +/* PORT E */ +#ifdef CONFIG_GPIO_SAM_PORTE_BASE_ADDRESS +static void port_e_sam_config_func(struct device *dev); + +static const struct gpio_sam_config port_e_sam_config = { + .regs = (Pio *)CONFIG_GPIO_SAM_PORTE_BASE_ADDRESS, + .periph_id = CONFIG_GPIO_SAM_PORTE_PERIPHERAL_ID, + .config_func = port_e_sam_config_func, +}; + +static struct gpio_sam_runtime port_e_sam_runtime; + +DEVICE_AND_API_INIT(port_e_sam, CONFIG_GPIO_SAM_PORTE_LABEL, gpio_sam_init, + &port_e_sam_runtime, &port_e_sam_config, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &gpio_sam_api); + +static void port_e_sam_config_func(struct device *dev) +{ + IRQ_CONNECT(CONFIG_GPIO_SAM_PORTE_IRQ, CONFIG_GPIO_SAM_PORTE_IRQ_PRIO, + gpio_sam_isr, DEVICE_GET(port_e_sam), 0); + irq_enable(CONFIG_GPIO_SAM_PORTE_IRQ); +} + +#endif /* CONFIG_GPIO_SAM_PORTE_BASE_ADDRESS */ diff --git a/dts/arm/atmel/sam4s.dtsi b/dts/arm/atmel/sam4s.dtsi index b9696ea8e33..f246f4de224 100644 --- a/dts/arm/atmel/sam4s.dtsi +++ b/dts/arm/atmel/sam4s.dtsi @@ -87,6 +87,30 @@ status = "disabled"; label = "USART_1"; }; + + porta: gpio@400E0E00 { + compatible = "atmel,sam-gpio"; + reg = <0x400E0E00 0x190>; + interrupts = <11 1>; + peripheral-id = <11>; + label = "PORTA"; + }; + + portb: gpio@400E1000 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1000 0x190>; + interrupts = <12 1>; + peripheral-id = <12>; + label = "PORTB"; + }; + + portc: gpio@400E1200 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1200 0x190>; + interrupts = <13 1>; + peripheral-id = <13>; + label = "PORTC"; + }; }; }; diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index 45f27e67908..87777b433c5 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -159,6 +159,46 @@ status = "disabled"; label = "ADC_1"; }; + + porta: gpio@400E0E00 { + compatible = "atmel,sam-gpio"; + reg = <0x400E0E00 0x190>; + interrupts = <10 1>; + peripheral-id = <10>; + label = "PORTA"; + }; + + portb: gpio@400E1000 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1000 0x190>; + interrupts = <11 1>; + peripheral-id = <11>; + label = "PORTB"; + }; + + portc: gpio@400E1200 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1200 0x190>; + interrupts = <12 1>; + peripheral-id = <12>; + label = "PORTC"; + }; + + portd: gpio@400E1400 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1400 0x190>; + interrupts = <16 1>; + peripheral-id = <16>; + label = "PORTD"; + }; + + porte: gpio@400E1600 { + compatible = "atmel,sam-gpio"; + reg = <0x400E1600 0x190>; + interrupts = <17 1>; + peripheral-id = <17>; + label = "PORTE"; + }; }; }; diff --git a/dts/bindings/gpio/atmel.sam-gpio.yaml b/dts/bindings/gpio/atmel.sam-gpio.yaml new file mode 100644 index 00000000000..8ebf12e2ce6 --- /dev/null +++ b/dts/bindings/gpio/atmel.sam-gpio.yaml @@ -0,0 +1,38 @@ +--- +title: Atmel SAM GPIO PORT driver +id: atmel,sam-gpio +version: 0.1 + +description: > + This is a representation of the SAM GPIO PORT nodes + +properties: + compatible: + type: string + category: required + description: compatible strings + constraint: "atmel,sam-gpio" + + reg: + type: int + description: mmio register space + generation: define + category: required + + interrupts: + type: compound + category: required + description: required interrupts + generation: define + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for API name) + generation: define + + peripheral-id: + type: int + description: peripheral ID + generation: define + category: required