diff --git a/CMakeLists.txt b/CMakeLists.txt index 42cbfc88fecfa3..44b00e19c80cc2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,6 +341,13 @@ add_subdirectory(subsys) add_subdirectory(drivers) add_subdirectory(tests) +# Add all generated zephyr sources in the same context as the zephyr library +# is created. Assure all sub directories that might invoke code generation +# are processed before. +get_property(zephyr_generated_sources GLOBAL PROPERTY zephyr_generated_sources_property) +set_source_files_properties(${zephyr_generated_sources} PROPERTIES GENERATED 1) +target_sources(zephyr PRIVATE ${zephyr_generated_sources}) + set(syscall_macros_h ${ZEPHYR_BINARY_DIR}/include/generated/syscall_macros.h) add_custom_target(syscall_macros_h_target DEPENDS ${syscall_macros_h}) diff --git a/arch/arm/soc/st_stm32/stm32f0/CMakeLists.txt b/arch/arm/soc/st_stm32/stm32f0/CMakeLists.txt index 3b3d0df2a5633e..4833d11e8ff980 100644 --- a/arch/arm/soc/st_stm32/stm32f0/CMakeLists.txt +++ b/arch/arm/soc/st_stm32/stm32f0/CMakeLists.txt @@ -1,3 +1,5 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_sources(soc.c) -zephyr_sources_ifdef(CONFIG_GPIO soc_gpio.c) +if(!CONFIG_PINCTRL) +zephyr_sources_ifdef(CONFIG_GPIO_STM32 soc_gpio.c) +endif() diff --git a/arch/arm/soc/st_stm32/stm32f0/Kconfig.defconfig.series b/arch/arm/soc/st_stm32/stm32f0/Kconfig.defconfig.series index 5e3c2438d6cd65..ad4860a9c46992 100644 --- a/arch/arm/soc/st_stm32/stm32f0/Kconfig.defconfig.series +++ b/arch/arm/soc/st_stm32/stm32f0/Kconfig.defconfig.series @@ -12,16 +12,9 @@ source "arch/arm/soc/st_stm32/stm32f0/Kconfig.defconfig.stm32f0*" config SOC_SERIES default "stm32f0" -if GPIO_STM32 - -config GPIO_STM32_PORTD - default y - -config GPIO_STM32_PORTF +config PINCTRL default y -endif # GPIO_STM32 - if I2C_STM32 config I2C_STM32_V2 diff --git a/arch/arm/soc/st_stm32/stm32f0/dts.fixup b/arch/arm/soc/st_stm32/stm32f0/dts.fixup index 7cbc106b57bba4..2ea0195f4935c0 100644 --- a/arch/arm/soc/st_stm32/stm32f0/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f0/dts.fixup @@ -2,51 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V6M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40013800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40013800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40013800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40013800_LABEL -#define USART_1_IRQ ST_STM32_USART_40013800_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V2_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_COMBINED_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_COMBINED_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V2_40005400_LABEL -#define CONFIG_I2C_1_COMBINED_IRQ ST_STM32_I2C_V2_40005400_IRQ_COMBINED -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V2_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V2_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_COMBINED_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_COMBINED_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V2_40005800_LABEL -#define CONFIG_I2C_2_COMBINED_IRQ ST_STM32_I2C_V2_40005800_IRQ_COMBINED -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V2_40005800_CLOCK_FREQUENCY - -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_FIFO_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_FIFO_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_FIFO_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_FIFO_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_FIFO_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_FIFO_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_FIFO_40003800_IRQ_0 - -#define CONFIG_CAN_1_BASE_ADDRESS ST_STM32_CAN_40006400_BASE_ADDRESS -#define CONFIG_CAN_1_BUS_SPEED ST_STM32_CAN_40006400_BUS_SPEED -#define CONFIG_CAN_1_NAME ST_STM32_CAN_40006400_LABEL -#define CONFIG_CAN_1_IRQ ST_STM32_CAN_40006400_IRQ_0 -#define CONFIG_CAN_1_IRQ_PRIORITY ST_STM32_CAN_40006400_IRQ_0_PRIORITY -#define CONFIG_CAN_1_SJW ST_STM32_CAN_40006400_SJW -#define CONFIG_CAN_1_PROP_SEG_PHASE_SEG1 ST_STM32_CAN_40006400_PROP_SEG_PHASE_SEG1 -#define CONFIG_CAN_1_PHASE_SEG2 ST_STM32_CAN_40006400_PHASE_SEG2 -#define CONFIG_CAN_1_CLOCK_BUS ST_STM32_CAN_40006400_CLOCK_BUS -#define CONFIG_CAN_1_CLOCK_BITS ST_STM32_CAN_40006400_CLOCK_BITS - #define FLASH_DEV_BASE_ADDRESS ST_STM32F0_FLASH_CONTROLLER_40022000_BASE_ADDRESS #define FLASH_DEV_NAME ST_STM32F0_FLASH_CONTROLLER_40022000_LABEL @@ -56,31 +11,4 @@ #define CONFIG_USB_NUM_BIDIR_ENDPOINTS ST_STM32_USB_40005C00_NUM_BIDIR_ENDPOINTS #define CONFIG_USB_RAM_SIZE ST_STM32_USB_40005C00_RAM_SIZE -#define CONFIG_PWM_STM32_1_DEV_NAME ST_STM32_PWM_40012C00_PWM_LABEL -#define CONFIG_PWM_STM32_1_PRESCALER ST_STM32_PWM_40012C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_2_DEV_NAME ST_STM32_PWM_40000000_PWM_LABEL -#define CONFIG_PWM_STM32_2_PRESCALER ST_STM32_PWM_40000000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_3_DEV_NAME ST_STM32_PWM_40000400_PWM_LABEL -#define CONFIG_PWM_STM32_3_PRESCALER ST_STM32_PWM_40000400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_6_DEV_NAME ST_STM32_PWM_40001000_PWM_LABEL -#define CONFIG_PWM_STM32_6_PRESCALER ST_STM32_PWM_40001000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_7_DEV_NAME ST_STM32_PWM_40001400_PWM_LABEL -#define CONFIG_PWM_STM32_7_PRESCALER ST_STM32_PWM_40001400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_14_DEV_NAME ST_STM32_PWM_40002000_PWM_LABEL -#define CONFIG_PWM_STM32_14_PRESCALER ST_STM32_PWM_40002000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_15_DEV_NAME ST_STM32_PWM_40014000_PWM_LABEL -#define CONFIG_PWM_STM32_15_PRESCALER ST_STM32_PWM_40014000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_16_DEV_NAME ST_STM32_PWM_40014400_PWM_LABEL -#define CONFIG_PWM_STM32_16_PRESCALER ST_STM32_PWM_40014400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_17_DEV_NAME ST_STM32_PWM_40014800_PWM_LABEL -#define CONFIG_PWM_STM32_17_PRESCALER ST_STM32_PWM_40014800_PWM_ST_PRESCALER - /* End of SoC Level DTS fixup file */ diff --git a/arch/arm/soc/st_stm32/stm32f0/soc.h b/arch/arm/soc/st_stm32/stm32f0/soc.h index de683323a0e2ae..0963eaab5a6377 100644 --- a/arch/arm/soc/st_stm32/stm32f0/soc.h +++ b/arch/arm/soc/st_stm32/stm32f0/soc.h @@ -43,6 +43,19 @@ #include #endif /* CONFIG_CLOCK_CONTROL_STM32_CUBE */ +#ifdef CONFIG_PINCTRL_STM32 +#include +#include +#include +#endif + +#ifdef CONFIG_GPIO_STM32 +#include +#include +#include +#include +#endif + #ifdef CONFIG_IWDG_STM32 #include #endif diff --git a/arch/arm/soc/st_stm32/stm32f1/dts.fixup b/arch/arm/soc/st_stm32/stm32f1/dts.fixup index 922434cfb0298a..df6e265f62f658 100644 --- a/arch/arm/soc/st_stm32/stm32f1/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f1/dts.fixup @@ -2,89 +2,10 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40013800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40013800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40013800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40013800_LABEL -#define USART_1_IRQ ST_STM32_USART_40013800_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_USART_3_BASE_ADDRESS ST_STM32_USART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_3_BAUD_RATE ST_STM32_USART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_3_IRQ_PRI ST_STM32_USART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_3_NAME ST_STM32_USART_40004800_LABEL -#define USART_3_IRQ ST_STM32_USART_40004800_IRQ_0 - -#define CONFIG_UART_STM32_PORT_4_BASE_ADDRESS ST_STM32_UART_40004C00_BASE_ADDRESS -#define CONFIG_UART_STM32_PORT_4_BAUD_RATE ST_STM32_UART_40004C00_CURRENT_SPEED -#define CONFIG_UART_STM32_PORT_4_IRQ_PRI ST_STM32_UART_40004C00_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_PORT_4_NAME ST_STM32_UART_40004C00_LABEL -#define PORT_4_IRQ ST_STM32_UART_40004C00_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V1_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_EVENT_IRQ_PRI ST_STM32_I2C_V1_40005400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_1_ERROR_IRQ_PRI ST_STM32_I2C_V1_40005400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V1_40005400_LABEL -#define CONFIG_I2C_1_EVENT_IRQ ST_STM32_I2C_V1_40005400_IRQ_EVENT -#define CONFIG_I2C_1_ERROR_IRQ ST_STM32_I2C_V1_40005400_IRQ_ERROR -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V1_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V1_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_EVENT_IRQ_PRI ST_STM32_I2C_V1_40005800_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_2_ERROR_IRQ_PRI ST_STM32_I2C_V1_40005800_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V1_40005800_LABEL -#define CONFIG_I2C_2_EVENT_IRQ ST_STM32_I2C_V1_40005800_IRQ_EVENT -#define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V1_40005800_IRQ_ERROR -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V1_40005800_CLOCK_FREQUENCY - -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_40003800_IRQ_0 - -#define CONFIG_SPI_3_BASE_ADDRESS ST_STM32_SPI_40003C00_BASE_ADDRESS -#define CONFIG_SPI_3_IRQ_PRI ST_STM32_SPI_40003C00_IRQ_0_PRIORITY -#define CONFIG_SPI_3_NAME ST_STM32_SPI_40003C00_LABEL -#define CONFIG_SPI_3_IRQ ST_STM32_SPI_40003C00_IRQ_0 - #define CONFIG_USB_BASE_ADDRESS ST_STM32_USB_40005C00_BASE_ADDRESS #define CONFIG_USB_IRQ ST_STM32_USB_40005C00_IRQ_USB #define CONFIG_USB_IRQ_PRI ST_STM32_USB_40005C00_IRQ_USB_PRIORITY #define CONFIG_USB_NUM_BIDIR_ENDPOINTS ST_STM32_USB_40005C00_NUM_BIDIR_ENDPOINTS #define CONFIG_USB_RAM_SIZE ST_STM32_USB_40005C00_RAM_SIZE -#define CONFIG_PWM_STM32_1_DEV_NAME ST_STM32_PWM_40012C00_PWM_LABEL -#define CONFIG_PWM_STM32_1_PRESCALER ST_STM32_PWM_40012C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_2_DEV_NAME ST_STM32_PWM_40000000_PWM_LABEL -#define CONFIG_PWM_STM32_2_PRESCALER ST_STM32_PWM_40000000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_3_DEV_NAME ST_STM32_PWM_40000400_PWM_LABEL -#define CONFIG_PWM_STM32_3_PRESCALER ST_STM32_PWM_40000400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_4_DEV_NAME ST_STM32_PWM_40000800_PWM_LABEL -#define CONFIG_PWM_STM32_4_PRESCALER ST_STM32_PWM_40000800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_5_DEV_NAME ST_STM32_PWM_40000C00_PWM_LABEL -#define CONFIG_PWM_STM32_5_PRESCALER ST_STM32_PWM_40000C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_6_DEV_NAME ST_STM32_PWM_40001000_PWM_LABEL -#define CONFIG_PWM_STM32_6_PRESCALER ST_STM32_PWM_40001000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_7_DEV_NAME ST_STM32_PWM_40001400_PWM_LABEL -#define CONFIG_PWM_STM32_7_PRESCALER ST_STM32_PWM_40001400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_8_DEV_NAME ST_STM32_PWM_40013400_PWM_LABEL -#define CONFIG_PWM_STM32_8_PRESCALER ST_STM32_PWM_40013400_PWM_ST_PRESCALER - /* End of SoC Level DTS fixup file */ diff --git a/arch/arm/soc/st_stm32/stm32f2/dts.fixup b/arch/arm/soc/st_stm32/stm32f2/dts.fixup index 3e4b48647bc47d..add0899e006a0e 100644 --- a/arch/arm/soc/st_stm32/stm32f2/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f2/dts.fixup @@ -2,42 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40011000_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40011000_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40011000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40011000_LABEL -#define USART_1_IRQ ST_STM32_USART_40011000_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_USART_3_BASE_ADDRESS ST_STM32_USART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_3_BAUD_RATE ST_STM32_USART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_3_IRQ_PRI ST_STM32_USART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_3_NAME ST_STM32_USART_40004800_LABEL -#define USART_3_IRQ ST_STM32_USART_40004800_IRQ_0 - -#define CONFIG_UART_STM32_USART_6_NAME ST_STM32_USART_40011400_LABEL -#define CONFIG_UART_STM32_USART_6_BASE_ADDRESS ST_STM32_USART_40011400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_6_BAUD_RATE ST_STM32_USART_40011400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_6_IRQ_PRI ST_STM32_USART_40011400_IRQ_0_PRIORITY -#define USART_6_IRQ ST_STM32_USART_40011400_IRQ_0 - -#define CONFIG_UART_STM32_UART_4_NAME ST_STM32_UART_40004C00_LABEL -#define CONFIG_UART_STM32_UART_4_BASE_ADDRESS ST_STM32_UART_40004C00_BASE_ADDRESS -#define CONFIG_UART_STM32_UART_4_BAUD_RATE ST_STM32_UART_40004C00_CURRENT_SPEED -#define CONFIG_UART_STM32_UART_4_IRQ_PRI ST_STM32_UART_40004C00_IRQ_0_PRIORITY -#define UART_4_IRQ ST_STM32_UART_40004C00_IRQ_0 - -#define CONFIG_UART_STM32_UART_5_NAME ST_STM32_UART_40005000_LABEL -#define CONFIG_UART_STM32_UART_5_BASE_ADDRESS ST_STM32_UART_40005000_BASE_ADDRESS -#define CONFIG_UART_STM32_UART_5_BAUD_RATE ST_STM32_UART_40005000_CURRENT_SPEED -#define CONFIG_UART_STM32_UART_5_IRQ_PRI ST_STM32_UART_40005000_IRQ_0_PRIORITY -#define UART_5_IRQ ST_STM32_UART_40005000_IRQ_0 - #define CONFIG_USB_BASE_ADDRESS ST_STM32_OTGFS_50000000_BASE_ADDRESS #define CONFIG_USB_IRQ ST_STM32_OTGFS_50000000_IRQ_OTGFS #define CONFIG_USB_IRQ_PRI ST_STM32_OTGFS_50000000_IRQ_OTGFS_PRIORITY diff --git a/arch/arm/soc/st_stm32/stm32f3/dts.fixup b/arch/arm/soc/st_stm32/stm32f3/dts.fixup index bd2cdc9a97f7d2..bc494d433a9552 100644 --- a/arch/arm/soc/st_stm32/stm32f3/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f3/dts.fixup @@ -2,54 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40013800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40013800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40013800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40013800_LABEL -#define USART_1_IRQ ST_STM32_USART_40013800_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V2_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_1_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V2_40005400_LABEL -#define CONFIG_I2C_1_EVENT_IRQ ST_STM32_I2C_V2_40005400_IRQ_EVENT -#define CONFIG_I2C_1_ERROR_IRQ ST_STM32_I2C_V2_40005400_IRQ_ERROR -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V2_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V2_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_2_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V2_40005800_LABEL -#define CONFIG_I2C_2_EVENT_IRQ ST_STM32_I2C_V2_40005800_IRQ_EVENT -#define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V2_40005800_IRQ_ERROR -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V2_40005800_CLOCK_FREQUENCY - -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_FIFO_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_FIFO_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_FIFO_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_FIFO_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_FIFO_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_FIFO_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_FIFO_40003800_IRQ_0 - -#define CONFIG_SPI_3_BASE_ADDRESS ST_STM32_SPI_FIFO_40003C00_BASE_ADDRESS -#define CONFIG_SPI_3_IRQ_PRI ST_STM32_SPI_FIFO_40003C00_IRQ_0_PRIORITY -#define CONFIG_SPI_3_NAME ST_STM32_SPI_FIFO_40003C00_LABEL -#define CONFIG_SPI_3_IRQ ST_STM32_SPI_FIFO_40003C00_IRQ_0 - -#define CONFIG_SPI_4_BASE_ADDRESS ST_STM32_SPI_FIFO_40013C00_BASE_ADDRESS -#define CONFIG_SPI_4_IRQ_PRI ST_STM32_SPI_FIFO_40013C00_IRQ_0_PRIORITY -#define CONFIG_SPI_4_NAME ST_STM32_SPI_FIFO_40013C00_LABEL -#define CONFIG_SPI_4_IRQ ST_STM32_SPI_FIFO_40013C00_IRQ_0 - #define FLASH_DEV_BASE_ADDRESS ST_STM32F3_FLASH_CONTROLLER_40022000_BASE_ADDRESS #define FLASH_DEV_NAME ST_STM32F3_FLASH_CONTROLLER_40022000_LABEL @@ -59,55 +11,4 @@ #define CONFIG_USB_NUM_BIDIR_ENDPOINTS ST_STM32_USB_40005C00_NUM_BIDIR_ENDPOINTS #define CONFIG_USB_RAM_SIZE ST_STM32_USB_40005C00_RAM_SIZE -#define CONFIG_PWM_STM32_1_DEV_NAME ST_STM32_PWM_40012C00_PWM_LABEL -#define CONFIG_PWM_STM32_1_PRESCALER ST_STM32_PWM_40012C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_2_DEV_NAME ST_STM32_PWM_40000000_PWM_LABEL -#define CONFIG_PWM_STM32_2_PRESCALER ST_STM32_PWM_40000000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_3_DEV_NAME ST_STM32_PWM_40000400_PWM_LABEL -#define CONFIG_PWM_STM32_3_PRESCALER ST_STM32_PWM_40000400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_4_DEV_NAME ST_STM32_PWM_40000800_PWM_LABEL -#define CONFIG_PWM_STM32_4_PRESCALER ST_STM32_PWM_40000800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_5_DEV_NAME ST_STM32_PWM_40000C00_PWM_LABEL -#define CONFIG_PWM_STM32_5_PRESCALER ST_STM32_PWM_40000C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_6_DEV_NAME ST_STM32_PWM_40001000_PWM_LABEL -#define CONFIG_PWM_STM32_6_PRESCALER ST_STM32_PWM_40001000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_7_DEV_NAME ST_STM32_PWM_40001400_PWM_LABEL -#define CONFIG_PWM_STM32_7_PRESCALER ST_STM32_PWM_40001400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_8_DEV_NAME ST_STM32_PWM_40013400_PWM_LABEL -#define CONFIG_PWM_STM32_8_PRESCALER ST_STM32_PWM_40013400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_12_DEV_NAME ST_STM32_PWM_40001800_PWM_LABEL -#define CONFIG_PWM_STM32_12_PRESCALER ST_STM32_PWM_40001800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_13_DEV_NAME ST_STM32_PWM_40001C00_PWM_LABEL -#define CONFIG_PWM_STM32_13_PRESCALER ST_STM32_PWM_40001C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_14_DEV_NAME ST_STM32_PWM_40002000_PWM_LABEL -#define CONFIG_PWM_STM32_14_PRESCALER ST_STM32_PWM_40002000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_15_DEV_NAME ST_STM32_PWM_40014000_PWM_LABEL -#define CONFIG_PWM_STM32_15_PRESCALER ST_STM32_PWM_40014000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_16_DEV_NAME ST_STM32_PWM_40014400_PWM_LABEL -#define CONFIG_PWM_STM32_16_PRESCALER ST_STM32_PWM_40014400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_17_DEV_NAME ST_STM32_PWM_40014800_PWM_LABEL -#define CONFIG_PWM_STM32_17_PRESCALER ST_STM32_PWM_40014800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_18_DEV_NAME ST_STM32_PWM_40009C00_PWM_LABEL -#define CONFIG_PWM_STM32_18_PRESCALER ST_STM32_PWM_40009C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_19_DEV_NAME ST_STM32_PWM_40015C00_PWM_LABEL -#define CONFIG_PWM_STM32_19_PRESCALER ST_STM32_PWM_40015C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_20_DEV_NAME ST_STM32_PWM_40015000_PWM_LABEL -#define CONFIG_PWM_STM32_20_PRESCALER ST_STM32_PWM_40015000_PWM_ST_PRESCALER - /* End of SoC Level DTS fixup file */ diff --git a/arch/arm/soc/st_stm32/stm32f4/dts.fixup b/arch/arm/soc/st_stm32/stm32f4/dts.fixup index a01e200f628ca2..07056e5ffaf7af 100644 --- a/arch/arm/soc/st_stm32/stm32f4/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f4/dts.fixup @@ -2,84 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40011000_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40011000_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40011000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40011000_LABEL -#define USART_1_IRQ ST_STM32_USART_40011000_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_USART_3_BASE_ADDRESS ST_STM32_USART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_3_BAUD_RATE ST_STM32_USART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_3_IRQ_PRI ST_STM32_USART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_3_NAME ST_STM32_USART_40004800_LABEL -#define USART_3_IRQ ST_STM32_USART_40004800_IRQ_0 - -#define CONFIG_UART_STM32_USART_6_NAME ST_STM32_USART_40011400_LABEL -#define CONFIG_UART_STM32_USART_6_BASE_ADDRESS ST_STM32_USART_40011400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_6_BAUD_RATE ST_STM32_USART_40011400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_6_IRQ_PRI ST_STM32_USART_40011400_IRQ_0_PRIORITY -#define USART_6_IRQ ST_STM32_USART_40011400_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V1_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_EVENT_IRQ_PRI ST_STM32_I2C_V1_40005400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_1_ERROR_IRQ_PRI ST_STM32_I2C_V1_40005400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V1_40005400_LABEL -#define CONFIG_I2C_1_EVENT_IRQ ST_STM32_I2C_V1_40005400_IRQ_EVENT -#define CONFIG_I2C_1_ERROR_IRQ ST_STM32_I2C_V1_40005400_IRQ_ERROR -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V1_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V1_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_EVENT_IRQ_PRI ST_STM32_I2C_V1_40005800_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_2_ERROR_IRQ_PRI ST_STM32_I2C_V1_40005800_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V1_40005800_LABEL -#define CONFIG_I2C_2_EVENT_IRQ ST_STM32_I2C_V1_40005800_IRQ_EVENT -#define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V1_40005800_IRQ_ERROR -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V1_40005800_CLOCK_FREQUENCY - -#define CONFIG_I2C_3_BASE_ADDRESS ST_STM32_I2C_V1_40005C00_BASE_ADDRESS -#define CONFIG_I2C_3_EVENT_IRQ_PRI ST_STM32_I2C_V1_40005C00_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_3_ERROR_IRQ_PRI ST_STM32_I2C_V1_40005C00_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_3_NAME ST_STM32_I2C_V1_40005C00_LABEL -#define CONFIG_I2C_3_EVENT_IRQ ST_STM32_I2C_V1_40005C00_IRQ_EVENT -#define CONFIG_I2C_3_ERROR_IRQ ST_STM32_I2C_V1_40005C00_IRQ_ERROR -#define CONFIG_I2C_3_BITRATE ST_STM32_I2C_V1_40005C00_CLOCK_FREQUENCY - -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_40003800_IRQ_0 - -#define CONFIG_SPI_3_BASE_ADDRESS ST_STM32_SPI_40003C00_BASE_ADDRESS -#define CONFIG_SPI_3_IRQ_PRI ST_STM32_SPI_40003C00_IRQ_0_PRIORITY -#define CONFIG_SPI_3_NAME ST_STM32_SPI_40003C00_LABEL -#define CONFIG_SPI_3_IRQ ST_STM32_SPI_40003C00_IRQ_0 - -#define CONFIG_SPI_4_BASE_ADDRESS ST_STM32_SPI_40013400_BASE_ADDRESS -#define CONFIG_SPI_4_IRQ_PRI ST_STM32_SPI_40013400_IRQ_0_PRIORITY -#define CONFIG_SPI_4_NAME ST_STM32_SPI_40013400_LABEL -#define CONFIG_SPI_4_IRQ ST_STM32_SPI_40013400_IRQ_0 - -#define CONFIG_SPI_5_BASE_ADDRESS ST_STM32_SPI_40015000_BASE_ADDRESS -#define CONFIG_SPI_5_IRQ_PRI ST_STM32_SPI_40015000_IRQ_0_PRIORITY -#define CONFIG_SPI_5_NAME ST_STM32_SPI_40015000_LABEL -#define CONFIG_SPI_5_IRQ ST_STM32_SPI_40015000_IRQ_0 - -#define CONFIG_SPI_6_BASE_ADDRESS ST_STM32_SPI_40015400_BASE_ADDRESS -#define CONFIG_SPI_6_IRQ_PRI ST_STM32_SPI_40015400_IRQ_0_PRIORITY -#define CONFIG_SPI_6_NAME ST_STM32_SPI_40015400_LABEL -#define CONFIG_SPI_6_IRQ ST_STM32_SPI_40015400_IRQ_0 - #define FLASH_DEV_BASE_ADDRESS ST_STM32F4_FLASH_CONTROLLER_40023C00_BASE_ADDRESS #define FLASH_DEV_NAME ST_STM32F4_FLASH_CONTROLLER_40023C00_LABEL @@ -99,46 +21,4 @@ #define CONFIG_USB_RAM_SIZE ST_STM32_OTGHS_40040000_RAM_SIZE #endif /* ST_STM32_OTGHS_40040000_BASE_ADDRESS */ -#define CONFIG_PWM_STM32_1_DEV_NAME ST_STM32_PWM_40010000_PWM_LABEL -#define CONFIG_PWM_STM32_1_PRESCALER ST_STM32_PWM_40010000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_2_DEV_NAME ST_STM32_PWM_40000000_PWM_LABEL -#define CONFIG_PWM_STM32_2_PRESCALER ST_STM32_PWM_40000000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_3_DEV_NAME ST_STM32_PWM_40000400_PWM_LABEL -#define CONFIG_PWM_STM32_3_PRESCALER ST_STM32_PWM_40000400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_4_DEV_NAME ST_STM32_PWM_40000800_PWM_LABEL -#define CONFIG_PWM_STM32_4_PRESCALER ST_STM32_PWM_40000800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_5_DEV_NAME ST_STM32_PWM_40000C00_PWM_LABEL -#define CONFIG_PWM_STM32_5_PRESCALER ST_STM32_PWM_40000C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_6_DEV_NAME ST_STM32_PWM_40001000_PWM_LABEL -#define CONFIG_PWM_STM32_6_PRESCALER ST_STM32_PWM_40001000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_7_DEV_NAME ST_STM32_PWM_40001400_PWM_LABEL -#define CONFIG_PWM_STM32_7_PRESCALER ST_STM32_PWM_40001400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_8_DEV_NAME ST_STM32_PWM_40010400_PWM_LABEL -#define CONFIG_PWM_STM32_8_PRESCALER ST_STM32_PWM_40010400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_9_DEV_NAME ST_STM32_PWM_40014000_PWM_LABEL -#define CONFIG_PWM_STM32_9_PRESCALER ST_STM32_PWM_40014000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_10_DEV_NAME ST_STM32_PWM_40014400_PWM_LABEL -#define CONFIG_PWM_STM32_10_PRESCALER ST_STM32_PWM_40014400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_11_DEV_NAME ST_STM32_PWM_40014800_PWM_LABEL -#define CONFIG_PWM_STM32_11_PRESCALER ST_STM32_PWM_40014800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_12_DEV_NAME ST_STM32_PWM_40001800_PWM_LABEL -#define CONFIG_PWM_STM32_12_PRESCALER ST_STM32_PWM_40001800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_13_DEV_NAME ST_STM32_PWM_40001C00_PWM_LABEL -#define CONFIG_PWM_STM32_13_PRESCALER ST_STM32_PWM_40001C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_14_DEV_NAME ST_STM32_PWM_40002000_PWM_LABEL -#define CONFIG_PWM_STM32_14_PRESCALER ST_STM32_PWM_40002000_PWM_ST_PRESCALER - /* End of SoC Level DTS fixup file */ diff --git a/arch/arm/soc/st_stm32/stm32f7/dts.fixup b/arch/arm/soc/st_stm32/stm32f7/dts.fixup index 16a4a0939a4104..b3145118401b23 100644 --- a/arch/arm/soc/st_stm32/stm32f7/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f7/dts.fixup @@ -2,78 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40011000_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40011000_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40011000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40011000_LABEL -#define USART_1_IRQ ST_STM32_USART_40011000_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_USART_3_BASE_ADDRESS ST_STM32_USART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_3_BAUD_RATE ST_STM32_USART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_3_IRQ_PRI ST_STM32_USART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_3_NAME ST_STM32_USART_40004800_LABEL -#define USART_3_IRQ ST_STM32_USART_40004800_IRQ_0 - -#define CONFIG_UART_STM32_USART_4_BASE_ADDRESS ST_STM32_USART_40004C00_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_4_BAUD_RATE ST_STM32_USART_40004C00_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_4_IRQ_PRI ST_STM32_USART_40004C00_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_4_NAME ST_STM32_USART_40004C00_LABEL -#define USART_4_IRQ ST_STM32_USART_40004C00_IRQ_0 - -#define CONFIG_UART_STM32_USART_5_BASE_ADDRESS ST_STM32_USART_40005000_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_5_BAUD_RATE ST_STM32_USART_40005000_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_5_IRQ_PRI ST_STM32_USART_40005000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_5_NAME ST_STM32_USART_40005000_LABEL -#define USART_5_IRQ ST_STM32_USART_40005000_IRQ_0 - -#define CONFIG_UART_STM32_USART_6_BASE_ADDRESS ST_STM32_USART_40011400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_6_BAUD_RATE ST_STM32_USART_40011400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_6_IRQ_PRI ST_STM32_USART_40011400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_6_NAME ST_STM32_USART_40011400_LABEL -#define USART_6_IRQ ST_STM32_USART_40011400_IRQ_0 - -#define CONFIG_UART_STM32_USART_7_BASE_ADDRESS ST_STM32_USART_40007800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_7_BAUD_RATE ST_STM32_USART_40007800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_7_IRQ_PRI ST_STM32_USART_40007800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_7_NAME ST_STM32_USART_40007800_LABEL -#define USART_7_IRQ ST_STM32_USART_40007800_IRQ_0 - -#define CONFIG_UART_STM32_USART_8_BASE_ADDRESS ST_STM32_USART_40007C00_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_8_BAUD_RATE ST_STM32_USART_40007C00_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_8_IRQ_PRI ST_STM32_USART_40007C00_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_8_NAME ST_STM32_USART_40007800_LABEL -#define USART_8_IRQ ST_STM32_USART_40007C00_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V2_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_1_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V2_40005400_LABEL -#define CONFIG_I2C_1_EVENT_IRQ ST_STM32_I2C_V2_40005400_IRQ_EVENT -#define CONFIG_I2C_1_ERROR_IRQ ST_STM32_I2C_V2_40005400_IRQ_ERROR -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V2_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V2_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_2_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V2_40005800_LABEL -#define CONFIG_I2C_2_EVENT_IRQ ST_STM32_I2C_V2_40005800_IRQ_EVENT -#define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V2_40005800_IRQ_ERROR -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V2_40005800_CLOCK_FREQUENCY - -#define CONFIG_I2C_3_BASE_ADDRESS ST_STM32_I2C_V2_40005C00_BASE_ADDRESS -#define CONFIG_I2C_3_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005C00_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_3_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005C00_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_3_NAME ST_STM32_I2C_V2_40005C00_LABEL -#define CONFIG_I2C_3_EVENT_IRQ ST_STM32_I2C_V2_40005C00_IRQ_EVENT -#define CONFIG_I2C_3_ERROR_IRQ ST_STM32_I2C_V2_40005C00_IRQ_ERROR -#define CONFIG_I2C_3_BITRATE ST_STM32_I2C_V2_40005C00_CLOCK_FREQUENCY - #ifdef ST_STM32_OTGFS_50000000_BASE_ADDRESS #define CONFIG_USB_BASE_ADDRESS ST_STM32_OTGFS_50000000_BASE_ADDRESS #define CONFIG_USB_IRQ ST_STM32_OTGFS_50000000_IRQ_OTGFS diff --git a/arch/arm/soc/st_stm32/stm32l0/dts.fixup b/arch/arm/soc/st_stm32/stm32l0/dts.fixup index fcd6919e960aca..0e6be7108eed1e 100644 --- a/arch/arm/soc/st_stm32/stm32l0/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32l0/dts.fixup @@ -2,52 +2,6 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V6M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40013800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40013800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40013800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40013800_LABEL -#define USART_1_IRQ ST_STM32_USART_40013800_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_LPUART_1_BASE_ADDRESS ST_STM32_LPUART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_LPUART_1_BAUD_RATE ST_STM32_LPUART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_LPUART_1_IRQ_PRI ST_STM32_LPUART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_LPUART_1_NAME ST_STM32_LPUART_40004800_LABEL -#define LPUART_1_IRQ ST_STM32_LPUART_40004800_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V2_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_COMBINED_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_COMBINED_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V2_40005400_LABEL -#define CONFIG_I2C_1_COMBINED_IRQ ST_STM32_I2C_V2_40005400_IRQ_COMBINED -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V2_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V2_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_COMBINED_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_COMBINED_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V2_40005800_LABEL -#define CONFIG_I2C_2_COMBINED_IRQ ST_STM32_I2C_V2_40005800_IRQ_COMBINED -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V2_40005800_CLOCK_FREQUENCY - -#define CONFIG_I2C_3_BASE_ADDRESS ST_STM32_I2C_V2_40007800_BASE_ADDRESS -#define CONFIG_I2C_3_COMBINED_IRQ_PRI ST_STM32_I2C_V2_40007800_IRQ_COMBINED_PRIORITY -#define CONFIG_I2C_3_NAME ST_STM32_I2C_V2_40007800_LABEL -#define CONFIG_I2C_3_COMBINED_IRQ ST_STM32_I2C_V2_40007800_IRQ_COMBINED -#define CONFIG_I2C_3_BITRATE ST_STM32_I2C_V2_40007800_CLOCK_FREQUENCY - -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_40003800_IRQ_0 - #define CONFIG_USB_BASE_ADDRESS ST_STM32_USB_40005C00_BASE_ADDRESS #define CONFIG_USB_IRQ ST_STM32_USB_40005C00_IRQ_USB #define CONFIG_USB_IRQ_PRI ST_STM32_USB_40005C00_IRQ_USB_PRIORITY diff --git a/arch/arm/soc/st_stm32/stm32l4/dts.fixup b/arch/arm/soc/st_stm32/stm32l4/dts.fixup index 426875190ce64b..c9635ff5531eb0 100644 --- a/arch/arm/soc/st_stm32/stm32l4/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32l4/dts.fixup @@ -2,87 +2,12 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS -#define CONFIG_UART_STM32_USART_1_BASE_ADDRESS ST_STM32_USART_40013800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_1_BAUD_RATE ST_STM32_USART_40013800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_1_IRQ_PRI ST_STM32_USART_40013800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_1_NAME ST_STM32_USART_40013800_LABEL -#define USART_1_IRQ ST_STM32_USART_40013800_IRQ_0 - -#define CONFIG_UART_STM32_USART_2_BASE_ADDRESS ST_STM32_USART_40004400_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_2_BAUD_RATE ST_STM32_USART_40004400_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_2_IRQ_PRI ST_STM32_USART_40004400_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_2_NAME ST_STM32_USART_40004400_LABEL -#define USART_2_IRQ ST_STM32_USART_40004400_IRQ_0 - -#define CONFIG_UART_STM32_USART_3_BASE_ADDRESS ST_STM32_USART_40004800_BASE_ADDRESS -#define CONFIG_UART_STM32_USART_3_BAUD_RATE ST_STM32_USART_40004800_CURRENT_SPEED -#define CONFIG_UART_STM32_USART_3_IRQ_PRI ST_STM32_USART_40004800_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_USART_3_NAME ST_STM32_USART_40004800_LABEL -#define USART_3_IRQ ST_STM32_USART_40004800_IRQ_0 - -#define CONFIG_UART_STM32_UART_4_BASE_ADDRESS ST_STM32_UART_40004C00_BASE_ADDRESS -#define CONFIG_UART_STM32_UART_4_BAUD_RATE ST_STM32_UART_40004C00_CURRENT_SPEED -#define CONFIG_UART_STM32_UART_4_IRQ_PRI ST_STM32_UART_40004C00_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_UART_4_NAME ST_STM32_UART_40004C00_LABEL -#define UART_4_IRQ ST_STM32_UART_40004C00_IRQ_0 - -#define CONFIG_UART_STM32_UART_5_BASE_ADDRESS ST_STM32_UART_40005000_BASE_ADDRESS -#define CONFIG_UART_STM32_UART_5_BAUD_RATE ST_STM32_UART_40005000_CURRENT_SPEED -#define CONFIG_UART_STM32_UART_5_IRQ_PRI ST_STM32_UART_40005000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_UART_5_NAME ST_STM32_UART_40005000_LABEL -#define UART_5_IRQ ST_STM32_UART_40005000_IRQ_0 - -#define CONFIG_UART_STM32_LPUART_1_BASE_ADDRESS ST_STM32_LPUART_40008000_BASE_ADDRESS -#define CONFIG_UART_STM32_LPUART_1_BAUD_RATE ST_STM32_LPUART_40008000_CURRENT_SPEED -#define CONFIG_UART_STM32_LPUART_1_IRQ_PRI ST_STM32_LPUART_40008000_IRQ_0_PRIORITY -#define CONFIG_UART_STM32_LPUART_1_NAME ST_STM32_LPUART_40008000_LABEL -#define LPUART_1_IRQ ST_STM32_LPUART_40008000_IRQ_0 - -#define CONFIG_I2C_1_BASE_ADDRESS ST_STM32_I2C_V2_40005400_BASE_ADDRESS -#define CONFIG_I2C_1_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_1_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_1_NAME ST_STM32_I2C_V2_40005400_LABEL -#define CONFIG_I2C_1_EVENT_IRQ ST_STM32_I2C_V2_40005400_IRQ_EVENT -#define CONFIG_I2C_1_ERROR_IRQ ST_STM32_I2C_V2_40005400_IRQ_ERROR -#define CONFIG_I2C_1_BITRATE ST_STM32_I2C_V2_40005400_CLOCK_FREQUENCY - -#define CONFIG_I2C_2_BASE_ADDRESS ST_STM32_I2C_V2_40005800_BASE_ADDRESS -#define CONFIG_I2C_2_EVENT_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_2_ERROR_IRQ_PRI ST_STM32_I2C_V2_40005800_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_2_NAME ST_STM32_I2C_V2_40005800_LABEL -#define CONFIG_I2C_2_EVENT_IRQ ST_STM32_I2C_V2_40005800_IRQ_EVENT -#define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V2_40005800_IRQ_ERROR -#define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V2_40005800_CLOCK_FREQUENCY - -#define CONFIG_I2C_4_BASE_ADDRESS ST_STM32_I2C_V2_40008400_BASE_ADDRESS -#define CONFIG_I2C_4_EVENT_IRQ_PRI ST_STM32_I2C_V2_40008400_IRQ_EVENT_PRIORITY -#define CONFIG_I2C_4_ERROR_IRQ_PRI ST_STM32_I2C_V2_40008400_IRQ_ERROR_PRIORITY -#define CONFIG_I2C_4_NAME ST_STM32_I2C_V2_40008400_LABEL -#define CONFIG_I2C_4_EVENT_IRQ ST_STM32_I2C_V2_40008400_IRQ_EVENT -#define CONFIG_I2C_4_ERROR_IRQ ST_STM32_I2C_V2_40008400_IRQ_ERROR -#define CONFIG_I2C_4_BITRATE ST_STM32_I2C_V2_40008400_CLOCK_FREQUENCY - #define CONFIG_RTC_0_BASE_ADDRESS ST_STM32_RTC_40002800_BASE_ADDRESS #define CONFIG_RTC_0_IRQ_PRI ST_STM32_RTC_40002800_IRQ_0_PRIORITY #define CONFIG_RTC_0_IRQ ST_STM32_RTC_40002800_IRQ_0 #define CONFIG_RTC_0_NAME ST_STM32_RTC_40002800_LABEL #define CONFIG_RTC_PRESCALER ST_STM32_RTC_40002800_PRESCALER -#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS -#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_FIFO_40013000_IRQ_0_PRIORITY -#define CONFIG_SPI_1_NAME ST_STM32_SPI_FIFO_40013000_LABEL -#define CONFIG_SPI_1_IRQ ST_STM32_SPI_FIFO_40013000_IRQ_0 - -#define CONFIG_SPI_2_BASE_ADDRESS ST_STM32_SPI_FIFO_40003800_BASE_ADDRESS -#define CONFIG_SPI_2_IRQ_PRI ST_STM32_SPI_FIFO_40003800_IRQ_0_PRIORITY -#define CONFIG_SPI_2_NAME ST_STM32_SPI_FIFO_40003800_LABEL -#define CONFIG_SPI_2_IRQ ST_STM32_SPI_FIFO_40003800_IRQ_0 - -#define CONFIG_SPI_3_BASE_ADDRESS ST_STM32_SPI_FIFO_40003C00_BASE_ADDRESS -#define CONFIG_SPI_3_IRQ_PRI ST_STM32_SPI_FIFO_40003C00_IRQ_0_PRIORITY -#define CONFIG_SPI_3_NAME ST_STM32_SPI_FIFO_40003C00_LABEL -#define CONFIG_SPI_3_IRQ ST_STM32_SPI_FIFO_40003C00_IRQ_0 - #define FLASH_DEV_BASE_ADDRESS ST_STM32L4_FLASH_CONTROLLER_40022000_BASE_ADDRESS #define FLASH_DEV_NAME ST_STM32L4_FLASH_CONTROLLER_40022000_LABEL @@ -102,51 +27,4 @@ #define CONFIG_USB_RAM_SIZE ST_STM32_OTGFS_50000000_RAM_SIZE #endif -#define CONFIG_PWM_STM32_1_DEV_NAME ST_STM32_PWM_40012C00_PWM_LABEL -#define CONFIG_PWM_STM32_1_PRESCALER ST_STM32_PWM_40012C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_2_DEV_NAME ST_STM32_PWM_40000000_PWM_LABEL -#define CONFIG_PWM_STM32_2_PRESCALER ST_STM32_PWM_40000000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_3_DEV_NAME ST_STM32_PWM_40000400_PWM_LABEL -#define CONFIG_PWM_STM32_3_PRESCALER ST_STM32_PWM_40000400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_4_DEV_NAME ST_STM32_PWM_40000800_PWM_LABEL -#define CONFIG_PWM_STM32_4_PRESCALER ST_STM32_PWM_40000800_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_5_DEV_NAME ST_STM32_PWM_40000C00_PWM_LABEL -#define CONFIG_PWM_STM32_5_PRESCALER ST_STM32_PWM_40000C00_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_6_DEV_NAME ST_STM32_PWM_40001000_PWM_LABEL -#define CONFIG_PWM_STM32_6_PRESCALER ST_STM32_PWM_40001000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_7_DEV_NAME ST_STM32_PWM_40001400_PWM_LABEL -#define CONFIG_PWM_STM32_7_PRESCALER ST_STM32_PWM_40001400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_8_DEV_NAME ST_STM32_PWM_40013400_PWM_LABEL -#define CONFIG_PWM_STM32_8_PRESCALER ST_STM32_PWM_40013400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_15_DEV_NAME ST_STM32_PWM_40014000_PWM_LABEL -#define CONFIG_PWM_STM32_15_PRESCALER ST_STM32_PWM_40014000_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_16_DEV_NAME ST_STM32_PWM_40014400_PWM_LABEL -#define CONFIG_PWM_STM32_16_PRESCALER ST_STM32_PWM_40014400_PWM_ST_PRESCALER - -#define CONFIG_PWM_STM32_17_DEV_NAME ST_STM32_PWM_40014800_PWM_LABEL -#define CONFIG_PWM_STM32_17_PRESCALER ST_STM32_PWM_40014800_PWM_ST_PRESCALER - -#define CONFIG_CAN_1_BASE_ADDRESS ST_STM32_CAN_40006400_BASE_ADDRESS -#define CONFIG_CAN_1_BUS_SPEED ST_STM32_CAN_40006400_BUS_SPEED -#define CONFIG_CAN_1_NAME ST_STM32_CAN_40006400_LABEL -#define CONFIG_CAN_1_IRQ_TX ST_STM32_CAN_40006400_IRQ_TX -#define CONFIG_CAN_1_IRQ_RX0 ST_STM32_CAN_40006400_IRQ_RX0 -#define CONFIG_CAN_1_IRQ_RX1 ST_STM32_CAN_40006400_IRQ_RX1 -#define CONFIG_CAN_1_IRQ_SCE ST_STM32_CAN_40006400_IRQ_SCE -#define CONFIG_CAN_1_IRQ_PRIORITY ST_STM32_CAN_40006400_IRQ_0_PRIORITY -#define CONFIG_CAN_1_SJW ST_STM32_CAN_40006400_SJW -#define CONFIG_CAN_1_PROP_SEG_PHASE_SEG1 ST_STM32_CAN_40006400_PROP_SEG_PHASE_SEG1 -#define CONFIG_CAN_1_PHASE_SEG2 ST_STM32_CAN_40006400_PHASE_SEG2 -#define CONFIG_CAN_1_CLOCK_BUS ST_STM32_CAN_40006400_CLOCK_BUS -#define CONFIG_CAN_1_CLOCK_BITS ST_STM32_CAN_40006400_CLOCK_BITS - /* End of SoC Level DTS fixup file */ diff --git a/boards/arm/nucleo_f030r8/CMakeLists.txt b/boards/arm/nucleo_f030r8/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/nucleo_f030r8/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/nucleo_f030r8/nucleo_f030r8.dts b/boards/arm/nucleo_f030r8/nucleo_f030r8.dts index 11716c7584bb73..b21cafb4807c20 100644 --- a/boards/arm/nucleo_f030r8/nucleo_f030r8.dts +++ b/boards/arm/nucleo_f030r8/nucleo_f030r8.dts @@ -20,7 +20,7 @@ leds { compatible = "gpio-leds"; green_led_2: led@0 { - gpios = <&gpioa 5 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioa GPIO_PORT_PIN5 GPIO_INT_ACTIVE_HIGH>; label = "User LD2"; }; }; @@ -29,7 +29,7 @@ compatible = "gpio-keys"; user_button: button@0 { label = "User"; - gpios = <&gpioc 13 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioc GPIO_PORT_PIN13 GPIO_INT_ACTIVE_LOW>; }; }; @@ -54,19 +54,27 @@ }; &i2c1 { + pinctrl-0 = <&i2c1_pins_a>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &i2c2 { + pinctrl-0 = <&i2c2_pins_a>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &spi1 { - status = "ok"; + pinctrl-0 = <&spi1_master_a>; + pinctrl-names = "default"; + status = "ok"; }; &spi2 { - status = "ok"; + pinctrl-0 = <&spi2_slave_a>; + pinctrl-names = "default"; + status = "ok"; }; diff --git a/boards/arm/nucleo_f030r8/nucleo_f030r8_defconfig b/boards/arm/nucleo_f030r8/nucleo_f030r8_defconfig index e47302bc4ee425..74a831fb183f0c 100644 --- a/boards/arm/nucleo_f030r8/nucleo_f030r8_defconfig +++ b/boards/arm/nucleo_f030r8/nucleo_f030r8_defconfig @@ -12,8 +12,8 @@ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 # Kernel Options due to Low Memory (8k) CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 +CONFIG_IDLE_STACK_SIZE=128 +CONFIG_ISR_STACK_SIZE=312 # Prevent Interrupt Vector Table in RAM CONFIG_IS_BOOTLOADER=y CONFIG_BOOTLOADER_SRAM_SIZE=8 @@ -25,8 +25,9 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl driver +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RUNTIME_DTS=n # GPIO Controller CONFIG_GPIO=y diff --git a/boards/arm/nucleo_f030r8/pinmux.c b/boards/arm/nucleo_f030r8/pinmux.c deleted file mode 100644 index 4ccf17a0d208d5..00000000000000 --- a/boards/arm/nucleo_f030r8/pinmux.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017 RnDity Sp. z o.o. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "pinmux/pinmux.h" - -#include "pinmux/stm32/pinmux_stm32.h" - -/* pin assignments for NUCLEO-F030R8 board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_1 - {STM32_PIN_PA9, STM32F0_PINMUX_FUNC_PA9_USART1_TX}, - {STM32_PIN_PA10, STM32F0_PINMUX_FUNC_PA10_USART1_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_UART_STM32_PORT_2 - {STM32_PIN_PA2, STM32F0_PINMUX_FUNC_PA2_USART2_TX}, - {STM32_PIN_PA3, STM32F0_PINMUX_FUNC_PA3_USART2_RX}, -#endif /* CONFIG_UART_STM32_PORT_2 */ -#ifdef CONFIG_I2C_1 - {STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_I2C1_SCL}, - {STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_I2C1_SDA}, -#endif /* CONFIG_I2C_1 */ -#ifdef CONFIG_I2C_2 - {STM32_PIN_PA11, STM32F0_PINMUX_FUNC_PA11_I2C2_SCL}, - {STM32_PIN_PA12, STM32F0_PINMUX_FUNC_PA12_I2C2_SDA}, -#endif /* CONFIG_I2C_2 */ -#ifdef CONFIG_SPI_1 - {STM32_PIN_PA4, STM32F0_PINMUX_FUNC_PA4_SPI1_NSS}, - {STM32_PIN_PA5, STM32F0_PINMUX_FUNC_PA5_SPI1_SCK}, - {STM32_PIN_PA6, STM32F0_PINMUX_FUNC_PA6_SPI1_MISO}, - {STM32_PIN_PA7, STM32F0_PINMUX_FUNC_PA7_SPI1_MOSI}, -#endif /* CONFIG_SPI_1 */ -#ifdef CONFIG_SPI_2 - {STM32_PIN_PB12, STM32F0_PINMUX_FUNC_PB12_SPI2_NSS}, - {STM32_PIN_PB13, STM32F0_PINMUX_FUNC_PB13_SPI2_SCK}, - {STM32_PIN_PB14, STM32F0_PINMUX_FUNC_PB14_SPI2_MISO}, - {STM32_PIN_PB15, STM32F0_PINMUX_FUNC_PB15_SPI2_MOSI}, -#endif /* CONFIG_SPI_2 */ -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/nucleo_f070rb/CMakeLists.txt b/boards/arm/nucleo_f070rb/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/nucleo_f070rb/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/nucleo_f070rb/nucleo_f070rb.dts b/boards/arm/nucleo_f070rb/nucleo_f070rb.dts index a732b43d5ca5c8..90977a535bbbd7 100644 --- a/boards/arm/nucleo_f070rb/nucleo_f070rb.dts +++ b/boards/arm/nucleo_f070rb/nucleo_f070rb.dts @@ -20,7 +20,7 @@ leds { compatible = "gpio-leds"; green_led_2: led@0 { - gpios = <&gpioa 5 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioa GPIO_PORT_PIN5 GPIO_INT_ACTIVE_HIGH>; label = "User LD2"; }; }; @@ -29,7 +29,7 @@ compatible = "gpio-keys"; user_button: button@0 { label = "User"; - gpios = <&gpioc 13 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioc GPIO_PORT_PIN13 GPIO_INT_ACTIVE_LOW>; }; }; @@ -64,5 +64,7 @@ }; &spi1 { + pinctrl-0 = <&spi1_master_a>; + pinctrl-names = "default"; status = "ok"; }; diff --git a/boards/arm/nucleo_f070rb/nucleo_f070rb_defconfig b/boards/arm/nucleo_f070rb/nucleo_f070rb_defconfig index ff26cc33913a41..d133755ea939bf 100644 --- a/boards/arm/nucleo_f070rb/nucleo_f070rb_defconfig +++ b/boards/arm/nucleo_f070rb/nucleo_f070rb_defconfig @@ -17,8 +17,8 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl Driver +CONFIG_PINCTRL=y # GPIO Controller CONFIG_GPIO=y diff --git a/boards/arm/nucleo_f070rb/pinmux.c b/boards/arm/nucleo_f070rb/pinmux.c deleted file mode 100644 index 533223917f160b..00000000000000 --- a/boards/arm/nucleo_f070rb/pinmux.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2018 qianfan Zhao - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "pinmux/pinmux.h" - -#include - -/* pin assignments for NUCLEO_F070RB board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_1 - {STM32_PIN_PA9, STM32F0_PINMUX_FUNC_PA9_USART1_TX}, - {STM32_PIN_PA10, STM32F0_PINMUX_FUNC_PA10_USART1_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_UART_STM32_PORT_2 - {STM32_PIN_PA2, STM32F0_PINMUX_FUNC_PA2_USART2_TX}, - {STM32_PIN_PA3, STM32F0_PINMUX_FUNC_PA3_USART2_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_I2C_1 - {STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_I2C1_SCL}, - {STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_I2C1_SDA}, -#endif /* CONFIG_I2C_1 */ -#ifdef CONFIG_I2C_2 - {STM32_PIN_PB10, STM32F0_PINMUX_FUNC_PB10_I2C2_SCL}, - {STM32_PIN_PB11, STM32F0_PINMUX_FUNC_PB11_I2C2_SDA}, -#endif /* CONFIG_I2C_2 */ -#ifdef CONFIG_SPI_1 - {STM32_PIN_PA5, STM32F0_PINMUX_FUNC_PA5_SPI1_SCK}, - {STM32_PIN_PA6, STM32F0_PINMUX_FUNC_PA6_SPI1_MISO}, - {STM32_PIN_PA7, STM32F0_PINMUX_FUNC_PA7_SPI1_MOSI}, -#endif /* CONFIG_SPI_1 */ -#ifdef CONFIG_SPI_2 - {STM32_PIN_PB13, STM32F0_PINMUX_FUNC_PB13_SPI2_SCK}, - {STM32_PIN_PB14, STM32F0_PINMUX_FUNC_PB14_SPI2_MISO}, - {STM32_PIN_PB15, STM32F0_PINMUX_FUNC_PB15_SPI2_MOSI}, -#endif /* CONFIG_SPI_2 */ -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/nucleo_f091rc/CMakeLists.txt b/boards/arm/nucleo_f091rc/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/nucleo_f091rc/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/nucleo_f091rc/Kconfig.defconfig b/boards/arm/nucleo_f091rc/Kconfig.defconfig index e1ba278a372298..ee5d5e18240396 100644 --- a/boards/arm/nucleo_f091rc/Kconfig.defconfig +++ b/boards/arm/nucleo_f091rc/Kconfig.defconfig @@ -1,6 +1,6 @@ # Kconfig - STM32 Nucleo-64 development board with STM32F091RC MCU # -# Copyright (c) 2017 Bobby Noelte +# Copyright (c) 2018 Bobby Noelte # # SPDX-License-Identifier: Apache-2.0 # @@ -29,12 +29,6 @@ endif # I2C if SPI -config SPI_1 - default y - -config SPI_2 - default y - config SPI_STM32_INTERRUPT default y diff --git a/boards/arm/nucleo_f091rc/doc/nucleof091rc.rst b/boards/arm/nucleo_f091rc/doc/nucleof091rc.rst index 52e00790f1534f..91571d3e9b2153 100644 --- a/boards/arm/nucleo_f091rc/doc/nucleof091rc.rst +++ b/boards/arm/nucleo_f091rc/doc/nucleof091rc.rst @@ -82,6 +82,8 @@ The Zephyr nucleo_f091rc board configuration supports the following hardware fea | UART | on-chip | serial port-polling; | | | | serial port-interrupt | +-----------+------------+-------------------------------------+ +| PINCTRL | on-chip | pinctrl (includes pinmux) | ++-----------+------------+-------------------------------------+ | PINMUX | on-chip | pinmux | +-----------+------------+-------------------------------------+ | GPIO | on-chip | gpio | @@ -96,6 +98,8 @@ The Zephyr nucleo_f091rc board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | SPI | on-chip | SPI controller | +-----------+------------+-------------------------------------+ +| CAN | on-chip | CAN controller | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. @@ -110,6 +114,13 @@ input (with or without pull-up or pull-down), or as peripheral alternate functio GPIO pins are shared with digital or analog alternate functions. All GPIOs are high current capable except for analog inputs. +LED +--- + +- LD1 / USB communication LED = ST-LINK/V2-1 +- LD2 / User LED = PA5 +- LD3 / Power LED = VCC + Board connectors: ----------------- .. image:: img/nucleo_f091rc_connectors.png @@ -121,20 +132,43 @@ Board connectors: Default Zephyr Peripheral Mapping: ---------------------------------- -- UART_1_TX : PB6 -- UART_1_RX : PB7 -- UART_2_TX : PA2 -- UART_2_RX : PA3 -- I2C1_SCL : PB8 -- I2C1_SDA : PB9 -- I2C2_SCL : PA11 -- I2C2_SDA : PA12 -- SPI1_SCK : PB3 -- SPI1_MISO : PB4 -- SPI1_MOSI : PB5 -- SPI2_SCK : PB13 -- SPI2_MISO : PB14 -- SPI2_MOSI : PB15 ++-----------+--------+------+------+ +| Signal | GPIO | CN7 | CN10 | ++===========+========+======+======+ +| LD2 | PA5 | | 11 | ++-----------+--------+------+------+ +| UART_1_TX | PB6 | | | ++-----------+--------+------+------+ +| UART_1_RX | PB7 | 21 | | ++-----------+--------+------+------+ +| UART_2_TX | PA2 | | 35 | ++-----------+--------+------+------+ +| UART_2_RX | PA3 | | 37 | ++-----------+--------+------+------+ +| I2C1_SCL | PF1 | 31 | | ++-----------+--------+------+------+ +| I2C1_SDA | PF0 | 29 | | ++-----------+--------+------+------+ +| I2C2_SCL | PA11 | | 14 | ++-----------+--------+------+------+ +| I2C2_SDA | PA12 | | 12 | ++-----------+--------+------+------+ +| SPI1_SCK | PB3 | | 31 | ++-----------+--------+------+------+ +| SPI1_MISO | PB4 | | 27 | ++-----------+--------+------+------+ +| SPI1_MOSI | PB5 | | 29 | ++-----------+--------+------+------+ +| SPI2_SCK | PB13 | | 30 | ++-----------+--------+------+------+ +| SPI2_MISO | PB14 | | 28 | ++-----------+--------+------+------+ +| SPI2_MOSI | PB15 | | 26 | ++-----------+--------+------+------+ +| CAN_TX | PB9 | | 5 | ++-----------+--------+------+------+ +| CAN_RX | PB8 | | 3 | ++-----------+--------+------+------+ For mode details please refer to `STM32 Nucleo-64 board User Manual`_. @@ -154,27 +188,102 @@ This interface is supported by the openocd version included in the Zephyr SDK. Flashing an application to Nucleo F091RC ---------------------------------------- -Here is an example for the :ref:`blinky-sample` application. +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the Nucleo F091RC board +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. .. zephyr-app-commands:: - :zephyr-app: samples/basic/blinky + :zephyr-app: samples/hello_world :board: nucleo_f091rc :goals: build flash -You will see the LED blinking every second. - Debugging ========= -You can debug an application in the usual way. Here is an example for the -:ref:`hello_world` application. +You can debug an application in the usual way. Here is an example for the +:ref:`button-sample` application. .. zephyr-app-commands:: - :zephyr-app: samples/hello_world + :zephyr-app: samples/basic/button :board: nucleo_f091rc :maybe-skip-config: :goals: debug +Testing the Nucleo board +************************ + +Testing the button and the LED +============================== + +There are 2 samples that allow you to test that the button and LED on +the board are working properly with Zephyr: +:ref:`blinky-sample` and :ref:`button-sample`. + +The button and LED definitions can be found in :file:`boards/arm/nucleo_f091rc/board.h`. + +You can build and flash the examples to make sure Zephyr is running correctly on +your board. With the :ref:`blinky-sample` you will see the LED blinking every second. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_f091rc + :goals: build flash + +Testing GPIO +============ + +To test the GPIO with loopback to itself a test harness must be set up +(a jumper connecting CN10 pin 27 to CN10 pin 29). + ++--------+--------+---------+----------+ +| Signal | GPIO | Connection on CN10 | ++========+========+=========+==========+ +| IN | PB4 | 27 | | ++--------+--------+---------+ jumper + +| OUT | PB5 | 29 | | ++--------+--------+---------+----------+ + +Start your favorite terminal program to listen for output. +Then build and flash the test application. + +.. zephyr-app-commands:: + :zephyr-app: tests/drivers/gpio/gpio_basic_api + :board: nucleo_f091rc + :goals: build flash + +Testing SPI +=========== + +To test the SPI with loopback to itself a test harness must be set up +(a jumper connecting CN10 pin 27 to CN10 pin 29). + ++--------+--------+---------+----------+ +| Signal | Master | Connection on CN10 | ++========+========+=========+==========+ +| SCK | PB3 | 31 | open | ++--------+--------+---------+----------+ +| MISO | PB4 | 27 | | ++--------+--------+---------+ jumper + +| MOSI | PB5 | 29 | | ++--------+--------+---------+----------+ + +Start your favorite terminal program to listen for output. +Then build and flash the test application. + +.. zephyr-app-commands:: + :zephyr-app: tests/drivers/spi/spi_loopback + :board: nucleo_f091rc + :goals: build flash + References ********** diff --git a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts index 9f7eacd7db0098..f794ccb8ca1e9d 100644 --- a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts +++ b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts @@ -20,7 +20,7 @@ leds { compatible = "gpio-leds"; green_led_2: led@0 { - gpios = <&gpioa 5 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioa GPIO_PORT_PIN5 GPIO_INT_ACTIVE_HIGH>; label = "User LD2"; }; }; @@ -29,7 +29,7 @@ compatible = "gpio-keys"; user_button: button@0 { label = "User"; - gpios = <&gpioc 13 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioc GPIO_PORT_PIN13 GPIO_INT_ACTIVE_LOW>; }; }; @@ -39,10 +39,27 @@ }; }; +&pinctrl { + status = "ok"; +}; + +&gpioa { + status = "ok"; +}; + +&gpiob { + status = "ok"; +}; + +&gpioc { + status = "ok"; +}; + &usart1 { current-speed = <115200>; pinctrl-0 = <&usart1_pins_a>; pinctrl-names = "default"; + status = "ok"; }; &usart2 { @@ -53,19 +70,34 @@ }; &i2c1 { + pinctrl-0 = <&i2c1_pins_b>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &i2c2 { + pinctrl-0 = <&i2c2_pins_a>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &spi1 { + pinctrl-0 = <&spi1_master_a>; + pinctrl-names = "default"; status = "ok"; }; &spi2 { + pinctrl-0 = <&spi2_slave_a>; + pinctrl-names = "default"; + status = "ok"; +}; + +&can1 { + pinctrl-0 = <&can_pins_b>; + pinctrl-names = "default"; + bus-speed = <250000>; status = "ok"; }; diff --git a/boards/arm/nucleo_f091rc/nucleo_f091rc_defconfig b/boards/arm/nucleo_f091rc/nucleo_f091rc_defconfig index 3012df76dacdfe..a7e6f0355cb0d2 100644 --- a/boards/arm/nucleo_f091rc/nucleo_f091rc_defconfig +++ b/boards/arm/nucleo_f091rc/nucleo_f091rc_defconfig @@ -17,12 +17,25 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl driver +CONFIG_PINCTRL=y # GPIO Controller CONFIG_GPIO=y +# SPI Controller +CONFIG_SPI=y +CONFIG_SPI_1=y +# Enable multiple wait on events in async SPI context +CONFIG_POLL=y + +# CAN controller +CONFIG_CAN=y +CONFIG_CAN_INIT_PRIORITY=80 +CONFIG_CAN_1=y +CONFIG_CAN_STM32=y +CONFIG_CAN_MAX_FILTER=5 + # Clock configuration CONFIG_CLOCK_CONTROL=y # SYSCLK selection diff --git a/boards/arm/nucleo_f091rc/pinmux.c b/boards/arm/nucleo_f091rc/pinmux.c deleted file mode 100644 index 20e8e203c896d7..00000000000000 --- a/boards/arm/nucleo_f091rc/pinmux.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017 RnDity Sp. z o.o. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include - -/* pin assignments for NUCLEO-F091RC board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_1 - {STM32_PIN_PB6, STM32F0_PINMUX_FUNC_PB6_USART1_TX}, - {STM32_PIN_PB7, STM32F0_PINMUX_FUNC_PB7_USART1_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_UART_STM32_PORT_2 - {STM32_PIN_PA2, STM32F0_PINMUX_FUNC_PA2_USART2_TX}, - {STM32_PIN_PA3, STM32F0_PINMUX_FUNC_PA3_USART2_RX}, -#endif /* CONFIG_UART_STM32_PORT_2 */ -#ifdef CONFIG_I2C_1 - {STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_I2C1_SCL}, - {STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_I2C1_SDA}, -#endif /* CONFIG_I2C_1 */ -#ifdef CONFIG_I2C_2 - {STM32_PIN_PA11, STM32F0_PINMUX_FUNC_PA11_I2C2_SCL}, - {STM32_PIN_PA12, STM32F0_PINMUX_FUNC_PA12_I2C2_SDA}, -#endif /* CONFIG_I2C_2 */ -#ifdef CONFIG_SPI_1 - {STM32_PIN_PB3, STM32F0_PINMUX_FUNC_PB3_SPI1_SCK}, - {STM32_PIN_PB4, STM32F0_PINMUX_FUNC_PB4_SPI1_MISO}, - {STM32_PIN_PB5, STM32F0_PINMUX_FUNC_PB5_SPI1_MOSI}, -#endif /* CONFIG_SPI_1 */ -#ifdef CONFIG_SPI_2 - {STM32_PIN_PB13, STM32F0_PINMUX_FUNC_PB13_SPI2_SCK}, - {STM32_PIN_PB14, STM32F0_PINMUX_FUNC_PB14_SPI2_MISO}, - {STM32_PIN_PB15, STM32F0_PINMUX_FUNC_PB15_SPI2_MOSI}, -#endif /* CONFIG_SPI_2 */ -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/stm32f072_eval/CMakeLists.txt b/boards/arm/stm32f072_eval/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/stm32f072_eval/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/stm32f072_eval/pinmux.c b/boards/arm/stm32f072_eval/pinmux.c deleted file mode 100644 index d997949bf9b8e1..00000000000000 --- a/boards/arm/stm32f072_eval/pinmux.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017 BayLibre, SAS - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include "pinmux/stm32/pinmux_stm32.h" - -/* pin assignments for STM32F072-EVAL board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_2 - {STM32_PIN_PD5, STM32F0_PINMUX_FUNC_PD5_USART2_TX}, - {STM32_PIN_PD6, STM32F0_PINMUX_FUNC_PD6_USART2_RX}, -#endif /* CONFIG_UART_STM32_PORT_2 */ -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/stm32f072_eval/stm32f072_eval.dts b/boards/arm/stm32f072_eval/stm32f072_eval.dts index 773dd6840a497e..0a3fe450611569 100644 --- a/boards/arm/stm32f072_eval/stm32f072_eval.dts +++ b/boards/arm/stm32f072_eval/stm32f072_eval.dts @@ -21,19 +21,19 @@ leds { compatible = "gpio-leds"; green_led_1: led@0 { - gpios = <&gpiod 8 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpiod GPIO_PORT_PIN8 GPIO_INT_ACTIVE_HIGH>; label = "User LD1"; }; orange_led_2: led@1 { - gpios = <&gpiod 9 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpiod GPIO_PORT_PIN9 GPIO_INT_ACTIVE_HIGH>; label = "User LD2"; }; red_led_3: led@2 { - gpios = <&gpiod 10 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpiod GPIO_PORT_PIN10 GPIO_INT_ACTIVE_HIGH>; label = "User LD3"; }; blue_led_4: led@3 { - gpios = <&gpiod 11 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpiod GPIO_PORT_PIN11 GPIO_INT_ACTIVE_HIGH>; label = "User LD4"; }; }; @@ -42,27 +42,27 @@ compatible = "gpio-keys"; tamper: tamper@0 { label = "tamper button"; - gpios = <&gpioc 13 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioc GPIO_PORT_PIN13 GPIO_INT_ACTIVE_LOW>; }; joy_sel: joystick@1 { label = "joystick selection"; - gpios = <&gpioa 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioa GPIO_PORT_PIN0 GPIO_INT_ACTIVE_LOW>; }; joy_down: joystick@2 { label = "joystick down"; - gpios = <&gpiof 10 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpiof GPIO_PORT_PIN10 GPIO_INT_ACTIVE_LOW>; }; joy_up: joystick@3 { label = "joystick up"; - gpios = <&gpiof 9 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpiof GPIO_PORT_PIN9 GPIO_INT_ACTIVE_LOW>; }; joy_left: joystick@4 { label = "joystick left"; - gpios = <&gpiof 2 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpiof GPIO_PORT_PIN2 GPIO_INT_ACTIVE_LOW>; }; joy_right: joystick@5 { label = "joystick right"; - gpios = <&gpioe 3 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioe GPIO_PORT_PIN3 GPIO_INT_ACTIVE_LOW>; }; }; diff --git a/boards/arm/stm32f072_eval/stm32f072_eval_defconfig b/boards/arm/stm32f072_eval/stm32f072_eval_defconfig index ec4c88ba789384..f493bab790877d 100644 --- a/boards/arm/stm32f072_eval/stm32f072_eval_defconfig +++ b/boards/arm/stm32f072_eval/stm32f072_eval_defconfig @@ -18,8 +18,8 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl driver +CONFIG_PINCTRL=y # GPIO Controller CONFIG_GPIO=y diff --git a/boards/arm/stm32f072b_disco/CMakeLists.txt b/boards/arm/stm32f072b_disco/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/stm32f072b_disco/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/stm32f072b_disco/doc/stm32f072b_disco.rst b/boards/arm/stm32f072b_disco/doc/stm32f072b_disco.rst index 8ca6f511d97e74..a74510dd228d72 100644 --- a/boards/arm/stm32f072b_disco/doc/stm32f072b_disco.rst +++ b/boards/arm/stm32f072b_disco/doc/stm32f072b_disco.rst @@ -92,6 +92,8 @@ features: +-----------+------------+-------------------------------------+ | SPI | on-chip | SPI controller | +-----------+------------+-------------------------------------+ +| CAN | on-chip | CAN controller | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. @@ -112,13 +114,15 @@ Default Zephyr Peripheral Mapping: ---------------------------------- - UART_1_TX : PB6 - UART_1_RX : PB7 -- I2C1_SCL : PB8 -- I2C1_SDA : PB9 +- I2C1_SCL : PF1 +- I2C1_SDA : PF0 - I2C2_SCL : PB10 - I2C2_SDA : PB11 - SPI1_SCK : PB3 - SPI1_MISO : PB4 - SPI1_MOSI : PB5 +- CAN_TX : PB9 +- CAN_RX : PB8 - USER_PB : PA0 - LD3 : PC6 - LD4 : PC8 diff --git a/boards/arm/stm32f072b_disco/pinmux.c b/boards/arm/stm32f072b_disco/pinmux.c deleted file mode 100644 index 116287f201e4da..00000000000000 --- a/boards/arm/stm32f072b_disco/pinmux.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017 Clage GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "pinmux/pinmux.h" - -#include - -/* pin assignments for STM32F072B-DISCO board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_1 - {STM32_PIN_PB6, STM32F0_PINMUX_FUNC_PB6_USART1_TX}, - {STM32_PIN_PB7, STM32F0_PINMUX_FUNC_PB7_USART1_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_I2C_1 - {STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_I2C1_SCL}, - {STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_I2C1_SDA}, -#endif /* CONFIG_I2C_1 */ -#ifdef CONFIG_I2C_2 - {STM32_PIN_PB10, STM32F0_PINMUX_FUNC_PB10_I2C2_SCL}, - {STM32_PIN_PB11, STM32F0_PINMUX_FUNC_PB11_I2C2_SDA}, -#endif /* CONFIG_I2C_2 */ -#ifdef CONFIG_SPI_1 - {STM32_PIN_PB3, STM32F0_PINMUX_FUNC_PB3_SPI1_SCK}, - {STM32_PIN_PB4, STM32F0_PINMUX_FUNC_PB4_SPI1_MISO}, - {STM32_PIN_PB5, STM32F0_PINMUX_FUNC_PB5_SPI1_MOSI}, -#endif /* CONFIG_SPI_1 */ -#ifdef CONFIG_CAN_1 - {STM32_PIN_PB8, STM32F0_PINMUX_FUNC_PB8_CAN_RX}, - {STM32_PIN_PB9, STM32F0_PINMUX_FUNC_PB9_CAN_TX}, -#endif /* CONFIG_CAN_1 */ - -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/stm32f072b_disco/stm32f072b_disco.dts b/boards/arm/stm32f072b_disco/stm32f072b_disco.dts index 2d9aa3fb8e897b..342e2c1f6395b7 100644 --- a/boards/arm/stm32f072b_disco/stm32f072b_disco.dts +++ b/boards/arm/stm32f072b_disco/stm32f072b_disco.dts @@ -20,19 +20,19 @@ leds { compatible = "gpio-leds"; red_up_led_3: led@0 { - gpios = <&gpioc 6 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN6 GPIO_INT_ACTIVE_HIGH>; label = "User LD3"; }; yellow_left_4: led@1 { - gpios = <&gpioc 8 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN8 GPIO_INT_ACTIVE_HIGH>; label = "User LD4"; }; green_right_led_5: led@2 { - gpios = <&gpioc 9 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN9 GPIO_INT_ACTIVE_HIGH>; label = "User LD5"; }; blue_low_led_6: led@3 { - gpios = <&gpioc 7 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN7 GPIO_INT_ACTIVE_HIGH>; label = "User LD6"; }; }; @@ -41,7 +41,7 @@ compatible = "gpio-keys"; user_button: button@0 { label = "User"; - gpios = <&gpioa 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioa GPIO_PORT_PIN0 GPIO_INT_ACTIVE_LOW>; }; }; @@ -62,16 +62,22 @@ }; &i2c1 { + pinctrl-0 = <&i2c1_pins_b>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &i2c2 { + pinctrl-0 = <&i2c2_pins_b>; + pinctrl-names = "default"; status = "ok"; clock-frequency = ; }; &spi1 { + pinctrl-0 = <&spi1_master_a>; + pinctrl-names = "default"; status = "ok"; }; diff --git a/boards/arm/stm32f072b_disco/stm32f072b_disco_defconfig b/boards/arm/stm32f072b_disco/stm32f072b_disco_defconfig index 716ef57595f7ab..134fc6791851d2 100644 --- a/boards/arm/stm32f072b_disco/stm32f072b_disco_defconfig +++ b/boards/arm/stm32f072b_disco/stm32f072b_disco_defconfig @@ -17,8 +17,8 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl driver +CONFIG_PINCTRL=y # GPIO Controller CONFIG_GPIO=y diff --git a/boards/arm/stm32f0_disco/CMakeLists.txt b/boards/arm/stm32f0_disco/CMakeLists.txt deleted file mode 100644 index aa8826b2113790..00000000000000 --- a/boards/arm/stm32f0_disco/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -zephyr_library() -zephyr_library_sources(pinmux.c) -zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/boards/arm/stm32f0_disco/pinmux.c b/boards/arm/stm32f0_disco/pinmux.c deleted file mode 100644 index d9ff08374bcd52..00000000000000 --- a/boards/arm/stm32f0_disco/pinmux.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 Nathan Tsoi - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "pinmux/pinmux.h" - -#include "pinmux/stm32/pinmux_stm32.h" - -/* pin assignments for STM32F0DISCOVERY board */ -static const struct pin_config pinconf[] = { -#ifdef CONFIG_UART_STM32_PORT_1 - {STM32_PIN_PA9, STM32F0_PINMUX_FUNC_PA9_USART1_TX}, - {STM32_PIN_PA10, STM32F0_PINMUX_FUNC_PA10_USART1_RX}, -#endif /* CONFIG_UART_STM32_PORT_1 */ -#ifdef CONFIG_UART_STM32_PORT_2 - {STM32_PIN_PA2, STM32F0_PINMUX_FUNC_PA2_USART2_TX}, - {STM32_PIN_PA3, STM32F0_PINMUX_FUNC_PA3_USART2_RX}, -#endif /* CONFIG_UART_STM32_PORT_2 */ -}; - -static int pinmux_stm32_init(struct device *port) -{ - ARG_UNUSED(port); - - stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf)); - - return 0; -} - -SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, - CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY); diff --git a/boards/arm/stm32f0_disco/stm32f0_disco.dts b/boards/arm/stm32f0_disco/stm32f0_disco.dts index 466fb5f7f8b701..36edc0dcb60a80 100644 --- a/boards/arm/stm32f0_disco/stm32f0_disco.dts +++ b/boards/arm/stm32f0_disco/stm32f0_disco.dts @@ -20,11 +20,11 @@ leds { compatible = "gpio-leds"; green_led_3: led@0 { - gpios = <&gpioc 9 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN9 GPIO_INT_ACTIVE_HIGH>; label = "User LD3"; }; blue_led_4: led@1 { - gpios = <&gpioc 8 GPIO_INT_ACTIVE_HIGH>; + gpios = <&gpioc GPIO_PORT_PIN8 GPIO_INT_ACTIVE_HIGH>; label = "User LD4"; }; }; @@ -33,7 +33,7 @@ compatible = "gpio-keys"; user_button: button@0 { label = "Key"; - gpios = <&gpioa 0 GPIO_INT_ACTIVE_LOW>; + gpios = <&gpioa GPIO_PORT_PIN0 GPIO_INT_ACTIVE_LOW>; }; }; diff --git a/boards/arm/stm32f0_disco/stm32f0_disco_defconfig b/boards/arm/stm32f0_disco/stm32f0_disco_defconfig index 25dd94a107bdf2..f3fa3c7c03c470 100644 --- a/boards/arm/stm32f0_disco/stm32f0_disco_defconfig +++ b/boards/arm/stm32f0_disco/stm32f0_disco_defconfig @@ -12,8 +12,8 @@ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 # Kernel Options due to Low Memory (8k) CONFIG_MAIN_STACK_SIZE=640 -CONFIG_IDLE_STACK_SIZE=200 -CONFIG_ISR_STACK_SIZE=512 +CONFIG_IDLE_STACK_SIZE=128 +CONFIG_ISR_STACK_SIZE=312 # Prevent Interrupt Vector Table in RAM CONFIG_IS_BOOTLOADER=y CONFIG_BOOTLOADER_SRAM_SIZE=8 @@ -25,8 +25,8 @@ CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Pinmux Driver -CONFIG_PINMUX=y +# Pinctrl Driver +CONFIG_PINCTRL=y # GPIO Controller CONFIG_GPIO=y diff --git a/cmake/dts.cmake b/cmake/dts.cmake index 8a1a54aecd82d7..05f8f7d80f90e8 100644 --- a/cmake/dts.cmake +++ b/cmake/dts.cmake @@ -10,6 +10,7 @@ # See ~/zephyr/doc/dts set(GENERATED_DTS_BOARD_H ${PROJECT_BINARY_DIR}/include/generated/generated_dts_board.h) set(GENERATED_DTS_BOARD_CONF ${PROJECT_BINARY_DIR}/include/generated/generated_dts_board.conf) +set(GENERATED_DTS_BOARD_EDTS ${PROJECT_BINARY_DIR}/include/generated/generated_dts_board.json) set_ifndef(DTS_SOURCE ${BOARD_ROOT}/boards/${ARCH}/${BOARD_FAMILY}/${BOARD}.dts) set_ifndef(DTS_COMMON_OVERLAYS ${ZEPHYR_BASE}/dts/common/common.dts) @@ -108,6 +109,7 @@ if(CONFIG_HAS_DTS) ${DTS_FIXUPS} --keyvalue ${GENERATED_DTS_BOARD_CONF} --include ${GENERATED_DTS_BOARD_H} + --edts ${GENERATED_DTS_BOARD_EDTS} ) # Run extract_dts_includes.py to create a .conf and a header file that can be diff --git a/cmake/extensions.cmake b/cmake/extensions.cmake index 9a9979e70ac62d..ee27b287927cc2 100644 --- a/cmake/extensions.cmake +++ b/cmake/extensions.cmake @@ -344,6 +344,17 @@ function(generate_inc_file_for_gen_target add_dependencies(${target} ${gen_target}) endfunction() +function(get_unique_generated_target_name + generated_file # The generated file + generated_target_name # the unique name + ) + string(RANDOM LENGTH 8 random_chars) + get_filename_component(basename ${generated_file} NAME) + string(REPLACE "." "_" basename ${basename}) + string(REPLACE "@" "_" basename ${basename}) + set(generated_target_name "gen_${basename}_${random_chars}" PARENT_SCOPE) +endfunction() + function(generate_inc_file_for_target target # The cmake target that depends on the generated file source_file # The source file to be converted to hex @@ -353,22 +364,131 @@ function(generate_inc_file_for_target # Ensure 'generated_file' is generated before 'target' by creating a # 'custom_target' for it and setting up a dependency between the two # targets + get_unique_generated_target_name(${generated_file} generated_target_name) + add_custom_target(${generated_target_name} DEPENDS ${generated_file}) + generate_inc_file_for_gen_target(${target} ${source_file} ${generated_file} + ${generated_target_name} ${ARGN}) +endfunction() - # But first create a unique name for the custom target - string( - RANDOM - LENGTH 8 - random_chars +function(target_sources_codegen + target # The cmake target that depends on the generated file ) + set(options) + set(oneValueArgs) + set(multiValueArgs CODEGEN_DEFINES DEPENDS) + cmake_parse_arguments(CODEGEN "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN}) + # prepend -D to all defines + string(REGEX REPLACE "([^;]+)" "-D;\\1" + CODEGEN_CODEGEN_DEFINES "${CODEGEN_CODEGEN_DEFINES}") + # Get all the files that make up codegen for dependency + file(GLOB CODEGEN_SOURCES + ${ZEPHYR_BASE}/scripts/dts/edtsdatabase.py + ${ZEPHYR_BASE}/scripts/codegen/modules/*.py + ${ZEPHYR_BASE}/scripts/codegen/templates/drivers/*.py + ${ZEPHYR_BASE}/scripts/codegen/*.py + ${ZEPHYR_BASE}/scripts/gen_code.py) + + message(STATUS "Will generate for target ${target}") + # Generated file must be generated to the current binary directory. + # Otherwise this would trigger CMake issue #14633: + # https://gitlab.kitware.com/cmake/cmake/issues/14633 + foreach(arg ${CODEGEN_UNPARSED_ARGUMENTS}) + if(IS_ABSOLUTE ${arg}) + set(template_file ${arg}) + get_filename_component(generated_file_name ${arg} NAME) + set(generated_file ${CMAKE_CURRENT_BINARY_DIR}/${generated_file_name}) + else() + set(template_file ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) + set(generated_file ${CMAKE_CURRENT_BINARY_DIR}/${arg}) + endif() + get_filename_component(template_dir ${template_file} DIRECTORY) - get_filename_component(basename ${generated_file} NAME) - string(REPLACE "." "_" basename ${basename}) - string(REPLACE "@" "_" basename ${basename}) + if(IS_DIRECTORY ${template_file}) + message(FATAL_ERROR "target_sources_codegen() was called on a directory") + endif() - set(generated_target_name "gen_${basename}_${random_chars}") + # Generate file from template + message(STATUS " from ${template_file}") + message(STATUS " to ${generated_file}") + add_custom_command( + COMMENT "CodeGen ${generated_file}" + OUTPUT ${generated_file} + DEPENDS + ${template_file} + ${CODEGEN_DEPENDS} + ${CODEGEN_SOURCES} + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/gen_code.py + ${CODEGEN_CODEGEN_DEFINES} + -D "PROJECT_NAME=${PROJECT_NAME}" + -D "PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" + -D "PROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}" + -D "CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}" + -D "CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}" + -D "CMAKE_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}" + -D "CMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}" + -D "CMAKE_CURRENT_LIST_DIR=${CMAKE_CURRENT_LIST_DIR}" + -D "CMAKE_FILES_DIRECTORY=${CMAKE_FILES_DIRECTORY}" + -D "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" + -D "CMAKE_SYSTEM=${CMAKE_SYSTEM}" + -D "CMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}" + -D "CMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}" + -D "CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}" + -D "CMAKE_C_COMPILER=${CMAKE_C_COMPILER}" + -D "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + -D "CMAKE_COMPILER_IS_GNUCC=${CMAKE_COMPILER_IS_GNUCC}" + -D "CMAKE_COMPILER_IS_GNUCXX=${CMAKE_COMPILER_IS_GNUCXX}" + -D "GENERATED_DTS_BOARD_H=${GENERATED_DTS_BOARD_H}" + -D "GENERATED_DTS_BOARD_CONF=${GENERATED_DTS_BOARD_CONF}" + -D "GENERATED_DTS_BOARD_EDTS=${GENERATED_DTS_BOARD_EDTS}" + --input "${template_file}" + --output "${generated_file}" + --log "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CodeGen.log" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + if("${target}" STREQUAL "zephyr") + # zephyr is special + get_unique_generated_target_name(${generated_file} generated_target_name) + add_custom_target(${generated_target_name} DEPENDS ${generated_file}) + add_dependencies(zephyr ${generated_target_name}) + # Remember all the files that are generated for zephyr. + # target_sources(zephyr PRIVATE ${zephyr_generated_sources}) + # is executed in the top level CMakeFile.txt context. + get_property(zephyr_generated_sources GLOBAL PROPERTY zephyr_generated_sources_property) + list(APPEND zephyr_generated_sources ${generated_file}) + set_property(GLOBAL PROPERTY zephyr_generated_sources_property "${zephyr_generated_sources}") + # Add template directory to include path to allow includes with + # relative path in generated file to work + zephyr_include_directories(${template_dir}) + else() + target_sources(${target} PRIVATE ${generated_file}) + # Add template directory to include path to allow includes with + # relative path in generated file to work + target_include_directories(${target} PRIVATE ${template_dir}) + endif() + endforeach() +endfunction() - add_custom_target(${generated_target_name} DEPENDS ${generated_file}) - generate_inc_file_for_gen_target(${target} ${source_file} ${generated_file} ${generated_target_name} ${ARGN}) +function(zephyr_sources_codegen) + target_sources_codegen(zephyr ${ARGN}) +endfunction() + +function(zephyr_sources_codegen_ifdef feature_toggle) + if(${${feature_toggle}}) + zephyr_sources_codegen(${ARGN}) + endif() +endfunction() + +function(zephyr_library_sources_codegen) + target_sources_codegen(${ZEPHYR_CURRENT_LIBRARY} ${ARGN}) +endfunction() + +function(zephyr_library_sources_codegen_ifdef feature_toggle) + if(${${feature_toggle}}) + zephyr_library_sources_codegen(${ARGN}) + endif() endfunction() # 1.2 zephyr_library_* @@ -424,6 +544,13 @@ macro(zephyr_library_named name) # This is a macro because we need add_library() to be executed # within the scope of the caller. set(ZEPHYR_CURRENT_LIBRARY ${name}) + + if("${name}" STREQUAL "zephyr") + # We have to mark all the generated files "GENERATED" in this context + get_property(zephyr_generated_files GLOBAL PROPERTY zephyr_generated_files_property) + set_source_files_properties(${zephyr_generated_files} PROPERTIES GENERATED 1) + endif() + add_library(${name} STATIC "") zephyr_append_cmake_library(${name}) diff --git a/doc/api/io_interfaces.rst b/doc/api/io_interfaces.rst index bd61d72ce3534b..5af8cc21ae3c4a 100644 --- a/doc/api/io_interfaces.rst +++ b/doc/api/io_interfaces.rst @@ -27,6 +27,9 @@ DMA Interface GPIO Interface ************** +.. doxygengroup:: gpio_interface_pin_defs + :project: Zephyr + .. doxygengroup:: gpio_interface :project: Zephyr @@ -58,6 +61,18 @@ PWM Interface .. doxygengroup:: pwm_interface :project: Zephyr +Pinctrl Interface +***************** + +.. doxygengroup:: pinctrl_interface_pin_configurations + :project: Zephyr + +.. doxygengroup:: pinctrl_interface_functions + :project: Zephyr + +.. doxygengroup:: pinctrl_interface + :project: Zephyr + Pinmux Interface **************** diff --git a/doc/contribute/contribute_guidelines.rst b/doc/contribute/contribute_guidelines.rst index 364ecb35ac3127..3e772c8fd35350 100644 --- a/doc/contribute/contribute_guidelines.rst +++ b/doc/contribute/contribute_guidelines.rst @@ -331,8 +331,11 @@ On Linux systems, you can install uncrustify with For Windows installation instructions see the `sourceforge listing for uncrustify `_. +Best coding practises +********************* + Coding Style -************ +============ Use these coding guidelines to ensure that your development complies with the project's style and naming conventions. @@ -368,6 +371,25 @@ it to contain: set -e exec exec git diff --cached | ${ZEPHYR_BASE}/scripts/checkpatch.pl - +Keep the code simple +==================== + +Keep the code as simple as possible. + +Code-generation preprocessing tools provide a convenient way to +simplify some repetitive or parameterized coding tasks. While Zephyr +development allows use of such tools, we recommend keeping this +use to a minimum and when it provides an appropriate and simple +coding solution that follows these rules: + +* Use code generation - by preprocessor, :ref:`codegen`, or other - only for + problems that cannot be solved in the source language. +* Limit code generation to declarative data. Avoid generating control logic + whenever possible. +* Use the preprocessor for code generation as the primary tool. +* Use :ref:`codegen` only if the preprocessor can not provide a simple solution. +* Use CMake only if :ref:`codegen` can not be used. + .. _Contribution workflow: Contribution Workflow diff --git a/doc/devices/drivers/drivers.rst b/doc/devices/drivers/drivers.rst index b0c71c056bb1b9..eef11f448278ff 100644 --- a/doc/devices/drivers/drivers.rst +++ b/doc/devices/drivers/drivers.rst @@ -41,6 +41,23 @@ are listed below. Certain implementations of this device driver do not generate sequences of values that are truly random. +Non Standard Drivers +******************** + +These device drivers are not present on all supported board configurations. + +* **General purpose input output**: The :ref:`device_drivers_gpio` deals with: + + - input and output on ports and pins, + - interrupt generation on pins, + - configuration of ports and pins. + +* **Pin controller**: The :ref:`device_drivers_pinctrl` deals with: + + - enumerating and naming controllable pins, + - multiplexing of pins, + - configuration of pins, + Synchronous Calls ***************** @@ -330,3 +347,13 @@ returned on failure. See https://github.com/zephyrproject-rtos/zephyr/wiki/Naming-Conventions#return-codes for details about this. +Further reading +*************** + +More information on specific device drivers can be found in the following subsections: + +.. toctree:: + :maxdepth: 1 + + gpio/gpio.rst + pinctrl/pinctrl.rst diff --git a/doc/devices/drivers/gpio/gpio.rst b/doc/devices/drivers/gpio/gpio.rst new file mode 100644 index 00000000000000..0c372cb9fc4a85 --- /dev/null +++ b/doc/devices/drivers/gpio/gpio.rst @@ -0,0 +1,342 @@ +.. _device_drivers_gpio: + +GPIO (general purpose input output) device driver +################################################# + +The **general pupose input output** device driver deals with: + +- input and output on **ports** and **pins**, +- interrupt generation on **pins**, +- configuration of **ports** and **pins** + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +General purpose input output concepts +************************************* + +A **GPIO device driver** + provides access to a GPIO *port*. + +A GPIO **port** + is a group of *pins* arranged in a group and controllable as a group. + +A **pin** + is the physical input/ output line of a chip. The pin + numberspace is local [#pin_number_space]_ to a *port*. This + pin space may be sparse - i.e. there may be gaps in the space with numbers + where no pin exists. + +GPIO device driver +****************** + +The GPIO device driver provides applications and other drivers to: + +- read from a GPIO port or port pin, +- write to GPIO port or port pin, +- get signalled on GPIO port or port pin changes or interrupts. + +Application programming interface +================================= + +The GPIO device driver API is provided by :file:`include/gpio.h`. + +The definition of GPIO pins differs slightly in case a PINCTRL device is +activated by ``CONFIG_PINCTRL``. Here generic pin defines are provided +for GPIO port pins. The pin defines allow to combine them to define +a set of pins. + +If no PINCTRL device is activated the GPIO interface uses sequential +pin numbers that can not be combined to define a set of pins. This +legacy API is to be completely replaced by the PINCTRL variant when +all GPIO drivers have been migrated to use the pin controller device +for pin configuration. + +Control properties +================== + +Pins +---- + +The pins are defined in the generic GPIO include file +:file:`include/gpio_common.h` (eg. :c:macro:`GPIO_PORT_PIN0`). + +The maximum number of pins managed by a GPIO port device driver is 32. + +Pin Configuration +================= + +Pin configuration by the GPIO pin configuration interface is deprecated. +Please use the PINCTRL pin configuration interface instead. + +A generic set of GPIO port pin configuration properties is defined in +:file:`include/gpio.h`. +The GPIO pin configuration properties can be mapped to the generic pin +configuration properties of the PINCTRL device that controls the GPIO +port pins. A GPIO driver that is using the PINCTRL device to configure +the pins is just doing this. + +**GPIO_DIR_IN** + GPIO pin to be input. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_INPUT_ENABLE`, + - :c:macro:`PINCTRL_CONFIG_OUTPUT_DISABLE` + +**GPIO_DIR_OUT** + GPIO pin to be output. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_INPUT_ENABLE`, + - :c:macro:`PINCTRL_CONFIG_OUTPUT_ENABLE` + +**GPIO_POL_NORMAL** + GPIO pin polarity is normal. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_OUTPUT_HIGH` + +**GPIO_POL_INV** + GPIO pin polarity is inverted. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_OUTPUT_LOW` + +**GPIO_PUD_NORMAL** + GPIO pin to have no pull-up or pull-down. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_BIAS_DISABLE` + +**GPIO_PUD_PULL_UP** + Pull-up GPIO pin. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_BIAS_PULL_UP` + +**GPIO_PUD_PULL_DOWN** + Pull-down GPIO pin. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_BIAS_PULL_DOWN` + +**GPIO_DS_DFLT_LOW** + Default drive strength when GPIO pin output is low. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT` + +**GPIO_DS_DFLT_HIGH** + Default drive strength when GPIO pin output is high. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT` + +**GPIO_DS_ALT_LOW** + Alternative drive strength when GPIO pin output is low. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_7` + +**GPIO_DS_ALT_HIGH** + Alternative drive strength when GPIO pin output is high. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_7` + +**GPIO_DS_DISCONNECT_LOW** + Disconnect pin when GPIO pin output is low. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_OPEN_SOURCE` + +**GPIO_DS_DISCONNECT_HIGH** + Disconnect pin when GPIO pin output is high. + + PINCTRL pin configuration property: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_OPEN_DRAIN` + +Signalling Configuration +======================== + +Pin signalling can be configured by the general GPIO configuration interface. + +:c:func:`gpio_pin_configure` + Set the configuration of a pin. + +A generic set of GPIO port pin signalling properties is defined in +:file:`include/gpio.h`. A GPIO driver may only support a subset of the +signalling properties. + +**GPIO_INT** + GPIO pin to trigger interrupt. + +**GPIO_INT_ACTIVE_LOW** + GPIO pin trigger on level low or falling edge. + +**GPIO_INT_ACTIVE_HIGH** + GPIO pin trigger on level high or rising edge. + +**GPIO_INT_CLOCK_SYNC** + GPIO pin trigger to be synchronized to clock pulses. + +**GPIO_INT_DEBOUNCE** + Enable GPIO pin trigger debounce. + +**GPIO_INT_LEVEL** + Do Level trigger. + +**GPIO_INT_EDGE** + Do Edge trigger. + +**GPIO_INT_DOUBLE_EDGE** + Interrupt triggers on both rising and falling edge. + + +GPIO device tree support +************************ + +Nodes +===== + +GPIO Controller Node +-------------------- + +The GPIO device is defined by a GPIO controller node. + +Required properties are: + +- gpio-controller: Indicates this device is a GPIO controller +- compatible: +- label: Should be a name string + + +Interaction with the PINCTRL device driver +========================================== + +To enable a pin controller to report the pins that are associated to a GPIO +device the gpio-ranges property shall be set in the device tree. Also the label +property shall be set and used as device name. + +The gpio-ranges property is of the form: + +.. code-block:: text + + gpio-ranges = <&[pin controller] [pin number in GPIO pin number space] + [pin number in pin controller number space] + [number of pins]>, + /* ... */ + ; + +A GPIO port definition in the device tree may look like: + +.. code-block:: DTS + + pinctrl: pin-controller@48000000 { + pin-controller; + /* ... */ + }; + + gpioa: gpio@40020000 { + gpio-controller; + compatible = "st,stm32-gpio-pinctrl"; + #gpio-cells = <2>; + reg = <0x40020000 0x400>; + label = "STM32_GPIOA"; + gpio-ranges = <&pinctrl GPIO_PORT_PIN0 PINCTRL_STM32_PINA0 16>; + }; + + +GPIO device driver implementation +********************************* + +Driver configuration information comes from three sources: + +- autoconf.h (Kconfig) +- generated_dts_board.h (device tree) +- soc.h + +Driver configuration by autoconf +================================ + +See :ref:`configuration` for the the full set of Kconfig symbols that are available. +Specific to the GPIO driver are: + +:c:macro:`CONFIG_GPIO` + Enable GPIO driver. + +Driver configuration by device tree +=================================== + +For a GPIO controller node the following information is extracted from the device tree +and provided in :file:`generated_dts_board.h`. + +The general device information for GPIO controllers: + +:c:macro:`SOC_GPIO_CONTROLLER_COUNT` + Number of GPIO controllers that are activated. All nodes that contain a + gpio-controller directive are counted. + +:c:macro:`SOC_GPIO_CONTROLLER_0` ... + The label prefix of GPIO controller 0 ... (e.g. 'ST_STM32_GPIO_PINCTRL_48000000'). + The define is generated if a gpio-controller directive is given in the node. + +General information that is extracted for every device type: + +**LABEL** + +**BASE_ADDRESS** + +**SIZE** + +**COMPATIBLE_COUNT** + +**COMPATIBLE_0_ID** + +The specific device information for GPIO controllers: + +**PINCTRL_CONTROLLER** + For all pin controllers that are referenced in a pinctrl-x directive + PINCTRL_CONTROLLER defines are generated. + +**PINCTRL** + For all subnodes of pin configurations referenced by active GPIO nodes + - pinctrl-x(&xxx, pinconf_a, ...) - PINCTRL defines are generated. + The pinctrl references the *PINCTRL_CONTROLLER* given in the pinctrl-x + directive. The pinctrl also references the *PINCTRL_STATE* the pin + controller associates to this pinctrl. + +Driver configuration by soc.h +============================= + +:file:`soc.h` may contain driver relevant information such as HAL header files. + +Drivers +======= + +.. toctree:: + :maxdepth: 1 + + gpio_stm32.rst + +Design Rationales +***************** + +.. [#pin_number_space] GPIO uses a **local pin number space** instead of + a global space to allow for object encapsulation. + diff --git a/doc/devices/drivers/gpio/gpio_stm32.rst b/doc/devices/drivers/gpio/gpio_stm32.rst new file mode 100644 index 00000000000000..72fdacb8f6e16f --- /dev/null +++ b/doc/devices/drivers/gpio/gpio_stm32.rst @@ -0,0 +1,68 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _device_driver_gpio_pinctrl_stm32: + +STM32 GPIO Device Driver +######################## + +.. contents:: + :depth: 1 + :local: + :backlinks: top + +STMicroelectronics's STM32 MCUs integrate several GPIO hardware controllers. + +Control Properties +****************** + +Pins +==== + +There are no specific STM32 pin definitions. Use the generic pin definitions from +:file:`include/gpio_common.h`. + +Signalling Configuration +************************ + +The STM32 GPIO PINCTRL device driver recognizes the following pin signalling +properties: + ++---------------------------------------+---------+--------------------------+ +| Property | Support | Comment | ++=======================================+=========+==========================+ +| GPIO_INT | **yes** | | ++---------------------------------------+---------+--------------------------+ +| TBD | no | | ++---------------------------------------+---------+--------------------------+ + +Device Tree Support +******************* + +Nodes +===== + +The STM32 GPIO device driver is based on and supports the following +device tree nodes: + +GPIO controller node +-------------------- + +Required properies: + + - gpio-controller: Indicates this device is a GPIO controller + - compatible: value must be: "st,stm32-gpio-pinctrl" + - label: Should be a name string + - st,bank-name: shall be one of "GPIOA", "GPIOB", ... + - gpio-ranges: + Defines a dedicated mapping between a pin controller and + a gpio controller. Format is <&phandle a b c> with: + + - (phandle): phandle of pin-controller. + - (a): gpio port pin base in range. + - (b): pin controller pin base in range. + - (c): gpio port pin count in range + + - clocks: clock that drives this bank + diff --git a/doc/devices/drivers/pinctrl/pinctrl.rst b/doc/devices/drivers/pinctrl/pinctrl.rst new file mode 100644 index 00000000000000..80ee1eaa26dae0 --- /dev/null +++ b/doc/devices/drivers/pinctrl/pinctrl.rst @@ -0,0 +1,1265 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _device_drivers_pinctrl: + +PINCTRL (pin controller) device driver +###################################### + +The **pin controller** device driver: + +- enumerates controllable **pins**, +- multiplexes **pins**, and +- configures **pins**. + +The Zephyr *pin controller* follows the concepts of the Linux PINCTRL +(PIN CONTROL) subsystem linux_pinctrl_. The following documentation +provides a summary of the concepts and definitions available in detail +in the Linux documentation ( linux_pinctrl_, linux_pinctrl_bindings_ ). +The Zephyr *pin controller* does not provide the full scope of the Linux +PINCTRL subsystem. Also the PINCTRL interface is specific to Zephyr and +not compatible to the Linux PINCTRL interface. However the device tree +bindings are kept compatible to the linux_pinctrl_bindings_ as much as +possible. + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +Pin controller concepts +*********************** + +A **PINCTRL device driver** + provides access to the *pin controller*. + +A **pin controller** + is a set of hardware resources, usually accessed via registers, that + can control *pins*. It may be able to multiplex, bias, set load capacitance, + set drive strength, etc. for individual *pins* or *groups* of pins. + There may be several pin controllers in a system which control only a set of + the available *pins*. + +A **pin** + is the physical input/output line of a chip. Pins are denoted by u16_t + integer numbers. The pin numberspace is local [#pin_number_space]_ to + a *pin controller*. This pin space may be sparse - i.e. there may be gaps + in the space with numbers where no pin exists. + +A pins **group** + is a set of *pins* that can be multiplexed to a + common *function*. Groups are denoted by u16_t integer numbers. The group + numberspace is local to each *pin controller*. The group number space may + be sparse or even non-existing. + +A pinctrl **state** + defines the *pin configuration* and the *pin multiplexing* to a *function* + of a *group* of *pins*. Pinctrl states are denoted by u16_t integer numbers. + The pinctrl state number space is local to a *pin controller*. + +A **function** + is a logical or physical function block of a chip. Common functions are + for example GPIO, USART, SPI, I2C, USB, ADC. Functions are + denoted by u16_t integer numbers. The function number space is local to a + *pin controller*. It may be sparse - a *pin controller* may not be able to + multiplex (aka. connect) a *pin* or a *group* of pins to a function block. + +**Pin configuration** + allows to control the pins properties, mostly the electrical ones, by software. + For example you may be able to make an output pin high impedance, + or "tristate" meaning it is effectively disconnected. You may be able to connect an + input pin to VDD or GND using a certain resistor value - pull up and pull down - so + that the pin has a stable value when nothing is driving the rail it is connected to, + or when it's unconnected. + +**Pin multiplexing** + allows to control the connection between *pins* and *functions* by software. + +**Pin state setting** + is the combination of *pin configuration* and *pin multiplexing* for a + *group* of *pins*. + +PINCTRL device driver +********************* + +The PINCTRL device driver provides applications and other drivers access: + +- to the drivers control properties sich as pins, groups, pinctrl states, + and functions, +- to pin configuration, +- to pin multiplexing, and +- to pin state setting. + +The driver also provides initial setup of pin configuration and pin multiplexing +controlled by the device tree pinctrl state information. + +Application programming interface +================================= + +The PINCTRL device driver API is provided by :file:`pinctrl.h`. + +The application programming interface is available in two extension stages: + +**Basic interface** + +Pin control, and initial pin setup at startup using device tree information. + +.. [PINCTRL_BASIC] Basic interface + +**Extended interface with run time access to device tree information** + +Extended pin control and pin setup at run time using device tree information. +The extended functionality is enabled by ``CONFIG_PINCTRL_RUNTIME_DTS``. + +Implementations of the extended interface usually need more FLASH and SRAM +memory than needed by the basic interface. + +.. [PINCTRL_RUNTIME_DTS] Extended interface + +Control properties +================== + +Pins +---- + +The pins are defined by the specific device driver in the associated pinctrl +device tree bindings file (e.g. :file:`include/dt-bindings/pinctrl/pinctrl_stm32.h` +for the STM32 PINCTRL device driver). + +The number of pins managed by a PINCTRL device driver may be retrieved by: + +:c:func:`pinctrl_get_pins_count()` + Get the number of pins selectable by this pin controller. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +Groups +------ + +The groups are defined by the device tree. Every pinctrl state of an active +node sets up a group with all the pins this pinctrl state controls. There may +be additional groups not covered by an active node's pinctrl state. + +The PINCTRL device driver has a mechanism for enumerating groups of pins and +retrieving the actual enumerated pins that are part of a certain group. + +:c:func:`pinctrl_get_groups_count()` + Get the number of groups selectable by this pin controller. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_group_pins()` + Get the pins that are in a pin group. + [PINCTRL_RUNTIME_DTS]_ + +The pin group associated with a certain device can be retrieved also. Example +for a group named "reset" of the device device_dev: + +.. code-block:: C + + u16_t function; + u16_t group; + + pinctrl_get_device_function(pinctrl_dev, device_dev, &function); + pinctrl_get_function_group(pinctrl_dev, function, "reset", &group); + +States +------ + +The states are defined by the device tree. Every pinctrl-x directive of an +active node defines a pinctrl state. + +The PINCTRL device driver has a mechanism for enumerating pinctrl states and +retrieving the pin group that is associated to a certain pinctrl state. + +:c:func:`pinctrl_get_states_count()` + Get the number of states selectable by this pin controller. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_state_group()` + Get the group of pins controlled by the pinctrl state. + [PINCTRL_RUNTIME_DTS]_ + +A pinctrl state associated with a certain device can be retrieved also. +Example for a state named "reset" of the device device_dev: + +.. code-block:: C + + u32_t function; + u16_t state; + + pinctrl_get_device_function(pinctrl_dev, device_dev, &function); + pinctrl_get_function_state(pinctrl_dev, function, "reset", &state); + +Functions +--------- + +Functions may either denote a device or a low level hardware pinmux control. +The device functions have function numbers in the range +[0 ... (:c:macro:`PINCTRL_FUNCTION_PINMUX_BASE` - 1)]. Hardware pinmux function +numbers start at :c:macro:`PINCTRL_FUNCTION_PINMUX_BASE`. + +There are two convenience functions to evaluate the type of a function: + +:c:func:`pinctrl_is_device_function()` + Is the function a client device multiplex control. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_is_pinmux_function()` + Is the function a hardware pinmux control. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +The function number that denotes a device can be retrieved by +:c:func:`pinctrl_get_device_function()`. + +The function numbers to be used for hardware pinmux control are usually defined +by the specific device driver in the associated pinctrl device tree bindings +(e.g. :file:`include/dt-bindings/pinctrl/pinctrl_{driver}.h`). + +The PINCTRL device driver allows to retrieve the number of functions supported +and the states that are associated to a function. Also the groups of pins that +can be muxed to a function can be fetched. + +:c:func:`pinctrl_get_functions_count()` + Get the number of selectable functions of this pin controller. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_function_group()` + Get the pin group with given name that can be muxed to the function. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_function_groups()` + Get the pin groups that can be muxed to the function. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_function_state()` + Get the pinctrl state with given name for the function. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_function_states()` + Get the pinctrl states that can be set for the function. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_get_device_function()` + Get the function that is associated to a device. + [PINCTRL_RUNTIME_DTS]_ + +GPIO ranges +----------- + +The PINCTRL device driver allows to map between the pin controller's +pin number space and the GPIO device pin number space. + +:c:func:`pinctrl_get_gpio_range()` + Get the pin controller pin number and pin mapping for a GPIO pin. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +Pin Configuration +================= + +:c:func:`pinctrl_config_get()` + Get the configuration of a pin. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_config_set()` + Configure a pin. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_config_group_get()` + Get the configuration of a group of pins. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_config_group_set()` + Configure a group of pins. + [PINCTRL_RUNTIME_DTS]_ + +A generic set of pin configuration properties is defined in +:file:`include/pinctrl.h`. +A pinctrl device driver may only support a subset of these +pin configuration properties. + +:c:macro:`PINCTRL_CONFIG_BIAS_DISABLE` + Disable any pin bias. + +:c:macro:`PINCTRL_CONFIG_BIAS_HIGH_IMPEDANCE` + High impedance mode ("third-state", "floating"). + +:c:macro:`PINCTRL_CONFIG_BIAS_BUS_HOLD` + Latch weakly. + +:c:macro:`PINCTRL_CONFIG_BIAS_PULL_UP` + Pull up the pin. + +:c:macro:`PINCTRL_CONFIG_BIAS_PULL_DOWN` + Pull down the pin. + +:c:macro:`PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT` + Use pin default pull state. + +:c:macro:`PINCTRL_CONFIG_DRIVE_PUSH_PULL` + Drive actively high and low. + +:c:macro:`PINCTRL_CONFIG_DRIVE_OPEN_DRAIN` + Drive with open drain (open collector). + Output can only sink current. + +:c:macro:`PINCTRL_CONFIG_DRIVE_OPEN_SOURCE` + Drive with open source (open emitter). + Output can only source current. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT` + Drive with default drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_1` + Drive with minimum drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_2` + Drive with minimum to medium drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_3` + Drive with minimum to medium drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_4` + Drive with medium drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_5` + Drive with medium to maximum drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_6` + Drive with medium to maximum drive strength. + +:c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_7` + Drive with maximum drive strength. + +:c:macro:`PINCTRL_CONFIG_INPUT_ENABLE` + Enable the pins input. + Does not affect the pin's ability to drive output. + +:c:macro:`PINCTRL_CONFIG_INPUT_DISABLE` + Disable the pins input. + Does not affect the pin's ability to drive output. + +:c:macro:`PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE` + Enable schmitt trigger mode for input. + +:c:macro:`PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE` + Disable schmitt trigger mode for input. + +:c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_NONE` + Do not debounce input. + +:c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_SHORT` + Debounce input with short debounce time. + +:c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_MEDIUM` + Debounce input with medium debounce time. + +:c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_LONG` + Debounce input with long debounce time. + +:c:macro:`PINCTRL_CONFIG_POWER_SOURCE_DEFAULT` + Select default power source for pin. + +:c:macro:`PINCTRL_CONFIG_POWER_SOURCE_1` + Select power source #1 for pin. + +:c:macro:`PINCTRL_CONFIG_POWER_SOURCE_2` + Select power source #2 for pin. + +:c:macro:`PINCTRL_CONFIG_POWER_SOURCE_3` + Select power source #3 for pin. + +:c:macro:`PINCTRL_CONFIG_LOW_POWER_ENABLE` + Enable low power mode. + +:c:macro:`PINCTRL_CONFIG_LOW_POWER_DISABLE` + Disable low power mode. + +:c:macro:`PINCTRL_CONFIG_OUTPUT_ENABLE` + Enable output on pin. + Such as connecting the output buffer to the drive stage. + Does not set the output drive. + +:c:macro:`PINCTRL_CONFIG_OUTPUT_DISABLE` + Disable output on pin. + Such as disconnecting the output buffer from the drive stage. + Does not reset the output drive. + +:c:macro:`PINCTRL_CONFIG_OUTPUT_LOW` + Set output to active low. + A "1" in the output buffer drives the output to low level. + +:c:macro:`PINCTRL_CONFIG_OUTPUT_HIGH` + Set output to active high. + A "1" in the output buffer drives the output to high level. + +:c:macro:`PINCTRL_CONFIG_SLEW_RATE_SLOW` + Select slow slew rate. + +:c:macro:`PINCTRL_CONFIG_SLEW_RATE_MEDIUM` + Select medium slew rate. + +:c:macro:`PINCTRL_CONFIG_SLEW_RATE_FAST` + Select fast slew rate. + +:c:macro:`PINCTRL_CONFIG_SLEW_RATE_HIGH` + Select high slew rate. + +:c:macro:`PINCTRL_CONFIG_SPEED_SLOW` + Select low toggle speed. + +:c:macro:`PINCTRL_CONFIG_SPEED_MEDIUM` + Select medium toggle speed. + +:c:macro:`PINCTRL_CONFIG_SPEED_FAST` + Select fast toggle speed. + +:c:macro:`PINCTRL_CONFIG_SPEED_HIGH` + Select high toggle speed. + +Pin Multiplexing +================ + +Access to the pin multiplexer may be managed by +:c:func:`pinctrl_mux_request()` and :c:func:`pinctrl_mux_free()`. + +:c:func:`pinctrl_mux_request()` + Request a pin for muxing. + [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_mux_free()` + Release a pin for muxing. + [PINCTRL_RUNTIME_DTS]_ + +The following multiplexing control functions do not adhere to any access +control. Use the above access management functions if access management is +necessary. + +:c:func:`pinctrl_mux_get()` + Get muxing function at pin. + [PINCTRL_BASIC]_ [PINCTRL_RUNTIME_DTS]_ + +:c:func:`pinctrl_mux_set()` + Set muxing function at pin. + If the [PINCTRL_BASIC]_ interface is selected the muxing function is + restricted to hardware multiplex control. In the [PINCTRL_RUNTIME_DTS]_ + interface also client device multiplex control is available. + +:c:func:`pinctrl_mux_group_set()` + Set muxing function for a group of pins. + [PINCTRL_RUNTIME_DTS]_ + + +Pin State Setting and Initialization +==================================== + +:c:func:`pinctrl_state_set()` + Set pinctrl state. + In the [PINCTRL_BASIC]_ interface the state is + restricted to the "default" state used for pin setup at startup. + If the [PINCTRL_RUNTIME_DTS]_ interface is selected all states + known in the device tree information can be set. + +The pinctrl device driver initializes pins based on device tree information. +Pins that are controlled by client devices that are + + - activated nodes in the device tree (status != "disabled") + - and where a "default" pin control is given + +are initialized during driver initialization. + +.. code-block:: DTS + + pinctrl-0 = <&xxx_pins_a &xxxx_pins_b>; + pinctrl-names = "default"; + status = "ok"; + + +Pin Concurrent Use by a Function and GPIO device driver +======================================================= + +The GPIO device driver is just another client to the PINCTRL device driver. + + +Interaction with GPIO device driver +=================================== + +The GPIO device driver uses the PINCTRL device driver as a backend. + + +Interaction with PINMUX device driver +===================================== + +The PINCTRL device driver also provides the PINMUX interface. No +extra pinmux device is needed. + +The PINMUX interface of the PINCTRL driver is for transition. The +PINCTRL multiplexing and configuration interfaces shall be used +instead. + + +PINCTRL device tree support +*************************** + +Nodes +===== + +Pin Controller Node +------------------- + +The pin controller device is defined by a pin controller node. + +Required properties are: + + - pin-controller: + - compatible: + - label: + + +Example: + +.. code-block:: DTS + + pinctrl: pin-controller@48000000 { + pin-controller; + compatible = "st,stm32-pinctrl"; + label = "PINCTRL"; + + /* pinctrl state nodes... */ + }; + +Pinctrl State Node +------------------ + +Pinctrl states are defined by pinctrl state nodes. The pinctrl state nodes are +sub-nodes of the pin controller node. A pinctrl state node represents a group +of pins and how they should be configured. + +A pinctrl state node is of the following format: + +.. code-block:: text + + [pinctrl-state-label]: [device-name]@[device-configuration-index] { + [pin-configuration-label] { + [property] = [value]; + ... + }; + ... + }; + +The device tree information is used to generate C defines: + +.. code-block:: C + + #define [NODE-LABEL]_PINCTRL_[PINCTRL-NAME]_[PIN-CONFIGURATION-LABEL]_[PROPERTY] [value] + +The following pin configuration properties are supported by the device tree. +*Pin controller* device drivers usually only support a subset of these +pin configuration properties. + +**pins**: + The **pins** property denotes to which pins the configuration applies to. + The *pins* are specified as a list of pin numbers from the *pin controller* + [#pin_number_space]_. + Either the *pins* or the *group* or the *pinmux* property shall be given + for a pin configuration. + +**group**: + The **group** property denotes to which *group* of *pins* the configuration + applies to. The *group* is specified as a group number from the + *pin controller* group number space. + Either the *pins* or the *group* or the *pinmux* property shall be given + for a pin configuration. + +**pinmux**: + The **pinmux** property denotes to which *pins* the configuration applies to + and defines the *pin multiplexing* of these *pins* at the same time. The + *pinmux* is specified as a list of integer values. The interpretation of the + integer value(s) is specific to the *pin controller* device driver. + Either the *pins* or the *group* or the *pinmux* property shall be given + for a pin configuration. + +**bias-disable** + Disable any pin bias. + +**bias-high-impedance** + High impedance mode ("third-state", "floating"). + +**bias-bus-hold** + Latch weakly. + +**bias-pull-up** + Pull up the pin. + +**bias-pull-down** + Pull down the pin. + +**bias-pull-pin-default** + Use pin default pull state. + +**drive-push-pull** + Drive actively high and low. + +**drive-open-drain** + Drive with open drain (open collector). + +**drive-open-source** + Drive with open source (open emitter). + +**drive-strength** + Drive strength. Generic drive strength values are: + + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_1`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_2`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_3`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_4`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_5`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_6`, + - :c:macro:`PINCTRL_CONFIG_DRIVE_STRENGTH_7`. + +**input-enable** + Enable the pins input. Does not affect the pin's ability to drive output. + +**input-disable** + Disable the pins input. Does not affect the pin's ability to drive output. + +**input-schmitt-enable** + Enable schmitt trigger mode for input. + +**input-schmitt-disable** + Disable schmitt trigger mode for input. + +**input-debounce** + Debounce input. Generic debounce values are: + + - :c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_NONE` + - :c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_SHORT` + - :c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_MEDIUM` + - :c:macro:`PINCTRL_CONFIG_INPUT_DEBOUNCE_LONG` + +**low-power-enable** + Enable low power mode. + +**low-power-disable** + Disable low power mode. + +**output-disable** + Disable output on pin. Such as disconnecting the output buffer from the drive stage. + Does not reset the output drive. + +**output-enable** + Enable output on pin. Such as connecting the output buffer to the drive stage. + Does not set the output drive. + +**output-low** + Set output to active low. A "1" in the output buffer drives the output to low level. + +**output-high** + Set output to active high. A "1" in the output buffer drives the output to high level. + +**power-source** + Power source. Generic power source values are: + + - :c:macro:`PINCTRL_CONFIG_POWER_SOURCE_DEFAULT` + - :c:macro:`PINCTRL_CONFIG_POWER_SOURCE_1` + - :c:macro:`PINCTRL_CONFIG_POWER_SOURCE_2` + - :c:macro:`PINCTRL_CONFIG_POWER_SOURCE_3` + +**slew-rate** + Slew rate. Generic slew rate values are: + + - :c:macro:`PINCTRL_CONFIG_SLEW_RATE_SLOW` + - :c:macro:`PINCTRL_CONFIG_SLEW_RATE_MEDIUM` + - :c:macro:`PINCTRL_CONFIG_SLEW_RATE_FAST` + - :c:macro:`PINCTRL_CONFIG_SLEW_RATE_HIGH` + +**speed** + Toggle speed. Slew rate may be unaffected. + Generic toggle speed values are: + + - :c:macro:`PINCTRL_CONFIG_SPEED_SLOW` + - :c:macro:`PINCTRL_CONFIG_SPEED_MEDIUM` + - :c:macro:`PINCTRL_CONFIG_SPEED_FAST` + - :c:macro:`PINCTRL_CONFIG_SPEED_HIGH` + +The following example device tree describes a pin controller with a pin +configuration node and a SPI. + +.. code-block:: DTS + + / { + /* ... */ + soc { + /* ... */ + pinctrl: pin-controller@48000000 { + compatible = "st,stm32-pinctrl"; + pin-controller; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x48000000 0x1800>; + label = "PINCTRL"; + /* ... */ + spi1_master_a: spi1@0 { + sck { + pinmux = ; + drive-push-pull; + bias-disable; + }; + miso { + pinmux = ; + bias-disable; + }; + mosi { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + /* ... */ + }; + /* ... */ + spi1: spi@40013000 { + spi-controller; + compatible = "st,stm32-spi-fifo"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + interrupts = <25 5>; + status = "disabled"; + label = "SPI_1"; + }; + }; + }; + /* ... */ + &pinctrl { + status = "ok"; + }; + + &spi1 { + pinctrl-0 = <&spi1_master_a>; + pinctrl-names = "default"; + status = "ok"; + }; + +The device tree information is extracted to :file:`generated_dts_board.h`. + +The SPI_1 is registered as FUNCTION_2 at the pin controller. +The "default" state of the SPI is registered as STATE_2. Three pin controls +are associated to this state: PINCTRL_4, PINCTRL_5 and PINCTRL_6. +PINCTRL_4 e.g. configures the pin sck. + +.. code-block:: C + :caption: Example generated_dts_board.h - pin controller node + + /* pin-controller@48000000 */ + #define ST_STM32_PINCTRL_48000000_BASE_ADDRESS_0 0x48000000 + ... + #define ST_STM32_PINCTRL_48000000_FUNCTION_2_CLIENT ST_STM32_SPI_FIFO_40013000 + ... + #define ST_STM32_PINCTRL_48000000_FUNCTION_COUNT 4 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_BUS_HOLD 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_DISABLE 1 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_HIGH_IMPEDANCE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_PULL_DOWN 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_PULL_PIN_DEFAULT 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_BIAS_PULL_UP 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_DRIVE_OPEN_DRAIN 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_DRIVE_OPEN_SOURCE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_DRIVE_PUSH_PULL 1 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_DRIVE_STRENGTH 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_GROUP 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_INPUT_DEBOUNCE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_INPUT_DISABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_INPUT_ENABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_INPUT_SCHMITT_DISABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_INPUT_SCHMITT_ENABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_LOW_POWER_DISABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_LOW_POWER_ENABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_OUTPUT_DISABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_OUTPUT_ENABLE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_OUTPUT_HIGH 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_OUTPUT_LOW 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_PINMUX 19,32768 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_PINS 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_POWER_SOURCE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_SLEW_RATE 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_SPEED 0 + #define ST_STM32_PINCTRL_48000000_PINCTRL_4_STATE_ID 2 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_5_STATE_ID 2 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_6_STATE_ID 2 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_COUNT 10 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_STATE_2_FUNCTION_ID 2 + #define ST_STM32_PINCTRL_48000000_PINCTRL_STATE_2_NAME_ID 0 + ... + #define ST_STM32_PINCTRL_48000000_PINCTRL_STATE_COUNT 4 + #define ST_STM32_PINCTRL_48000000_SIZE_0 6144 + #define ST_STM32_PINCTRL_48000000_STATE_NAME_0 default + #define ST_STM32_PINCTRL_48000000_STATE_NAME_COUNT 1 + #define ST_STM32_PINCTRL_48000000_BASE_ADDRESS ST_STM32_PINCTRL_48000000_BASE_ADDRESS_0 + #define ST_STM32_PINCTRL_48000000_SIZE ST_STM32_PINCTRL_48000000_SIZE_0 + +The relevant pin control information is also given for the SPI node. + +.. code-block:: C + :caption: Example generated_dts_board.h - SPI node + + /* spi@40013000 */ + #define ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS_0 0x40013000 + #define ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS_1 0x400 + #define ST_STM32_SPI_FIFO_40013000_IRQ_0 25 + #define ST_STM32_SPI_FIFO_40013000_IRQ_0_PRIORITY 5 + #define ST_STM32_SPI_FIFO_40013000_LABEL "SPI_1" + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_CONTROLLER_0_CONTROLLER ST_STM32_PINCTRL_48000000 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_CONTROLLER_0_FUNCTION_ID 2 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_CONTROLLER_COUNT 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_CONTROLLER_ID 0 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_MISO_BIAS_DISABLE 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_MISO_PINMUX 20,32768 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_MOSI_BIAS_DISABLE 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_MOSI_DRIVE_PUSH_PULL 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_MOSI_PINMUX 21,32768 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_SCK_BIAS_DISABLE 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_SCK_DRIVE_PUSH_PULL 1 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_SCK_PINMUX 19,32768 + #define ST_STM32_SPI_FIFO_40013000_PINCTRL_DEFAULT_STATE_ID 2 + #define ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS ST_STM32_SPI_FIFO_40013000_BASE_ADDRESS_0 + +Also generic device information is available for the soc node. + +.. code-block:: C + :caption: Example generated_dts_board.h - soc node + + /* soc */ + #define SOC_PIN_CONTROLLER_COUNT 1 + #define SOC_PIN_CONTROLLER_0 ST_STM32_PINCTRL_48000000 + #define SOC_SPI_CONTROLLER_COUNT 1 + #define SOC_SPI_CONTROLLER_0 ST_STM32_SPI_FIFO_40013000 + +Pin Initialization +================== + +Pin initialization is defined by the pinctrl named "default". + +In the following example pinctrl-0 is named "default". All pin states +requested by pinctrl-0 (pina_state0_node_other and pinb_state0_node_other) +will be set at initialization time. + +.. code-block:: DTS + + pinctrl: pinctrl@48000000 { + pin-controller; + /* ... */ + + pina_state0_node_other { + /* ... */ + }; + pina_state1_node_other { + /* ... */ + }; + pinb_state0_node_other { + /* ... */ + }; + pinb_state1_node_other { + /* ... */ + }; + }; + + other: other@50000000 { + /* ... */ + pinctrl-0 = <&pina_state0_node_other, &pinb_state0_node_other>; + pinctrl-1 = <&pina_state1_node_other, &pinb_state1_node_other>; + pinctrl-names = "default", "xxxx"; + status = "ok"; + }; + +Interaction with the GPIO device driver +======================================= + +GPIO to PINCTRL pin mapping by pinctrl-x +---------------------------------------- + +The GPIO device as a client device to the pin-controller may have at least +one pinctrl-x directive that references the pin-controller and sets all port +pins to GPIO input. By this all pin-controller pins that are associated to +the GPIO port can be retrieved by :c:func:`pinctrl_get_group_pins`. The name +of the group to retrieve corresponds to the pinctrl name of the pinctrl-x +directive. + +.. code-block:: DTS + + pinctrl: pin-controller@48000000 { + pin-controller; + /* ... */ + + gpioa_in: gpioa@0 { + pin0: { + pinmux = <...>; + /* ... */ + } + /* ... */ + } + }; + + gpioa: gpio@40020000 { + gpio-controller; + /* ... */ + pinctrl-0 = <&gpioa_in>; + pinctrl-names = <"reset", ...>; + }; + +A gpio driver may retrieve the pin-controller pins associate to it´s port: + +.. code-block:: C + + u32_t function; + u32_t group; + u16_t pins[16]; + u16_t num_pins = 16; + + pinctrl_get_device_function(pinctrl_dev, gpio_dev, &function); + pinctrl_get_function_group(pinctrl_dev, function, "reset", &group); + pinctrl_get_group_pins(pinctrl_dev, group, &pins[0], &num_pins); + +GPIO to PINCTRL pin mapping by gpio-ranges +------------------------------------------ + +To enable a pin controller and/ or a GPIO port to retrieve the pin mapping +between them the gpio-ranges property may be set in the device tree. Also +the label property shall be set and used as device name in this case. + +The gpio-ranges property is of the form: + +.. code-block:: text + + gpio-ranges = <&[pin controller] [pin number in GPIO pin number space] + [pin number in pin controller number space] + [number of pins]>, + /* ... */ + ; + +A GPIO port definition in the device tree may look like: + +.. code-block:: DTS + + pinctrl: pin-controller@48000000 { + pin-controller; + /* ... */ + }; + + gpioa: gpio@48001000 { + gpio-controller; + compatible = "st,stm32-gpio-pinctrl"; + #gpio-cells = <2>; + reg = <0x480010000 0x400>; + label = "GPIOE"; + gpio-ranges = <&pinctrl GPIO_PORT_PIN0 PINCTRL_STM32_PINE0 16>; + }; + +The GPIO port pin 0 is mapped to the pinctrl pin E0. In total 16 pins are +mapped starting at pinctrl pin EO and continuing with the consecutively +following pin numbers. + +GPIO_RANGE defines are generated for the GPIO node and for the PINCTRL +node. + +.. code-block:: C + + /* gpio@48001000 */ + #define ST_STM32_GPIO_PINCTRL_48001000_BASE_ADDRESS_0 0x48001000 + #define ST_STM32_GPIO_PINCTRL_48001000_GPIO_RANGE_0_BASE 1 + #define ST_STM32_GPIO_PINCTRL_48001000_GPIO_RANGE_0_CONTROLLER ST_STM32_PINCTRL_48000000 + #define ST_STM32_GPIO_PINCTRL_48001000_GPIO_RANGE_0_CONTROLLER_BASE 64 + #define ST_STM32_GPIO_PINCTRL_48001000_GPIO_RANGE_0_NPINS 16 + #define ST_STM32_GPIO_PINCTRL_48001000_GPIO_RANGE_COUNT 1 + #define ST_STM32_GPIO_PINCTRL_48001000_LABEL "GPIOE" + #define ST_STM32_GPIO_PINCTRL_48001000_SIZE_0 1024 + #define ST_STM32_GPIO_PINCTRL_48001000_BASE_ADDRESS ST_STM32_GPIO_PINCTRL_48001000_BASE_ADDRESS_0 + #define ST_STM32_GPIO_PINCTRL_48001000_SIZE ST_STM32_GPIO_PINCTRL_48001000_SIZE_0 + +.. code-block:: C + + /* pin-controller@48000000 */ + #define ST_STM32_PINCTRL_48000000_BASE_ADDRESS_0 0x48000000 + ... + #define ST_STM32_PINCTRL_48000000_GPIO_RANGE_4_BASE 64 + #define ST_STM32_PINCTRL_48000000_GPIO_RANGE_4_CLIENT ST_STM32_GPIO_PINCTRL_48001000 + #define ST_STM32_PINCTRL_48000000_GPIO_RANGE_4_CLIENT_BASE 1 + #define ST_STM32_PINCTRL_48000000_GPIO_RANGE_4_NPINS 16 + ... + #define ST_STM32_PINCTRL_48000000_GPIO_RANGE_COUNT 6 + ... + +Interaction with the PINMUX device driver +========================================= + +The pinmux device shall be disabled if a pin controller is used. + +.. code-block:: DTS + + pinctrl: pin-controller@48000000 { + pin-controller; + /* ... */ + status = "ok"; + }; + + pinmux: pinmux@48000400 { + /* ... */ + status = "disabled"; + }; + + +PINCTRL device driver implementation +************************************ + +Driver Configuration +==================== + +Driver configuration information comes from three sources: + - autoconf.h (Kconfig) + - generated_dts_board.h (device tree) + - soc.h + +Driver configuration by autoconf.h +---------------------------------- + +See :ref:`configuration` for the the full set of Kconfig symbols that are available. +Specific to the pin controller driver are: + +:c:macro:`CONFIG_PINCTRL` + Enable pinctrl driver. + +:c:macro:`CONFIG_PINCTRL_RUNTIME_DTS` + Enable run time pin configuration control based on device tree + information. When enabled the [PINCTRL_RUNTIME_DTS]_ API is available. + +:c:macro:`CONFIG_PINCTRL_PINMUX` + Enable the generic shim that maps from the pinmux interface to the pinctrl + interface. + +:c:macro:`CONFIG_PINCTRL_INIT_PRIORITY` + Initialization priority for the pinctrl driver. + +:c:macro:`CONFIG_PINCTRL_NAME` + Pinctrl driver name. May be used if no label information is given in the device + tree. + +Driver configuration by device tree +----------------------------------- + +For a pin controller node the following information is extracted from the device tree +and provided in :file:`generated_dts_board.h`. + +The general device information for pin controllers: + +:c:macro:`SOC_PIN_CONTROLLER_COUNT` + Number of pin controllers that are activated. All nodes that contain a + pin-controller directive are counted. + +:c:macro:`SOC_PIN_CONTROLLER_0` ... + The label prefix of pin controller 0 ... (e.g. 'ST_STM32_PINCTRL_48000000'). + The define is generated if a pin-controller directive is given in the node. + +General information that is extracted for every device type: + +**LABEL** + +**BASE_ADDRESS** + +**SIZE** + +**COMPATIBLE_COUNT** + +**COMPATIBLE_0_ID** + +The specific device information for pin controllers: + +**FUNCTION** + For all active client nodes that reference a pin-controller by + pinctrl-x(&pinctrl, ...) FUNCTION defines are generated. + The function equals the client node. + +**STATE_NAME** + For all pinctrl names of pinctrl-x directives of active client nodes + STATE_NAME defines are generated. This is mostly to allow deduplication of + commonly used state names such as e.g. "default". + +**PINCTRL_STATE** + For all pinctrl-x directives of active client nodes PINCTRL_STATE defines + are generated. + The pinctrl state references the *FUNCTION* (aka. node) it is given in. + The pinctrl state also references the *STATE_NAME* given in the + pinctrl-names directive associated to the pinctrl-x directive. + + All the pins that a pinctrl state controls are regarded to be a pin group. + The name of the pin group is the same as the name of the pinctrl state. + +**PINCTRL** + For all subnodes of pin configurations referenced by active client nodes - + pinctrl-x(&xxx, pinconf_a, ...) - PINCTRL defines are generated. + The pinctrl references the *FUNCTION* (aka. node) it is referenced from. + The pinctrl also references the *PINCTRL_STATE* it is referenced from. + +**GPIO_RANGE** + For all gpio-ranges directives of active GPIO nodes GPIO_RANGE defines are + generated. + +The datasets for the clients of pin controllers are: + +**PINCTRL_CONTROLLER** + For all pin controllers that are referenced in a pinctrl-x directive + PINCTRL_CONTROLLER defines are generated. + +**PINCTRL** + For all subnodes of pin configurations referenced by active client nodes + - pinctrl-x(&xxx, pinconf_a, ...) - PINCTRL defines are generated. + The pinctrl references the *PINCTRL_CONTROLLER* given in the pinctrl-x + directive. The pinctrl also references the *PINCTRL_STATE* the pin + controller associates to this pinctrl. + +Driver configuration by soc.h +----------------------------- + +:file:`soc.h` may contain driver relevant information such as HAL header files. + +Driver structures and content generation +======================================== + +A driver implementation may either use a specific (DTS) script or the +inline code generation to generate driver structures and content. + +Using the pin controller driver template +---------------------------------------- + +The pin controller template :file:`pinctrl_tmpl.c` is a template for pin +controller driver implementation. The template parameters are given by +global variables in the inline code generation snippet. +The template is expanded by inline code generation with Python. +The template generates the appropriate data structures +and fills them using the information provided in :file:`generated_dts_board.conf`. + +A pin controller driver implementer has to write five hardware/ device specific +functions to implement: + + - :c:func:`pinctrl_config_get()`, + - :c:func:`pinctrl_config_set()`, + - :c:func:`pinctrl_mux_get()`, + - :c:func:`pinctrl_mux_set()`, + - and device initialization. + +Additionally two Python functions have to be provided that extract the pin number +and the multiplexer value from the pinmux value(s) given in the device tree: + + - :py:func:`pinmux_pin(pinmux)` + - :py:func:`pinmux_mux(pinmux)` + +The template expects the following globals to be set: + + - compatible + The compatible string of the driver (e.g. 'st,stm32-pinctrl') + - data_info + device data type definition (e.g. 'struct pinctrl_stm32_data') + - config_get + C function name of device config_get function. + - mux_free + C function name of device mux_free function. + - mux_get + C function name of device mux_get function. + - mux_set + C function name of device mux_set function. + - device_init + C function name of device init function + - :py:func:`pinmux_pin(pinmux)` + Python function that extracts the pin number from the pinmux property. + - :py:func:`pinmux_mux(pinmux)` + Python function that extracts the mux value from the pinmux property. + +The structure of a pin controller driver may look like this example +of the STM32 driver (:file:`drivers/pinctrl/pinctrl_stm32.c`): + +.. code-block:: C + :caption: Example pinctrl_stm32.c + + /** + * @code{.codegen} + * compatible = 'st,stm32-pinctrl' + * codegen.if_device_tree_controller_compatible('PIN', compatible) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + ... + struct pinctrl_stm32_data { + ... + } + ... + /* --- API (using the PINCTRL template code) --- */ + + /* forward declarations */ + static int pinctrl_stm32_config_get(struct device *dev, u16_t pin, + u32_t *config); + static int pinctrl_stm32_config_set(struct device *dev, u16_t pin, + u32_t config); + static int pinctrl_stm32_mux_get(struct device *dev, u16_t pin, u16_t *func); + static int pinctrl_stm32_mux_set(struct device *dev, u16_t pin, u16_t func); + static int pinctrl_stm32_device_init(struct device *dev); + + /** + * @code{.codegen} + * # compatible already set + * data_info = 'struct pinctrl_stm32_data' + * config_get = 'pinctrl_stm32_config_get' + * config_set = 'pinctrl_stm32_config_set' + * mux_get = 'pinctrl_stm32_mux_get' + * mux_set = 'pinctrl_stm32_mux_set' + * device_init = 'pinctrl_stm32_device_init' + * def pinmux_pin(pinmux): + * return pinmux.split(',')[0] + * def pinmux_mux(pinmux): + * return pinmux.split(',')[1] + * codegen.out_include('pinctrl_tmpl.c') + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + + static int pinctrl_stm32_config_get(struct device *dev, u16_t pin, + u32_t *config) + { ... } + + static int pinctrl_stm32_config_set(struct device *dev, u16_t pin, + u32_t config) + { ... } + + static int pinctrl_stm32_mux_get(struct device *dev, u16_t pin, u16_t *func) + { ... } + + static int pinctrl_stm32_mux_set(struct device *dev, u16_t pin, u16_t func) + { ... } + + static int pinctrl_stm32_device_init(struct device *dev) + { ... } + +Drivers +======= + +.. toctree:: + :maxdepth: 1 + + pinctrl_stm32.rst + +Design Rationales +***************** + +.. [#pin_number_space] PINCTRL uses a **local pin number space** instead of + a global space to allow for object encapsulation. + +References +********** + +.. target-notes:: + +.. _linux_pinctrl: https://www.kernel.org/doc/Documentation/pinctrl.txt +.. _linux_pinctrl_bindings: https://www.kernel.org/doc/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt diff --git a/doc/devices/drivers/pinctrl/pinctrl_stm32.rst b/doc/devices/drivers/pinctrl/pinctrl_stm32.rst new file mode 100644 index 00000000000000..636ce6584eeac8 --- /dev/null +++ b/doc/devices/drivers/pinctrl/pinctrl_stm32.rst @@ -0,0 +1,352 @@ +.. + Copyright (c) 2017 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _device_driver_pinctrl_stm32: + +STM32 PINCTRL (Pin Controller) Device Driver +############################################ + +.. contents:: + :depth: 1 + :local: + :backlinks: top + +STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config +hardware controller. It controls the input/output settings on the +available pins and also provides the ability to multiplex and configure +the output of various on-chip controllers onto these pads. + +Control Properties +****************** + +Applications and other device drivers may access the control properties of the +STM32 PINCTRL device driver by the following files: + + - Pins: :file:`include/dt-bindings/pinctrl/pinctrl_stm32.h` + - Groups: :file:`include/dt-bindings/pinctrl/pinctrl_stm32.h` + - Functions: :file:`include/dt-bindings/pinctrl/pinctrl_stm32.h` + +There are no groups, and functions for groups defined. + +There are pin defines available for all port pins [PINCTRL_STM32_PINA0 ... +PINCTRL_STM32_PINA15] to [PINCTRL_STM32_PINH0 ... PINCTRL_STM32_PINH15]. + +Pin Configuration +***************** + +The pin configuration options supported by the STM32 PINCTRL device driver are +a subset of the generic configuration options given in +:file:`include/pinctrl_common.h`. + ++---------------------------------------+---------+--------------------------+ +| Property | Support | Comment | ++=======================================+=========+==========================+ +| PINCTRL_CONFIG_BIAS_DISABLE | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_BIAS_HIGH_IMPEDANCE | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_BIAS_BUS_HOLD | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_BIAS_PULL_UP | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_BIAS_PULL_DOWN | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_PUSH_PULL | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_OPEN_DRAIN | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_OPEN_SOURCE | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_1 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_2 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_3 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_4 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_5 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_6 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_DRIVE_STRENGTH_7 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_ENABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_DISABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_DEBOUNCE_NONE | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_DEBOUNCE_SHORT | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_DEBOUNCE_MEDIUM | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_INPUT_DEBOUNCE_LONG | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_POWER_SOURCE_DEFAULT | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_POWER_SOURCE_1 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_POWER_SOURCE_2 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_POWER_SOURCE_3 | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_LOW_POWER_ENABLE | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_LOW_POWER_DISABLE | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_OUTPUT_ENABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_OUTPUT_DISABLE | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_OUTPUT_LOW | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_OUTPUT_HIGH | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SLEW_RATE_SLOW | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SLEW_RATE_MEDIUM | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SLEW_RATE_FAST | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SLEW_RATE_HIGH | no | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SPEED_SLOW | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SPEED_MEDIUM | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SPEED_FAST | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_CONFIG_SPEED_HIGH | **yes** | | ++---------------------------------------+---------+--------------------------+ + +Pin Multiplexing +**************** + +The STM32 PINCTRL driver supports pin multiplex control by device function and +by hardware pinmux function. The hardware pinmux functions are defined in +:file:`include/dt-bindings/pinctrl/pinctrl_stm32.h`. + ++---------------------------------------+---------+--------------------------+ +| Pinmux Function | Support | Comment | ++=======================================+=========+==========================+ +| PINCTRL_STM32_FUNCTION_ALT_0 | **yes** | | ++---------------------------------------+---------+--------------------------+ +| ... | | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_STM32_FUNCTION_ALT_15 | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_STM32_FUNCTION_INPUT | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_STM32_FUNCTION_OUTPUT | **yes** | | ++---------------------------------------+---------+--------------------------+ +| PINCTRL_STM32_FUNCTION_ANALOG | **yes** | | ++---------------------------------------+---------+--------------------------+ + +Pin Initialization +****************** + +The STM32 PINCTRL driver supports pin initialization by pinctrls named +"default". + +Device Tree Support +******************* + +Nodes +===== + +The STM32 PINCTRL device driver is based on and supports the following +device tree nodes: + +Pin controller node +------------------- + +Required properies: + - compatible: value must be: "st,stm32-pinctrl" + - #address-cells: The value of this property must be 1 + - #size-cells: The value of this property must be 1 + - label: Should be a name string + +.. code-block:: DTS + + pinctrl: pin-controller@40020000 { + pin-controller; + compatible = "st,stm32-pinctrl"; + label = "PINCTRL"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40020000 0x3000>; + + /* pin configuration nodes follow... */ + }; + +GPIO controller node +-------------------- + +Required properties: + + - gpio-ranges: Defines a dedicated mapping between a pin-controller and + a gpio controller. Format is <&phandle a b c> with: + + - (phandle): phandle of pin-controller. + - (a): gpio port pin base in range. + - (b): pin-controller pin base in range. + - (c): gpio port pin count in range + +.. code-block:: DTS + + pinctrl: pin-controller@40020000 { + pin-controller; + /* ... */ + }; + + gpioa: gpio@40020000 { + gpio-controller; + /* ... */ + gpio-ranges = <&pinctrl GPIO_PORT_PIN0 PINCTRL_STM32_PINA0 16>; + }; + + +Device nodes +------------ + +Required properties: + + - pinctrl-0: Pin control definition for pinctrl state 0. + - pinctrl-names: Names of the pinctrl states. + - label: Should be the name string used in DEVICE_INIT(). + +Optional properties: + + - pinctrl-1,2,...: Pin control definition for pinctrl state 1 or 2 or .... + +Pinctrl state nodes +------------------- + +The STM32 PINCTRL device driver recognizes the following pin configuration +properties given in the device tree: + ++---------------------------------------+---------+--------------------------+ +| Property | Support | Comment | ++=======================================+=========+==========================+ +| pins | no | | ++---------------------------------------+---------+--------------------------+ +| group | no | | ++---------------------------------------+---------+--------------------------+ +| pinmux | **yes** | see _`pinmux` | ++---------------------------------------+---------+--------------------------+ +| bias-disable | **yes** | | ++---------------------------------------+---------+--------------------------+ +| bias-high-impedance | no | | ++---------------------------------------+---------+--------------------------+ +| bias-pull-up | **yes** | | ++---------------------------------------+---------+--------------------------+ +| bias-pull-down | **yes** | | ++---------------------------------------+---------+--------------------------+ +| bias-pull-pin-default | **yes** | | ++---------------------------------------+---------+--------------------------+ +| drive-push-pull | **yes** | | ++---------------------------------------+---------+--------------------------+ +| drive-open-drain | **yes** | | ++---------------------------------------+---------+--------------------------+ +| drive-open-source | no | | ++---------------------------------------+---------+--------------------------+ +| drive-strength | no | | ++---------------------------------------+---------+--------------------------+ +| input-enable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| input-disable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| input-schmitt-enable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| input-schmitt-disable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| input-debounce | no | | ++---------------------------------------+---------+--------------------------+ +| low-power-enable | no | | ++---------------------------------------+---------+--------------------------+ +| low-power-disable | no | | ++---------------------------------------+---------+--------------------------+ +| output-disable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| output-enable | partial | set by mux function only | ++---------------------------------------+---------+--------------------------+ +| output-low | no | | ++---------------------------------------+---------+--------------------------+ +| output-high | no | | ++---------------------------------------+---------+--------------------------+ +| power-source | no | | ++---------------------------------------+---------+--------------------------+ +| slew-rate | no | | ++---------------------------------------+---------+--------------------------+ +| speed | **yes** | | ++---------------------------------------+---------+--------------------------+ + +pinmux +------ + +The pinmux property value must be given by the tuple pin-number and +pin-function. + +.. code-block:: text + + [pin-configuration-label] { + pinmux = <[pin-number] [pin-function]>; + ... + }; + +Example of pin 6 and 7 of GPIO port B multiplexed to alternate function 0: + +.. code-block:: DTS + + pin-controller { + /* ... */ + usart1_pins_a: usart1@0 { + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + }; + + &usart1 { + pinctrl-0 = <&usart1_pins_a>; + pinctrl-names = "default"; + status = "okay"; + }; + +STM32 PINCTRL Implementation +**************************** + +Pins +==== + +.. doxygengroup:: pinctrl_interface_stm32_pin_defs + :project: Zephyr + +Groups +====== + +.. doxygengroup:: pinctrl_interface_stm32_group_defs + :project: Zephyr + +Functions +========= + +.. doxygengroup:: pinctrl_interface_stm32_func_defs + :project: Zephyr + diff --git a/doc/subsystems/codegen/build.rst b/doc/subsystems/codegen/build.rst new file mode 100644 index 00000000000000..4ecc1ccf359b8e --- /dev/null +++ b/doc/subsystems/codegen/build.rst @@ -0,0 +1,29 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_build: + +Code Generation in the Build Process +#################################### + +Code generation has to be invoked as part of the build process. Zephyr uses +`CMake `_ as the tool to manage building the project. + +A file that contains inline code generation has to be added to the project +by one of the following commands in a :file:`CMakeList.txt` file. + +.. function:: zephyr_sources_codegen(codegen_file.c [CODEGEN_DEFINES defines..] [DEPENDS target.. file..]) + +.. function:: zephyr_sources_codegen_ifdef(ifguard codegen_file.c [CODEGEN_DEFINES defines..] [DEPENDS target.. file..]) + +.. function:: zephyr_library_sources_codegen(codegen_file.c [CODEGEN_DEFINES defines..] [DEPENDS target.. file..]) + +.. function:: zephyr_library_sources_codegen_ifdef(ifguard codegen_file.c [CODEGEN_DEFINES defines..] [DEPENDS target.. file..]) + +The arguments given by the ``CODEGEN_DEFINES`` keyword have to be of the form +``define_name=define_value``. The arguments become globals in the python +snippets and can be accessed by ``define_name``. + +Dependencies given by the ``DEPENDS`` key word are added to the dependencies +of the generated file. diff --git a/doc/subsystems/codegen/codegen.rst b/doc/subsystems/codegen/codegen.rst new file mode 100644 index 00000000000000..cc7b1bb3eed387 --- /dev/null +++ b/doc/subsystems/codegen/codegen.rst @@ -0,0 +1,90 @@ +.. + Copyright (c) 2004-2015 Ned Batchelder + SPDX-License-Identifier: MIT + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_intro: + +Introduction +############ + +Python snippets that are inlined in a source file are used as code generators. +The tool to scan the source file for the Python snippets and process them is +Codegen. Codegen and part of this documentation is based on +`Cog `_ from Ned Batchelder. + +The processing of source files is controlled by the CMake extension functions: +zephyr_sources_codegen(..) or zephyr_library_sources_codegen(..). The generated +source files are added to the Zephyr sources. During build the source files are +processed by Codegen and the generated source files are written to the CMake +binary directory. + +The inlined Python snippets can contain any Python code, they are regular +Python scripts. All Python snippets in a source file and all Python snippets of +included template files are treated as a python script with a common set of +global Python variables. Global data created in one snippet can be used in +another snippet that is processed later on. This feature could be used, for +example, to customize included template files. + +An inlined Python snippet can always access the codegen module. The codegen +module encapsulates and provides all the functions to retrieve information +(options, device tree properties, CMake variables, config properties) and to +output the generated code. + +Codegen transforms files in a very simple way: it finds chunks of Python code +embedded in them, executes the Python code, and places its output combined with +the original file into the generated file. The original file can contain +whatever text you like around the Python code. It will usually be source code. + +For example, if you run this file through Codegen: + +:: + + /* This is my C file. */ + ... + /** + * @code{.codegen} + * fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] + * for fn in fnames: + * codegen.outl("void %s();" % fn) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + ... + +it will come out like this: + +:: + + /* This is my C file. */ + ... + /** + * @code{.codegen} + * fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] + * for fn in fnames: + * codegen.outl("void %s();" % fn) + * @endcode{.codegen} + */ + void DoSomething(); + void DoAnotherThing(); + void DoLastThing(); + /** @code{.codeins}@endcode */ + ... + +Lines with ``@code{.codegen}`` or ``@code{.codeins}@endcode`` are marker lines. +The lines between ``@code{.codegen}`` and ``@endcode{.codegen}`` are the +generator Python code. The lines between ``@endcode{.codegen}`` and +``@code{.codeins}@endcode`` are the output from the generator. + +When Codegen runs, it discards the last generated Python output, executes the +generator Python code, and writes its generated output into the file. All text +lines outside of the special markers are passed through unchanged. + +The Codegen marker lines can contain any text in addition to the marker tokens. +This makes it possible to hide the generator Python code from the source file. + +In the sample above, the entire chunk of Python code is a C comment, so the +Python code can be left in place while the file is treated as C code. + + diff --git a/doc/subsystems/codegen/codegen_principle.png b/doc/subsystems/codegen/codegen_principle.png new file mode 100644 index 00000000000000..b1f340731f3ac5 Binary files /dev/null and b/doc/subsystems/codegen/codegen_principle.png differ diff --git a/doc/subsystems/codegen/codegen_principle_access.png b/doc/subsystems/codegen/codegen_principle_access.png new file mode 100644 index 00000000000000..e0319d463cd8a0 Binary files /dev/null and b/doc/subsystems/codegen/codegen_principle_access.png differ diff --git a/doc/subsystems/codegen/codegen_principle_import.png b/doc/subsystems/codegen/codegen_principle_import.png new file mode 100644 index 00000000000000..e8c681833a0b98 Binary files /dev/null and b/doc/subsystems/codegen/codegen_principle_import.png differ diff --git a/doc/subsystems/codegen/codegen_principle_include.png b/doc/subsystems/codegen/codegen_principle_include.png new file mode 100644 index 00000000000000..1b58b41dd00989 Binary files /dev/null and b/doc/subsystems/codegen/codegen_principle_include.png differ diff --git a/doc/subsystems/codegen/functions.rst b/doc/subsystems/codegen/functions.rst new file mode 100644 index 00000000000000..45b56c1ab39e23 --- /dev/null +++ b/doc/subsystems/codegen/functions.rst @@ -0,0 +1,216 @@ +.. + Copyright (c) 2004-2015 Ned Batchelder + SPDX-License-Identifier: MIT + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_functions: + +Code Generation Functions +######################### + +A module called ``codegen`` provides the core functions for inline +code generation. It encapsulates all the functions to retrieve information +(options, device tree properties, CMake variables, config properties) and +to output the generated code. + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +The ``codegen`` module is automatically imported by all code snippets. No +explicit import is necessary. + +Output +------ + +.. function:: codegen.out(sOut=’’ [, dedent=False][, trimblanklines=False]) + + Writes text to the output. + + :param sOut: The string to write to the output. + :param dedent: If dedent is True, then common initial white space is + removed from the lines in sOut before adding them to the + output. + :param trimblanklines: If trimblanklines is True, + then an initial and trailing blank line are removed + from sOut before adding them to the output. + + ``dedent`` and ``trimblanklines`` make it easier to use + multi-line strings, and they are only are useful for multi-line strings: + + :: + + codegen.out(""" + These are lines I + want to write into my source file. + """, dedent=True, trimblanklines=True) + +.. function:: codegen.outl + + Same as codegen.out, but adds a trailing newline. + +.. attribute:: codegen.inFile + + An attribute, the path of the input file. + +.. attribute:: codegen.outFile + + An attribute, the path of the output file. + +.. attribute:: codegen.firstLineNum + + An attribute, the line number of the first line of Python code in the + generator. This can be used to distinguish between two generators in the + same input file, if needed. + +.. attribute:: codegen.previous + + An attribute, the text output of the previous run of this generator. This + can be used for whatever purpose you like, including outputting again with + codegen.out() + +The codegen module also provides a set of convenience functions: + + +Code generation module import +----------------------------- + +.. function:: codegen.module_import(module_name) + + Import a module from the codegen/modules package. + + After import the module's functions and variables can be accessed by + module_name.func() and module_name.var. + + :param module_name: Module to import. Specified without any path. + + See :ref:`codegen_modules` for the available modules. + +Template file inclusion +----------------------- + +.. function:: codegen.out_include(include_file) + + Write the text from include_file to the output. The :file:`include_file` + is processed by Codegen. Inline code generation in ``include_file`` + can access the globals defined in the ``including source file`` before + inclusion. The ``including source file`` can access the globals defined in + the ``include_file`` (after inclusion). + + :param include_file: path of include file, either absolute path or relative + to current directory or relative to templates directory + (e.g. 'templates/drivers/simple_tmpl.c') + + See :ref:`codegen_templates` for the templates in the Codegen templates + folders. + +.. function:: codegen.guard_include() + + Prevent the current file to be included by ``codegen.out_include()`` + when called the next time. + +Configuration property access +----------------------------- + +.. function:: codegen.config_property(property_name [, default=""]) + + Get the value of a configuration property from :file:`autoconf.h`. If + ``property_name`` is not given in :file:`autoconf.h` the default value is + returned. + +CMake variable access +--------------------- + +.. function:: codegen.cmake_variable(variable_name [, default=""]) + + Get the value of a CMake variable. If variable_name is not provided to + Codegen by CMake the default value is returned. The following variables + are provided to Codegen: + + - "PROJECT_NAME" + - "PROJECT_SOURCE_DIR" + - "PROJECT_BINARY_DIR" + - "CMAKE_SOURCE_DIR" + - "CMAKE_BINARY_DIR" + - "CMAKE_CURRENT_SOURCE_DIR" + - "CMAKE_CURRENT_BINARY_DIR" + - "CMAKE_CURRENT_LIST_DIR" + - "CMAKE_FILES_DIRECTORY" + - "CMAKE_PROJECT_NAME" + - "CMAKE_SYSTEM" + - "CMAKE_SYSTEM_NAME" + - "CMAKE_SYSTEM_VERSION" + - "CMAKE_SYSTEM_PROCESSOR" + - "CMAKE_C_COMPILER" + - "CMAKE_CXX_COMPILER" + - "CMAKE_COMPILER_IS_GNUCC" + - "CMAKE_COMPILER_IS_GNUCXX" + - "GENERATED_DTS_BOARD_H" + - "GENERATED_DTS_BOARD_CONF" + +.. function:: codegen.cmake_cache_variable(variable_name [, default=""]) + + Get the value of a CMake variable from CMakeCache.txt. If variable_name + is not given in CMakeCache.txt the default value is returned. + +Extended device tree database access +------------------------------------ + +.. function:: codegen.edts() + + Get the extended device tree database. + + :return: extended device tree database + +Guarding chunks of source code +------------------------------ + +.. function:: codegen.outl_guard_config(property_name) + + Write a guard (#if [guard]) C preprocessor directive to output. + + If there is a configuration property of the given name the property value + is used as guard value, otherwise it is set to 0. + + :param property_name: Name of the configuration property. + +.. function:: codegen.outl_unguard_config(property_name) + + Write an unguard (#endif) C preprocessor directive to output. + + This is the closing command for codegen.outl_guard_config(). + + :param property_name: Name of the configuration property. + +Error handling +-------------- + +.. function:: codegen.error(msg='Error raised by codegen.' [, frame_index=0] [, snippet_lineno=0]) + + Raise a codegen.Error exception. + + Instead of raising standard python errors, codegen generators can use + this function. Extra information is added that maps the python snippet + line seen by the Python interpreter to the line of the file that inlines + the python snippet. + + :param msg: Exception message. + :param frame_index: Call frame index. The call frame offset of the function + calling codegen.error(). Zero if directly called in a + snippet. Add one for every level of function call. + :param snippet_lineno: Line number within snippet. + +Logging +------- + +.. function:: codegen.log(message [, message_type=None] [, end="\n"] [, logonly=True]) + +.. function:: codegen.msg(msg) + + Prints msg to stdout with a “Message: ” prefix. + +.. function:: codegen.prout(s [, end="\n"]) + +.. function:: codegen.prerr(s [, end="\n"]) diff --git a/doc/subsystems/codegen/index.rst b/doc/subsystems/codegen/index.rst new file mode 100644 index 00000000000000..129749e02530d8 --- /dev/null +++ b/doc/subsystems/codegen/index.rst @@ -0,0 +1,29 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen: + +Inline Code Generation +###################### + +For some repetitive or parameterized coding tasks, it's convenient to +use a code generating tool to build C code fragments, instead of writing +(or editing) that source code by hand. Such a tool can also access CMake build +parameters and device tree information to generate source code automatically +tailored and tuned to a specific project configuration. + +The Zephyr project supports a code generating tool that processes embedded +Python "snippets" inlined in your source files. It can be used, for example, +to generate source code that creates and fills data structures, adapts +programming logic, creates configuration-specific code fragments, and more. + +.. toctree:: + :maxdepth: 1 + + codegen + functions + modules + templates + build + principle diff --git a/doc/subsystems/codegen/modules.rst b/doc/subsystems/codegen/modules.rst new file mode 100644 index 00000000000000..3a53d5d8ad5e2f --- /dev/null +++ b/doc/subsystems/codegen/modules.rst @@ -0,0 +1,322 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_modules: + +Code Generation Modules +####################### + +Code generation modules provide supporting functions for code generation. + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +Modules have to be imported to gain access to the module's functions +and variables. + + :: + + /* This file uses modules. */ + ... + /** + * @code{.codegen} + * codegen.import_module('my_special_module') + * my_special_module.do_everything(): + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + ... + +Device declare module +********************* + +:: + + codegen.import_module('devicedeclare') + +The devicedeclare module provides functions to generate driver device +instantiations. + +Driver info templates +--------------------- + +The device declaration functions work on templates that feature placeholder +substitution. + +Device instance property placeholders: + +- ${device-name}: device instance name. + Name is generated by the declaration function. +- ${driver-name}: device instance driver name. + Name is taken from the device tree node property 'label'. +- ${device-data}: device instance data structure name. + Name is generated by the declaration function. +- ${device-config-info}: device instance configuration structure name. + Name is generated by the declaration function. +- ${device-config-irq}: device instance interrupt configuration function name. + Name is generated by the declaration function. + +Device instance device tree property placeholders: + +* ${[path to DTS property]}: device instance device tree node property. + The property path supports every node property that is documented in the + node yaml bindings. It also supports yaml heuristics, like 'bus-master' and + will use documented '"#cells"'. + +Device tree property placeholders: + +- ${[device id]:[path to DTS property]}: device node property value. + The device node property is defined by the property path of the device + given by the device id. + The device id is usually also taken from a DTS property e.g. + ${${clocks/0/provider}:device-name}. + +KConfig configuration parameter placeholders: + +- ${CONFIG_[configuration parameter]}: KConfig configuration parameter value. + +Declaration of device instances +------------------------------- + +.. function:: devicedeclare.device_declare(compatibles, init_prio_flag, kernel_level, irq_func, init_func, api, data_struct, config_struct) + + Generate device instances code for all devices activated ('status' = 'ok') + in the board device tree file matching the provided compatibles. + + Most of the parameters aim at filling the DEVICE_AND_API_INIT macro. + Other parameters are there to help code generation to fit driver specifics. + + Instance code will only be generated if the Kconfig variable is set. The + variable name is build with the device node label name (e.g: CONFIG_I2C_1). + + :param compatibles: List of compatibles supported by the driver + (e.g. ['st,stm32-spi-fifo', 'st,stm32-spi']) + :param init_prio_flag: Flag for driver activation priority + (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEVICE) + :param kernel_level: Flag for driver activation priority (e.g. POST_KERNEL) + :param irq_func: Two elements python dict providing driver isr function + prefix (e.g. 'irq_func' \: 'stm32_i2c_isr') and flag to be + used for driver IRQ code control + (e.g. 'irq_flag' \: 'CONFIG_I2C_STM32_INTERRUPT'). + If irq_func is 'None', no IRQ code is generated. + 'device_declare' will generate as much IRQ code as + declared by device node. + If the 'interrupts-names' property is provided in the node, + isr names will be generated using matching values as + function postfixes. + :param init_func: Name of the driver init function (e.g. 'i2c_stm32_init'). + :param api: Name of the driver api structure (e.g. 'api_funcs'). + :param data_struct: Two elements python list providing elements for driver + '_data' structure generation. + :param config_struct: Two elements python list providing elements for driver + '_config' structure generation. + +'data_struct' and 'config_struct' will be processed the same way: + +* First element (e.g. 'i2c_stm32_config') should be the structure name. +* Second element is a 'c' template code between triple double quotes (""" """). + It should provide the expected code to be generated for the structure. + For instance: + +.. code-block:: python + + """ + .i2c = (I2C_TypeDef *)${reg/0/address/0}, + .pclken = { + .enr = ${clocks/0/bits}, + .bus = ${clocks/0/bus}, + }, + #ifdef CONFIG_I2C_STM32_INTERRUPT + .irq_config_func = st_stm32_i2c_v1_${node_index}_config_irq, + #endif + .bitrate = ${clock-frequency}, + """ + +If the second element of 'data_struct' or 'config_struct' list is not provided, +an empty structure is generated. + +Finally, for the above depicted example, 'device_declare' will generate, +for device instance 'I2C1': + +.. code-block:: c + + #ifdef CONFIG_I2C_STM32_INTERRUPT + DEVICE_DECLARE(st_stm32_i2c_v1_i2c_1); + static void st_stm32_i2c_v1_i2c_1_config_irq(struct device *dev) + { + IRQ_CONNECT(31, + 0, + stm32_i2c_isr_event, + DEVICE_GET(st_stm32_i2c_v1_i2c_1), + 0); + irq_enable(31); + IRQ_CONNECT(32, + 0, + stm32_i2c_isr_error, + DEVICE_GET(st_stm32_i2c_v1_i2c_1), + 0); + irq_enable(32); + } + #endif /* CONFIG_I2C_STM32_INTERRUPT */ + + static const struct i2c_stm32_config st_stm32_i2c_v1_i2c_1_config = { + .i2c = (I2C_TypeDef *)0x40005400, + .pclken = { + .enr = 131072, + .bus = 2, + }, + #ifdef CONFIG_I2C_STM32_INTERRUPT + .irq_config_func = st_stm32_i2c_v1_i2c_1_config_irq, + #endif + .bitrate = 400000, + }; + + static struct i2c_stm32_data st_stm32_i2c_v1_i2c_1_data = {}; + + DEVICE_AND_API_INIT(st_stm32_i2c_v1_i2c_1, + "I2C_1", + i2c_stm32_init, + &st_stm32_i2c_v1_i2c_1_data, + &st_stm32_i2c_v1_i2c_1_config, + POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &api_funcs); + +Raw declaration of a single device instance +------------------------------------------- + +.. function:: devicedeclare.device_declare_single(device_config, driver_name, device_init, device_levels device_prio, device_api, device_info) + + Generate device instances code for a device instance that: + + - matches the driver name and that + - is activated ('status' = 'ok') in the board device tree file and that is + - configured by Kconfig. + + The ``device_declare_single`` function enables a detailed control of the + device info definition. It's primary use is for complex device instance + initialisation that can not be accomplished by ``device_declare``. + + :param device_config: + Configuration variables for device instantiation. + (e.g. 'CONFIG_SPI_0') + :param driver_name: + Driver name for device instantiation. + (e.g. 'SPI_0') + :param device_init: + Device initialisation function. + (e.g. 'spi_stm32_init') + :param device_level: + Driver initialisation level. + (e.g. 'PRE_KERNEL_1') + :param device_prios: + Driver initialisation priority definition. + (e.g. 32) + :param device_api: + Identifier of the device api. + (e.g. 'spi_stm32_driver_api') + :param device_info: + Device info template for device driver config, data and interrupt + initialisation. + :param device_defaults: + Default property values. + (e.g. { 'label' : 'My default label' }) + +Raw declaration of multiple device instances +-------------------------------------------- + +.. function:: devicedeclare.device_declare_multi(device_configs, driver_names, device_inits, device_levels, device_prios, device_api, device_info) + + Generate device instances code for all device instances that: + + - match the driver names and that + - are activated ('status' = 'ok') in the board device tree file and that are + - configured by Kconfig. + + The ``device_declare_multi`` function enables a detailed control of the + device info definition. It's primary use is for complex device instance + initialisation that can not be accomplished by ``device_declare``. + + :param device_configs: + A list of configuration variables for device instantiation. + (e.g. ['CONFIG_SPI_0', 'CONFIG_SPI_1']) + :param driver_names: + A list of driver names for device instantiation. The list shall be + ordered the same way as the list of device configs. + (e.g. ['SPI_0', 'SPI_1']) + :param device_inits: + A list of device initialisation functions or a one single function. + The list shall be ordered as the list of device configs. + (e.g. 'spi_stm32_init') + :param device_levels: + A list of driver initialisation levels or one single level definition. + The list shall be ordered as the list of device configs. + (e.g. 'PRE_KERNEL_1') + :param device_prios: + A list of driver initialisation priorities or one single priority + definition. The list shall be ordered as the list of device configs. + (e.g. 32) + :param device_api: + Identifier of the device api. + (e.g. 'spi_stm32_driver_api') + :param device_info: + Device info template for device driver config, data and interrupt + initialisation. + :param device_defaults: + Default property values. + (e.g. { 'label' : 'My default label' }) + +Example: + +.. code-block:: C + + /** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_SPI_{}'.format(x) for x in range(1, 4)] + * driver_names = ['SPI_{}'.format(x) for x in range(1, 4)] + * device_inits = 'spi_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_SPI_INIT_PRIORITY' + * device_api = 'spi_stm32_driver_api' + * device_info = \ + * """ + * #if CONFIG_SPI_STM32_INTERRUPT + * DEVICE_DECLARE(${device-name}); + * static void ${device-config-irq}(struct device *dev) + * { + * IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority}, \\ + * spi_stm32_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/0/irq}); + * } + * #endif + * static const struct spi_stm32_config ${device-config-info} = { + * .spi = (SPI_TypeDef *)${reg/0/address/0}, + * .pclken.bus = ${clocks/0/bus}, + * .pclken.enr = ${clocks/0/bits}, + * #if CONFIG_SPI_STM32_INTERRUPT + * .config_irq = ${device-config-irq}, + * #endif + * }; + * static struct spi_stm32_data ${device-data} = { + * SPI_CONTEXT_INIT_LOCK(${device-data}, ctx), + * SPI_CONTEXT_INIT_SYNC(${device-data}, ctx), + * }; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ diff --git a/doc/subsystems/codegen/principle.rst b/doc/subsystems/codegen/principle.rst new file mode 100644 index 00000000000000..4fa4a0b3d2700b --- /dev/null +++ b/doc/subsystems/codegen/principle.rst @@ -0,0 +1,48 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_principle: + +Code Generation Principle +######################### + +How code generation works in Zephyr. + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +Principle +--------- + +.. image:: codegen_principle.png + :width: 500px + :align: center + :alt: Principle + +Inclusion of other inline code +------------------------------ + +.. image:: codegen_principle_include.png + :width: 500px + :align: center + :alt: Include other inline code + +Access to Zephyr data +--------------------- + +.. image:: codegen_principle_access.png + :width: 500px + :align: center + :alt: Access Zephyr data + +Import of Python modules +------------------------ + +.. image:: codegen_principle_import.png + :width: 500px + :align: center + :alt: Import Python modules + diff --git a/doc/subsystems/codegen/templates.rst b/doc/subsystems/codegen/templates.rst new file mode 100644 index 00000000000000..9c414a05ce0641 --- /dev/null +++ b/doc/subsystems/codegen/templates.rst @@ -0,0 +1,98 @@ +.. + Copyright (c) 2018 Bobby Noelte + SPDX-License-Identifier: Apache-2.0 + +.. _codegen_templates: + +Code Generation Templates +######################### + +Code generation templates provide sopisticated code generation functions. + +.. contents:: + :depth: 2 + :local: + :backlinks: top + +Templates have to be included to gain access to the template's functions +and variables. + + :: + + /* This file uses templates. */ + ... + /** + * @code{.codegen} + * template_in_var = 1 + * codegen.out_include('templates/template_tmpl.c') + * if template_out_var not None: + * codegen.outl("int x = %s;" % template_out_var) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + ... + +Device drivers +************** + +Pin controller drivers +---------------------- + +:: + + codegen.out_include('templates/drivers/pinctrl_tmpl.c') + +The template generates the most part of a pinctrl driver including driver +instantiation. + + The template expects the following globals to be set: + +.. attribute:: compatible + + The compatible string of the driver (e.g. 'st,stm32-pinctrl') + +.. attribute:: config_get + + C function name of device config_get function. + +.. attribute:: mux_free + + C function name of device mux_free function. + +.. attribute:: mux_get + + C function name of device mux_get function. + +.. attribute:: mux_set + + C function name of device mux_set function. + +.. attribute:: device_init + + C function name of device init function + +.. attribute:: data_info + + device data type definition (e.g. 'struct pinctrl_stm32_data') + +Usage example: + +:: + + /** + * @code{.codegen} + * compatible = 'st,stm32-pinctrl' + * config_get = 'pinctrl_stm32_config_get' + * config_set = 'pinctrl_stm32_config_set' + * mux_get = 'pinctrl_stm32_mux_get' + * mux_set = 'pinctrl_stm32_mux_set' + * device_init = 'pinctrl_stm32_device_init' + * data_info = 'struct pinctrl_stm32_data' + * codegen.out_include('templates/drivers/pinctrl_tmpl.c') + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + + + + diff --git a/doc/subsystems/subsystems.rst b/doc/subsystems/subsystems.rst index 4d1b2aa3bd13b3..6673318a66b59b 100644 --- a/doc/subsystems/subsystems.rst +++ b/doc/subsystems/subsystems.rst @@ -11,6 +11,7 @@ to applications. bluetooth/bluetooth.rst c_library + codegen/index dfu logging/index mgmt diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 77092775bc3868..51d6e462cf4ef7 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory_if_kconfig(led) add_subdirectory_if_kconfig(led_strip) add_subdirectory_if_kconfig(modem) add_subdirectory_if_kconfig(pci) +add_subdirectory_if_kconfig(pinctrl) add_subdirectory_if_kconfig(pinmux) add_subdirectory_if_kconfig(pwm) add_subdirectory_if_kconfig(rtc) diff --git a/drivers/Kconfig b/drivers/Kconfig index 86afd4ad577ef2..031b10f09c21f6 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -43,6 +43,8 @@ source "drivers/i2s/Kconfig" source "drivers/pwm/Kconfig" +source "drivers/pinctrl/Kconfig" + source "drivers/pinmux/Kconfig" source "drivers/adc/Kconfig" diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index 7b683babc3de35..b32e73dfd3160d 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -1,2 +1,2 @@ -zephyr_sources_ifdef(CONFIG_CAN_STM32 stm32_can.c) +zephyr_sources_codegen_ifdef(CONFIG_CAN_STM32 stm32_can.c) zephyr_sources_ifdef(CONFIG_USERSPACE can_handlers.c) diff --git a/drivers/can/stm32_can.c b/drivers/can/stm32_can.c index b9cbc85909fd8a..5d40a680f031f4 100644 --- a/drivers/can/stm32_can.c +++ b/drivers/can/stm32_can.c @@ -839,51 +839,66 @@ static const struct can_driver_api can_api_funcs = { .detach = can_stm32_detach }; -#ifdef CONFIG_CAN_1 - -static void config_can_1_irq(CAN_TypeDef *can); - -static const struct can_stm32_config can_stm32_cfg_1 = { - .can = (CAN_TypeDef *)CONFIG_CAN_1_BASE_ADDRESS, - .bus_speed = CONFIG_CAN_1_BUS_SPEED, - .swj = CONFIG_CAN_1_SJW, - .prop_bs1 = CONFIG_CAN_1_PROP_SEG_PHASE_SEG1, - .bs2 = CONFIG_CAN_1_PHASE_SEG2, - .pclken = { - .enr = CONFIG_CAN_1_CLOCK_BITS, - .bus = CONFIG_CAN_1_CLOCK_BUS, - }, - .config_irq = config_can_1_irq -}; - -static struct can_stm32_data can_stm32_dev_data_1; - -DEVICE_AND_API_INIT(can_stm32_1, CONFIG_CAN_1_NAME, &can_stm32_init, - &can_stm32_dev_data_1, &can_stm32_cfg_1, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &can_api_funcs); - -static void config_can_1_irq(CAN_TypeDef *can) -{ - SYS_LOG_DBG("Enable CAN1 IRQ"); -#ifdef CONFIG_SOC_SERIES_STM32F0X - IRQ_CONNECT(CONFIG_CAN_1_IRQ, CONFIG_CAN_1_IRQ_PRIORITY, can_stm32_isr, - DEVICE_GET(can_stm32_1), 0); - irq_enable(CONFIG_CAN_1_IRQ); -#else - IRQ_CONNECT(CONFIG_CAN_1_IRQ_RX0, CONFIG_CAN_1_IRQ_PRIORITY, - can_stm32_rx_isr, DEVICE_GET(can_stm32_1), 0); - irq_enable(CONFIG_CAN_1_IRQ_RX0); - - IRQ_CONNECT(CONFIG_CAN_1_IRQ_TX, CONFIG_CAN_1_IRQ_PRIORITY, - can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0); - irq_enable(CONFIG_CAN_1_IRQ_TX); - - IRQ_CONNECT(CONFIG_CAN_1_IRQ_SCE, CONFIG_CAN_1_IRQ_PRIORITY, - can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0); - irq_enable(CONFIG_CAN_1_IRQ_SCE); -#endif - can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1; -} - -#endif /*CONFIG_CAN_1*/ +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_CAN_1', ] + * driver_names = ['CAN_1', ] + * device_inits = 'can_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE' + * device_api = 'can_api_funcs' + * device_info = \ + * """ + * DEVICE_DECLARE(${device-name}); + * static void ${device-config-irq}(CAN_TypeDef *can) + * { + * SYS_LOG_DBG("Enable ${driver-name} IRQ"); + * #ifdef CONFIG_SOC_SERIES_STM32F0X + * IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority},\\ + * can_stm32_isr, + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/0/irq}); + * #else + * IRQ_CONNECT(${interrupts/rx0/irq}, ${interrupts/rx0/priority}, \\ + * can_stm32_rx_isr, + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/rx0/irq}); + * IRQ_CONNECT(${interrupts/tx/irq}, ${interrupts/tx/priority}, \\ + * can_stm32_tx_isr, + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/tx/irq}); + * IRQ_CONNECT(${interrupts/sce/irq}, ${interrupts/sce/priority}, \\ + * can_stm32_tx_isr, + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/sce/irq}); + * #endif + * can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1; + * } + * static const struct can_stm32_config ${device-config-info} = { + * .can = (CAN_TypeDef *)${reg/0/address/0}, + * .bus_speed = ${bus-speed}, + * .swj = ${sjw}, + * .prop_bs1 = ${prop_seg_phase_seg1}, + * .bs2 = ${phase_seg2}, + * .pclken = { + * .enr = ${clocks/0/bits}, + * .bus = ${clocks/0/bus}, + * }, + * .config_irq = ${device-config-irq}, + * }; + * static struct can_stm32_data ${device-data}; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index a5ee19bd175b6d..7442df4608d25c 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -1,5 +1,8 @@ zephyr_library() +if(CONFIG_PINCTRL) +zephyr_library_sources_codegen_ifdef(CONFIG_GPIO_STM32 gpio_pinctrl_stm32.c) +else() zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_NIOS2 gpio_altera_nios2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ATMEL_SAM3 gpio_atmel_sam3.c) zephyr_library_sources_ifdef(CONFIG_GPIO_CC2650 gpio_cc2650.c) @@ -24,5 +27,6 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_STM32 gpio_stm32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SAM0 gpio_sam0.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SAM gpio_sam.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c) +endif() zephyr_library_sources_ifdef(CONFIG_USERSPACE gpio_handlers.c) diff --git a/drivers/gpio/Kconfig.stm32 b/drivers/gpio/Kconfig.stm32 index 5e596bba81641e..d902c6f7e0a01f 100644 --- a/drivers/gpio/Kconfig.stm32 +++ b/drivers/gpio/Kconfig.stm32 @@ -6,8 +6,8 @@ # menuconfig GPIO_STM32 - bool "GPIO Driver for STM32 family of MCUs" - depends on GPIO && SOC_FAMILY_STM32 + bool "GPIO driver for STM32 family of MCUs" + default y if GPIO && SOC_FAMILY_STM32 select HAS_DTS_GPIO help Enable GPIO driver for STM32 line of MCUs diff --git a/drivers/gpio/gpio_pinctrl_stm32.c b/drivers/gpio/gpio_pinctrl_stm32.c new file mode 100644 index 00000000000000..1b22d393061873 --- /dev/null +++ b/drivers/gpio/gpio_pinctrl_stm32.c @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2016 Open-RnD Sp. z o.o. + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief STM32 GPIO implementation + * @defgroup device_driver_gpio_stm32_pin_controller STM32 GPIO inplementation + * + * A common driver for STM32 GPIOs. SoC specific adaptions are done by + * device tree and soc.h. + * + * The driver uses the PINCTRL device driver as a backend. + * + * @{ + */ + +#include +#include +#include + +#include +#include +#include +#include + +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_GPIO_LEVEL +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "gpio_utils.h" /* _gpio_manage_callback, _gpio_fire_callbacks */ + +/** + * @brief Configuration info for one GPIO device + */ +struct gpio_stm32_config { + /** Pin controller that controls the GPIO port pins. */ + const char *pinctrl_name; + /** Name of the GPIO bank (one of "GPIOA", ...) */ + const char *bank_name; + /** Pin-controller pin number of GPIO port pin 0 */ + u16_t pinctrl_base; + /** STM32Cube GPIOx */ + GPIO_TypeDef *ll_gpio_port; +}; + +/** + * @brief Driver data for one GPIO device. + */ +struct gpio_stm32_data { + /** Pin mask to enabled INT pins generate a callback */ + u32_t cb_pins; + /* User ISR callbacks */ + sys_slist_t cb; + /** PINCTRL GPIO function */ + u16_t pinctrl_function; + /** STM32Cube LL_SYSCFG_EXTI_PORTx */ + u32_t ll_syscfg_exti_port; +}; + +/** + * @brief Get pin controller for this GPIO. + * + * @param dev Pointer to the device structure for the driver instance. + * @return Pointer to device structure of pin controller. + */ +static inline struct device *gpio_stm32_pin_controller(struct device *dev) +{ + const struct gpio_stm32_config *cfg = dev->config->config_info; + + return device_get_binding(cfg->pinctrl_name); +} + +/** + * @brief Convert external interrupt line number to SYSCFG line definiton. + * + * @param exti_line Number of external interrupt line [0..15]. + * @return STM32CubeMX LL_SYSCFG_EXTI_LINEx. + */ +static inline u32_t gpio_stm32_ll_syscfg_exti_line(u8_t exti_line) +{ + + const u32_t ll_syscfg_exti_line[16] = { + LL_SYSCFG_EXTI_LINE0, + LL_SYSCFG_EXTI_LINE1, + LL_SYSCFG_EXTI_LINE2, + LL_SYSCFG_EXTI_LINE3, + LL_SYSCFG_EXTI_LINE4, + LL_SYSCFG_EXTI_LINE5, + LL_SYSCFG_EXTI_LINE6, + LL_SYSCFG_EXTI_LINE7, + LL_SYSCFG_EXTI_LINE8, + LL_SYSCFG_EXTI_LINE9, + LL_SYSCFG_EXTI_LINE10, + LL_SYSCFG_EXTI_LINE11, + LL_SYSCFG_EXTI_LINE12, + LL_SYSCFG_EXTI_LINE13, + LL_SYSCFG_EXTI_LINE14, + LL_SYSCFG_EXTI_LINE15 + }; + + return ll_syscfg_exti_line[exti_line]; +} + +/** + * @brief EXTI interrupt callback + * + * @param line External interrupt line (same as port pin idx). + * @param arg Device driver structure of GPIO device. + */ +static void gpio_stm32_isr(int line, void *arg) +{ + struct device *dev = arg; + struct gpio_stm32_data *data = dev->driver_data; + + u32_t pin_mask = GPIO_PORT_PIN(line); + + if (pin_mask & data->cb_pins) { + _gpio_fire_callbacks(&data->cb, dev, pin_mask); + } +} + +/* --- SoC specific functions --- */ + +/** + * @brief Connect external interrupt line to GPIO. + * + * @param dev Pointer to the device structure for the driver instance. + * @param exti_line Number of external interrupt line [0..15]. + */ +static inline void gpio_stm32_syscfg_set_exti_source(struct device *dev, + u8_t exti_line) +{ + struct gpio_stm32_data *data = dev->driver_data; + +#if !CONFIG_SOC_SERIES_STM32F1X + /* Assure system configuration register (SYSCFG) is + * clocked by associated peripherial bus clock. + * SYSCFG manages the external interrupt line + * connection to the GPIOs (among other purposes). + */ + struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); + + struct stm32_pclken pclken = { +#if CONFIG_SOC_SERIES_STM32F0X + .bus = STM32_CLOCK_BUS_APB1_2, + .enr = LL_APB1_GRP2_PERIPH_SYSCFG, +#elif CONFIG_SOC_SERIES_STM32F3X || \ + CONFIG_SOC_SERIES_STM32F4X || \ + CONFIG_SOC_SERIES_STM32F7X || \ + CONFIG_SOC_SERIES_STM32L0X || \ + CONFIG_SOC_SERIES_STM32L4X + .bus = STM32_CLOCK_BUS_APB2, + .enr = LL_APB2_GRP1_PERIPH_SYSCFG, +#else +#error "Unknown STM32 SoC series" +#endif + }; + + clock_control_on(clk, (clock_control_subsys_t *)&pclken); +#endif + + /* Connect external line to GPIO */ + LL_SYSCFG_SetEXTISource( + data->ll_syscfg_exti_port, + gpio_stm32_ll_syscfg_exti_line(exti_line)); +} + +/* --- API --- */ + +/** + * @brief Configure pin or port + * + * @param dev Pointer to the device structure for the driver instance. + * @param access_op GPIO_ACCESS_BY_PIN or GPIO_ACCESS_BY_PORT + * @param pin Pin to be configured in case of GPIO_ACCESS_BY_PIN. + * @param flags GPIO configuration flags + */ +static int gpio_stm32_config(struct device *dev, int access_op, + u32_t pin, int flags) +{ + const struct gpio_stm32_config *cfg = dev->config->config_info; + u32_t pin_mask; + + if (access_op == GPIO_ACCESS_BY_PIN) { + pin_mask = pin; + } else { + pin = GPIO_PORT_PIN0 | GPIO_PORT_PIN1 | GPIO_PORT_PIN2 | + GPIO_PORT_PIN3 | GPIO_PORT_PIN4 | GPIO_PORT_PIN5 | + GPIO_PORT_PIN6 | GPIO_PORT_PIN7 | GPIO_PORT_PIN8 | + GPIO_PORT_PIN9 | GPIO_PORT_PIN10 | GPIO_PORT_PIN11 | + GPIO_PORT_PIN12 | GPIO_PORT_PIN13 | GPIO_PORT_PIN14 | + GPIO_PORT_PIN15; + pin_mask = GPIO_PORT_PIN0; + } + + while (pin != 0) { + u32_t gpio_port_pin = pin & pin_mask; + + pin &= ~pin_mask; /* remove this pin from pin(s) */ + pin_mask = pin_mask << 1; /* prepare for next pin */ + if (!gpio_port_pin) { + continue; + } + int err; + u16_t pinctrl_pin = + cfg->pinctrl_base + gpio_port_pin_idx(gpio_port_pin); + + SYS_LOG_DBG("Configure GPIO pin: 0x%x, " + "PINCTRL pin: %d, flags: 0x%x.", + gpio_port_pin, (int)pinctrl_pin, flags); + +#if CONFIG_PINCTRL_RUNTIME_DTS + /* request pin */ + err = pinctrl_mux_request(gpio_stm32_pin_controller(dev), + pinctrl_pin, dev->config->name); + + if (err) { + SYS_LOG_DBG("Mux request failed (%d) - " + "GPIO pin: 0x%x, PINCTRL pin: %d.", + err, gpio_port_pin, (int)pinctrl_pin); + return err; + } +#endif + /* convert GPIO flags to PINCTRL pin configuration + * and configure pin + */ + u32_t config = 0; + u16_t func; + + err = pinctrl_config_get(gpio_stm32_pin_controller(dev), + pinctrl_pin, &config); + if (err) { + SYS_LOG_DBG("Config get failed (%d) - " + "GPIO pin: 0x%x, PINCTRL pin: %d.", + err, gpio_port_pin, (int)pinctrl_pin); + return err; + } + config &= ~PINCTRL_CONFIG_INPUT_MASK; + config &= ~PINCTRL_CONFIG_OUTPUT_MASK; + if ((flags & GPIO_DIR_MASK) == GPIO_DIR_OUT) { + config |= PINCTRL_CONFIG_INPUT_ENABLE; + config |= PINCTRL_CONFIG_OUTPUT_ENABLE; + func = PINCTRL_STM32_FUNCTION_OUTPUT; + } else { + config |= PINCTRL_CONFIG_INPUT_ENABLE; + config |= PINCTRL_CONFIG_OUTPUT_DISABLE; + func = PINCTRL_STM32_FUNCTION_INPUT; + } + if ((flags & GPIO_POL_MASK) == GPIO_POL_INV) { + config &= ~PINCTRL_CONFIG_OUTPUT_HIGH; + config |= PINCTRL_CONFIG_OUTPUT_LOW; + } else { + config &= ~PINCTRL_CONFIG_OUTPUT_LOW; + config |= PINCTRL_CONFIG_OUTPUT_HIGH; + } + config &= ~PINCTRL_CONFIG_BIAS_MASK; + switch (flags & GPIO_PUD_MASK) { + case GPIO_PUD_PULL_UP: + config |= PINCTRL_CONFIG_BIAS_PULL_UP; + break; + case GPIO_PUD_PULL_DOWN: + config |= PINCTRL_CONFIG_BIAS_PULL_DOWN; + break; + case GPIO_PUD_NORMAL: + default: + config |= PINCTRL_CONFIG_BIAS_DISABLE; + break; + } + config &= ~PINCTRL_CONFIG_DRIVE_MASK; + config &= ~PINCTRL_CONFIG_DRIVE_STRENGTH_MASK; + if ((flags & GPIO_DS_LOW_MASK) == GPIO_DS_DISCONNECT_LOW) { + config |= PINCTRL_CONFIG_DRIVE_OPEN_SOURCE; + /* low is disconnect, take high values */ + if ((flags & GPIO_DS_HIGH_MASK) == GPIO_DS_ALT_HIGH) { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_7; + } else { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT; + } + } else if ((flags & GPIO_DS_HIGH_MASK) == + GPIO_DS_DISCONNECT_HIGH) { + config |= PINCTRL_CONFIG_DRIVE_OPEN_DRAIN; + /* high is disconnect, take low values */ + if ((flags & GPIO_DS_LOW_MASK) == GPIO_DS_ALT_LOW) { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_7; + } else { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT; + } + } else { + config |= PINCTRL_CONFIG_DRIVE_PUSH_PULL; + if (((flags & GPIO_DS_LOW_MASK) == GPIO_DS_ALT_LOW) || + ((flags & GPIO_DS_HIGH_MASK) == GPIO_DS_ALT_HIGH)) { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_7; + } else { + config |= PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT; + } + } + err = pinctrl_config_set(gpio_stm32_pin_controller(dev), + pinctrl_pin, config); + if (err) { + SYS_LOG_DBG("Configure failed (%d) - " + "GPIO pin: 0x%x, PINCTRL pin: %d.", + err, gpio_port_pin, (int)pinctrl_pin); + return err; + } + err = pinctrl_mux_set(gpio_stm32_pin_controller(dev), + pinctrl_pin, func); + if (err) { + SYS_LOG_DBG("Mux failed (%d) - " + "GPIO pin: 0x%x, PINCTRL pin: %d.", + err, gpio_port_pin, (int)pinctrl_pin); + return err; + } + SYS_LOG_DBG("Configured GPIO pin: 0x%x, PINCTRL pin: %d.", + gpio_port_pin, (int)pinctrl_pin); + /* setup pin signalling */ + if (flags & GPIO_INT) { + /* There is no level interrupt mode for exti */ + if (flags & GPIO_INT_LEVEL) { + return -ENOTSUP; + } + u8_t exti_line = gpio_port_pin_idx(gpio_port_pin); + + SYS_LOG_DBG("Setup interrupt GPIO pin: 0x%x, line: %d.", + gpio_port_pin, (int)exti_line); + + /* Register callback on EXTI line interrupt. + * Unset any callback already registered. + * @TODO find a better way + */ + stm32_exti_unset_callback(exti_line); + stm32_exti_set_callback(exti_line, gpio_stm32_isr, dev); + + /* Connect external interrupt line to GPIO. */ + gpio_stm32_syscfg_set_exti_source(dev, exti_line); + + if (flags & GPIO_INT_EDGE) { + int edge = 0; + + if (flags & GPIO_INT_DOUBLE_EDGE) { + edge = STM32_EXTI_TRIG_RISING | + STM32_EXTI_TRIG_FALLING; + } else if (flags & GPIO_INT_ACTIVE_HIGH) { + edge = STM32_EXTI_TRIG_RISING; + } else { + edge = STM32_EXTI_TRIG_FALLING; + } + /* Configure interrupt trigger mode */ + stm32_exti_trigger(exti_line, edge); + } + /* Enable interrupt for this line */ + stm32_exti_enable(exti_line); + + SYS_LOG_DBG("Interrupt enabled " + "GPIO pin: 0x%x, line: %d.", + gpio_port_pin, (int)exti_line); + } + } + + return 0; +} + +/** + * @brief Set the pin or port output + */ +static int gpio_stm32_write(struct device *dev, int access_op, + u32_t pin, u32_t value) +{ + const struct gpio_stm32_config *cfg = dev->config->config_info; + + if (access_op == GPIO_ACCESS_BY_PIN) { +#if CONFIG_PINCTRL_RUNTIME_DTS + u16_t pinctrl_pin = cfg->pinctrl_base + gpio_port_pin_idx(pin); + /* request pin */ + int err = pinctrl_mux_request( + gpio_stm32_pin_controller(dev), pinctrl_pin, + dev->config->name); + + if (err) { + return err; + } +#endif + if (value > 0) { + LL_GPIO_SetOutputPin(cfg->ll_gpio_port, pin); + } else { + LL_GPIO_ResetOutputPin(cfg->ll_gpio_port, pin); + } + } else { + u32_t value_curr = LL_GPIO_ReadOutputPort(cfg->ll_gpio_port); + + value = (value_curr & ~pin) | (value & pin); + LL_GPIO_WriteOutputPort(cfg->ll_gpio_port, value); + } + + return 0; +} + +/** + * @brief Read data value from the port. + * + * Read the input state of a port or a pin. + * + * In case port access is requested by GPIO_ACCESS_BY_PORT the state of each + * pin is represented by one bit in the returned value. Pin 0 corresponds to + * the least significant bit, pin 31 corresponds to the most + * significant bit. Unused bits for ports with less that 32 physical + * pins are returned as 0. + * + * In case a single pin is requested value is set to 1 in case the pin is set, + * 0 otherwise. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin in case single pin value is requested by GPIO_ACCESS_BY_PIN. + * @param access_op GPIO_ACCESS_BY_PIN or GPIO_ACCESS_BY_PORT + * @param value Integer pointer to receive the data value from the port. + * @return 0 if successful, negative errno code on failure. + */ +static int gpio_stm32_read(struct device *dev, int access_op, u32_t pin, + u32_t *value) +{ + const struct gpio_stm32_config *cfg = dev->config->config_info; + + if (access_op == GPIO_ACCESS_BY_PIN) { + if (LL_GPIO_IsInputPinSet(cfg->ll_gpio_port, pin)) { + *value = 1; + } else { + *value = 0; + } + } else { + *value = LL_GPIO_ReadInputPort(cfg->ll_gpio_port); + } + + return 0; +} + +static int gpio_stm32_manage_callback(struct device *dev, + struct gpio_callback *callback, + bool set) +{ + struct gpio_stm32_data *data = dev->driver_data; + + _gpio_manage_callback(&data->cb, callback, set); + + return 0; +} + +static int gpio_stm32_enable_callback(struct device *dev, int access_op, + u32_t pin) +{ + struct gpio_stm32_data *data = dev->driver_data; + + if (access_op == GPIO_ACCESS_BY_PIN) { + data->cb_pins |= pin; + } else { + data->cb_pins |= + GPIO_PORT_PIN0 | GPIO_PORT_PIN1 | GPIO_PORT_PIN2 | + GPIO_PORT_PIN3 | GPIO_PORT_PIN4 | GPIO_PORT_PIN5 | + GPIO_PORT_PIN6 | GPIO_PORT_PIN7 | GPIO_PORT_PIN8 | + GPIO_PORT_PIN9 | GPIO_PORT_PIN10 | GPIO_PORT_PIN11 | + GPIO_PORT_PIN12 | GPIO_PORT_PIN13 | GPIO_PORT_PIN14 | + GPIO_PORT_PIN15; + } + + return 0; +} + +static int gpio_stm32_disable_callback(struct device *dev, + int access_op, u32_t pin) +{ + struct gpio_stm32_data *data = dev->driver_data; + + if (access_op == GPIO_ACCESS_BY_PIN) { + data->cb_pins &= ~pin; + } else { + data->cb_pins = 0; + } + return 0; +} + +static const struct gpio_driver_api gpio_stm32_driver_api = { + .config = gpio_stm32_config, + .write = gpio_stm32_write, + .read = gpio_stm32_read, + .manage_callback = gpio_stm32_manage_callback, + .enable_callback = gpio_stm32_enable_callback, + .disable_callback = gpio_stm32_disable_callback, +}; + +/** + * @brief Initialize GPIO port + * + * Perform basic initialization of a GPIO port. + * + * Clock enable is delegated to PINCTRL driver. + * + * @param device GPIO device struct + * + * @return 0 + */ +static int gpio_stm32_init(struct device *device) +{ + const struct gpio_stm32_config *cfg = + device->config->config_info; + + struct gpio_stm32_data *data = device->driver_data; + + __ASSERT(gpio_stm32_pin_controller(device) + == device_get_binding("PINCTRL"), + "GPIO pin controller not given (0x%x != 0x%x)", + (u32_t)gpio_stm32_pin_controller(device), + (u32_t)device_get_binding("PINCTRL")); + + switch (cfg->bank_name[4] - 'A') { +#if CONFIG_GPIO_STM32_PORTA + case 0: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTA; + break; +#endif +#if CONFIG_GPIO_STM32_PORTB + case 1: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTB; + break; +#endif +#if CONFIG_GPIO_STM32_PORTC + case 2: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTC; + break; +#endif +#if CONFIG_GPIO_STM32_PORTD + case 3: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTD; + break; +#endif +#if CONFIG_GPIO_STM32_PORTE + case 4: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTE; + break; +#endif +#if CONFIG_GPIO_STM32_PORTF + case 5: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTF; + break; +#endif +#if CONFIG_GPIO_STM32_PORTG + case 6: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTG; + break; +#endif +#if CONFIG_GPIO_STM32_PORTH + case 7: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTH; + break; +#endif +#if CONFIG_GPIO_STM32_PORTI + case 8: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTI; + break; +#endif +#if CONFIG_GPIO_STM32_PORTJ + case 9: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTJ; + break; +#endif +#if CONFIG_GPIO_STM32_PORTK + case 10: + data->ll_syscfg_exti_port = LL_SYSCFG_EXTI_PORTK; + break; +#endif + default: + __ASSERT(0, "GPIO bank unknown"); + break; + } + return 0; +} + +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_GPIO_STM32_PORT{}'.format(chr(x)) \ + * for x in range(ord('A'), ord('K') + 1)] + * driver_names = ['GPIO{}'.format(chr(x)) \ + * for x in range(ord('A'), ord('K') + 1)] + * device_inits = 'gpio_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEFAULT' + * device_api = 'gpio_stm32_driver_api' + * device_info = \ + * """ + * static const struct gpio_stm32_config ${device-config-info} = { + * .ll_gpio_port = (GPIO_TypeDef *)${reg/0/address/0}, + * .pinctrl_name = "${${gpio-ranges/0/pin-controller}:driver-name}", + * .pinctrl_base = ${gpio-ranges/0/pin-controller-base}, + * .bank_name = "${st,bank-name}", + * }; + * static struct gpio_stm32_data ${device-data}; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +/** @} device_driver_gpio_stm32_pin_controller */ + diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index b80a7ad4b104d3..a326b618a2f157 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -17,14 +17,11 @@ zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWIHS i2c_sam_twihs.c) zephyr_library_sources_ifdef(CONFIG_I2C_SBCON i2c_sbcon.c) zephyr_library_sources_ifdef(CONFIG_I2C_NIOS2 i2c_nios2.c) -zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 - i2c_ll_stm32_v1.c - i2c_ll_stm32.c - ) -zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V2 - i2c_ll_stm32_v2.c - i2c_ll_stm32.c - ) +zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32_v1.c) +zephyr_library_sources_codegen_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32.c) + +zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V2 i2c_ll_stm32_v2.c) +zephyr_library_sources_codegen_ifdef(CONFIG_I2C_STM32_V2 i2c_ll_stm32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE i2c_handlers.c) diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 48195747a84eb3..7b57747ebe5906 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 BayLibre, SAS * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2018 Bobby Noelte * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +19,23 @@ #define SYS_LOG_LEVEL CONFIG_SYS_LOG_I2C_LEVEL #include +#if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) +/* + * STM32F0/3 I2C's independent clock source supports only + * HSI and SYSCLK, not APB1. We force I2C clock source to SYSCLK. + * I2C2 on STM32F0 uses APB1 clock as I2C clock source + */ +#define LL_I2C_NO_CLOCKSOURCE 0x12345678 /* dummy value */ +#define LL_I2C_1_CLOCKSOURCE LL_RCC_I2C1_CLKSOURCE_SYSCLK +#if defined(CONFIG_SOC_SERIES_STM32F3X) +#define LL_I2C_2_CLOCKSOURCE LL_RCC_I2C2_CLKSOURCE_SYSCLK +#else +/* I2C2 on STM32F0 uses APB1 clock - can't set clock source */ +#define LL_I2C_2_CLOCKSOURCE LL_I2C_NO_CLOCKSOURCE +#endif +#define LL_I2C_3_CLOCKSOURCE LL_RCC_I2C3_CLKSOURCE_SYSCLK +#endif + int i2c_stm32_runtime_configure(struct device *dev, u32_t config) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); @@ -26,18 +44,24 @@ int i2c_stm32_runtime_configure(struct device *dev, u32_t config) u32_t clock = 0; #if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) - LL_RCC_ClocksTypeDef rcc_clocks; - - /* - * STM32F0/3 I2C's independent clock source supports only - * HSI and SYSCLK, not APB1. We force clock variable to - * SYSCLK frequency. - */ - LL_RCC_GetSystemClocksFreq(&rcc_clocks); - clock = rcc_clocks.SYSCLK_Frequency; + if (cfg->ll_clock_source != LL_I2C_NO_CLOCKSOURCE) { + LL_RCC_ClocksTypeDef rcc_clocks; + + /* + * STM32F0/3 I2C's independent clock source supports only + * HSI and SYSCLK, not APB1. We force clock variable to + * SYSCLK frequency. + */ + LL_RCC_GetSystemClocksFreq(&rcc_clocks); + clock = rcc_clocks.SYSCLK_Frequency; + } else + /* I2C2 on STM32F0 uses APB1 clock as I2C clock source */ #else - clock_control_get_rate(device_get_binding(STM32_CLOCK_CONTROL_NAME), + { + clock_control_get_rate( + device_get_binding(STM32_CLOCK_CONTROL_NAME), (clock_control_subsys_t *) &cfg->pclken, &clock); + } #endif /* CONFIG_SOC_SERIES_STM32F3X) || CONFIG_SOC_SERIES_STM32F0X */ data->dev_config = config; @@ -171,221 +195,82 @@ static int i2c_stm32_init(struct device *dev) clock_control_on(clock, (clock_control_subsys_t *) &cfg->pclken); #if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) - /* - * STM32F0/3 I2C's independent clock source supports only - * HSI and SYSCLK, not APB1. We force I2C clock source to SYSCLK. - * I2C2 on STM32F0 uses APB1 clock as I2C clock source - */ - - switch ((u32_t)cfg->i2c) { -#ifdef CONFIG_I2C_1 - case CONFIG_I2C_1_BASE_ADDRESS: - LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_SYSCLK); - break; -#endif /* CONFIG_I2C_1 */ - -#if defined(CONFIG_SOC_SERIES_STM32F3X) && defined(CONFIG_I2C_2) - case CONFIG_I2C_2_BASE_ADDRESS: - LL_RCC_SetI2CClockSource(LL_RCC_I2C2_CLKSOURCE_SYSCLK); - break; -#endif /* CONFIG_SOC_SERIES_STM32F3X && CONFIG_I2C_2 */ - -#ifdef CONFIG_I2C_3 - case CONFIG_I2C_3_BASE_ADDRESS: - LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_SYSCLK); - break; -#endif /* CONFIG_I2C_3 */ + if (cfg->ll_clock_source != LL_I2C_NO_CLOCKSOURCE) { + LL_RCC_SetI2CClockSource(cfg->ll_clock_source); } -#endif /* CONFIG_SOC_SERIES_STM32F3X) || CONFIG_SOC_SERIES_STM32F0X */ +#endif bitrate_cfg = _i2c_map_dt_bitrate(cfg->bitrate); ret = i2c_stm32_runtime_configure(dev, I2C_MODE_MASTER | bitrate_cfg); if (ret < 0) { - SYS_LOG_ERR("i2c: failure initializing"); + SYS_LOG_ERR("i2c: failure initializing %s", dev->config->name); return ret; } return 0; } -#ifdef CONFIG_I2C_1 - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_1(struct device *port); -#endif - -static const struct i2c_stm32_config i2c_stm32_cfg_1 = { - .i2c = (I2C_TypeDef *)CONFIG_I2C_1_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP1_PERIPH_I2C1, - .bus = STM32_CLOCK_BUS_APB1, - }, -#ifdef CONFIG_I2C_STM32_INTERRUPT - .irq_config_func = i2c_stm32_irq_config_func_1, -#endif - .bitrate = CONFIG_I2C_1_BITRATE, -}; - -static struct i2c_stm32_data i2c_stm32_dev_data_1; - -DEVICE_AND_API_INIT(i2c_stm32_1, CONFIG_I2C_1_NAME, &i2c_stm32_init, - &i2c_stm32_dev_data_1, &i2c_stm32_cfg_1, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &api_funcs); - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_1(struct device *dev) -{ -#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT - IRQ_CONNECT(CONFIG_I2C_1_COMBINED_IRQ, CONFIG_I2C_1_COMBINED_IRQ_PRI, - stm32_i2c_combined_isr, DEVICE_GET(i2c_stm32_1), 0); - irq_enable(CONFIG_I2C_1_COMBINED_IRQ); -#else - IRQ_CONNECT(CONFIG_I2C_1_EVENT_IRQ, CONFIG_I2C_1_EVENT_IRQ_PRI, - stm32_i2c_event_isr, DEVICE_GET(i2c_stm32_1), 0); - irq_enable(CONFIG_I2C_1_EVENT_IRQ); - - IRQ_CONNECT(CONFIG_I2C_1_ERROR_IRQ, CONFIG_I2C_1_ERROR_IRQ_PRI, - stm32_i2c_error_isr, DEVICE_GET(i2c_stm32_1), 0); - irq_enable(CONFIG_I2C_1_ERROR_IRQ); -#endif -} -#endif - -#endif /* CONFIG_I2C_1 */ - -#ifdef CONFIG_I2C_2 - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_2(struct device *port); -#endif - -static const struct i2c_stm32_config i2c_stm32_cfg_2 = { - .i2c = (I2C_TypeDef *)CONFIG_I2C_2_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP1_PERIPH_I2C2, - .bus = STM32_CLOCK_BUS_APB1, - }, -#ifdef CONFIG_I2C_STM32_INTERRUPT - .irq_config_func = i2c_stm32_irq_config_func_2, -#endif - .bitrate = CONFIG_I2C_2_BITRATE, -}; - -static struct i2c_stm32_data i2c_stm32_dev_data_2; - -DEVICE_AND_API_INIT(i2c_stm32_2, CONFIG_I2C_2_NAME, &i2c_stm32_init, - &i2c_stm32_dev_data_2, &i2c_stm32_cfg_2, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &api_funcs); - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_2(struct device *dev) -{ -#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT - IRQ_CONNECT(CONFIG_I2C_2_COMBINED_IRQ, CONFIG_I2C_2_COMBINED_IRQ_PRI, - stm32_i2c_combined_isr, DEVICE_GET(i2c_stm32_2), 0); - irq_enable(CONFIG_I2C_2_COMBINED_IRQ); -#else - IRQ_CONNECT(CONFIG_I2C_2_EVENT_IRQ, CONFIG_I2C_2_EVENT_IRQ_PRI, - stm32_i2c_event_isr, DEVICE_GET(i2c_stm32_2), 0); - irq_enable(CONFIG_I2C_2_EVENT_IRQ); - - IRQ_CONNECT(CONFIG_I2C_2_ERROR_IRQ, CONFIG_I2C_2_ERROR_IRQ_PRI, - stm32_i2c_error_isr, DEVICE_GET(i2c_stm32_2), 0); - irq_enable(CONFIG_I2C_2_ERROR_IRQ); -#endif -} -#endif - -#endif /* CONFIG_I2C_2 */ - -#ifdef CONFIG_I2C_3 - -#ifndef I2C3_BASE -#error "I2C_3 is not available on the platform that you selected" -#endif /* I2C3_BASE */ - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_3(struct device *port); -#endif - -static const struct i2c_stm32_config i2c_stm32_cfg_3 = { - .i2c = (I2C_TypeDef *)CONFIG_I2C_3_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP1_PERIPH_I2C3, - .bus = STM32_CLOCK_BUS_APB1, - }, -#ifdef CONFIG_I2C_STM32_INTERRUPT - .irq_config_func = i2c_stm32_irq_config_func_3, -#endif - .bitrate = CONFIG_I2C_3_BITRATE, -}; - -static struct i2c_stm32_data i2c_stm32_dev_data_3; - -DEVICE_AND_API_INIT(i2c_stm32_3, CONFIG_I2C_3_NAME, &i2c_stm32_init, - &i2c_stm32_dev_data_3, &i2c_stm32_cfg_3, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &api_funcs); - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_3(struct device *dev) -{ - IRQ_CONNECT(CONFIG_I2C_3_EVENT_IRQ, CONFIG_I2C_3_EVENT_IRQ_PRI, - stm32_i2c_event_isr, DEVICE_GET(i2c_stm32_3), 0); - irq_enable(CONFIG_I2C_3_EVENT_IRQ); - - IRQ_CONNECT(CONFIG_I2C_3_ERROR_IRQ, CONFIG_I2C_3_ERROR_IRQ_PRI, - stm32_i2c_error_isr, DEVICE_GET(i2c_stm32_3), 0); - irq_enable(CONFIG_I2C_3_ERROR_IRQ); -} -#endif - -#endif /* CONFIG_I2C_3 */ - -#ifdef CONFIG_I2C_4 - -#ifndef I2C4_BASE -#error "I2C_4 is not available on the platform that you selected" -#endif /* I2C4_BASE */ - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_4(struct device *port); -#endif - -static const struct i2c_stm32_config i2c_stm32_cfg_4 = { - .i2c = (I2C_TypeDef *)CONFIG_I2C_4_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP2_PERIPH_I2C4, - .bus = STM32_CLOCK_BUS_APB1_2, - }, -#ifdef CONFIG_I2C_STM32_INTERRUPT - .irq_config_func = i2c_stm32_irq_config_func_4, -#endif - .bitrate = CONFIG_I2C_4_BITRATE, -}; - -static struct i2c_stm32_data i2c_stm32_dev_data_4; - -DEVICE_AND_API_INIT(i2c_stm32_4, CONFIG_I2C_4_NAME, &i2c_stm32_init, - &i2c_stm32_dev_data_4, &i2c_stm32_cfg_4, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &api_funcs); - -#ifdef CONFIG_I2C_STM32_INTERRUPT -static void i2c_stm32_irq_config_func_4(struct device *dev) -{ - IRQ_CONNECT(CONFIG_I2C_4_EVENT_IRQ, CONFIG_I2C_4_EVENT_IRQ_PRI, - stm32_i2c_event_isr, DEVICE_GET(i2c_stm32_4), 0); - irq_enable(CONFIG_I2C_4_EVENT_IRQ); - - IRQ_CONNECT(CONFIG_I2C_4_ERROR_IRQ, CONFIG_I2C_4_ERROR_IRQ_PRI, - stm32_i2c_error_isr, DEVICE_GET(i2c_stm32_4), 0); - irq_enable(CONFIG_I2C_4_ERROR_IRQ); -} -#endif - -#endif /* CONFIG_I2C_4 */ - +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_I2C_{}'.format(x) for x in range(0, 5)] + * driver_names = ['I2C_{}'.format(x) for x in range(0, 5)] + * device_inits = 'i2c_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE' + * device_api = 'api_funcs' + * device_info = \ + * """ + * #if CONFIG_I2C_STM32_INTERRUPT + * DEVICE_DECLARE(${device-name}); + * static void ${device-config-irq}(struct device *dev) + * { + * #ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT + * IRQ_CONNECT(${interrupts/combined/irq}, \\ + * ${interrupts/combined/priority}, \\ + * stm32_i2c_combined_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/combined/irq}); + * #else + * IRQ_CONNECT(${interrupts/event/irq}, \\ + * ${interrupts/event/priority}, \\ + * stm32_i2c_event_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/event/irq}); + * IRQ_CONNECT(${interrupts/error/irq}, \\ + * ${interrupts/error/priority}, \\ + * stm32_i2c_error_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/error/irq}); + * #endif + * } + * #endif + * static const struct i2c_stm32_config ${device-config-info} = { + * .i2c = (I2C_TypeDef *)${reg/0/address/0}, + * .pclken.bus = ${clocks/0/bus}, + * .pclken.enr = ${clocks/0/bits}, + * #if CONFIG_I2C_STM32_INTERRUPT + * .irq_config_func = ${device-config-irq}, + * #endif + * .bitrate = ${clock-frequency}, + * #if defined(CONFIG_SOC_SERIES_STM32F3X) \\ + * || defined(CONFIG_SOC_SERIES_STM32F0X) + * .ll_clock_source = LL_${driver-name}_CLOCKSOURCE, + * #endif + * }; + * static struct i2c_stm32_data ${device-data}; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index 2a184d9ab55eec..a0818714473c35 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 BayLibre, SAS * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2018 Bobby Noelte * * SPDX-License-Identifier: Apache-2.0 * @@ -18,6 +19,9 @@ struct i2c_stm32_config { struct stm32_pclken pclken; I2C_TypeDef *i2c; u32_t bitrate; +#if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) + u32_t ll_clock_source; +#endif }; struct i2c_stm32_data { diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 19d27067ba5faa..2d4c86d07c161f 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -6,6 +6,6 @@ zephyr_sources_ifdef(CONFIG_MVIC mvic.c) zephyr_sources_ifdef(CONFIG_PIC_DISABLE i8259.c) zephyr_sources_ifdef(CONFIG_PLIC plic.c) zephyr_sources_ifdef(CONFIG_SHARED_IRQ shared_irq.c) -zephyr_sources_ifdef(CONFIG_SOC_FAMILY_STM32 exti_stm32.c) +zephyr_sources_codegen_ifdef(CONFIG_EXTI_STM32 exti_stm32.c) zephyr_sources_ifdef(CONFIG_CAVS_ICTL cavs_ictl.c) zephyr_sources_ifdef(CONFIG_DW_ICTL dw_ictl.c) diff --git a/drivers/interrupt_controller/exti_stm32.c b/drivers/interrupt_controller/exti_stm32.c index 42dbc18bcf40a5..bf528a391ddd9d 100644 --- a/drivers/interrupt_controller/exti_stm32.c +++ b/drivers/interrupt_controller/exti_stm32.c @@ -434,17 +434,34 @@ static int stm32_exti_init(struct device *dev) return 0; } -static struct stm32_exti_data exti_data; -DEVICE_INIT(exti_stm32, STM32_EXTI_NAME, stm32_exti_init, - &exti_data, NULL, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_data = [ 'stm32_exti_data', \ + * """ + * #define EXTI_STM32_DEVICE_NAME ${device-name} + * """] + * + * devicedeclare.device_declare( \ + * ['st,stm32-exti', ], + * 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE', + * 'PRE_KERNEL_1', + * None, + * 'stm32_exti_init', + * None, + * device_data, + * None) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ /** * @brief set & unset for the interrupt callbacks */ void stm32_exti_set_callback(int line, stm32_exti_callback_t cb, void *arg) { - struct device *dev = DEVICE_GET(exti_stm32); + struct device *dev = DEVICE_GET(EXTI_STM32_DEVICE_NAME); struct stm32_exti_data *data = dev->driver_data; __ASSERT(data->cb[line].cb == NULL, @@ -456,7 +473,7 @@ void stm32_exti_set_callback(int line, stm32_exti_callback_t cb, void *arg) void stm32_exti_unset_callback(int line) { - struct device *dev = DEVICE_GET(exti_stm32); + struct device *dev = DEVICE_GET(EXTI_STM32_DEVICE_NAME); struct stm32_exti_data *data = dev->driver_data; data->cb[line].cb = NULL; @@ -473,266 +490,267 @@ static void __stm32_exti_connect_irqs(struct device *dev) #ifdef CONFIG_SOC_SERIES_STM32F0X IRQ_CONNECT(EXTI0_1_IRQn, CONFIG_EXTI_STM32_EXTI1_0_IRQ_PRI, - __stm32_exti_isr_0_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_3_IRQn, CONFIG_EXTI_STM32_EXTI3_2_IRQ_PRI, - __stm32_exti_isr_2_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_15_IRQn, CONFIG_EXTI_STM32_EXTI15_4_IRQ_PRI, - __stm32_exti_isr_4_15, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4_15, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif CONFIG_SOC_SERIES_STM32F1X IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif CONFIG_SOC_SERIES_STM32F2X IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(PVD_IRQn, CONFIG_EXTI_STM32_PVD_IRQ_PRI, - __stm32_exti_isr_16, DEVICE_GET(exti_stm32), + __stm32_exti_isr_16, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_Alarm_IRQn, CONFIG_EXTI_STM32_RTC_ALARM_IRQ_PRI, - __stm32_exti_isr_17, DEVICE_GET(exti_stm32), + __stm32_exti_isr_17, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(OTG_FS_WKUP_IRQn, CONFIG_EXTI_STM32_OTG_FS_WKUP_IRQ_PRI, - __stm32_exti_isr_18, DEVICE_GET(exti_stm32), + __stm32_exti_isr_18, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(TAMP_STAMP_IRQn, CONFIG_EXTI_STM32_TAMP_STAMP_IRQ_PRI, - __stm32_exti_isr_21, DEVICE_GET(exti_stm32), + __stm32_exti_isr_21, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_WKUP_IRQn, CONFIG_EXTI_STM32_RTC_WKUP_IRQ_PRI, - __stm32_exti_isr_22, DEVICE_GET(exti_stm32), + __stm32_exti_isr_22, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif CONFIG_SOC_SERIES_STM32F3X IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_TSC_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif CONFIG_SOC_SERIES_STM32F4X IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(PVD_IRQn, CONFIG_EXTI_STM32_PVD_IRQ_PRI, - __stm32_exti_isr_16, DEVICE_GET(exti_stm32), + __stm32_exti_isr_16, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_Alarm_IRQn, CONFIG_EXTI_STM32_RTC_ALARM_IRQ_PRI, - __stm32_exti_isr_17, DEVICE_GET(exti_stm32), + __stm32_exti_isr_17, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(OTG_FS_WKUP_IRQn, CONFIG_EXTI_STM32_OTG_FS_WKUP_IRQ_PRI, - __stm32_exti_isr_18, DEVICE_GET(exti_stm32), + __stm32_exti_isr_18, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(TAMP_STAMP_IRQn, CONFIG_EXTI_STM32_TAMP_STAMP_IRQ_PRI, - __stm32_exti_isr_21, DEVICE_GET(exti_stm32), + __stm32_exti_isr_21, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_WKUP_IRQn, CONFIG_EXTI_STM32_RTC_WKUP_IRQ_PRI, - __stm32_exti_isr_22, DEVICE_GET(exti_stm32), + __stm32_exti_isr_22, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif CONFIG_SOC_SERIES_STM32F7X IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(PVD_IRQn, CONFIG_EXTI_STM32_PVD_IRQ_PRI, - __stm32_exti_isr_16, DEVICE_GET(exti_stm32), + __stm32_exti_isr_16, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_Alarm_IRQn, CONFIG_EXTI_STM32_RTC_ALARM_IRQ_PRI, - __stm32_exti_isr_17, DEVICE_GET(exti_stm32), + __stm32_exti_isr_17, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(OTG_FS_WKUP_IRQn, CONFIG_EXTI_STM32_OTG_FS_WKUP_IRQ_PRI, - __stm32_exti_isr_18, DEVICE_GET(exti_stm32), + __stm32_exti_isr_18, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(TAMP_STAMP_IRQn, CONFIG_EXTI_STM32_TAMP_STAMP_IRQ_PRI, - __stm32_exti_isr_21, DEVICE_GET(exti_stm32), + __stm32_exti_isr_21, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(RTC_WKUP_IRQn, CONFIG_EXTI_STM32_RTC_WKUP_IRQ_PRI, - __stm32_exti_isr_22, DEVICE_GET(exti_stm32), + __stm32_exti_isr_22, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(LPTIM1_IRQn, CONFIG_EXTI_STM32_LPTIM1_IRQ_PRI, - __stm32_exti_isr_23, DEVICE_GET(exti_stm32), + __stm32_exti_isr_23, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif defined(CONFIG_SOC_SERIES_STM32L0X) IRQ_CONNECT(EXTI0_1_IRQn, CONFIG_EXTI_STM32_EXTI1_0_IRQ_PRI, - __stm32_exti_isr_0_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_3_IRQn, CONFIG_EXTI_STM32_EXTI3_2_IRQ_PRI, - __stm32_exti_isr_2_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_15_IRQn, CONFIG_EXTI_STM32_EXTI15_4_IRQ_PRI, - __stm32_exti_isr_4_15, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4_15, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #elif defined(CONFIG_SOC_SERIES_STM32L4X) IRQ_CONNECT(EXTI0_IRQn, CONFIG_EXTI_STM32_EXTI0_IRQ_PRI, - __stm32_exti_isr_0, DEVICE_GET(exti_stm32), + __stm32_exti_isr_0, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI1_IRQn, CONFIG_EXTI_STM32_EXTI1_IRQ_PRI, - __stm32_exti_isr_1, DEVICE_GET(exti_stm32), + __stm32_exti_isr_1, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI2_IRQn, CONFIG_EXTI_STM32_EXTI2_IRQ_PRI, - __stm32_exti_isr_2, DEVICE_GET(exti_stm32), + __stm32_exti_isr_2, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI3_IRQn, CONFIG_EXTI_STM32_EXTI3_IRQ_PRI, - __stm32_exti_isr_3, DEVICE_GET(exti_stm32), + __stm32_exti_isr_3, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI4_IRQn, CONFIG_EXTI_STM32_EXTI4_IRQ_PRI, - __stm32_exti_isr_4, DEVICE_GET(exti_stm32), + __stm32_exti_isr_4, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI9_5_IRQn, CONFIG_EXTI_STM32_EXTI9_5_IRQ_PRI, - __stm32_exti_isr_9_5, DEVICE_GET(exti_stm32), + __stm32_exti_isr_9_5, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); IRQ_CONNECT(EXTI15_10_IRQn, CONFIG_EXTI_STM32_EXTI15_10_IRQ_PRI, - __stm32_exti_isr_15_10, DEVICE_GET(exti_stm32), + __stm32_exti_isr_15_10, DEVICE_GET(EXTI_STM32_DEVICE_NAME), 0); #endif } + diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt new file mode 100644 index 00000000000000..2022b72ccfbfa7 --- /dev/null +++ b/drivers/pinctrl/CMakeLists.txt @@ -0,0 +1,5 @@ +zephyr_library() + +zephyr_library_sources_codegen_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c) + +zephyr_library_sources_ifdef(CONFIG_USERSPACE pinctrl_handlers.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig new file mode 100644 index 00000000000000..4cae950a8c7b95 --- /dev/null +++ b/drivers/pinctrl/Kconfig @@ -0,0 +1,76 @@ +# Kconfig - Pinctrl configuration options + +# +# Copyright (c) 2017 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# Pinctrl options +# +menuconfig PINCTRL + bool "PINCTRL driver" + default n + +if PINCTRL + +config PINCTRL_RUNTIME_DTS + bool "Enable run time pin configuration control based on DTS" + default y + help + Supports extended pin controller functionality. + + Enable if run time pin configuration control based on + device tree information is needed. + +config PINCTRL_PINMUX + bool "Enable generic PINMUX interface for pinctrl drivers" + default y + help + Map PINMUX functions to PINCTRL functions. + + Enable to use the PINMUX interface with pinctrl drivers. + This interface is for transition. Only use if necessary + by drivers calling this interface. + +config PINCTRL_INIT_PRIORITY + int + prompt "Init priority" + default 2 + help + Pinctrl driver initialization priority. + + Pinctrl driver almost certainly should be initialized before the + rest of hardware devices (which may need specific pins already + configured for them). + Thus, its priority should be between KERNEL_INIT_PRIORITY_DEFAULT + and KERNEL_INIT_PRIORITY_DEVICE. There are exceptions to this + rule for particular boards. Don't change this value unless you + know what you are doing. + +config SYS_LOG_PINCTRL_LEVEL + int + prompt "PINCTRL Driver Log level" + depends on SYS_LOG + default 0 + range 0 4 + help + Sets log level for PINCTRL drivers. + + Levels are: + + - 0 OFF, do not write + + - 1 ERROR, only write SYS_LOG_ERR + + - 2 WARNING, write SYS_LOG_WRN in addition to previous level + + - 3 INFO, write SYS_LOG_INF in addition to previous levels + + - 4 DEBUG, write SYS_LOG_DBG in addition to previous levels + +source "drivers/pinctrl/Kconfig.stm32" + + +endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.stm32 b/drivers/pinctrl/Kconfig.stm32 new file mode 100644 index 00000000000000..acae0f96833ba8 --- /dev/null +++ b/drivers/pinctrl/Kconfig.stm32 @@ -0,0 +1,13 @@ +# Kconfig - configuration for STM32 pinctrl +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +config PINCTRL_STM32 + bool "Pinctrl driver for STM32 MCUs" + default y if PINCTRL && SOC_FAMILY_STM32 + help + Enable pin controller for STM32 MCUs + diff --git a/drivers/pinctrl/pinctrl_handlers.c b/drivers/pinctrl/pinctrl_handlers.c new file mode 100644 index 00000000000000..088533d45e4f8a --- /dev/null +++ b/drivers/pinctrl/pinctrl_handlers.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +Z_SYSCALL_HANDLER(pinctrl_get_pins_count, dev) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_get_pins_count((struct device *)dev); +} + +Z_SYSCALL_HANDLER(pinctrl_get_groups_count, dev) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_get_groups_count((struct device *)dev); +} + +Z_SYSCALL_HANDLER(pinctrl_get_group_pins, dev, group, pins, num_pins) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(pins, sizeof(u16_t) * *num_pins); + Z_SYSCALL_MEMORY_WRITE(num_pins, sizeof(u16_t)); + return _impl_pinctrl_get_group_pins( + (struct device *)dev, group, (u16_t *)pins, (u16_t *)num_pins); +} + +Z_SYSCALL_HANDLER(pinctrl_get_states_count, dev) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_get_states_count((struct device *)dev); +} + +Z_SYSCALL_HANDLER(pinctrl_get_state_group, dev, state, group) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(group, sizeof(u16_t)); + return pinctrl_get_state_group( + (struct device *)dev, func, name, (u16_t *)group); +} + +Z_SYSCALL_HANDLER(pinctrl_get_functions_count, dev) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_get_functions_count((struct device *)dev); +} + +Z_SYSCALL_HANDLER(pinctrl_get_function_group, dev, func, name, group) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(group, sizeof(u16_t)); + return _impl_pinctrl_get_function_group( + (struct device *)dev, func, name, (u16_t *)group); +} + +Z_SYSCALL_HANDLER(pinctrl_get_function_groups, dev, func, groups, num_groups) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(groups, sizeof(u16_t) * *num_groups); + Z_SYSCALL_MEMORY_WRITE(num_groups, sizeof(u16_t)); + return _impl_pinctrl_get_function_groups((struct device *)dev, + func, + (u16_t *)groups, + (u16_t *)num_groups); +} + +Z_SYSCALL_HANDLER(pinctrl_get_function_state, dev, func, name, state) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(state, sizeof(u16_t)); + return _impl_pinctrl_get_function_state( + (struct device *)dev, func, name, (u16_t *)state); +} + +Z_SYSCALL_HANDLER(pinctrl_get_function_states, dev, func, states, num_states) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(states, sizeof(u16_t) * *num_states); + Z_SYSCALL_MEMORY_WRITE(num_states, sizeof(u16_t)); + return _impl_pinctrl_get_function_states((struct device *)dev, + func, + (u16_t *)states, + (u16_t *)num_states); +} + +Z_SYSCALL_HANDLER(pinctrl_get_device_function, dev, other, func) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(func, sizeof(u16_t)); + return _impl_pinctrl_get_device_function( + (struct device *)dev, (struct device *)other, (u16_t *)func); +} + +Z_SYSCALL_HANDLER(pinctrl_get_gpio_range, dev, gpio, gpio_pin, pin, base_pin, + num_pins) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_OBJ(gpio, K_OBJ_DRIVER_GPIO); + Z_SYSCALL_MEMORY_WRITE(pin, sizeof(u16_t)); + Z_SYSCALL_MEMORY_WRITE(base_pin, sizeof(u16_t)); + Z_SYSCALL_MEMORY_WRITE(num_pins, sizeof(u8_t)); + return _impl_pinctrl_get_gpio_range((struct device *)dev, + (struct device *)gpio, + gpio_pin, + (u16_t *)pin, + (u16_t *)base_pin, + (u8_t *)num_pins); +} + +Z_SYSCALL_HANDLER(pinctrl_config_get, dev, pin, config) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(config, sizeof(u32_t)); + return _impl_pinctrl_config_get( + (struct device *)dev, pin, (u32_t *)config); +} + +Z_SYSCALL_HANDLER(pinctrl_config_set, dev, pin, config) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_config_set((struct device *)dev, pin, config); +} + +Z_SYSCALL_HANDLER(pinctrl_config_group_get, dev, group, configs, num_configs) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(configs, sizeof(u32_t) * *num_configs); + Z_SYSCALL_MEMORY_WRITE(num_configs, sizeof(u16_t)); + return _impl_pinctrl_config_group_get((struct device *)dev, + group, + (u32_t *)configs, + (u16_t *)num_configs); +} + +Z_SYSCALL_HANDLER(pinctrl_config_group_set, dev, group, configs, num_configs) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_config_group_get( + (struct device *)dev, group, configs, num_configs); +} + +Z_SYSCALL_HANDLER(pinctrl_mux_request, dev, pin, owner) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_mux_request((struct device *)dev, pin, owner); +} + +Z_SYSCALL_HANDLER(pinctrl_mux_free, dev, pin, owner) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_mux_free((struct device *)dev, pin, owner); +} + +Z_SYSCALL_HANDLER(pinctrl_mux_get, dev, pin, func) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + Z_SYSCALL_MEMORY_WRITE(func, sizeof(u32_t)); + return _impl_pinctrl_mux_get((struct device *)dev, pin, (u32_t *)func); +} + +Z_SYSCALL_HANDLER(pinctrl_mux_set, dev, pin, func) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_mux_set((struct device *)dev, pin, func); +} + +Z_SYSCALL_HANDLER(pinctrl_mux_group_set, dev, group, func) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_mux_group_set((struct device *)dev, group, func); +} + +Z_SYSCALL_HANDLER(pinctrl_state_set, dev, state) +{ + Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_PINCTRL); + return _impl_pinctrl_mux_get((struct device *)dev, state); +} diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c new file mode 100644 index 00000000000000..c436aec0c7b613 --- /dev/null +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief STM32 pinctrl implementation + * @defgroup device_driver_pinctrl_stm32 STM32 pinctrl inplementation + * + * A common driver for STM32 pinctrl. SoC specific adaptions are + * done by device tree and soc.h. + * + * @{ + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * @def PINCTRL_STM32_GPIO_COUNT + * @brief Number of GPIO ports that may be managed by the pinctrl driver. + * + * This is the total number of GPIO ports available. The number of activated + * GPIO ports may be less. + */ +/* GPIOx is defined by the STM32 CubeMX library. */ +#if defined(GPIOK) +#define PINCTRL_STM32_GPIO_COUNT 11 +#elif defined(GPIOJ) +#define PINCTRL_STM32_GPIO_COUNT 10 +#elif defined(GPIOI) +#define PINCTRL_STM32_GPIO_COUNT 9 +#elif defined(GPIOH) +#define PINCTRL_STM32_GPIO_COUNT 8 +#elif defined(GPIOG) +#define PINCTRL_STM32_GPIO_COUNT 7 +#elif defined(GPIOF) +#define PINCTRL_STM32_GPIO_COUNT 6 +#elif defined(GPIOE) +#define PINCTRL_STM32_GPIO_COUNT 5 +#elif defined(GPIOD) +#define PINCTRL_STM32_GPIO_COUNT 4 +#elif defined(GPIOC) +#define PINCTRL_STM32_GPIO_COUNT 3 +#elif defined(GPIOB) +#define PINCTRL_STM32_GPIO_COUNT 2 +#elif defined(GPIOA) +#define PINCTRL_STM32_GPIO_COUNT 1 +#else +#define PINCTRL_STM32_GPIO_COUNT 0 +#error "Missing GPIOx definition!" +#endif + +/** + * @brief Driver data for one PINCTRL device. + */ +struct pinctrl_stm32_data { + /** clock control device */ + struct device *clk; + /** Peripherial bus clock enable info for gpio devices */ + struct stm32_pclken pclken_gpio; +}; + +/** + * @brief GPIO info. + */ +struct pinctrl_stm32_gpio { + u32_t ll_gpio_pclken_enr; + GPIO_TypeDef *ll_gpio_port; +}; + +/** + * @brief GPIO data. + */ +static const struct pinctrl_stm32_gpio + pinctrl_stm32_gpio_data[PINCTRL_STM32_GPIO_COUNT] = { +/** + * @code{.codegen} + * # Evaluate the clock bus for the GPIOs. + * # @todo Take clock bus from device tree + * bus = None + * if codegen.config_property('CONFIG_SOC_SERIES_STM32F0X', 0) or \ + * codegen.config_property('CONFIG_SOC_SERIES_STM32F3X', 0) or \ + * codegen.config_property('CONFIG_SOC_SERIES_STM32F4X', 0) or \ + * codegen.config_property('CONFIG_SOC_SERIES_STM32F7X', 0): + * bus = 'AHB1' + * elif codegen.config_property('CONFIG_SOC_SERIES_STM32F1X', 0): + * bus = 'APB1' + * elif codegen.config_property('CONFIG_SOC_SERIES_STM32L4X', 0): + * bus = 'AHB2' + * # Iterate the possible GPIOs + * for x in range(0, 11): + * port = 'GPIO{}'.format(chr(ord('A') + x)) + * codegen.outl('#if PINCTRL_STM32_GPIO_COUNT > {}'.format(x)) + * codegen.outl('\t{') + * codegen.outl('#if defined({})'.format(port)) + * codegen.outl('\t\t.ll_gpio_pclken_enr = LL_{}_GRP1_PERIPH_{},'.format( + * bus, port)) + * codegen.outl('\t\t.ll_gpio_port = {},'.format(port)) + * codegen.outl('#else') + * codegen.outl('\t\t.ll_gpio_pclken_enr = 0,') + * codegen.outl('\t\t.ll_gpio_port = 0,') + * codegen.outl('#endif'.format(port)) + * codegen.outl('\t},') + * codegen.outl('#endif') + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ +}; + +/* --- API (using the PINCTRL template code) --- */ + +/* forward declarations */ +static int pinctrl_stm32_config_get(struct device *dev, u16_t pin, + u32_t *config); +static int pinctrl_stm32_config_set(struct device *dev, u16_t pin, + u32_t config); +static int pinctrl_stm32_mux_get(struct device *dev, u16_t pin, u16_t *func); +static int pinctrl_stm32_mux_set(struct device *dev, u16_t pin, u16_t func); +static int pinctrl_stm32_device_init(struct device *dev); + +/** + * @code{.codegen} + * compatible = 'st,stm32-pinctrl' + * config_get = 'pinctrl_stm32_config_get' + * config_set = 'pinctrl_stm32_config_set' + * mux_get = 'pinctrl_stm32_mux_get' + * mux_set = 'pinctrl_stm32_mux_set' + * device_init = 'pinctrl_stm32_device_init' + * data_info = 'struct pinctrl_stm32_data' + * codegen.out_include('templates/drivers/pinctrl_tmpl.c') + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +/** + * @brief Convert pin number to STM32CubeMX GPIO port descriptor. + * + * @param pin Pin number + * @return STM32CubeMX GPIO port descriptor + */ +static GPIO_TypeDef *pinctrl_stm32_ll_gpio_port(u16_t pin) +{ + int port_idx = (pin >> 4) & 0x0F; + + __ASSERT((port_idx < PINCTRL_STM32_GPIO_COUNT), + "pin unknown - no GPIO port descriptor"); + __ASSERT((pinctrl_stm32_gpio_data[port_idx].ll_gpio_port != 0), + "pin unknown - no GPIO port descriptor"); + + return pinctrl_stm32_gpio_data[port_idx].ll_gpio_port; +} + +/** + * @brief Convert pin number to STM32CubeMX GPIO pin descriptor. + * + * @param pin Pin number + * @return STM32CubeMX GPIO pin descriptor + */ +static inline u32_t pinctrl_stm32_ll_gpio_pin(u16_t pin) +{ + return 0x01U << (pin & 0x0F); +} + +/** + * @brief Get STM32CubeMX GPIO mode associated to function. + * + * @param func Function + * @return STM32CubeMX GPIO mode + */ +static u32_t pinctrl_stm32_ll_gpio_mode(u16_t func) +{ + switch (func) { + case PINCTRL_STM32_FUNCTION_ALT_0: + case PINCTRL_STM32_FUNCTION_ALT_1: + case PINCTRL_STM32_FUNCTION_ALT_2: + case PINCTRL_STM32_FUNCTION_ALT_3: + case PINCTRL_STM32_FUNCTION_ALT_4: + case PINCTRL_STM32_FUNCTION_ALT_5: + case PINCTRL_STM32_FUNCTION_ALT_6: + case PINCTRL_STM32_FUNCTION_ALT_7: + case PINCTRL_STM32_FUNCTION_ALT_8: + case PINCTRL_STM32_FUNCTION_ALT_9: + case PINCTRL_STM32_FUNCTION_ALT_10: + case PINCTRL_STM32_FUNCTION_ALT_11: + case PINCTRL_STM32_FUNCTION_ALT_12: + case PINCTRL_STM32_FUNCTION_ALT_13: + case PINCTRL_STM32_FUNCTION_ALT_14: + case PINCTRL_STM32_FUNCTION_ALT_15: + return LL_GPIO_MODE_ALTERNATE; + case PINCTRL_STM32_FUNCTION_INPUT: + return LL_GPIO_MODE_INPUT; + case PINCTRL_STM32_FUNCTION_OUTPUT: + return LL_GPIO_MODE_OUTPUT; + case PINCTRL_STM32_FUNCTION_ANALOG: + return LL_GPIO_MODE_ANALOG; + } + __ASSERT(0, "function 0x%x unknown - no LL_GPIO_MODE", (int)func); + return 0; +} + +static inline u32_t pinctrl_stm32_ll_gpio_alt_func(u16_t func) +{ + if ((func >= PINCTRL_STM32_FUNCTION_ALT_0) && + (func <= PINCTRL_STM32_FUNCTION_ALT_15)) { + return func - PINCTRL_STM32_FUNCTION_ALT_0; + } + __ASSERT(0, "function 0x%x unknown - no LL_GPIO_ALT_FUNC", (int)func); + return func; +} + +/** + * @brief Enable GPIO port to be clocked by associated peripherial bus clock. + * + * @param dev Pointer to the device structure for the driver instance. + * @param port_idx Index of GPIO port + */ +static void pinctrl_stm32_gpio_enable_clock(struct device *dev, int port_idx) +{ + __ASSERT((port_idx < PINCTRL_STM32_GPIO_COUNT), + "port unknown - invalid port_idx"); + __ASSERT((pinctrl_stm32_gpio_data[port_idx].ll_gpio_port != 0), + "port unknown - invalid port_idx"); + + struct pinctrl_stm32_data *data = dev->driver_data; + /* data->pclken_gpio.bus already set by init */ + data->pclken_gpio.enr = + pinctrl_stm32_gpio_data[port_idx].ll_gpio_pclken_enr; + clock_control_on( + data->clk, + (clock_control_subsys_t)&data->pclken_gpio); +} + +/** + * Get the configuration of a pin. + * + * The following configuration options are supported. + * + * Options set by configuration or mux function: + * - @ref PINCTRL_CONFIG_BIAS_DISABLE + * + * Options set by configuration: + * - @ref PINCTRL_CONFIG_BIAS_PULL_UP + * - @ref PINCTRL_CONFIG_BIAS_PULL_DOWN + * - @ref PINCTRL_CONFIG_DRIVE_PUSH_PULL + * - @ref PINCTRL_CONFIG_DRIVE_OPEN_DRAIN + * - @ref PINCTRL_CONFIG_SPEED_SLOW + * - @ref PINCTRL_CONFIG_SPEED_MEDIUM + * - @ref PINCTRL_CONFIG_SPEED_HIGH + * + * Options set/ forced by mux function only: + * - @ref PINCTRL_CONFIG_INPUT_ENABLE + * - @ref PINCTRL_CONFIG_INPUT_DISABLE + * - @ref PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE + * - @ref PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE + * - @ref PINCTRL_CONFIG_OUTPUT_ENABLE + * - @ref PINCTRL_CONFIG_OUTPUT_DISABLE + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param config + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + * @retval -EINVAL if requested pin is available but disabled + */ +static int pinctrl_stm32_config_get(struct device *dev, u16_t pin, + u32_t *config) +{ + ARG_UNUSED(dev); + + if (pin >= pinctrl_tmpl_control_get_pins_count(dev)) { + return -ENOTSUP; + } + + *config = 0; + + GPIO_TypeDef *ll_gpio_port = pinctrl_stm32_ll_gpio_port(pin); + u32_t ll_gpio_pin = pinctrl_stm32_ll_gpio_pin(pin); + + /* current pin mode (muxing function) */ + switch (LL_GPIO_GetPinMode(ll_gpio_port, ll_gpio_pin)) { + case LL_GPIO_MODE_ALTERNATE: + *config |= PINCTRL_CONFIG_OUTPUT_ENABLE | + PINCTRL_CONFIG_INPUT_ENABLE | + PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE; + break; + case LL_GPIO_MODE_OUTPUT: + *config |= PINCTRL_CONFIG_OUTPUT_ENABLE | + PINCTRL_CONFIG_INPUT_ENABLE | + PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE; + break; + case LL_GPIO_MODE_INPUT: + *config |= PINCTRL_CONFIG_INPUT_ENABLE | + PINCTRL_CONFIG_OUTPUT_DISABLE | + PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE; + break; + case LL_GPIO_MODE_ANALOG: + *config |= PINCTRL_CONFIG_OUTPUT_DISABLE | + PINCTRL_CONFIG_INPUT_DISABLE | + PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE | + PINCTRL_CONFIG_BIAS_DISABLE; + break; + } + + if (!(*config | PINCTRL_CONFIG_BIAS_DISABLE)) { + switch (LL_GPIO_GetPinOutputType(ll_gpio_port, ll_gpio_pin)) { + case LL_GPIO_OUTPUT_PUSHPULL: + *config |= PINCTRL_CONFIG_BIAS_DISABLE; + break; + case LL_GPIO_PULL_UP: + *config |= PINCTRL_CONFIG_BIAS_PULL_UP; + break; + case LL_GPIO_PULL_DOWN: + *config |= PINCTRL_CONFIG_BIAS_PULL_DOWN; + break; + } + } + + switch (LL_GPIO_GetPinSpeed(ll_gpio_port, ll_gpio_pin)) { + case LL_GPIO_SPEED_FREQ_LOW: + *config |= PINCTRL_CONFIG_SPEED_SLOW; + break; + case LL_GPIO_SPEED_FREQ_MEDIUM: + *config |= PINCTRL_CONFIG_SPEED_MEDIUM; + break; + case LL_GPIO_SPEED_FREQ_HIGH: + *config |= PINCTRL_CONFIG_SPEED_HIGH; + break; + } + + switch (LL_GPIO_GetPinOutputType(ll_gpio_port, ll_gpio_pin)) { + case LL_GPIO_OUTPUT_PUSHPULL: + *config |= PINCTRL_CONFIG_DRIVE_PUSH_PULL; + break; + case LL_GPIO_OUTPUT_OPENDRAIN: + *config |= PINCTRL_CONFIG_DRIVE_OPEN_DRAIN; + break; + } + + return 0; +} + +/** + * @brief Configure a pin. + * + * The following configuration options are supported: + * - @ref PINCTRL_CONFIG_BIAS_DISABLE + * - @ref PINCTRL_CONFIG_BIAS_PULL_UP + * - @ref PINCTRL_CONFIG_BIAS_PULL_DOWN + * - @ref PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT + * - @ref PINCTRL_CONFIG_DRIVE_PUSH_PULL + * - @ref PINCTRL_CONFIG_DRIVE_OPEN_DRAIN + * - @ref PINCTRL_CONFIG_SPEED_SLOW + * - @ref PINCTRL_CONFIG_SPEED_MEDIUM + * - @ref PINCTRL_CONFIG_SPEED_FAST + * - @ref PINCTRL_CONFIG_SPEED_HIGH + * + * @note For safety purposes the pin should be reset to input before + * configuration. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param config + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + */ +static int pinctrl_stm32_config_set(struct device *dev, u16_t pin, u32_t config) +{ + ARG_UNUSED(dev); + + if (pin >= pinctrl_tmpl_control_get_pins_count(dev)) { + return -ENOTSUP; + } + + u32_t ll_gpio_output_type = LL_GPIO_OUTPUT_PUSHPULL; + u32_t ll_gpio_speed = LL_GPIO_SPEED_FREQ_LOW; + u32_t ll_gpio_pull = LL_GPIO_PULL_NO; + + GPIO_TypeDef *ll_gpio_port = pinctrl_stm32_ll_gpio_port(pin); + u32_t ll_gpio_pin = pinctrl_stm32_ll_gpio_pin(pin); + + switch (config & PINCTRL_CONFIG_SPEED_HIGH) { + case PINCTRL_CONFIG_SPEED_SLOW: + ll_gpio_speed = LL_GPIO_SPEED_FREQ_LOW; + break; + case PINCTRL_CONFIG_SPEED_MEDIUM: + ll_gpio_speed = LL_GPIO_SPEED_FREQ_MEDIUM; + break; + case PINCTRL_CONFIG_SPEED_FAST: + case PINCTRL_CONFIG_SPEED_HIGH: + ll_gpio_speed = LL_GPIO_SPEED_FREQ_HIGH; + break; + } + LL_GPIO_SetPinSpeed(ll_gpio_port, ll_gpio_pin, ll_gpio_speed); + + if (config & (PINCTRL_CONFIG_BIAS_DISABLE | + PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT)) { + ll_gpio_pull = LL_GPIO_PULL_NO; + } else if (config & PINCTRL_CONFIG_BIAS_PULL_UP) { + ll_gpio_pull = LL_GPIO_PULL_UP; + } else if (config & PINCTRL_CONFIG_BIAS_PULL_DOWN) { + ll_gpio_pull = LL_GPIO_PULL_DOWN; + } + LL_GPIO_SetPinPull(ll_gpio_port, ll_gpio_pin, ll_gpio_pull); + + if (config & PINCTRL_CONFIG_DRIVE_OPEN_DRAIN) { + ll_gpio_output_type = LL_GPIO_OUTPUT_OPENDRAIN; + } else if (config & PINCTRL_CONFIG_DRIVE_PUSH_PULL) { + ll_gpio_output_type = LL_GPIO_OUTPUT_PUSHPULL; + } + LL_GPIO_SetPinOutputType( + ll_gpio_port, ll_gpio_pin, ll_gpio_output_type); + + return 0; +} + +/** + * @brief Get muxing function at pin + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param[out] func Muxing function + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + */ +static int pinctrl_stm32_mux_get(struct device *dev, u16_t pin, u16_t *func) +{ + ARG_UNUSED(dev); + + if (pin >= pinctrl_tmpl_control_get_pins_count(dev)) { + return -ENOTSUP; + } + + GPIO_TypeDef *ll_gpio_port = pinctrl_stm32_ll_gpio_port(pin); + u32_t ll_gpio_pin = pinctrl_stm32_ll_gpio_pin(pin); + + /* current pin mode (muxing function) */ + switch (LL_GPIO_GetPinMode(ll_gpio_port, ll_gpio_pin)) { + case LL_GPIO_MODE_ALTERNATE: + if (ll_gpio_pin <= LL_GPIO_PIN_7) { + *func = LL_GPIO_GetAFPin_0_7(ll_gpio_port, ll_gpio_pin); + } else { + *func = LL_GPIO_GetAFPin_8_15(ll_gpio_port, + ll_gpio_pin); + } + *func += PINCTRL_STM32_FUNCTION_ALT_0; + break; + case LL_GPIO_MODE_OUTPUT: + *func = PINCTRL_STM32_FUNCTION_OUTPUT; + break; + case LL_GPIO_MODE_INPUT: + *func = PINCTRL_STM32_FUNCTION_INPUT; + break; + case LL_GPIO_MODE_ANALOG: + *func = PINCTRL_STM32_FUNCTION_ANALOG; + break; + } + + return 0; +} + +/** + * @brief Set muxing function at pin + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param func Muxing function + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + * @retval -EINVAL if requested function is unknown + */ +static int pinctrl_stm32_mux_set(struct device *dev, u16_t pin, u16_t func) +{ + /* func always denotes a hardware pinmux control + * due to the usage of the pinctrl_tmpl. + */ + GPIO_TypeDef *ll_gpio_port = pinctrl_stm32_ll_gpio_port(pin); + u32_t ll_gpio_pin = pinctrl_stm32_ll_gpio_pin(pin); + u32_t ll_gpio_mode = pinctrl_stm32_ll_gpio_mode(func); + + if (ll_gpio_mode == LL_GPIO_MODE_ALTERNATE) { + if (pinctrl_stm32_ll_gpio_alt_func(func) <= LL_GPIO_AF_7) { + /* valid alternate function */ + if (pinctrl_stm32_ll_gpio_pin(pin) <= LL_GPIO_PIN_7) { + LL_GPIO_SetAFPin_0_7( + ll_gpio_port, + ll_gpio_pin, + pinctrl_stm32_ll_gpio_alt_func(func)); + } else { + LL_GPIO_SetAFPin_8_15( + ll_gpio_port, + ll_gpio_pin, + pinctrl_stm32_ll_gpio_alt_func(func)); + } + } + } + LL_GPIO_SetPinMode(ll_gpio_port, ll_gpio_pin, ll_gpio_mode); + return 0; +} + +/** + * @brief Initialise pin controller. + * + * Enable all GPIOS controlled by the pin controller (currently all GPIOs) + * to be clocked by the associated peripherial bus clock. + * + * @param dev Pointer to the device structure for the driver instance. + */ +static int pinctrl_stm32_device_init(struct device *dev) +{ + /* Enable all GPIOS to be clocked by the associated peripherial bus + * clock + */ + struct pinctrl_stm32_data *data = dev->driver_data; + + data->clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); + /** + * @code{.codegen} + * # GPIO bus was already evaluated above (bus). + * codegen.outl('data->pclken_gpio.bus = STM32_CLOCK_BUS_{};'.format( + * bus)) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + for (int port_idx = 0; port_idx < PINCTRL_STM32_GPIO_COUNT; + port_idx++) { + pinctrl_stm32_gpio_enable_clock(dev, port_idx); + } + + return 0; +} + +/** @} device_driver_pinctrl_stm32 */ diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 1565e78ddff97b..d1244eef3f3812 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -3,7 +3,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_PWM_PCA9685 pwm_pca9685.c) zephyr_library_sources_ifdef(CONFIG_PWM_DW pwm_dw.c) zephyr_library_sources_ifdef(CONFIG_PWM_QMSI pwm_qmsi.c) -zephyr_library_sources_ifdef(CONFIG_PWM_STM32 pwm_stm32.c) +zephyr_library_sources_codegen_ifdef(CONFIG_PWM_STM32 pwm_stm32.c) zephyr_library_sources_ifdef(CONFIG_PWM_NRF5_SW pwm_nrf5_sw.c) zephyr_library_sources_ifdef(CONFIG_PWM_NRFX pwm_nrfx.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_FTM pwm_mcux_ftm.c) diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index 8b478961d5f077..84a5c0e6e72238 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -202,138 +202,43 @@ static int pwm_stm32_init(struct device *dev) return 0; } -#define PWM_DEVICE_INIT_STM32(n, apb, grp, prescaler) \ - static struct pwm_stm32_data pwm_stm32_dev_data_ ## n = { \ - /* Default case */ \ - .pwm_prescaler = prescaler, \ - }; \ - \ - static const struct pwm_stm32_config pwm_stm32_dev_cfg_ ## n = { \ - .pwm_base = TIM ## n ## _BASE, \ - .pclken = { .bus = STM32_CLOCK_BUS_ ## apb, \ - .enr = LL_##apb##_##grp##_PERIPH_TIM##n }, \ - }; \ - \ - DEVICE_AND_API_INIT(pwm_stm32_ ## n, \ - CONFIG_PWM_STM32_ ## n ## _DEV_NAME, \ - pwm_stm32_init, \ - &pwm_stm32_dev_data_ ## n, \ - &pwm_stm32_dev_cfg_ ## n, \ - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,\ - &pwm_stm32_drv_api_funcs); - -#ifdef CONFIG_PWM_STM32_1 -/* 16-bit advanced-control timer */ -#ifdef CONFIG_SOC_SERIES_STM32F0X -PWM_DEVICE_INIT_STM32(1, APB1, GRP2, CONFIG_PWM_STM32_1_PRESCALER) -#else -PWM_DEVICE_INIT_STM32(1, APB2, GRP1, CONFIG_PWM_STM32_1_PRESCALER) -#endif /*CONFIG_SOC_SERIES_STM32F0X */ -#endif /* CONFIG_PWM_STM32_1 */ - -#ifdef CONFIG_PWM_STM32_2 -/* 32-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(2, APB1, GRP1, CONFIG_PWM_STM32_2_PRESCALER) -#endif /* CONFIG_PWM_STM32_2 */ - -#ifdef CONFIG_PWM_STM32_3 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(3, APB1, GRP1, CONFIG_PWM_STM32_3_PRESCALER) -#endif /* CONFIG_PWM_STM32_3 */ - -#ifdef CONFIG_PWM_STM32_4 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(4, APB1, GRP1, CONFIG_PWM_STM32_4_PRESCALER) -#endif /* CONFIG_PWM_STM32_4 */ - -#ifdef CONFIG_PWM_STM32_5 -/* 32-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(5, APB1, GRP1, CONFIG_PWM_STM32_5_PRESCALER) -#endif /* CONFIG_PWM_STM32_5 */ - -#ifdef CONFIG_PWM_STM32_6 -/* 16-bit basic timer */ -PWM_DEVICE_INIT_STM32(6, APB1, GRP1, CONFIG_PWM_STM32_6_PRESCALER) -#endif /* CONFIG_PWM_STM32_6 */ - -#ifdef CONFIG_PWM_STM32_7 -/* 16-bit basic timer */ -PWM_DEVICE_INIT_STM32(7, APB1, GRP1, CONFIG_PWM_STM32_7_PRESCALER) -#endif /* CONFIG_PWM_STM32_7 */ - -#ifdef CONFIG_PWM_STM32_8 -/* 16-bit advanced-control timer */ -PWM_DEVICE_INIT_STM32(8, APB2, GRP1, CONFIG_PWM_STM32_8_PRESCALER) -#endif /* CONFIG_PWM_STM32_8 */ - -#ifdef CONFIG_PWM_STM32_9 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(9, APB2, GRP1, CONFIG_PWM_STM32_9_PRESCALER) -#endif /* CONFIG_PWM_STM32_9 */ - -#ifdef CONFIG_PWM_STM32_10 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(10, APB2, GRP1, CONFIG_PWM_STM32_10_PRESCALER) -#endif /* CONFIG_PWM_STM32_10 */ - -#ifdef CONFIG_PWM_STM32_11 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(11, APB2, GRP1, CONFIG_PWM_STM32_11_PRESCALER) -#endif /* CONFIG_PWM_STM32_11 */ - -#ifdef CONFIG_PWM_STM32_12 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(12, APB1, GRP1, CONFIG_PWM_STM32_12_PRESCALER) -#endif /* CONFIG_PWM_STM32_12 */ - -#ifdef CONFIG_PWM_STM32_13 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(13, APB1, GRP1, CONFIG_PWM_STM32_13_PRESCALER) -#endif /* CONFIG_PWM_STM32_13 */ - -#ifdef CONFIG_PWM_STM32_14 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(14, APB1, GRP1, CONFIG_PWM_STM32_14_PRESCALER) -#endif /* CONFIG_PWM_STM32_14 */ - -#ifdef CONFIG_PWM_STM32_15 -/* 16-bit general-purpose timer */ -#ifdef CONFIG_SOC_SERIES_STM32F0X -PWM_DEVICE_INIT_STM32(15, APB1, GRP2, CONFIG_PWM_STM32_15_PRESCALER) -#else -PWM_DEVICE_INIT_STM32(15, APB2, GRP1, CONFIG_PWM_STM32_15_PRESCALER) -#endif /* CONFIG_SOC_SERIES_STM32F0X */ -#endif /* CONFIG_PWM_STM32_15 */ - -#ifdef CONFIG_PWM_STM32_16 -/* 16-bit general-purpose timer */ -#ifdef CONFIG_SOC_SERIES_STM32F0X -PWM_DEVICE_INIT_STM32(16, APB1, GRP2, CONFIG_PWM_STM32_16_PRESCALER) -#else -PWM_DEVICE_INIT_STM32(16, APB2, GRP1, CONFIG_PWM_STM32_16_PRESCALER) -#endif /* CONFIG_SOC_SERIES_STM32F0X */ -#endif /* CONFIG_PWM_STM32_16 */ - -#ifdef CONFIG_PWM_STM32_17 -/* 16-bit general-purpose timer */ -#ifdef CONFIG_SOC_SERIES_STM32F0X -PWM_DEVICE_INIT_STM32(17, APB1, GRP2, CONFIG_PWM_STM32_17_PRESCALER) -#else -PWM_DEVICE_INIT_STM32(17, APB2, GRP1, CONFIG_PWM_STM32_17_PRESCALER) -#endif /* CONFIG_SOC_SERIES_STM32F0X */ -#endif /* CONFIG_PWM_STM32_17 */ - -#ifdef CONFIG_PWM_STM32_18 -/* 16-bit advanced timer */ -PWM_DEVICE_INIT_STM32(18, APB1, GRP1, CONFIG_PWM_STM32_18_PRESCALER) -#endif /* CONFIG_PWM_STM32_18 */ - -#ifdef CONFIG_PWM_STM32_19 -/* 16-bit general-purpose timer */ -PWM_DEVICE_INIT_STM32(19, APB2, GRP1, CONFIG_PWM_STM32_19_PRESCALER) -#endif /* CONFIG_PWM_STM32_19 */ - -#ifdef CONFIG_PWM_STM32_20 -/* 16-bit advanced timer */ -PWM_DEVICE_INIT_STM32(20, APB2, GRP1, CONFIG_PWM_STM32_20_PRESCALER) -#endif /* CONFIG_PWM_STM32_20 */ +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_PWM_STM32_{}'.format(x) for x in range(1, 21)] + * driver_names = ['PWM_{}'.format(x) for x in range(1, 21)] + * device_inits = 'pwm_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE' + * device_api = 'pwm_stm32_drv_api_funcs' + * device_info = \ + * """ + * static const struct pwm_stm32_config ${device-config-info} = { + * .pwm_base = (u32_t)${${parent-device}:reg/0/address/0}, + * .pclken.bus = ${${parent-device}:clocks/0/bus}, + * .pclken.enr = ${${parent-device}:clocks/0/bits}, + * .pwm_num_chan = ${st,pwm-num-chan}, + * .capture_num_chan = ${st,capture-num-chan}, + * }; + * static struct pwm_stm32_data ${device-data} = { + * .pwm_prescaler = ${st,prescaler}, + * }; + * """ + * device_defaults = { + * 'st,pwm-num-chan' : 0, + * 'st,capture-num-chan' : 0, + * } + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info, + * device_defaults) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ diff --git a/drivers/pwm/pwm_stm32.h b/drivers/pwm/pwm_stm32.h index 6991bba8e88e7b..54705ddce3f2be 100644 --- a/drivers/pwm/pwm_stm32.h +++ b/drivers/pwm/pwm_stm32.h @@ -18,6 +18,8 @@ extern "C" { /** Configuration data */ struct pwm_stm32_config { u32_t pwm_base; + u8_t pwm_num_chan; + u8_t capture_num_chan; /* clock subsystem driving this peripheral */ struct stm32_pclken pclken; }; diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 3bc2c2fbc42c43..4cb773a4f57468 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -20,7 +20,7 @@ zephyr_library_sources_if_kconfig(uart_riscv_qemu.c) zephyr_library_sources_if_kconfig(uart_sam.c) zephyr_library_sources_if_kconfig(usart_sam.c) zephyr_library_sources_if_kconfig(uart_stellaris.c) -zephyr_library_sources_if_kconfig(uart_stm32.c) +zephyr_library_sources_codegen_ifdef(CONFIG_UART_STM32 uart_stm32.c) zephyr_library_sources_if_kconfig(uart_sam0.c) zephyr_library_sources_if_kconfig(usart_mcux_lpc.c) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index a12ca080d1b46e..7fd43d211d58f7 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Open-RnD Sp. z o.o. * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2018 Bobby Noelte. * * SPDX-License-Identifier: Apache-2.0 */ @@ -352,161 +353,52 @@ static int uart_stm32_init(struct device *dev) return 0; } -/* Define clocks */ -#define STM32_CLOCK_UART(clock_bus, clock_enr) \ - .pclken = { .bus = clock_bus, \ - .enr = clock_enr } - -#ifdef CONFIG_UART_INTERRUPT_DRIVEN -#define STM32_UART_IRQ_HANDLER_DECL(name) \ - static void uart_stm32_irq_config_func_##name(struct device *dev) -#define STM32_UART_IRQ_HANDLER_FUNC(name) \ - .irq_config_func = uart_stm32_irq_config_func_##name, -#define STM32_UART_IRQ_HANDLER(name) \ -static void uart_stm32_irq_config_func_##name(struct device *dev) \ -{ \ - IRQ_CONNECT(name##_IRQ, \ - CONFIG_UART_STM32_##name##_IRQ_PRI, \ - uart_stm32_isr, DEVICE_GET(uart_stm32_##name), \ - 0); \ - irq_enable(name##_IRQ); \ -} -#else -#define STM32_UART_IRQ_HANDLER_DECL(name) -#define STM32_UART_IRQ_HANDLER_FUNC(name) -#define STM32_UART_IRQ_HANDLER(name) -#endif - -#define STM32_UART_INIT(name, clock_bus, clock_enr) \ -STM32_UART_IRQ_HANDLER_DECL(name); \ - \ -static const struct uart_stm32_config uart_stm32_cfg_##name = { \ - .uconf = { \ - .base = (u8_t *)CONFIG_UART_STM32_##name##_BASE_ADDRESS,\ - STM32_UART_IRQ_HANDLER_FUNC(name) \ - }, \ - STM32_CLOCK_UART(clock_bus, clock_enr), \ - .baud_rate = CONFIG_UART_STM32_##name##_BAUD_RATE \ -}; \ - \ -static struct uart_stm32_data uart_stm32_data_##name = { \ -}; \ - \ -DEVICE_AND_API_INIT(uart_stm32_##name, CONFIG_UART_STM32_##name##_NAME, \ - &uart_stm32_init, \ - &uart_stm32_data_##name, &uart_stm32_cfg_##name, \ - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ - &uart_stm32_driver_api); \ - \ -STM32_UART_IRQ_HANDLER(name) - -/* - * STM32F0 and STM32L0 series differ from other STM32 series by some - * peripheral names (UART vs USART). Besides, STM32F0 doesn't have APB2 bus, - * so APB1 GRP2 should be accessed instead. +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_UART_STM32_PORT_{}'.format(x) \ + * for x in range(1, 11)] + \ + * ['CONFIG_UART_STM32_LPUART_{}'.format(x) \ + * for x in range(1, 2)] + * driver_names = ['UART_{}'.format(x) for x in range(1, 11)] + \ + * ['LPUART_{}'.format(x) for x in range(1, 2)] + * device_inits = 'uart_stm32_init' + * device_levels = 'PRE_KERNEL_1' + * device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE' + * device_api = 'uart_stm32_driver_api' + * device_info = \ + * """ + * #if CONFIG_UART_INTERRUPT_DRIVEN + * DEVICE_DECLARE(${device-name}); + * static void ${device-config-irq}(struct device *dev) + * { + * IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority}, \\ + * uart_stm32_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/0/irq}); + * } + * #endif + * static const struct uart_stm32_config ${device-config-info} = { + * .uconf.base = (u8_t *)${reg/0/address/0}, + * #ifdef CONFIG_UART_INTERRUPT_DRIVEN + * .uconf.irq_config_func = ${device-config-irq}, + * #endif + * .pclken.bus = ${clocks/0/bus}, + * .pclken.enr = ${clocks/0/bits}, + * .baud_rate = ${current-speed}, + * }; + * static struct uart_stm32_data ${device-data}; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} */ -#if defined(CONFIG_SOC_SERIES_STM32F0X) - -#ifdef CONFIG_UART_STM32_PORT_1 -STM32_UART_INIT(USART_1, STM32_CLOCK_BUS_APB1_2, LL_APB1_GRP2_PERIPH_USART1) -#endif /* CONFIG_UART_STM32_PORT_1 */ - -#ifdef CONFIG_UART_STM32_PORT_2 -STM32_UART_INIT(USART_2, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART2) -#endif /* CONFIG_UART_STM32_PORT_2 */ - -#ifdef CONFIG_UART_STM32_PORT_3 -STM32_UART_INIT(USART_3, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART3) -#endif /* CONFIG_UART_STM32_PORT_3 */ - -#ifdef CONFIG_UART_STM32_PORT_4 -STM32_UART_INIT(USART_4, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART4) -#endif /* CONFIG_UART_STM32_PORT_4 */ - -#ifdef CONFIG_UART_STM32_PORT_5 -STM32_UART_INIT(USART_5, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART5) -#endif /* CONFIG_UART_STM32_PORT_5 */ - -#ifdef CONFIG_UART_STM32_PORT_6 -STM32_UART_INIT(USART_6, STM32_CLOCK_BUS_APB1_2, LL_APB1_GRP2_PERIPH_USART6) -#endif /* CONFIG_UART_STM32_PORT_6 */ - -#ifdef CONFIG_UART_STM32_PORT_7 -STM32_UART_INIT(USART_7, STM32_CLOCK_BUS_APB1_2, LL_APB1_GRP2_PERIPH_USART7) -#endif /* CONFIG_UART_STM32_PORT_7 */ - -#ifdef CONFIG_UART_STM32_PORT_8 -STM32_UART_INIT(USART_8, STM32_CLOCK_BUS_APB1_2, LL_APB1_GRP2_PERIPH_USART8) -#endif /* CONFIG_UART_STM32_PORT_8 */ - -#elif defined(CONFIG_SOC_SERIES_STM32L0X) - -#ifdef CONFIG_UART_STM32_PORT_1 -STM32_UART_INIT(USART_1, STM32_CLOCK_BUS_APB2, LL_APB2_GRP1_PERIPH_USART1) -#endif /* CONFIG_UART_STM32_PORT_1 */ - -#ifdef CONFIG_UART_STM32_PORT_2 -STM32_UART_INIT(USART_2, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART2) -#endif /* CONFIG_UART_STM32_PORT_2 */ - -#ifdef CONFIG_UART_STM32_PORT_4 -STM32_UART_INIT(USART_4, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART4) -#endif /* CONFIG_UART_STM32_PORT_4 */ - -#ifdef CONFIG_UART_STM32_PORT_5 -STM32_UART_INIT(USART_5, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART5) -#endif /* CONFIG_UART_STM32_PORT_5 */ - -#ifdef CONFIG_UART_STM32_LPUART_1 -STM32_UART_INIT(LPUART_1, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_LPUART1) -#endif /* CONFIG_UART_STM32_LPUART_1 */ - -#else - -#ifdef CONFIG_UART_STM32_PORT_1 -STM32_UART_INIT(USART_1, STM32_CLOCK_BUS_APB2, LL_APB2_GRP1_PERIPH_USART1) -#endif /* CONFIG_UART_STM32_PORT_1 */ - -#ifdef CONFIG_UART_STM32_PORT_2 -STM32_UART_INIT(USART_2, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART2) -#endif /* CONFIG_UART_STM32_PORT_2 */ - -#ifdef CONFIG_UART_STM32_PORT_3 -STM32_UART_INIT(USART_3, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_USART3) -#endif /* CONFIG_UART_STM32_PORT_3 */ - -#ifdef CONFIG_UART_STM32_PORT_4 -STM32_UART_INIT(UART_4, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_UART4) -#endif /* CONFIG_UART_STM32_PORT_4 */ - -#ifdef CONFIG_UART_STM32_PORT_5 -STM32_UART_INIT(UART_5, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_UART5) -#endif /* CONFIG_UART_STM32_PORT_5 */ - -#ifdef CONFIG_UART_STM32_PORT_6 -STM32_UART_INIT(USART_6, STM32_CLOCK_BUS_APB2, LL_APB2_GRP1_PERIPH_USART6) -#endif /* CONFIG_UART_STM32_PORT_6 */ - -#ifdef CONFIG_UART_STM32_PORT_7 -STM32_UART_INIT(UART_7, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_UART7) -#endif /* CONFIG_UART_STM32_PORT_7 */ - -#ifdef CONFIG_UART_STM32_PORT_8 -STM32_UART_INIT(UART_8, STM32_CLOCK_BUS_APB1, LL_APB1_GRP1_PERIPH_UART8) -#endif /* CONFIG_UART_STM32_PORT_8 */ - -#ifdef CONFIG_UART_STM32_PORT_9 -STM32_UART_INIT(UART_9, STM32_CLOCK_BUS_APB2, LL_APB2_GRP1_PERIPH_UART9) -#endif /* CONFIG_UART_STM32_PORT_9 */ - -#ifdef CONFIG_UART_STM32_PORT_10 -STM32_UART_INIT(UART_10, STM32_CLOCK_BUS_APB2, LL_APB2_GRP1_PERIPH_UART10) -#endif /* CONFIG_UART_STM32_PORT_10 */ - -#ifdef CONFIG_SOC_SERIES_STM32L4X -#ifdef CONFIG_UART_STM32_LPUART_1 -STM32_UART_INIT(LPUART_1, STM32_CLOCK_BUS_APB1_2, LL_APB1_GRP2_PERIPH_LPUART1) -#endif /* CONFIG_UART_STM32_LPUART_1 */ -#endif /* CONFIG_SOC_SERIES_STM32L4X */ - -#endif +/** @code{.codeins}@endcode */ diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index e5a3590764dd53..896aae1543185a 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -2,7 +2,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_SPI_DW spi_dw.c) zephyr_library_sources_ifdef(CONFIG_SPI_INTEL spi_intel.c) -zephyr_library_sources_ifdef(CONFIG_SPI_STM32 spi_ll_stm32.c) +zephyr_library_sources_codegen_ifdef(CONFIG_SPI_STM32 spi_ll_stm32.c) zephyr_library_sources_ifdef(CONFIG_SPI_MCUX_DSPI spi_mcux_dspi.c) zephyr_library_sources_ifdef(CONFIG_SPI_SAM0 spi_sam0.c) zephyr_library_sources_ifdef(CONFIG_NRFX_SPI spi_nrfx_spi.c) diff --git a/drivers/spi/Kconfig.stm32 b/drivers/spi/Kconfig.stm32 index b52ad79d4b6595..a656ea8981feb6 100644 --- a/drivers/spi/Kconfig.stm32 +++ b/drivers/spi/Kconfig.stm32 @@ -8,7 +8,7 @@ menuconfig SPI_STM32 bool "STM32 MCU SPI controller driver" - depends on SPI && SOC_FAMILY_STM32 + default y if SPI && SOC_FAMILY_STM32 select HAS_DTS_SPI select USE_STM32_LL_SPI help diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index e617319bb3e37a..aaab4711bac9a6 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -1,23 +1,58 @@ /* * Copyright (c) 2016 BayLibre, SAS + * Copyright (c) 2018 Bobby Noelte * * SPDX-License-Identifier: Apache-2.0 */ +/** @file + * @brief STM32 SPI implementation + * @defgroup device_driver_spi_stm32 STM32 SPI inplementation + * + * A common driver for STM32 SPI. SoC specific adaptions are + * done by device tree and soc.h. + * + * @{ + */ + +#include +#include +#include + +#include + #define SYS_LOG_LEVEL CONFIG_SYS_LOG_SPI_LEVEL #include #include +#include #include -#include -#include +#include +#include #include -#include #include #include -#include "spi_ll_stm32.h" +#include "spi_context.h" + +/** + * @brief Configuration info for one SPI device + */ +struct spi_stm32_config { + struct stm32_pclken pclken; + SPI_TypeDef *spi; +#ifdef CONFIG_SPI_STM32_INTERRUPT + void (*config_irq)(struct device *dev); +#endif +}; + +/** + * @brief Driver data for one SPI device. + */ +struct spi_stm32_data { + struct spi_context ctx; +}; #define DEV_CFG(dev) \ (const struct spi_stm32_config * const)(dev->config->config_info) @@ -449,7 +484,7 @@ static int spi_stm32_transceive_async(struct device *dev, } #endif /* CONFIG_SPI_ASYNC */ -static const struct spi_driver_api api_funcs = { +static const struct spi_driver_api spi_stm32_driver_api = { .transceive = spi_stm32_transceive, #ifdef CONFIG_SPI_ASYNC .transceive_async = spi_stm32_transceive_async, @@ -468,7 +503,7 @@ static int spi_stm32_init(struct device *dev) (clock_control_subsys_t) &cfg->pclken); #ifdef CONFIG_SPI_STM32_INTERRUPT - cfg->irq_config(dev); + cfg->config_irq(dev); #endif spi_context_unlock_unconditionally(&data->ctx); @@ -476,121 +511,52 @@ static int spi_stm32_init(struct device *dev) return 0; } -#ifdef CONFIG_SPI_1 - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_1(struct device *port); -#endif - -static const struct spi_stm32_config spi_stm32_cfg_1 = { - .spi = (SPI_TypeDef *) CONFIG_SPI_1_BASE_ADDRESS, - .pclken = { -#ifdef CONFIG_SOC_SERIES_STM32F0X - .enr = LL_APB1_GRP2_PERIPH_SPI1, - .bus = STM32_CLOCK_BUS_APB1_2 -#else - .enr = LL_APB2_GRP1_PERIPH_SPI1, - .bus = STM32_CLOCK_BUS_APB2 -#endif - }, -#ifdef CONFIG_SPI_STM32_INTERRUPT - .irq_config = spi_stm32_irq_config_func_1, -#endif -}; - -static struct spi_stm32_data spi_stm32_dev_data_1 = { - SPI_CONTEXT_INIT_LOCK(spi_stm32_dev_data_1, ctx), - SPI_CONTEXT_INIT_SYNC(spi_stm32_dev_data_1, ctx), -}; - -DEVICE_AND_API_INIT(spi_stm32_1, CONFIG_SPI_1_NAME, &spi_stm32_init, - &spi_stm32_dev_data_1, &spi_stm32_cfg_1, - POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - &api_funcs); - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_1(struct device *dev) -{ - IRQ_CONNECT(CONFIG_SPI_1_IRQ, CONFIG_SPI_1_IRQ_PRI, - spi_stm32_isr, DEVICE_GET(spi_stm32_1), 0); - irq_enable(CONFIG_SPI_1_IRQ); -} -#endif - -#endif /* CONFIG_SPI_1 */ - -#ifdef CONFIG_SPI_2 - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_2(struct device *port); -#endif - -static const struct spi_stm32_config spi_stm32_cfg_2 = { - .spi = (SPI_TypeDef *) CONFIG_SPI_2_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP1_PERIPH_SPI2, - .bus = STM32_CLOCK_BUS_APB1 - }, -#ifdef CONFIG_SPI_STM32_INTERRUPT - .irq_config = spi_stm32_irq_config_func_2, -#endif -}; - -static struct spi_stm32_data spi_stm32_dev_data_2 = { - SPI_CONTEXT_INIT_LOCK(spi_stm32_dev_data_2, ctx), - SPI_CONTEXT_INIT_SYNC(spi_stm32_dev_data_2, ctx), -}; - -DEVICE_AND_API_INIT(spi_stm32_2, CONFIG_SPI_2_NAME, &spi_stm32_init, - &spi_stm32_dev_data_2, &spi_stm32_cfg_2, - POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - &api_funcs); - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_2(struct device *dev) -{ - IRQ_CONNECT(CONFIG_SPI_2_IRQ, CONFIG_SPI_2_IRQ_PRI, - spi_stm32_isr, DEVICE_GET(spi_stm32_2), 0); - irq_enable(CONFIG_SPI_2_IRQ); -} -#endif - -#endif /* CONFIG_SPI_2 */ - -#ifdef CONFIG_SPI_3 - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_3(struct device *port); -#endif - -static const struct spi_stm32_config spi_stm32_cfg_3 = { - .spi = (SPI_TypeDef *) CONFIG_SPI_3_BASE_ADDRESS, - .pclken = { - .enr = LL_APB1_GRP1_PERIPH_SPI3, - .bus = STM32_CLOCK_BUS_APB1 - }, -#ifdef CONFIG_SPI_STM32_INTERRUPT - .irq_config = spi_stm32_irq_config_func_3, -#endif -}; - -static struct spi_stm32_data spi_stm32_dev_data_3 = { - SPI_CONTEXT_INIT_LOCK(spi_stm32_dev_data_3, ctx), - SPI_CONTEXT_INIT_SYNC(spi_stm32_dev_data_3, ctx), -}; - -DEVICE_AND_API_INIT(spi_stm32_3, CONFIG_SPI_3_NAME, &spi_stm32_init, - &spi_stm32_dev_data_3, &spi_stm32_cfg_3, - POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, - &api_funcs); - -#ifdef CONFIG_SPI_STM32_INTERRUPT -static void spi_stm32_irq_config_func_3(struct device *dev) -{ - IRQ_CONNECT(CONFIG_SPI_3_IRQ, CONFIG_SPI_3_IRQ_PRI, - spi_stm32_isr, DEVICE_GET(spi_stm32_3), 0); - irq_enable(CONFIG_SPI_3_IRQ); -} -#endif +/** + * @code{.codegen} + * codegen.import_module('devicedeclare') + * + * device_configs = ['CONFIG_SPI_{}'.format(x) for x in range(1, 7)] + * driver_names = ['SPI_{}'.format(x) for x in range(1, 7)] + * device_inits = 'spi_stm32_init' + * device_levels = 'POST_KERNEL' + * device_prios = 'CONFIG_SPI_INIT_PRIORITY' + * device_api = 'spi_stm32_driver_api' + * device_info = \ + * """ + * #if CONFIG_SPI_STM32_INTERRUPT + * DEVICE_DECLARE(${device-name}); + * static void ${device-config-irq}(struct device *dev) + * { + * IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority}, \\ + * spi_stm32_isr, \\ + * DEVICE_GET(${device-name}), 0); + * irq_enable(${interrupts/0/irq}); + * } + * #endif + * static const struct spi_stm32_config ${device-config-info} = { + * .spi = (SPI_TypeDef *)${reg/0/address/0}, + * .pclken.bus = ${clocks/0/bus}, + * .pclken.enr = ${clocks/0/bits}, + * #if CONFIG_SPI_STM32_INTERRUPT + * .config_irq = ${device-config-irq}, + * #endif + * }; + * static struct spi_stm32_data ${device-data} = { + * SPI_CONTEXT_INIT_LOCK(${device-data}, ctx), + * SPI_CONTEXT_INIT_SYNC(${device-data}, ctx), + * }; + * """ + * + * devicedeclare.device_declare_multi( \ + * device_configs, + * driver_names, + * device_inits, + * device_levels, + * device_prios, + * device_api, + * device_info) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ -#endif /* CONFIG_SPI_3 */ +/** @} device_driver_spi_stm32 */ diff --git a/drivers/spi/spi_ll_stm32.h b/drivers/spi/spi_ll_stm32.h deleted file mode 100644 index 2cf7d9e9a0c824..00000000000000 --- a/drivers/spi/spi_ll_stm32.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016 BayLibre, SAS - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _STM32_SPI_H_ -#define _STM32_SPI_H_ - -#include "spi_context.h" - -typedef void (*irq_config_func_t)(struct device *port); - -struct spi_stm32_config { - struct stm32_pclken pclken; - SPI_TypeDef *spi; -#ifdef CONFIG_SPI_STM32_INTERRUPT - irq_config_func_t irq_config; -#endif -}; - -struct spi_stm32_data { - struct spi_context ctx; -}; - -#endif /* _STM32_SPI_H_ */ diff --git a/dts/arm/st/stm32f0-pinctrl.dtsi b/dts/arm/st/stm32f0-pinctrl.dtsi index 111269200b3460..1afadd0f7da1f4 100644 --- a/dts/arm/st/stm32f0-pinctrl.dtsi +++ b/dts/arm/st/stm32f0-pinctrl.dtsi @@ -1,54 +1,278 @@ /* * Copyright (c) 2017 RnDity Sp. z o.o. + * Copyright (c) 2018 Bobby Noelte * * SPDX-License-Identifier: Apache-2.0 */ -#include - / { soc { pinctrl: pin-controller@48000000 { usart1_pins_a: usart1@0 { - rx_tx { - rx = ; - tx = ; + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; }; }; usart1_pins_b: usart1@1 { - rx_tx { - rx = ; - tx = ; + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; }; }; usart2_pins_a: usart2@0 { - rx_tx { - rx = ; - tx = ; + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + usart2_pins_d: usart2@3 { + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + usart8_pins_c1: usart8@21 { + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + usart8_pins_c2: usart8@22 { + rx { + pinmux = ; + bias-disable; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + i2c1_pins_a: i2c1@0 { + scl { + pinmux = ; + drive-push-pull; + bias-disable; + }; + sda { + pinmux = ; + bias-disable; + }; + }; + i2c1_pins_b: i2c1@1 { + scl { + pinmux = ; + drive-push-pull; + bias-disable; + }; + sda { + pinmux = ; + bias-disable; }; }; - usart2_pins_b: usart2@1 { - rx_tx { - rx = ; - tx = ; + i2c2_pins_a: i2c2@0 { + scl { + pinmux = ; + drive-push-pull; + bias-disable; + }; + sda { + pinmux = ; + bias-disable; }; }; - usart2_pins_d: usart2@2 { - rx_tx { - rx = ; - tx = ; + i2c2_pins_b: i2c2@1 { + scl { + pinmux = ; + drive-push-pull; + bias-disable; + }; + sda { + pinmux = ; + bias-disable; + }; + }; + spi1_master_a: spi1@0 { + sck { + pinmux = ; + drive-push-pull; + bias-disable; + }; + miso { + pinmux = ; + bias-disable; + }; + mosi { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + spi1_slave_a: spi1@1 { + sck { + pinmux = ; + bias-disable; + }; + miso { + pinmux = ; + drive-push-pull; + bias-disable; + }; + mosi { + pinmux = ; + bias-disable; + }; + }; + spi1_master_b: spi1@2 { + sck { + pinmux = ; + drive-push-pull; + bias-disable; + }; + miso { + pinmux = ; + bias-disable; + }; + mosi { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + spi1_slave_b: spi1@3 { + sck { + pinmux = ; + bias-disable; + }; + miso { + pinmux = ; + drive-push-pull; + bias-disable; + }; + mosi { + pinmux = ; + bias-disable; + }; + }; + spi2_master_a: spi2@0 { + sck { + pinmux = ; + drive-push-pull; + bias-disable; + }; + miso { + pinmux = ; + bias-disable; + }; + mosi { + pinmux = ; + drive-push-pull; + bias-disable; + }; + }; + spi2_slave_a: spi2@1 { + sck { + pinmux = ; + bias-disable; + }; + miso { + pinmux = ; + drive-push-pull; + bias-disable; + }; + mosi { + pinmux = ; + bias-disable; }; }; can_pins_a: can@0 { - rx_tx { - rx = ; - tx = ; + rx { + pinmux = ; + bias-pull-up; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; }; }; can_pins_b: can@1 { - rx_tx { - rx = ; - tx = ; + rx { + pinmux = ; + bias-pull-up; + }; + tx { + pinmux = ; + drive-push-pull; + bias-disable; }; }; }; diff --git a/dts/arm/st/stm32f0.dtsi b/dts/arm/st/stm32f0.dtsi index 3eeca4ca33e372..d2f6187fdd2eca 100644 --- a/dts/arm/st/stm32f0.dtsi +++ b/dts/arm/st/stm32f0.dtsi @@ -4,12 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include #include #include #include +#include + +#include +#include / { cpus { @@ -56,56 +58,82 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40010400 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40010400 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@48000000 { - compatible = "st,stm32-pinmux"; + compatible = "st,stm32-pinctrl"; + pin-controller; #address-cells = <1>; #size-cells = <1>; reg = <0x48000000 0x1800>; + label = "PINCTRL"; + }; - gpioa: gpio@48000000 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48000000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00020000>; - label = "GPIOA"; - }; + gpioa: gpio@48000000 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00020000>; + st,bank-name = "GPIOA"; + label = "GPIOA"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINA0 16>; + }; - gpiob: gpio@48000400 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48000400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>; - label = "GPIOB"; - }; + gpiob: gpio@48000400 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48000400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>; + st,bank-name = "GPIOB"; + label = "GPIOB"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINB0 16>; + }; - gpioc: gpio@48000800 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48000800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00080000>; - label = "GPIOC"; - }; + gpioc: gpio@48000800 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48000800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00080000>; + st,bank-name = "GPIOC"; + label = "GPIOC"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINC0 16>; + }; - gpiod: gpio@48000c00 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48000c00 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00100000>; - label = "GPIOD"; - }; + gpiod: gpio@48000C00 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00100000>; + st,bank-name = "GPIOD"; + label = "GPIOD"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PIND0 16>; + }; - gpiof: gpio@48001400 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48001400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00400000>; - label = "GPIOF"; - }; + gpiof: gpio@48001400 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48001400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00400000>; + st,bank-name = "GPIOF"; + label = "GPIOF"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINF0 16>; }; usart1: serial@40013800 { @@ -157,7 +185,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x40013000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00001000>; interrupts = <25 3>; status = "disabled"; label = "SPI_1"; diff --git a/dts/arm/st/stm32f072.dtsi b/dts/arm/st/stm32f072.dtsi index c09c82bf7e4308..aca0b3c61a4678 100644 --- a/dts/arm/st/stm32f072.dtsi +++ b/dts/arm/st/stm32f072.dtsi @@ -8,18 +8,6 @@ / { soc { - pinctrl: pin-controller@48000000 { - - gpioe: gpio@48001000 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48001000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00200000>; - label = "GPIOE"; - }; - }; - timers2: timers@40000000 { compatible = "st,stm32-timers"; reg = <0x40000000 0x400>; @@ -46,6 +34,18 @@ label = "SPI_2"; }; + gpioe: gpio@48001000 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00200000>; + st,bank-name = "GPIOE"; + label = "GPIOE"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINE0 16>; + }; + usb: usb@40005c00 { compatible = "st,stm32-usb"; reg = <0x40005c00 0x400>; diff --git a/dts/arm/st/stm32f091.dtsi b/dts/arm/st/stm32f091.dtsi index a9a51cbd2c467b..859af480348600 100644 --- a/dts/arm/st/stm32f091.dtsi +++ b/dts/arm/st/stm32f091.dtsi @@ -8,6 +8,60 @@ / { soc { + usart3: serial@40004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_3"; + }; + + usart4: serial@40004C00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004C00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00080000>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_4"; + }; + + usart5: serial@40005000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40005000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00100000>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_5"; + }; + + usart6: serial@40011400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40011400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000020>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_6"; + }; + + usart7: serial@40011800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40011800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000040>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_7"; + }; + + usart8: serial@40011C00 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40011C00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000080>; + interrupts = <29 0>; + status = "disabled"; + label = "UART_8"; + }; + timers2: timers@40000000 { compatible = "st,stm32-timers"; reg = <0x40000000 0x400>; @@ -31,19 +85,34 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>; interrupts = <26 3>; status = "disabled"; - label = "SPI_2"; + label= "SPI_2"; }; - pinctrl: pin-controller@48000000 { + gpioe: gpio@48001000 { + compatible = "st,stm32-gpio-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00200000>; + st,bank-name = "GPIOE"; + label = "GPIOE"; + gpio-ranges = <&pinctrl \ + GPIO_PORT_PIN0 PINCTRL_STM32_PINE0 16>; + }; - gpioe: gpio@48001000 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48001000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00200000>; - label = "GPIOE"; - }; + can1: can@40006400 { + compatible = "st,stm32-can"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40006400 0x400>; + interrupts = <30 0>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; + status = "disabled"; + label = "CAN_1"; + bus-speed = <250000>; + sjw = <1>; + prop_seg_phase_seg1 = <5>; + phase_seg2 = <6>; }; }; }; diff --git a/dts/arm/st/stm32f1.dtsi b/dts/arm/st/stm32f1.dtsi index 0a74c5b5f69c7e..293304b55b4f2f 100644 --- a/dts/arm/st/stm32f1.dtsi +++ b/dts/arm/st/stm32f1.dtsi @@ -44,6 +44,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40010400 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40010400 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@40010800 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32f2.dtsi b/dts/arm/st/stm32f2.dtsi index 0b4935c4ec575d..02ca5da60328a2 100644 --- a/dts/arm/st/stm32f2.dtsi +++ b/dts/arm/st/stm32f2.dtsi @@ -50,6 +50,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40013C00 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40013C00 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@40020000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32f3.dtsi b/dts/arm/st/stm32f3.dtsi index 1fa601068bdcfb..57c9015e1ea770 100644 --- a/dts/arm/st/stm32f3.dtsi +++ b/dts/arm/st/stm32f3.dtsi @@ -54,6 +54,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40010400 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40010400 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@48000000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32f4.dtsi b/dts/arm/st/stm32f4.dtsi index 8cef22a651d264..3f46c26b8fb459 100644 --- a/dts/arm/st/stm32f4.dtsi +++ b/dts/arm/st/stm32f4.dtsi @@ -56,6 +56,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40013C00 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40013C00 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@40020000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32f7.dtsi b/dts/arm/st/stm32f7.dtsi index c811a5d61d302d..34aa49c2a21260 100644 --- a/dts/arm/st/stm32f7.dtsi +++ b/dts/arm/st/stm32f7.dtsi @@ -44,6 +44,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40013C00 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40013C00 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@40020000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32l0.dtsi b/dts/arm/st/stm32l0.dtsi index e5da065dcc5b8b..1724801d761e1d 100644 --- a/dts/arm/st/stm32l0.dtsi +++ b/dts/arm/st/stm32l0.dtsi @@ -56,6 +56,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40010400 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40010400 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@50000000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/arm/st/stm32l4.dtsi b/dts/arm/st/stm32l4.dtsi index 725347a3ea09bc..106bfd02aab13c 100644 --- a/dts/arm/st/stm32l4.dtsi +++ b/dts/arm/st/stm32l4.dtsi @@ -57,6 +57,15 @@ label = "STM32_CLK_RCC"; }; + exti: interrupt-controller@40010400 { + compatible = "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40010400 0x400>; + label = "EXTI_STM32"; + status = "ok"; + }; + pinctrl: pin-controller@48000000 { compatible = "st,stm32-pinmux"; #address-cells = <1>; diff --git a/dts/bindings/can/can.yaml b/dts/bindings/can/can.yaml index d490304b9a7fbe..f52ff1f7a04fc2 100644 --- a/dts/bindings/can/can.yaml +++ b/dts/bindings/can/can.yaml @@ -10,6 +10,11 @@ child: bus: can properties: + compatible: + type: string + category: required + description: compatible strings + generation: define "#address-cells": type: int category: required @@ -23,6 +28,11 @@ properties: category: required description: Human readable string describing the device (used by Zephyr for API name) generation: define + clocks: + type: array + category: required + description: Clock gate information + generation: define bus-speed: type: int category: required diff --git a/dts/bindings/can/st,stm32-can.yaml b/dts/bindings/can/st,stm32-can.yaml index 93425f993f827e..ea9cb3fd30fcf0 100644 --- a/dts/bindings/can/st,stm32-can.yaml +++ b/dts/bindings/can/st,stm32-can.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32-can" reg: diff --git a/dts/bindings/clock/clock-consumer.yaml b/dts/bindings/clock/clock-consumer.yaml new file mode 100644 index 00000000000000..0c34052d2be6ab --- /dev/null +++ b/dts/bindings/clock/clock-consumer.yaml @@ -0,0 +1,72 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +# -- Assigned clock parents and rates -- +# Some platforms may require initial configuration of default parent clocks +# and clock frequencies. Such a configuration can be specified in a device tree +# node through assigned-clocks, assigned-clock-parents and assigned-clock-rates +# properties. +--- +title: Clock Consumer Base Structure +id: clock-consumer +version: 0.1 + +description: > + This binding gives the base structures for all clock consumers. + +properties: + + clocks: + type: array + category: required + description: > + List of phandle and clock specifier pairs, one pair for each clock + input to the device. Note - if the clock provider specifies '0' for + clock-cells, then only the phandle portion of the pair will appear. + generation: define + + clock-names: + type: array + category: optional + description: > + List of clock input name strings sorted in the same order as the clocks + property. + generation: define + + clock-ranges: + type: empty + category: optional + description: > + Empty property indicating that child nodes can inherit named clocks from + this node. Useful for bus nodes to provide a clock to their children. + generation: define + + assigned-clocks: + type: array + category: optional + description: > + List of phandle and clock specifier pairs, one pair for each assigned + clock input. Note - if the clock provider specifies '0' for + clock-cells, then only the phandle portion of the pair will appear. + generation: define + + assigned-clock-parents: + type: array + category: optional + description: > + List of parent clocks in the form of a phandle and clock + specifier pair. The list shall correspond to the clocks listed in the + assigned-clocks directive. + generation: define + + assigned-clock-rates: + type: array + category: optional + description: > + List of frequencies in Hz. The list shall correspond to the clocks + listed in the assigned-clocks directive. + generation: define +... diff --git a/dts/bindings/clock/clock-provider.yaml b/dts/bindings/clock/clock-provider.yaml new file mode 100644 index 00000000000000..c7f7b5535cb3ea --- /dev/null +++ b/dts/bindings/clock/clock-provider.yaml @@ -0,0 +1,51 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Clock Provider Base Structure +id: clock-provider +version: 0.1 + +description: > + This binding gives the base structures for all clock providers. + +properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + + label: + type: string + category: required + description: Human readable string describing the clock (used by Zephyr for API name) + generation: define + + "#clock-cells": + type: int + category: required + description: > + This device is providing controllable clocks, the + clock_cells property needs to be specified. + generation: define + + clock-output-names: + type: array + category: optional + description: > + A list of strings of clock output signal names indexed by the first + cell in the clock specifier. + generation: define + + clock-indices: + type: array + category: optional + description: > + The identifying number for the clocks in the node. If it is not linear + from zero, then this allows the mapping of identifiers into the + clock-output-names array. + generation: define +... diff --git a/dts/bindings/clock/fixed-clock.yaml b/dts/bindings/clock/fixed-clock.yaml new file mode 100644 index 00000000000000..41d521c93e7e03 --- /dev/null +++ b/dts/bindings/clock/fixed-clock.yaml @@ -0,0 +1,52 @@ +# +# Copyright (c) 2017, b0661n0e17e@gmail.com +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Simple fixed-rate clock sources. +id: fixed-clock +version: 0.1 + +description: > + Binding for simple fixed-rate clock sources. + +inherits: + !include clock-provider.yaml + +properties: + compatible: + constraint: "fixed-clock" + + "#clock-cells": + constraint: 0 + + clock-frequency: + type: int + category: required + description: Frequency of clock in Hz. Should be a single cell. + generation: define + + clock-accuracy: + type: int + category: optional + description: Accuracy of clock in ppb (parts per billion). Should be a single cell. + generation: define + + oscillator: + type: int + category: optional + description: clock is an oszillator (a quartz) + generation: define + + pinctrl-\d+: + type: array + category: optional + description: pinmux information for clock IN, OUT + generation: define + + pinctrl-names: + type: array + description: names to assign to states + category: required +... diff --git a/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml b/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml index 08aeb36a3083fd..b8cefc44ea9e19 100644 --- a/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml +++ b/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "atmel,sam0-nvmctrl" ... diff --git a/dts/bindings/flash_controller/fixed-partitions.yaml b/dts/bindings/flash_controller/fixed-partitions.yaml new file mode 100644 index 00000000000000..0476cc1186200b --- /dev/null +++ b/dts/bindings/flash_controller/fixed-partitions.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Fixed Partitions Base Structure +id: partitions +version: 0.1 + +description: > + This binding gives the base structures for all fixed partitions. + +inherits: + !include partitions.yaml + +properties: + compatible: + constraint: "fixed-partitions" +... diff --git a/dts/bindings/flash_controller/flash-controller.yaml b/dts/bindings/flash_controller/flash-controller.yaml index e0b9d0eedf33a9..f30ed6628919c7 100644 --- a/dts/bindings/flash_controller/flash-controller.yaml +++ b/dts/bindings/flash_controller/flash-controller.yaml @@ -7,6 +7,12 @@ description: > This binding gives the base structures for all flash controller devices properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + label: type: string category: required diff --git a/dts/bindings/flash_controller/flash.yaml b/dts/bindings/flash_controller/flash.yaml new file mode 100644 index 00000000000000..640098c848db42 --- /dev/null +++ b/dts/bindings/flash_controller/flash.yaml @@ -0,0 +1,27 @@ +--- +title: Flash Base Structure +id: flash +version: 0.1 + +description: > + This binding gives the base structures for all flash devices + +properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for API name) + generation: define + + reg: + type: array + description: mmio register space + generation: define + category: required +... diff --git a/dts/bindings/flash_controller/nordic,nrf51-flash-controller.yaml b/dts/bindings/flash_controller/nordic,nrf51-flash-controller.yaml index 96128c0657cd36..a39fc91b365b3a 100644 --- a/dts/bindings/flash_controller/nordic,nrf51-flash-controller.yaml +++ b/dts/bindings/flash_controller/nordic,nrf51-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "nrf,nrf51-flash-controller" ... diff --git a/dts/bindings/flash_controller/nordic,nrf52-flash-controller.yaml b/dts/bindings/flash_controller/nordic,nrf52-flash-controller.yaml index 428cd8443cf35c..1c84b23c40f1a1 100644 --- a/dts/bindings/flash_controller/nordic,nrf52-flash-controller.yaml +++ b/dts/bindings/flash_controller/nordic,nrf52-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "nrf,nrf52-flash-controller" ... diff --git a/dts/bindings/flash_controller/nxp,kinetis-ftfa.yaml b/dts/bindings/flash_controller/nxp,kinetis-ftfa.yaml index a29914c5890014..4257357c481acf 100644 --- a/dts/bindings/flash_controller/nxp,kinetis-ftfa.yaml +++ b/dts/bindings/flash_controller/nxp,kinetis-ftfa.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "nxp,kinetis-ftfa" ... diff --git a/dts/bindings/flash_controller/nxp,kinetis-ftfe.yaml b/dts/bindings/flash_controller/nxp,kinetis-ftfe.yaml index 411f1dc17e605c..aaac2faffa6049 100644 --- a/dts/bindings/flash_controller/nxp,kinetis-ftfe.yaml +++ b/dts/bindings/flash_controller/nxp,kinetis-ftfe.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "nxp,kinetis-ftfe" ... diff --git a/dts/bindings/flash_controller/nxp,kinetis-ftfl.yaml b/dts/bindings/flash_controller/nxp,kinetis-ftfl.yaml index 611a88220598b5..246d24e3a7125b 100644 --- a/dts/bindings/flash_controller/nxp,kinetis-ftfl.yaml +++ b/dts/bindings/flash_controller/nxp,kinetis-ftfl.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "nxp,kinetis-ftfl" ... diff --git a/dts/bindings/flash_controller/partitions.yaml b/dts/bindings/flash_controller/partitions.yaml new file mode 100644 index 00000000000000..d4d61c8f379813 --- /dev/null +++ b/dts/bindings/flash_controller/partitions.yaml @@ -0,0 +1,50 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Partitions Base Structure +id: partitions +version: 0.1 + +description: > + This binding gives the base structures for all partitions. + +properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + + "#address-cells": + type: int + category: required + description: > + <1>: for partitions that require a single 32-bit cell to represent their + size/address (aka the value is below 4 GiB) + <2>: for partitions that require two 32-bit cells to represent their + size/address (aka the value is 4 GiB or greater). + + "#size-cells": + type: int + category: required + description: > + <1>: for partitions that require a single 32-bit cell to represent their + size/address (aka the value is below 4 GiB) + <2>: for partitions that require two 32-bit cells to represent their + size/address (aka the value is 4 GiB or greater). + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for API name) + generation: define + + reg: + type: array + description: partition sectors address/ size + generation: define + category: required +... diff --git a/dts/bindings/flash_controller/soc-nv-flash.yaml b/dts/bindings/flash_controller/soc-nv-flash.yaml new file mode 100644 index 00000000000000..8e27f2a4af6dc3 --- /dev/null +++ b/dts/bindings/flash_controller/soc-nv-flash.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: SoC Non Volatile Flash Base Structure +id: soc-nv-flash +version: 0.1 + +description: > + This binding gives the base structures for all SoC flashes. + +inherits: + !include flash.yaml + +properties: + compatible: + constraint: "soc-nv-flash" +... diff --git a/dts/bindings/flash_controller/st,stm32f0-flash-controller.yaml b/dts/bindings/flash_controller/st,stm32f0-flash-controller.yaml index 263a59b4d334e9..3600dcf4be25af 100644 --- a/dts/bindings/flash_controller/st,stm32f0-flash-controller.yaml +++ b/dts/bindings/flash_controller/st,stm32f0-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32f0-flash-controller" ... diff --git a/dts/bindings/flash_controller/st,stm32f3-flash-controller.yaml b/dts/bindings/flash_controller/st,stm32f3-flash-controller.yaml index 4b750026138f69..08d37f11055a73 100644 --- a/dts/bindings/flash_controller/st,stm32f3-flash-controller.yaml +++ b/dts/bindings/flash_controller/st,stm32f3-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32f3-flash-controller" ... diff --git a/dts/bindings/flash_controller/st,stm32f4-flash-controller.yaml b/dts/bindings/flash_controller/st,stm32f4-flash-controller.yaml index 90e0b316481846..33981d584e9859 100644 --- a/dts/bindings/flash_controller/st,stm32f4-flash-controller.yaml +++ b/dts/bindings/flash_controller/st,stm32f4-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32f4-flash-controller" ... diff --git a/dts/bindings/flash_controller/st,stm32l4-flash-controller.yaml b/dts/bindings/flash_controller/st,stm32l4-flash-controller.yaml index eb637a43c60aa7..978ce593f267df 100644 --- a/dts/bindings/flash_controller/st,stm32l4-flash-controller.yaml +++ b/dts/bindings/flash_controller/st,stm32l4-flash-controller.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32l4-flash-controller" ... diff --git a/dts/bindings/gpio/gpio-pinctrl.yaml b/dts/bindings/gpio/gpio-pinctrl.yaml new file mode 100644 index 00000000000000..eac0c87cdd058a --- /dev/null +++ b/dts/bindings/gpio/gpio-pinctrl.yaml @@ -0,0 +1,53 @@ +--- +title: GPIO with PINCTRL base structure +id: gpio-pinctrl +version: 0.1 + +description: > + This binding gives the base structures for all GPIO devices node using a PINCTRL backend + +properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + + gpio-controller: + type: string + category: required + description: device controller identification + generation: define + + compatible: + type: string + category: required + description: compatible strings + + "#gpio-cells": + type: int + category: required + description: should be 2. + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for device name) + generation: define + + gpio-ranges: + type: array + category: optional + description: gpio range in pin controller + generation: define + + pinctrl-\d+: + type: array + category: optional + description: pinmux information for GPIO I/0 + generation: structure + +"#cells": + - pin + - flags +... diff --git a/dts/bindings/gpio/st,stm32-gpio-pinctrl.yaml b/dts/bindings/gpio/st,stm32-gpio-pinctrl.yaml new file mode 100644 index 00000000000000..943e67b2f7d6e8 --- /dev/null +++ b/dts/bindings/gpio/st,stm32-gpio-pinctrl.yaml @@ -0,0 +1,37 @@ +--- +title: STM32 GPIO with PINCTRL backend +id: st,stm32-gpio-pinctrl +version: 0.1 + +description: > + This is a representation of the STM32 GPIO node using a PINCTRL backend + +inherits: + !include gpio-pinctrl.yaml + +properties: + compatible: + type: string + category: required + description: compatible strings + constraint: "st,stm32-gpio-pinctrl" + generation: define + + reg: + type: int + description: mmio register space + generation: define + category: required + + interrupts: + type: compound + category: required + description: required interrupts + generation: define + + st,bank-name: + type: string + category: required + description: bank name (one of "GPIOA", "GPIOB", ...) + generation: define +... diff --git a/dts/bindings/i2c/i2c.yaml b/dts/bindings/i2c/i2c.yaml index 664a7346e1f6b9..27ff6b7527f8d5 100644 --- a/dts/bindings/i2c/i2c.yaml +++ b/dts/bindings/i2c/i2c.yaml @@ -1,5 +1,6 @@ # # Copyright (c) 2017 I-SENSE group of ICCS +# Copyright (c) 2018 Bobby Noelte # # SPDX-License-Identifier: Apache-2.0 # @@ -15,6 +16,11 @@ child: bus: i2c properties: + compatible: + type: string + category: required + description: compatible strings + generation: define "#address-cells": type: int category: required diff --git a/dts/bindings/interrupt-controller/st,stm32-exti.yaml b/dts/bindings/interrupt-controller/st,stm32-exti.yaml new file mode 100644 index 00000000000000..ad834bbeaecc16 --- /dev/null +++ b/dts/bindings/interrupt-controller/st,stm32-exti.yaml @@ -0,0 +1,50 @@ +--- +title: STM32 External Interrupt Controller +id: st,stm32-exti +version: 0.1 + +description: > + This binding describes the STM32 External Interrupt Controller. + +properties: + compatible: + category: required + type: string + description: compatible strings + constraint: "st,stm32-exti" + generation: define + + interrupt-controller: + type: string + category: required + description: device controller identification + generation: define + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for API name) + generation: define + + reg: + category: required + type: int + description: mmio register space + generation: define + + "#interrupt-cells": + type: int + category: required + description: > + Specifies the number of cells to encode an interrupt specifier. + constraint: 2 + + interrupts: + type: array + category: optional + description: > + interrupts references to primary interrupt controller + (only needed for exti controller with multiple exti under + same parent interrupt - st,stm32-exti and st,stm32h7-exti) + generation: define +... diff --git a/dts/bindings/pinctrl/pinctrl.yaml b/dts/bindings/pinctrl/pinctrl.yaml new file mode 100644 index 00000000000000..f292c4b49481fb --- /dev/null +++ b/dts/bindings/pinctrl/pinctrl.yaml @@ -0,0 +1,42 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: Pinctrl Base Structure +id: pinctrl +version: 0.1 + +description: > + This binding gives the base structures for all pin controller devices + +properties: + pin-controller: + type: string + category: required + description: device controller identification + generation: define + + compatible: + type: string + category: required + description: compatible strings + generation: define + + "#address-cells": + type: int + category: required + description: should be 1. + + "#size-cells": + type: int + category: required + description: should be 0. + + label: + type: string + category: required + description: Human readable string describing the device (used by Zephyr for device name) + generation: define +... diff --git a/dts/bindings/pinctrl/st,stm32-pinctrl.yaml b/dts/bindings/pinctrl/st,stm32-pinctrl.yaml new file mode 100644 index 00000000000000..afd6ed4e45a991 --- /dev/null +++ b/dts/bindings/pinctrl/st,stm32-pinctrl.yaml @@ -0,0 +1,22 @@ +--- +title: STM32 PINCTRL +id: st,stm32-pinctrl +version: 0.1 + +description: > + This binding gives a base representation of the STM32 PINCTRL + +inherits: + !include pinctrl.yaml + +properties: + compatible: + constraint: "st,stm32-pinctrl" + + reg: + type: int + description: mmio register space + generation: define + category: required + +... diff --git a/dts/bindings/pwm/pwm.yaml b/dts/bindings/pwm/pwm.yaml index 91ab63137fc3a8..4c07218b24f6b9 100644 --- a/dts/bindings/pwm/pwm.yaml +++ b/dts/bindings/pwm/pwm.yaml @@ -12,6 +12,12 @@ description: > This binding gives the base structures for all PWM devices properties: + compatible: + type: string + category: required + description: compatible strings + generation: define + clocks: type: array category: required @@ -23,4 +29,10 @@ properties: category: required description: Human readable string describing the device (used by Zephyr for API name) generation: define + + pinctrl-\d+: + type: array + category: optional + description: pinmux information for PWMx output + generation: define ... diff --git a/dts/bindings/pwm/st,stm32-pwm.yaml b/dts/bindings/pwm/st,stm32-pwm.yaml index b9e9a62a2e89bb..c69f9cb58c3f07 100644 --- a/dts/bindings/pwm/st,stm32-pwm.yaml +++ b/dts/bindings/pwm/st,stm32-pwm.yaml @@ -6,22 +6,28 @@ version: 0.1 description: > This binding gives a base representation of the STM32 PWM +inherits: + !include pwm.yaml + properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32-pwm" - label: - type: string - category: required - description: Human readable string describing the device (used by Zephyr for API name) - generation: define - st,prescaler: type: int category: required description: Clock prescaler at the input of the timer generation: define + + st,pwm-num-chan: + type: int + category: optional + description: Number of available PWM channels. Default is 0. + generation: define + + st,capture-num-chan: + type: int + category: optional + description: Number of available Capture channels. Default is 0. + generation: define ... diff --git a/dts/bindings/serial/st,stm32-usart.yaml b/dts/bindings/serial/st,stm32-usart.yaml index ee09aea9d7a2a3..c92b638d01afa0 100644 --- a/dts/bindings/serial/st,stm32-usart.yaml +++ b/dts/bindings/serial/st,stm32-usart.yaml @@ -11,9 +11,6 @@ inherits: properties: compatible: - type: string - category: required - description: compatible strings constraint: "st,stm32-usart" reg: diff --git a/dts/bindings/serial/uart.yaml b/dts/bindings/serial/uart.yaml index 195f40636b7ac6..8bb152132e5cd7 100644 --- a/dts/bindings/serial/uart.yaml +++ b/dts/bindings/serial/uart.yaml @@ -10,6 +10,11 @@ child: bus: uart properties: + compatible: + type: string + category: required + description: compatible strings + generation: define clock-frequency: type: int category: optional diff --git a/dts/bindings/spi/spi.yaml b/dts/bindings/spi/spi.yaml index 92ac952669ea2d..47bb6aafbdb3e5 100644 --- a/dts/bindings/spi/spi.yaml +++ b/dts/bindings/spi/spi.yaml @@ -15,6 +15,11 @@ child: bus: spi properties: + compatible: + type: string + category: required + description: compatible strings + generation: define "#address-cells": type: int category: required @@ -37,6 +42,9 @@ properties: type: compound category: optional generation: define, use-prop-name - - + pinctrl-\d+: + type: array + category: optional + description: pinmux information for SCK, MOSI, MISO + generation: define ... diff --git a/dts/bindings/spi/st,stm32-spi-fifo.yaml b/dts/bindings/spi/st,stm32-spi-fifo.yaml index ceb61c44b00f0e..101401e671fe96 100644 --- a/dts/bindings/spi/st,stm32-spi-fifo.yaml +++ b/dts/bindings/spi/st,stm32-spi-fifo.yaml @@ -28,6 +28,12 @@ properties: generation: define category: required + clocks: + type: array + category: required + description: required clocks + generation: define + interrupts: type: array category: required diff --git a/dts/bindings/timer/st,stm32-timers.yaml b/dts/bindings/timer/st,stm32-timers.yaml index 5d92337fd3de51..4b5a440dd45017 100644 --- a/dts/bindings/timer/st,stm32-timers.yaml +++ b/dts/bindings/timer/st,stm32-timers.yaml @@ -21,6 +21,7 @@ properties: category: required description: compatible strings constraint: "st,stm32-timers" + generation: define label: type: string diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index fe1105a8964223..6d9e49bd4fb0aa 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -1,183 +1,28 @@ /* * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2018 Bobby Noelte * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __DT_BINDINGS_GPIO_GPIO_H -#define __DT_BINDINGS_GPIO_GPIO_H - - -/** - * @name GPIO direction flags - * The `GPIO_DIR_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify whether a GPIO pin will be used for input or output. - * @{ - */ -/** GPIO pin to be input. */ -#define GPIO_DIR_IN (0 << 0) - -/** GPIO pin to be output. */ -#define GPIO_DIR_OUT (1 << 0) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DIR_MASK 0x1 -/** @endcond */ -/** @} */ - - -/** - * @name GPIO interrupt flags - * The `GPIO_INT_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify how input GPIO pins will trigger interrupts. - * @{ - */ -/** GPIO pin to trigger interrupt. */ -#define GPIO_INT (1 << 1) - -/** GPIO pin trigger on level low or falling edge. */ -#define GPIO_INT_ACTIVE_LOW (0 << 2) - -/** GPIO pin trigger on level high or rising edge. */ -#define GPIO_INT_ACTIVE_HIGH (1 << 2) - -/** GPIO pin trigger to be synchronized to clock pulses. */ -#define GPIO_INT_CLOCK_SYNC (1 << 3) - -/** Enable GPIO pin debounce. */ -#define GPIO_INT_DEBOUNCE (1 << 4) - -/** Do Level trigger. */ -#define GPIO_INT_LEVEL (0 << 5) - -/** Do Edge trigger. */ -#define GPIO_INT_EDGE (1 << 5) - -/** Interrupt triggers on both rising and falling edge. - * Must be combined with GPIO_INT_EDGE. - */ -#define GPIO_INT_DOUBLE_EDGE (1 << 6) -/** @} */ - - -/** - * @name GPIO polarity flags - * The `GPIO_POL_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the polarity of a GPIO pin. - * @{ - */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_POS 7 -/** @endcond */ - -/** GPIO pin polarity is normal. */ -#define GPIO_POL_NORMAL (0 << GPIO_POL_POS) - -/** GPIO pin polarity is inverted. */ -#define GPIO_POL_INV (1 << GPIO_POL_POS) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_POL_MASK (1 << GPIO_POL_POS) -/** @endcond */ -/** @} */ - - -/** - * @name GPIO pull flags - * The `GPIO_PUD_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the pull-up or pull-down electrical configuration of a GPIO pin. - * @{ - */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_POS 8 -/** @endcond */ - -/** Pin is neither pull-up nor pull-down. */ -#define GPIO_PUD_NORMAL (0 << GPIO_PUD_POS) - -/** Enable GPIO pin pull-up. */ -#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_POS) - -/** Enable GPIO pin pull-down. */ -#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_POS) - -/** @cond INTERNAL_HIDDEN */ -#define GPIO_PUD_MASK (3 << GPIO_PUD_POS) -/** @endcond */ -/** @} */ - /** - * @name GPIO drive strength flags - * The `GPIO_DS_*` flags are used with `gpio_pin_configure` or `gpio_port_configure`, - * to specify the drive strength configuration of a GPIO pin. - * - * The drive strength of individual pins can be configured - * independently for when the pin output is low and high. - * - * The `GPIO_DS_*_LOW` enumerations define the drive strength of a pin - * when output is low. - - * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin - * when output is high. + * @file + * @brief GPIO device tree defines + * @defgroup device_driver_gpio_dts GPIO device tree defines + * @ingroup device_driver_gpio * - * The `DISCONNECT` drive strength indicates that the pin is placed in a - * high impedance state and not driven, this option is used to - * configure hardware that supports a open collector drive mode. + * Device tree defines for the GPIO device driver. * - * The interface supports two different drive strengths: - * `DFLT` - The lowest drive strength supported by the HW - * `ALT` - The highest drive strength supported by the HW - * - * On hardware that supports only one standard drive strength, both - * `DFLT` and `ALT` have the same behavior. - * - * On hardware that does not support a disconnect mode, `DISCONNECT` - * will behave the same as `DFLT`. + * @note Not to be used with the legacy GPIO device driver. * @{ */ -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_LOW_POS 12 -#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_POS) -/** @endcond */ - -/** Default drive strength standard when GPIO pin output is low. - */ -#define GPIO_DS_DFLT_LOW (0x0 << GPIO_DS_LOW_POS) -/** Alternative drive strength when GPIO pin output is low. - * For hardware that does not support configurable drive strength - * use the default drive strength. - */ -#define GPIO_DS_ALT_LOW (0x1 << GPIO_DS_LOW_POS) - -/** Disconnect pin when GPIO pin output is low. - * For hardware that does not support disconnect use the default - * drive strength. - */ -#define GPIO_DS_DISCONNECT_LOW (0x3 << GPIO_DS_LOW_POS) +#ifndef _GPIO_DTS_H +#define _GPIO_DTS_H -/** @cond INTERNAL_HIDDEN */ -#define GPIO_DS_HIGH_POS 14 -#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_POS) -/** @endcond */ - -/** Default drive strength when GPIO pin output is high. - */ -#define GPIO_DS_DFLT_HIGH (0x0 << GPIO_DS_HIGH_POS) - -/** Alternative drive strength when GPIO pin output is high. - * For hardware that does not support configurable drive strengths - * use the default drive strength. - */ -#define GPIO_DS_ALT_HIGH (0x1 << GPIO_DS_HIGH_POS) - -/** Disconnect pin when GPIO pin output is high. - * For hardware that does not support disconnect use the default - * drive strength. - */ -#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_POS) -/** @} */ +#include +#endif /* _GPIO_DTS_H */ +/** @} device_driver_gpio_dts */ -#endif /* __DT_BINDINGS_GPIO_GPIO_H */ diff --git a/include/dt-bindings/pinctrl/pinctrl_stm32.h b/include/dt-bindings/pinctrl/pinctrl_stm32.h new file mode 100644 index 00000000000000..9bb12c5acc9bfb --- /dev/null +++ b/include/dt-bindings/pinctrl/pinctrl_stm32.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2017 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief STM32 pinctrl device tree defines + * @defgroup device_driver_pinctrl_stm32_dts STM32 pinctrl device tree defines + * @ingroup device_driver_pinctrl_stm32 + * + * Device tree defines for the STM32 PINCTRL device driver. + * + * @note Not to be used with the STM32 PINMUX and GPIO driver. + * @{ + */ + +#ifndef _PINCTRL_STM32_DTS_H +#define _PINCTRL_STM32_DTS_H + +#include + +/** + * @brief numerical IDs for IO ports + */ + +#define PINCTRL_STM32_PORTA 0 /* IO port A */ +#define PINCTRL_STM32_PORTB 1 /* .. */ +#define PINCTRL_STM32_PORTC 2 +#define PINCTRL_STM32_PORTD 3 +#define PINCTRL_STM32_PORTE 4 +#define PINCTRL_STM32_PORTF 5 +#define PINCTRL_STM32_PORTG 6 +#define PINCTRL_STM32_PORTH 7 /* IO port H */ + +/** + * @def PINCTRL_STM32_PIN + * @brief helper macro to encode an IO port pin in a numerical format + */ +#define PINCTRL_STM32_PIN(_port, _pin) \ + (_port << 4 | _pin) + +/** + * @brief PINCTRL STM32 Pin Defines + * @defgroup pinctrl_interface_stm32_pin_defs PINCTRL STM32 Pin Defines + * @ingroup device_driver_pinctrl_stm32_dts + * @{ + */ + +/** + * @def PINCTRL_STM32_PINA0 + * @brief Pin A0 + */ +#define PINCTRL_STM32_PINA0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 0) +#define PINCTRL_STM32_PINA1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 1) +#define PINCTRL_STM32_PINA2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 2) +#define PINCTRL_STM32_PINA3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 3) +#define PINCTRL_STM32_PINA4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 4) +#define PINCTRL_STM32_PINA5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 5) +#define PINCTRL_STM32_PINA6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 6) +#define PINCTRL_STM32_PINA7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 7) +#define PINCTRL_STM32_PINA8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 8) +#define PINCTRL_STM32_PINA9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 9) +#define PINCTRL_STM32_PINA10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 10) +#define PINCTRL_STM32_PINA11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 11) +#define PINCTRL_STM32_PINA12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 12) +#define PINCTRL_STM32_PINA13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 13) +#define PINCTRL_STM32_PINA14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 14) +#define PINCTRL_STM32_PINA15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTA, 15) + +#define PINCTRL_STM32_PINB0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 0) +#define PINCTRL_STM32_PINB1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 1) +#define PINCTRL_STM32_PINB2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 2) +#define PINCTRL_STM32_PINB3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 3) +#define PINCTRL_STM32_PINB4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 4) +#define PINCTRL_STM32_PINB5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 5) +#define PINCTRL_STM32_PINB6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 6) +#define PINCTRL_STM32_PINB7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 7) +#define PINCTRL_STM32_PINB8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 8) +#define PINCTRL_STM32_PINB9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 9) +#define PINCTRL_STM32_PINB10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 10) +#define PINCTRL_STM32_PINB11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 11) +#define PINCTRL_STM32_PINB12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 12) +#define PINCTRL_STM32_PINB13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 13) +#define PINCTRL_STM32_PINB14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 14) +#define PINCTRL_STM32_PINB15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTB, 15) + +#define PINCTRL_STM32_PINC0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 0) +#define PINCTRL_STM32_PINC1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 1) +#define PINCTRL_STM32_PINC2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 2) +#define PINCTRL_STM32_PINC3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 3) +#define PINCTRL_STM32_PINC4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 4) +#define PINCTRL_STM32_PINC5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 5) +#define PINCTRL_STM32_PINC6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 6) +#define PINCTRL_STM32_PINC7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 7) +#define PINCTRL_STM32_PINC8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 8) +#define PINCTRL_STM32_PINC9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 9) +#define PINCTRL_STM32_PINC10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 10) +#define PINCTRL_STM32_PINC11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 11) +#define PINCTRL_STM32_PINC12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 12) +#define PINCTRL_STM32_PINC13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 13) +#define PINCTRL_STM32_PINC14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 14) +#define PINCTRL_STM32_PINC15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTC, 15) + +#define PINCTRL_STM32_PIND0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 0) +#define PINCTRL_STM32_PIND1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 1) +#define PINCTRL_STM32_PIND2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 2) +#define PINCTRL_STM32_PIND3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 3) +#define PINCTRL_STM32_PIND4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 4) +#define PINCTRL_STM32_PIND5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 5) +#define PINCTRL_STM32_PIND6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 6) +#define PINCTRL_STM32_PIND7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 7) +#define PINCTRL_STM32_PIND8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 8) +#define PINCTRL_STM32_PIND9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 9) +#define PINCTRL_STM32_PIND10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 10) +#define PINCTRL_STM32_PIND11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 11) +#define PINCTRL_STM32_PIND12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 12) +#define PINCTRL_STM32_PIND13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 13) +#define PINCTRL_STM32_PIND14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 14) +#define PINCTRL_STM32_PIND15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTD, 15) + +#define PINCTRL_STM32_PINE0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 0) +#define PINCTRL_STM32_PINE1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 1) +#define PINCTRL_STM32_PINE2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 2) +#define PINCTRL_STM32_PINE3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 3) +#define PINCTRL_STM32_PINE4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 4) +#define PINCTRL_STM32_PINE5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 5) +#define PINCTRL_STM32_PINE6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 6) +#define PINCTRL_STM32_PINE7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 7) +#define PINCTRL_STM32_PINE8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 8) +#define PINCTRL_STM32_PINE9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 9) +#define PINCTRL_STM32_PINE10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 10) +#define PINCTRL_STM32_PINE11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 11) +#define PINCTRL_STM32_PINE12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 12) +#define PINCTRL_STM32_PINE13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 13) +#define PINCTRL_STM32_PINE14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 14) +#define PINCTRL_STM32_PINE15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTE, 15) + +#define PINCTRL_STM32_PINF0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 0) +#define PINCTRL_STM32_PINF1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 1) +#define PINCTRL_STM32_PINF2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 2) +#define PINCTRL_STM32_PINF3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 3) +#define PINCTRL_STM32_PINF4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 4) +#define PINCTRL_STM32_PINF5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 5) +#define PINCTRL_STM32_PINF6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 6) +#define PINCTRL_STM32_PINF7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 7) +#define PINCTRL_STM32_PINF8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 8) +#define PINCTRL_STM32_PINF9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 9) +#define PINCTRL_STM32_PINF10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 10) +#define PINCTRL_STM32_PINF11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 11) +#define PINCTRL_STM32_PINF12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 12) +#define PINCTRL_STM32_PINF13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 13) +#define PINCTRL_STM32_PINF14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 14) +#define PINCTRL_STM32_PINF15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTF, 15) + +#define PINCTRL_STM32_PING0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 0) +#define PINCTRL_STM32_PING1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 1) +#define PINCTRL_STM32_PING2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 2) +#define PINCTRL_STM32_PING3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 3) +#define PINCTRL_STM32_PING4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 4) +#define PINCTRL_STM32_PING5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 5) +#define PINCTRL_STM32_PING6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 6) +#define PINCTRL_STM32_PING7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 7) +#define PINCTRL_STM32_PING8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 8) +#define PINCTRL_STM32_PING9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 9) +#define PINCTRL_STM32_PING10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 10) +#define PINCTRL_STM32_PING11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 11) +#define PINCTRL_STM32_PING12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 12) +#define PINCTRL_STM32_PING13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 13) +#define PINCTRL_STM32_PING14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 14) +#define PINCTRL_STM32_PING15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTG, 15) + +#define PINCTRL_STM32_PINH0 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 0) +#define PINCTRL_STM32_PINH1 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 1) +#define PINCTRL_STM32_PINH2 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 2) +#define PINCTRL_STM32_PINH3 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 3) +#define PINCTRL_STM32_PINH4 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 4) +#define PINCTRL_STM32_PINH5 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 5) +#define PINCTRL_STM32_PINH6 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 6) +#define PINCTRL_STM32_PINH7 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 7) +#define PINCTRL_STM32_PINH8 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 8) +#define PINCTRL_STM32_PINH9 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 9) +#define PINCTRL_STM32_PINH10 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 10) +#define PINCTRL_STM32_PINH11 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 11) +#define PINCTRL_STM32_PINH12 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 12) +#define PINCTRL_STM32_PINH13 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 13) +#define PINCTRL_STM32_PINH14 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 14) +#define PINCTRL_STM32_PINH15 PINCTRL_STM32_PIN(PINCTRL_STM32_PORTH, 15) + +/** @} pinctrl_interface_stm32_pin_defs */ + +/** + * @brief PINCTRL STM32 Group Defines + * @defgroup pinctrl_interface_stm32_group_defs PINCTRL STM32 Group Definess + * @ingroup device_driver_pinctrl_stm32_dts + * @{ + */ + +/** Groups are currently not supported. */ + +/** @} pinctrl_interface_stm32_group_defs */ + +/** + * @brief PINCTRL STM32 Function Defines + * @defgroup pinctrl_interface_stm32_func_defs PINCTRL STM32 Function Defines + * @ingroup device_driver_pinctrl_stm32_dts + * @{ + */ + +/* Alternate Functions */ +#define PINCTRL_STM32_FUNCTION_ALT_0 PINCTRL_FUNCTION_HARDWARE_0 +#define PINCTRL_STM32_FUNCTION_ALT_1 PINCTRL_FUNCTION_HARDWARE_1 +#define PINCTRL_STM32_FUNCTION_ALT_2 PINCTRL_FUNCTION_HARDWARE_2 +#define PINCTRL_STM32_FUNCTION_ALT_3 PINCTRL_FUNCTION_HARDWARE_3 +#define PINCTRL_STM32_FUNCTION_ALT_4 PINCTRL_FUNCTION_HARDWARE_4 +#define PINCTRL_STM32_FUNCTION_ALT_5 PINCTRL_FUNCTION_HARDWARE_5 +#define PINCTRL_STM32_FUNCTION_ALT_6 PINCTRL_FUNCTION_HARDWARE_6 +#define PINCTRL_STM32_FUNCTION_ALT_7 PINCTRL_FUNCTION_HARDWARE_7 +#define PINCTRL_STM32_FUNCTION_ALT_8 PINCTRL_FUNCTION_HARDWARE_8 +#define PINCTRL_STM32_FUNCTION_ALT_9 PINCTRL_FUNCTION_HARDWARE_9 +#define PINCTRL_STM32_FUNCTION_ALT_10 PINCTRL_FUNCTION_HARDWARE_10 +#define PINCTRL_STM32_FUNCTION_ALT_11 PINCTRL_FUNCTION_HARDWARE_11 +#define PINCTRL_STM32_FUNCTION_ALT_12 PINCTRL_FUNCTION_HARDWARE_12 +#define PINCTRL_STM32_FUNCTION_ALT_13 PINCTRL_FUNCTION_HARDWARE_13 +#define PINCTRL_STM32_FUNCTION_ALT_14 PINCTRL_FUNCTION_HARDWARE_14 +#define PINCTRL_STM32_FUNCTION_ALT_15 PINCTRL_FUNCTION_HARDWARE_15 + +/* General Functions */ +#define PINCTRL_STM32_FUNCTION_INPUT PINCTRL_FUNCTION_HARDWARE_16 +#define PINCTRL_STM32_FUNCTION_OUTPUT PINCTRL_FUNCTION_HARDWARE_17 +#define PINCTRL_STM32_FUNCTION_ANALOG PINCTRL_FUNCTION_HARDWARE_18 + +/** @} pinctrl_interface_stm32_func_defs */ + +#endif /* _PINCTRL_STM32_DTS_H */ + +/** @} device_driver_pinctrl_stm32_dts */ diff --git a/include/gpio.h b/include/gpio.h index d174837b8b893c..46d47b320a9b8a 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -32,6 +32,44 @@ extern "C" { * @{ */ +/** --------------------------------------------------- + * @todo Work around until all GPIO drivers support + * the pin definitions + * --------------------------------------------------- + */ +#if CONFIG_PINCTRL + +#include +#include + +/** + * Get pin index from port pin number. + * + * @param pin Pin number + * @return Pin index [0..31] + * @retval -EINVAL on error + */ +static inline int gpio_port_pin_idx(u32_t pin) +{ + if (!pin) { + return -EINVAL; + } +#if defined(__GNUC__) && (__SIZEOF_INT__ == 4) + return 31 - __builtin_clz(pin); +#elif defined(__GNUC__) && (__SIZEOF_LONG__ == 4) + return 31 - __builtin_clzl(pin); +#else + int idx = 0; +#define step(x) \ + do { if (pin >= ((u32_t)1) << x) idx += x, pin >>= x; } while (0) + step(16); step(8); step(4); step(2); step(1); +#undef step + return idx; +#endif +} + +#endif + /** @cond INTERNAL_HIDDEN */ #define GPIO_ACCESS_BY_PIN 0 #define GPIO_ACCESS_BY_PORT 1 diff --git a/include/gpio_common.h b/include/gpio_common.h new file mode 100644 index 00000000000000..6abd36e13b9b88 --- /dev/null +++ b/include/gpio_common.h @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _GPIO_COMMON_H_ +#define _GPIO_COMMON_H_ + +/** + * @name GPIO direction flags + * The `GPIO_DIR_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify whether a GPIO pin will be used for input + * or output. + * @{ + */ +/** GPIO pin to be input. */ +#define GPIO_DIR_IN (0 << 0) + +/** GPIO pin to be output. */ +#define GPIO_DIR_OUT (1 << 0) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DIR_MASK 0x1 +/** @endcond */ +/** @} */ + + +/** + * @name GPIO interrupt flags + * The `GPIO_INT_*` flags are used with `gpio_pin_configure` or ` + * gpio_port_configure`, to specify how input GPIO pins will trigger + * interrupts. + * @{ + */ +/** GPIO pin to trigger interrupt. */ +#define GPIO_INT (1 << 1) + +/** GPIO pin trigger on level low or falling edge. */ +#define GPIO_INT_ACTIVE_LOW (0 << 2) + +/** GPIO pin trigger on level high or rising edge. */ +#define GPIO_INT_ACTIVE_HIGH (1 << 2) + +/** GPIO pin trigger to be synchronized to clock pulses. */ +#define GPIO_INT_CLOCK_SYNC (1 << 3) + +/** Enable GPIO pin debounce. */ +#define GPIO_INT_DEBOUNCE (1 << 4) + +/** Do Level trigger. */ +#define GPIO_INT_LEVEL (0 << 5) + +/** Do Edge trigger. */ +#define GPIO_INT_EDGE (1 << 5) + +/** Interrupt triggers on both rising and falling edge. + * Must be combined with GPIO_INT_EDGE. + */ +#define GPIO_INT_DOUBLE_EDGE (1 << 6) +/** @} */ + + +/** + * @name GPIO polarity flags + * The `GPIO_POL_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the polarity of a GPIO pin. + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define GPIO_POL_POS 7 +/** @endcond */ + +/** GPIO pin polarity is normal. */ +#define GPIO_POL_NORMAL (0 << GPIO_POL_POS) + +/** GPIO pin polarity is inverted. */ +#define GPIO_POL_INV (1 << GPIO_POL_POS) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_POL_MASK (1 << GPIO_POL_POS) +/** @endcond */ +/** @} */ + + +/** + * @name GPIO pull flags + * The `GPIO_PUD_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the pull-up or pull-down electrical + * configuration of a GPIO pin. + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define GPIO_PUD_POS 8 +/** @endcond */ + +/** Pin is neither pull-up nor pull-down. */ +#define GPIO_PUD_NORMAL (0 << GPIO_PUD_POS) + +/** Enable GPIO pin pull-up. */ +#define GPIO_PUD_PULL_UP (1 << GPIO_PUD_POS) + +/** Enable GPIO pin pull-down. */ +#define GPIO_PUD_PULL_DOWN (2 << GPIO_PUD_POS) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_PUD_MASK (3 << GPIO_PUD_POS) +/** @endcond */ +/** @} */ + + +/** + * @name GPIO drive strength flags + * The `GPIO_DS_*` flags are used with `gpio_pin_configure` or + * `gpio_port_configure`, to specify the drive strength configuration of a + * GPIO pin. + * + * The drive strength of individual pins can be configured + * independently for when the pin output is low and high. + * + * The `GPIO_DS_*_LOW` enumerations define the drive strength of a pin + * when output is low. + + * The `GPIO_DS_*_HIGH` enumerations define the drive strength of a pin + * when output is high. + * + * The `DISCONNECT` drive strength indicates that the pin is placed in a + * high impedance state and not driven, this option is used to + * configure hardware that supports a open collector drive mode. + * + * The interface supports two different drive strengths: + * `DFLT` - The lowest drive strength supported by the HW + * `ALT` - The highest drive strength supported by the HW + * + * On hardware that supports only one standard drive strength, both + * `DFLT` and `ALT` have the same behavior. + * + * On hardware that does not support a disconnect mode, `DISCONNECT` + * will behave the same as `DFLT`. + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DS_LOW_POS 12 +#define GPIO_DS_LOW_MASK (0x3 << GPIO_DS_LOW_POS) +/** @endcond */ + +/** Default drive strength standard when GPIO pin output is low. + */ +#define GPIO_DS_DFLT_LOW (0x0 << GPIO_DS_LOW_POS) + +/** Alternative drive strength when GPIO pin output is low. + * For hardware that does not support configurable drive strength + * use the default drive strength. + */ +#define GPIO_DS_ALT_LOW (0x1 << GPIO_DS_LOW_POS) + +/** Disconnect pin when GPIO pin output is low. + * For hardware that does not support disconnect use the default + * drive strength. + */ +#define GPIO_DS_DISCONNECT_LOW (0x3 << GPIO_DS_LOW_POS) + +/** @cond INTERNAL_HIDDEN */ +#define GPIO_DS_HIGH_POS 14 +#define GPIO_DS_HIGH_MASK (0x3 << GPIO_DS_HIGH_POS) +/** @endcond */ + +/** Default drive strength when GPIO pin output is high. + */ +#define GPIO_DS_DFLT_HIGH (0x0 << GPIO_DS_HIGH_POS) + +/** Alternative drive strength when GPIO pin output is high. + * For hardware that does not support configurable drive strengths + * use the default drive strength. + */ +#define GPIO_DS_ALT_HIGH (0x1 << GPIO_DS_HIGH_POS) + +/** Disconnect pin when GPIO pin output is high. + * For hardware that does not support disconnect use the default + * drive strength. + */ +#define GPIO_DS_DISCONNECT_HIGH (0x3 << GPIO_DS_HIGH_POS) +/** @} */ + +/** + * @brief GPIO Pin Defines + * @defgroup gpio_interface_pin_defs GPIO Pin Defines + * @ingroup gpio_interface + * + * @note Not to be used with the legacy GPIO device driver. + * @{ + */ + +/** + * @def GPIO_PORT_PIN + * @brief Helper to create pin number from pin index. + * + * @param idx Index of pin within port [0..31] + * @return Pin number + */ +#define GPIO_PORT_PIN(idx) (1U << (idx)) + +/** + * @def GPIO_PORT_PIN_IDX + * @brief Helper to create pin index from pin number. + * + * Pin number shall be one of GPIO_PORT_PINx (only one bit set). + * + * @note For runtime calculation use gpio_port_pin_idx() instead. + * + * @param pin Pin number + * @return Index of pin within port [0..31] + */ +#define GPIO_PORT_PIN_IDX(pin) ( \ + (((pin & GPIO_PORT_PIN(0)) >> 0) * 0) + \ + (((pin & GPIO_PORT_PIN(1)) >> 1) * 1) + \ + (((pin & GPIO_PORT_PIN(2)) >> 2) * 2) + \ + (((pin & GPIO_PORT_PIN(3)) >> 3) * 3) + \ + (((pin & GPIO_PORT_PIN(4)) >> 4) * 4) + \ + (((pin & GPIO_PORT_PIN(5)) >> 5) * 5) + \ + (((pin & GPIO_PORT_PIN(6)) >> 6) * 6) + \ + (((pin & GPIO_PORT_PIN(7)) >> 7) * 7) + \ + (((pin & GPIO_PORT_PIN(8)) >> 8) * 8) + \ + (((pin & GPIO_PORT_PIN(9)) >> 9) * 9) + \ + (((pin & GPIO_PORT_PIN(10)) >> 10) * 10) + \ + (((pin & GPIO_PORT_PIN(11)) >> 11) * 11) + \ + (((pin & GPIO_PORT_PIN(12)) >> 12) * 12) + \ + (((pin & GPIO_PORT_PIN(13)) >> 13) * 13) + \ + (((pin & GPIO_PORT_PIN(14)) >> 14) * 14) + \ + (((pin & GPIO_PORT_PIN(15)) >> 15) * 15) + \ + (((pin & GPIO_PORT_PIN(16)) >> 16) * 16) + \ + (((pin & GPIO_PORT_PIN(17)) >> 17) * 17) + \ + (((pin & GPIO_PORT_PIN(18)) >> 18) * 18) + \ + (((pin & GPIO_PORT_PIN(19)) >> 19) * 19) + \ + (((pin & GPIO_PORT_PIN(20)) >> 20) * 20) + \ + (((pin & GPIO_PORT_PIN(21)) >> 21) * 21) + \ + (((pin & GPIO_PORT_PIN(22)) >> 22) * 22) + \ + (((pin & GPIO_PORT_PIN(23)) >> 23) * 23) + \ + (((pin & GPIO_PORT_PIN(24)) >> 24) * 24) + \ + (((pin & GPIO_PORT_PIN(25)) >> 25) * 25) + \ + (((pin & GPIO_PORT_PIN(26)) >> 26) * 26) + \ + (((pin & GPIO_PORT_PIN(27)) >> 27) * 27) + \ + (((pin & GPIO_PORT_PIN(28)) >> 28) * 28) + \ + (((pin & GPIO_PORT_PIN(29)) >> 29) * 29) + \ + (((pin & GPIO_PORT_PIN(30)) >> 30) * 30) + \ + (((pin & GPIO_PORT_PIN(31)) >> 31) * 31)) + +/** + * @def GPIO_PORT_PIN0 + * @brief Pin 0 of the GPIO port. + */ +#define GPIO_PORT_PIN0 GPIO_PORT_PIN(0) + +/** + * @def GPIO_PORT_PIN1 + * @brief Pin 1 of the GPIO port. + */ +#define GPIO_PORT_PIN1 GPIO_PORT_PIN(1) + +/** + * @def GPIO_PORT_PIN2 + * @brief Pin 2 of the GPIO port. + */ +#define GPIO_PORT_PIN2 GPIO_PORT_PIN(2) + +/** + * @def GPIO_PORT_PIN3 + * @brief Pin 3 of the GPIO port. + */ +#define GPIO_PORT_PIN3 GPIO_PORT_PIN(3) + +/** + * @def GPIO_PORT_PIN4 + * @brief Pin 4 of the GPIO port. + */ +#define GPIO_PORT_PIN4 GPIO_PORT_PIN(4) + +/** + * @def GPIO_PORT_PIN5 + * @brief Pin 5 of the GPIO port. + */ +#define GPIO_PORT_PIN5 GPIO_PORT_PIN(5) + +/** + * @def GPIO_PORT_PIN6 + * @brief Pin 6 of the GPIO port. + */ +#define GPIO_PORT_PIN6 GPIO_PORT_PIN(6) + +/** + * @def GPIO_PORT_PIN7 + * @brief Pin 7 of the GPIO port. + */ +#define GPIO_PORT_PIN7 GPIO_PORT_PIN(7) + +/** + * @def GPIO_PORT_PIN8 + * @brief Pin 8 of the GPIO port. + */ +#define GPIO_PORT_PIN8 GPIO_PORT_PIN(8) + +/** + * @def GPIO_PORT_PIN9 + * @brief Pin 9 of the GPIO port. + */ +#define GPIO_PORT_PIN9 GPIO_PORT_PIN(9) + +/** + * @def GPIO_PORT_PIN10 + * @brief Pin 10 of the GPIO port. + */ +#define GPIO_PORT_PIN10 GPIO_PORT_PIN(10) + +/** + * @def GPIO_PORT_PIN11 + * @brief Pin 11 of the GPIO port. + */ +#define GPIO_PORT_PIN11 GPIO_PORT_PIN(11) + +/** + * @def GPIO_PORT_PIN12 + * @brief Pin 12 of the GPIO port. + */ +#define GPIO_PORT_PIN12 GPIO_PORT_PIN(12) + +/** + * @def GPIO_PORT_PIN13 + * @brief Pin 13 of the GPIO port. + */ +#define GPIO_PORT_PIN13 GPIO_PORT_PIN(13) + +/** + * @def GPIO_PORT_PIN14 + * @brief Pin 14 of the GPIO port. + */ +#define GPIO_PORT_PIN14 GPIO_PORT_PIN(14) + +/** + * @def GPIO_PORT_PIN15 + * @brief Pin 15 of the GPIO port. + */ +#define GPIO_PORT_PIN15 GPIO_PORT_PIN(15) + +/** + * @def GPIO_PORT_PIN16 + * @brief Pin 16 of the GPIO port. + */ +#define GPIO_PORT_PIN16 GPIO_PORT_PIN(16) + +/** + * @def GPIO_PORT_PIN17 + * @brief Pin 17 of the GPIO port. + */ +#define GPIO_PORT_PIN17 GPIO_PORT_PIN(17) + +/** + * @def GPIO_PORT_PIN18 + * @brief Pin 18 of the GPIO port. + */ +#define GPIO_PORT_PIN18 GPIO_PORT_PIN(18) + +/** + * @def GPIO_PORT_PIN19 + * @brief Pin 19 of the GPIO port. + */ +#define GPIO_PORT_PIN19 GPIO_PORT_PIN(19) + +/** + * @def GPIO_PORT_PIN20 + * @brief Pin 20 of the GPIO port. + */ +#define GPIO_PORT_PIN20 GPIO_PORT_PIN(20) + +/** + * @def GPIO_PORT_PIN21 + * @brief Pin 21 of the GPIO port. + */ +#define GPIO_PORT_PIN21 GPIO_PORT_PIN(21) + +/** + * @def GPIO_PORT_PIN22 + * @brief Pin 22 of the GPIO port. + */ +#define GPIO_PORT_PIN22 GPIO_PORT_PIN(22) + +/** + * @def GPIO_PORT_PIN23 + * @brief Pin 23 of the GPIO port. + */ +#define GPIO_PORT_PIN23 GPIO_PORT_PIN(23) + +/** + * @def GPIO_PORT_PIN24 + * @brief Pin 24 of the GPIO port. + */ +#define GPIO_PORT_PIN24 GPIO_PORT_PIN(24) + +/** + * @def GPIO_PORT_PIN25 + * @brief Pin 25 of the GPIO port. + */ +#define GPIO_PORT_PIN25 GPIO_PORT_PIN(25) + +/** + * @def GPIO_PORT_PIN26 + * @brief Pin 26 of the GPIO port. + */ +#define GPIO_PORT_PIN26 GPIO_PORT_PIN(26) + +/** + * @def GPIO_PORT_PIN27 + * @brief Pin 27 of the GPIO port. + */ +#define GPIO_PORT_PIN27 GPIO_PORT_PIN(27) + +/** + * @def GPIO_PORT_PIN28 + * @brief Pin 28 of the GPIO port. + */ +#define GPIO_PORT_PIN28 GPIO_PORT_PIN(28) + +/** + * @def GPIO_PORT_PIN29 + * @brief Pin 29 of the GPIO port. + */ +#define GPIO_PORT_PIN29 GPIO_PORT_PIN(29) + +/** + * @def GPIO_PORT_PIN30 + * @brief Pin 30 of the GPIO port. + */ +#define GPIO_PORT_PIN30 GPIO_PORT_PIN(30) + +/** + * @def GPIO_PORT_PIN31 + * @brief Pin 31 of the GPIO port. + */ +#define GPIO_PORT_PIN31 GPIO_PORT_PIN(31) + + +/** @} gpio_interface_pin_defs */ + +#endif /* _GPIO_COMMON_H_ */ diff --git a/include/pinctrl.h b/include/pinctrl.h new file mode 100644 index 00000000000000..9620e1352963b4 --- /dev/null +++ b/include/pinctrl.h @@ -0,0 +1,918 @@ +/* + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Public APIs for PINCTRL drivers + */ + +#ifndef __INCLUDE_PINCTRL_H +#define __INCLUDE_PINCTRL_H + +/** + * @brief PINCTRL Interface + * @defgroup pinctrl_interface PINCTRL Interface + * @ingroup io_interfaces + * + * Pin control interface for + * - pin control: get pin control properties + * - pin configuration: configure a pins electronic properties + * - pin multiplexing: reuse the same pin for different purposes + * @{ + */ + +#include + +#include +#include +#include + + +/** + * @def PINCTRL_CONFIG + * @brief Create a pinctrl pin configuration value. + * + * The configuration defines shall be the + * @ref pinctrl_interface_pin_configurations "pinctrl pin configurations" + * given in the pinctrl_common.h file. + */ +#define PINCTRL_CONFIG(...) _PINCTRL_CONFIG0(__VA_ARGS__) +/** + * @def _PINCTRL_CONFIG0 + * @internal + */ +#define _PINCTRL_CONFIG0(...) \ + _PINCTRL_CONFIG32(__VA_ARGS__, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +/** + * @def _PINCTRL_CONFIG32 + * @internal + */ +#define _PINCTRL_CONFIG32(c0, c1, c2, c3, c4, c5, c6, c7, \ + c8, c9, c10, c11, c12, c13, c14, c15, \ + c16, c17, c18, c19, c20, c21, c22, c23, \ + c24, c25, c26, c27, c28, c29, c30, c31, \ + ...) \ + (c0 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | \ + c8 | c9 | c10 | c11 | c12 | c13 | c14 | c15 | \ + c16 | c17 | c18 | c19 | c20 | c21 | c22 | c23 | \ + c24 | c25 | c26 | c17 | c28 | c29 | c30 | c31) + + +#ifdef __cplusplus +extern "C" { +#endif + +struct pinctrl_control_api { + u16_t (*get_pins_count)(struct device *dev); +#if CONFIG_PINCTRL_RUNTIME_DTS + int (*get_groups_count)(struct device *dev); + int (*get_group_pins)(struct device *dev, u16_t group, + u16_t *pins, u16_t *num_pins); + u16_t (*get_states_count)(struct device *dev); + int (*get_state_group)(struct device *dev, u16_t state, u16_t *group); + u16_t (*get_functions_count)(struct device *dev); + int (*get_function_group)(struct device *dev, u16_t func, + const char *name, u16_t *group); + int (*get_function_groups)(struct device *dev, u16_t func, + u16_t *groups, u16_t *num_groups); + int (*get_function_state)(struct device *dev, u16_t func, + const char *name, u16_t *state); + int (*get_function_states)(struct device *dev, u16_t func, + u16_t *states, u16_t *num_states); + int (*get_device_function)(struct device *dev, struct device *client, + u16_t *func); +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + int (*get_gpio_range)(struct device *dev, struct device *gpio, + u32_t gpio_pin, u16_t *pin, u16_t *base_pin, + u8_t *num_pins); +}; + +struct pinctrl_config_api { + int (*get)(struct device *dev, u16_t pin, u32_t *config); + int (*set)(struct device *dev, u16_t pin, u32_t config); +#if CONFIG_PINCTRL_RUNTIME_DTS + int (*group_get)(struct device *dev, u16_t group, + u32_t *configs, u16_t *num_configs); + int (*group_set)(struct device *dev, u16_t group, + const u32_t *configs, u16_t num_configs); +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +}; + +struct pinctrl_mux_api { + int (*get)(struct device *dev, u16_t pin, u16_t *func); + int (*set)(struct device *dev, u16_t pin, u16_t func); +#if CONFIG_PINCTRL_RUNTIME_DTS + int (*group_set)(struct device *dev, u16_t group, u16_t func); + int (*request)(struct device *dev, u16_t pin, const char *owner); + int (*free)(struct device *dev, u16_t pin, const char *owner); +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +}; + +struct pinctrl_state_api { + int (*set)(struct device *dev, u16_t state); +}; + +struct pinctrl_driver_api { + struct pinctrl_control_api control; + struct pinctrl_config_api config; + struct pinctrl_mux_api mux; + struct pinctrl_state_api state; +}; + +/** + * Get the number of pins controlled by this pin controller. + * + * @param dev Pointer to the device structure for the driver instance. + * @return number of pins + */ +__syscall u16_t pinctrl_get_pins_count(struct device *dev); + +/** @internal + */ +static inline u16_t _impl_pinctrl_get_pins_count(struct device *dev) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_pins_count(dev); +} + +/** + * Get the number of groups selectable by this pin controller. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @return number of groups + */ +__syscall u16_t pinctrl_get_groups_count(struct device *dev); + +/** @internal + */ +static inline u16_t _impl_pinctrl_get_groups_count(struct device *dev) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_groups_count(dev); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return 0; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the pins that are in a pin group. + * + * Returns an array of pin numbers. The applicable pins + * are returned in @p pins and the number of pins in @p num_pins. The + * number of pins returned is bounded by the initial value of @p num_pins + * when called. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param group Group + * @param[in,out] pins Array of pins. + * @param[in,out] num_pins Size of the array of pins. + * @retval 0 on success + * @retval -EINVAL if number of pins exceeds array size. + * @retval -ENOTSUP if requested group is not available on this controller + */ +__syscall int pinctrl_get_group_pins(struct device *dev, u16_t group, + u16_t *pins, u16_t *num_pins); + +/** @internal + */ +static inline int _impl_pinctrl_get_group_pins(struct device *dev, u16_t group, + u16_t *pins, u16_t *num_pins) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_group_pins(dev, group, pins, num_pins); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the number of states selectable by this pin controller. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @return number of states + */ +__syscall u16_t pinctrl_get_states_count(struct device *dev); + +/** @internal + */ +static inline u16_t _impl_pinctrl_get_states_count(struct device *dev) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_states_count(dev); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return 0; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the group of pins controlled by the pinctrl state. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param state State + * @param[out] group Group + * @retval 0 on success + * @retval -ENOTSUP if requested state is not available on this controller + */ +__syscall int pinctrl_get_state_group(struct device *dev, u16_t state, + u16_t *group); + +/** @internal + */ +static inline int _impl_pinctrl_get_state_group(struct device *dev, + u16_t state, u16_t *group) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_state_group(dev, state, group); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the number of selectable functions of this pin controller. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @return number of functions + */ +__syscall u16_t pinctrl_get_functions_count(struct device *dev); + +/** @internal + */ +static inline u16_t _impl_pinctrl_get_functions_count(struct device *dev) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_functions_count(dev); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return 0; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the pin group of given name that is related to given function. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param func Function + * @param name Group name + * @param[out] group Group + * @retval 0 on success + * @retval -ENODEV if requested function is not available on this controller + * @retval -ENOTSUP if there is no group with the requested name for + * the function + */ +__syscall int pinctrl_get_function_group(struct device *dev, u16_t func, + const char *name, u16_t *group); + +/** @internal + */ +static inline int _impl_pinctrl_get_function_group(struct device *dev, + u16_t func, + const char *name, + u16_t *group) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_function_group(dev, func, name, group); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the groups of pins that can be multiplexed to the function. + * + * Returns an array of group numbers. The group number can be used with + * pinctrl_get_group_pins() to retrieve the pins. The applicable groups + * are returned in @p groups and the number of groups in @p num_groups. The + * number of groups returned is bounded by the initial value of @p num_groups + * when called. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param func Function + * @param[out] groups Array of groups. + * @param[in,out] num_groups Size of the array of groups. + * @retval 0 on success + * @retval -ENODEV if requested function is not available on this controller + * @retval -ENOTSUP if there is no group + * @retval -EINVAL if the number of available groups exceeds array size + */ +__syscall int pinctrl_get_function_groups(struct device *dev, u16_t func, + u16_t *groups, u16_t *num_groups); + +/** @internal + */ +static inline int _impl_pinctrl_get_function_groups(struct device *dev, + u16_t func, + u16_t *groups, + u16_t *num_groups) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_function_groups(dev, func, groups, num_groups); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the state of given name that can be applied to given function. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param func Function + * @param name State name + * @param[out] state State + * @retval 0 on success + * @retval -ENODEV if function is unknown to pin controller + * @retval -ENOTSUP if there is no state with the requested name for + * the function + */ +__syscall int pinctrl_get_function_state(struct device *dev, u16_t func, + const char *name, u16_t *state); + +/** @internal + */ +static inline int _impl_pinctrl_get_function_state(struct device *dev, + u16_t func, + const char *name, + u16_t *state) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_function_state(dev, func, name, state); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the states that can be applied to the function. + * + * Returns an array of state numbers. The state number can be used with + * pinctrl_get_state_group() to retrieve the associated pin group. + * The applicable states are returned in @p states and the number of states + * in @p num_states. The number of states returned is bounded by the initial + * value of @p num_states when called. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param func Function + * @param[out] states Array of states. + * @param[in,out] num_states Size of the array of states. + * @retval 0 on success + * @retval -ENODEV if function is unknown to pin controller + * @retval -ENOTSUP if there is no state + * @retval -EINVAL if the number of available states exceeds array size + */ +__syscall int pinctrl_get_function_states(struct device *dev, u16_t func, + u16_t *states, u16_t *num_states); + +/** @internal + */ +static inline int _impl_pinctrl_get_function_states(struct device *dev, + u16_t func, + u16_t *states, + u16_t *num_states) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_function_states(dev, func, states, num_states); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Get the function that is associated to a client device. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param client Pointer to the device structure of the client driver instance. + * @param[out] func Function + * @retval 0 on success + * @retval -ENOTSUP if there is no function for the requested device + */ +__syscall int pinctrl_get_device_function(struct device *dev, + struct device *client, u16_t *func); + +/** @internal + */ +static inline int _impl_pinctrl_get_device_function(struct device *dev, + struct device *client, + u16_t *func) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_device_function(dev, client, func); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * Is the function a client device multiplex control. + * + * @param func Function + * @return >0 if the function denotes a client device, 0 otherwise. + */ +static inline int pinctrl_is_device_function(u16_t func) +{ + return (func >= PINCTRL_FUNCTION_DEVICE_BASE); +} + +/** + * Is the function a hardware pinmux control. + * + * @param func Function + * @return >0 if the function is a hardware pinmux control, 0 otherwise. + */ +static inline int pinctrl_is_pinmux_function(u16_t func) +{ + return (func < PINCTRL_FUNCTION_DEVICE_BASE); +} + +/** + * Get the pin controller pin number and pin mapping for a GPIO pin. + * + * @note Pin controller pins are numbered consecutively. + * + * @param dev Pointer to the device structure for the driver instance. + * @param gpio Pointer to the device structure of the GPIO driver instance. + * @param gpio_pin GPIO pin in GPIO number space. + * @param[out] pin GPIO pin in pin-controller number space. + * @param[out] base_pin Base pin of gpio range in pin-controller number space. + * @param[out] num_pins Number of pins in gpio range. + * @retval 0 on success + * @retval -ENOTSUP if there is no gpio range for the requested GPIO pin. + */ +__syscall int pinctrl_get_gpio_range(struct device *dev, struct device *gpio, + u32_t gpio_pin, u16_t *pin, + u16_t *base_pin, u8_t *num_pins); + +/** @internal + */ +static inline int _impl_pinctrl_get_gpio_range(struct device *dev, + struct device *gpio, + u32_t gpio_pin, u16_t *pin, + u16_t *base_pin, u8_t *num_pins) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->control.get_gpio_range(dev, gpio, gpio_pin, pin, base_pin, + num_pins); +} + +/** + * Get the configuration of a pin. + * + * The configuration returned may be different to the configuration set by + * pinctrl_config_set(). Some configuration options may be set or reset by + * the current function selection. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param[out] config + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + * @retval -EINVAL if requested pin is available but disabled + */ +__syscall int pinctrl_config_get(struct device *dev, u16_t pin, u32_t *config); + +/** @internal + */ +static inline int _impl_pinctrl_config_get(struct device *dev, u16_t pin, + u32_t *config) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->config.get(dev, pin, config); +} + +/** + * @brief Configure a pin. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param config + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + */ +__syscall int pinctrl_config_set(struct device *dev, u16_t pin, u32_t config); + +/** @internal + */ +static inline int _impl_pinctrl_config_set(struct device *dev, u16_t pin, + u32_t config) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->config.set(dev, pin, config); +} + +/** + * @brief Get the configuration of a pin group. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param group Pin group + * @param[out] configs set to the configuration of the pins in the group + * @param[in,out] num_configs number of pin configurations requested/ set. + * @retval 0 on success + * @retval -ENOTSUP if configuration read out is not available for this group + * @retval -EINVAL if the number of available configurations exceeds requested + */ +__syscall int pinctrl_config_group_get(struct device *dev, + u16_t group, u32_t *configs, + u16_t *num_configs); + +/** @internal + */ +static inline int _impl_pinctrl_config_group_get(struct device *dev, + u16_t group, u32_t *configs, + u16_t *num_configs) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->config.group_get(dev, group, configs, num_configs); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + + +/** + * @brief Configure a group of pins. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param group Pin group + * @param configs The configurations of the pins in the group + * @param num_configs number of pin configurations to set. + * @retval 0 on success + * @retval -ENOTSUP if configuration is not available for this group + * @retval -EINVAL if number of configurations does not match pins in group + */ +__syscall int pinctrl_config_group_set(struct device *dev, + u16_t group, const u32_t *configs, + u16_t num_configs); + +/** @internal + */ +static inline int _impl_pinctrl_config_group_set(struct device *dev, + u16_t group, + const u32_t *configs, + u16_t num_configs) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->config.group_set(dev, group, configs, num_configs); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * @brief Request a pin for muxing. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param owner A representation of the owner; typically the device + * name that controls its mux function, or the requested GPIO name + * @retval 0 on success + * @retval -EBUSY pin already used + * @retval -ENOTSUP requested pin is not available on this controller + * @retval -ENOMEM can not handle request + */ +__syscall int pinctrl_mux_request(struct device *dev, u16_t pin, + const char *owner); + +/** @internal + */ +static inline int _impl_pinctrl_mux_request(struct device *dev, u16_t pin, + const char *owner) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->mux.request(dev, pin, owner); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * @brief Release a pin for muxing. + * + * After release another may become owner of the pin. + * + * Only the owner may release a muxed pin. + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param owner A representation of the owner; typically the device + * name that controls its mux function, or the requested GPIO name + * @retval 0 on success + * @retval -EACCES owner does not own the pin + * @retval -ENOTSUP requested pin is not available on this controller + */ +__syscall int pinctrl_mux_free(struct device *dev, u16_t pin, + const char *owner); + +/** @internal + */ +static inline int _impl_pinctrl_mux_free(struct device *dev, u16_t pin, + const char *owner) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->mux.free(dev, pin, owner); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * @brief Get muxing function at pin + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param[out] func Muxing function + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + */ +__syscall int pinctrl_mux_get(struct device *dev, u16_t pin, u16_t *func); + +/** @internal + */ +static inline int _impl_pinctrl_mux_get(struct device *dev, u16_t pin, + u16_t *func) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->mux.get(dev, pin, func); +} + +/** + * @brief Set muxing function at pin + * + * @param dev Pointer to the device structure for the driver instance. + * @param pin Pin + * @param func Muxing function + * @retval 0 on success + * @retval -ENOTSUP if requested pin is not available on this controller + */ +__syscall int pinctrl_mux_set(struct device *dev, u16_t pin, u16_t func); + +/** @internal + */ +static inline int _impl_pinctrl_mux_set(struct device *dev, u16_t pin, + u16_t func) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->mux.set(dev, pin, func); +} + +/** + * @brief Set muxing function for a group of pins + * + * @note To be enabled by CONFIG_PINCTRL_RUNTIME_DTS. + * + * @param dev Pointer to the device structure for the driver instance. + * @param group Group + * @param func Muxing function + * @retval 0 on success + * @retval -ENOTSUP if requested function or group is not available + * on this controller + * @retval -EINVAL if group does no belong to function + */ +__syscall int pinctrl_mux_group_set(struct device *dev, u16_t group, + u16_t func); + +/** @internal + */ +static inline int _impl_pinctrl_mux_group_set(struct device *dev, u16_t group, + u16_t func) +{ +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->mux.group_set(dev, group, func); +#else + __ASSERT(0, "To be enabled by CONFIG_PINCTRL_RUNTIME_DTS."); + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +} + +/** + * @brief Set pinctrl state. + * + * @param dev Pointer to the device structure for the driver instance. + * @param state State + * @retval 0 on success + * @retval -ENOTSUP if requested state is not available on this controller + */ +__syscall int pinctrl_state_set(struct device *dev, u16_t state); + +/** @internal + */ +static inline int _impl_pinctrl_state_set(struct device *dev, u16_t state) +{ + const struct pinctrl_driver_api *api = + (const struct pinctrl_driver_api *)dev->driver_api; + + return api->state.set(dev, state); +} + + +#if defined(CONFIG_PINCTRL_PINMUX) + +/** + * @brief PINCTRL PINMUX interface + * @defgroup pinctrl_interface_pinmux PINCTRL PINMUX interface + * @ingroup pinctrl_interface + * @{ + */ + +#define CONFIG_PINMUX_NAME CONFIG_PINCTRL_NAME + +#define PINMUX_FUNC_A PINCTRL_FUNCTION_HARDWARE_0 +#define PINMUX_FUNC_B PINCTRL_FUNCTION_HARDWARE_1 +#define PINMUX_FUNC_C PINCTRL_FUNCTION_HARDWARE_2 +#define PINMUX_FUNC_D PINCTRL_FUNCTION_HARDWARE_3 +#define PINMUX_FUNC_E PINCTRL_FUNCTION_HARDWARE_4 +#define PINMUX_FUNC_F PINCTRL_FUNCTION_HARDWARE_5 +#define PINMUX_FUNC_G PINCTRL_FUNCTION_HARDWARE_6 +#define PINMUX_FUNC_H PINCTRL_FUNCTION_HARDWARE_7 + +#define PINMUX_PULLUP_ENABLE (0x1) +#define PINMUX_PULLUP_DISABLE (0x0) + +#define PINMUX_INPUT_ENABLED (0x1) +#define PINMUX_OUTPUT_ENABLED (0x0) + +/** + * @brief Set pin function. + * + * @deprecated Use pinctrl_mux_set() instead. + */ +static inline int pinmux_pin_set(struct device *dev, u32_t pin, u16_t func) +{ + return pinctrl_mux_set(dev, (u16_t)pin, func); +} + +/** + * @brief Get pin function. + * + * @deprecated Use pinctrl_mux_get() instead. + */ +static inline int pinmux_pin_get(struct device *dev, u32_t pin, u16_t *func) +{ + return pinctrl_mux_get(dev, (u16_t)pin, func); +} + +/** + * @brief Set pin pullup. + * + * @deprecated Use pinctrl_config_set() instead. + */ +static inline int pinmux_pin_pullup(struct device *dev, u32_t pin, u8_t func) +{ + int ret; + u32_t config; + + ret = pinctrl_config_get(dev, (u16_t)pin, &config); + if (ret != 0) { + return ret; + } + config &= ~PINCTRL_CONFIG_BIAS_MASK; + if (func == PINMUX_PULLUP_ENABLE) { + config |= PINCTRL_CONFIG_BIAS_PULL_UP; + } else { + config |= PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT; + } + return pinctrl_config_set(dev, (u16_t)pin, config); +} + +/** + * @brief Enable pin input. + * + * @deprecated Use pinctrl_config_set() instead. + */ +static inline int pinmux_pin_input_enable(struct device *dev, u32_t pin, + u8_t func) +{ + int ret; + u32_t config; + + ret = pinctrl_config_get(dev, (u16_t)pin, &config); + if (ret != 0) { + return ret; + } + config &= ~PINCTRL_CONFIG_INPUT_MASK; + if (func == PINMUX_INPUT_ENABLED) { + config |= PINCTRL_CONFIG_INPUT_ENABLE; + } else { + config |= PINCTRL_CONFIG_INPUT_DISABLE; + } + return pinctrl_config_set(dev, (u16_t)pin, config); +} + +/** + * @} pinctrl_interface_pinmux + */ + +#endif /* defined(CONFIG_PINCTRL_PINMUX) */ + +#ifdef __cplusplus +} +#endif + +/** + * @} pinctrl_interface + */ + +#include + +#endif /* __INCLUDE_PINCTRL_H */ diff --git a/include/pinctrl_common.h b/include/pinctrl_common.h new file mode 100644 index 00000000000000..0dcbbe157de1a5 --- /dev/null +++ b/include/pinctrl_common.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2017 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _PINCTRL_COMMON_H_ +#define _PINCTRL_COMMON_H_ + +/** + * @brief PINCTRL Pin Configurations + * @defgroup pinctrl_interface_pin_configurations PINCTRL Pin Configurations + * @ingroup pinctrl_interface + * @{ + */ + +/** + * @def PINCTRL_CONFIG_BIAS_DISABLE + * @brief Disable any pin bias. + */ +#define PINCTRL_CONFIG_BIAS_DISABLE (1<<0) +/** + * @def PINCTRL_CONFIG_BIAS_HIGH_IMPEDANCE + * @brief High impedance mode ("third-state", "floating"). + */ +#define PINCTRL_CONFIG_BIAS_HIGH_IMPEDANCE (1<<1) +/** + * @def PINCTRL_CONFIG_BIAS_BUS_HOLD + * @brief Latch weakly. + */ +#define PINCTRL_CONFIG_BIAS_BUS_HOLD (1<<2) +/** + * @def PINCTRL_CONFIG_BIAS_PULL_UP + * @brief Pull up the pin. + */ +#define PINCTRL_CONFIG_BIAS_PULL_UP (1<<3) +/** + * @def PINCTRL_CONFIG_BIAS_PULL_DOWN + * @brief Pull down the pin. + */ +#define PINCTRL_CONFIG_BIAS_PULL_DOWN (1<<4) +/** + * @def PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT + * @brief Use pin default pull state. + */ +#define PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT (1<<5) +/** + * @def PINCTRL_CONFIG_DRIVE_PUSH_PULL + * @brief Drive actively high and low. + */ +#define PINCTRL_CONFIG_DRIVE_PUSH_PULL (1<<6) +/** + * @def PINCTRL_CONFIG_DRIVE_OPEN_DRAIN + * @brief Drive with open drain (open collector). + */ +#define PINCTRL_CONFIG_DRIVE_OPEN_DRAIN (1<<7) +/** + * @def PINCTRL_CONFIG_DRIVE_OPEN_SOURCE + * @brief Drive with open source (open emitter). + */ +#define PINCTRL_CONFIG_DRIVE_OPEN_SOURCE (1<<8) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT + * @brief Drive with default drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_DEFAULT (0<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_1 + * @brief Drive with minimum drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_1 (1<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_2 + * @brief Drive with minimum to medium drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_2 (2<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_3 + * @brief Drive with minimum to medium drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_3 (3<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_4 + * @brief Drive with medium drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_4 (4<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_5 + * @brief Drive with medium to maximum drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_5 (5<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_6 + * @brief Drive with medium to maximum drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_6 (6<<9) +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_7 + * @brief Drive with maximum drive strength. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_7 (7<<9) +/** + * @def PINCTRL_CONFIG_INPUT_ENABLE + * @brief Enable the pins input. + * @note Does not affect the pin's ability to drive output. + */ +#define PINCTRL_CONFIG_INPUT_ENABLE (1<<12) +/** + * @def PINCTRL_CONFIG_INPUT_DISABLE + * @brief Disable the pins input. + * @note Does not affect the pin's ability to drive output. + */ +#define PINCTRL_CONFIG_INPUT_DISABLE (1<<13) +/** + * @def PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE + * @brief Enable schmitt trigger mode for input. + */ +#define PINCTRL_CONFIG_INPUT_SCHMITT_ENABLE (1<<14) +/** + * @def PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE + * @brief Disable schmitt trigger mode for input. + */ +#define PINCTRL_CONFIG_INPUT_SCHMITT_DISABLE (1<<15) +/** + * @def PINCTRL_CONFIG_INPUT_DEBOUNCE_NONE + * @brief Do not debounce input. + */ +#define PINCTRL_CONFIG_INPUT_DEBOUNCE_NONE (0<<16) +/** + * @def PINCTRL_CONFIG_INPUT_DEBOUNCE_SHORT + * @brief Debounce input with short debounce time. + */ +#define PINCTRL_CONFIG_INPUT_DEBOUNCE_SHORT (1<<16) +/** + * @def PINCTRL_CONFIG_INPUT_DEBOUNCE_MEDIUM + * @brief Debounce input with medium debounce time. + */ +#define PINCTRL_CONFIG_INPUT_DEBOUNCE_MEDIUM (2<<16) +/** + * @def PINCTRL_CONFIG_INPUT_DEBOUNCE_LONG + * @brief Debounce input with long debounce time. + */ +#define PINCTRL_CONFIG_INPUT_DEBOUNCE_LONG (3<<16) +/** + * @def PINCTRL_CONFIG_POWER_SOURCE_DEFAULT + * @brief Select default power source for pin. + */ +#define PINCTRL_CONFIG_POWER_SOURCE_DEFAULT (0<<18) +/** + * @def PINCTRL_CONFIG_POWER_SOURCE_1 + * @brief Select power source #1 for pin. + */ +#define PINCTRL_CONFIG_POWER_SOURCE_1 (1<<18) +/** + * @def PINCTRL_CONFIG_POWER_SOURCE_2 + * @brief Select power source #2 for pin. + */ +#define PINCTRL_CONFIG_POWER_SOURCE_2 (2<<18) +/** + * @def PINCTRL_CONFIG_POWER_SOURCE_3 + * @brief Select power source #3 for pin. + */ +#define PINCTRL_CONFIG_POWER_SOURCE_3 (3<<18) +/** + * @def PINCTRL_CONFIG_LOW_POWER_ENABLE + * @brief Enable low power mode. + */ +#define PINCTRL_CONFIG_LOW_POWER_ENABLE (1<<20) +/** + * @def PINCTRL_CONFIG_LOW_POWER_DISABLE + * @brief Disable low power mode. + */ +#define PINCTRL_CONFIG_LOW_POWER_DISABLE (1<<21) +/** + * @def PINCTRL_CONFIG_OUTPUT_ENABLE + * @brief Enable output on pin. + * + * Such as connecting the output buffer to the drive stage. + * + * @note Does not set the output drive. + */ +#define PINCTRL_CONFIG_OUTPUT_ENABLE (1<<22) +/** + * @def PINCTRL_CONFIG_OUTPUT_DISABLE + * @brief Disable output on pin. + * + * Such as disconnecting the output buffer from the drive stage. + * + * @note Does not reset the output drive. + */ +#define PINCTRL_CONFIG_OUTPUT_DISABLE (1<<23) +/** + * @def PINCTRL_CONFIG_OUTPUT_LOW + * @brief Set output to active low. + * + * A "1" in the output buffer drives the output to low level. + */ +#define PINCTRL_CONFIG_OUTPUT_LOW (1<<24) +/** + * @def PINCTRL_CONFIG_OUTPUT_HIGH + * @brief Set output to active high. + * + * A "1" in the output buffer drives the output to high level. + */ +#define PINCTRL_CONFIG_OUTPUT_HIGH (1<<25) +/** + * @def PINCTRL_CONFIG_SLEW_RATE_SLOW + * @brief Select slow slew rate. + */ +#define PINCTRL_CONFIG_SLEW_RATE_SLOW (0<<26) +/** + * @def PINCTRL_CONFIG_SLEW_RATE_MEDIUM + * @brief Select medium slew rate. + */ +#define PINCTRL_CONFIG_SLEW_RATE_MEDIUM (1<<26) +/** + * @def PINCTRL_CONFIG_SLEW_RATE_FAST + * @brief Select fast slew rate. + */ +#define PINCTRL_CONFIG_SLEW_RATE_FAST (2<<26) +/** + * @def PINCTRL_CONFIG_SLEW_RATE_HIGH + * @brief Select high slew rate. + */ +#define PINCTRL_CONFIG_SLEW_RATE_HIGH (3<<26) +/** + * @def PINCTRL_CONFIG_SPEED_SLOW + * @brief Select low toggle speed. + * + * @note Slew rate may be unaffected. + */ +#define PINCTRL_CONFIG_SPEED_SLOW (0<<28) +/** + * @def PINCTRL_CONFIG_SPEED_MEDIUM + * @brief Select medium toggle speed. + * + * @note Slew rate may be unaffected. + */ +#define PINCTRL_CONFIG_SPEED_MEDIUM (1<<28) +/** + * @def PINCTRL_CONFIG_SPEED_FAST + * @brief Select fast toggle speed. + * + * @note Slew rate may be unaffected. + */ +#define PINCTRL_CONFIG_SPEED_FAST (2<<28) +/** + * @def PINCTRL_CONFIG_SPEED_HIGH + * @brief Select high toggle speed. + * + * @note Slew rate may be unaffected. + */ +#define PINCTRL_CONFIG_SPEED_HIGH (3<<28) + +/** + * @def PINCTRL_CONFIG_BIAS_MASK + * @brief Mask for all PINCTRL_CONFIG_BIAS_xxx values. + */ +#define PINCTRL_CONFIG_BIAS_MASK (PINCTRL_CONFIG_BIAS_BUS_HOLD\ + | PINCTRL_CONFIG_BIAS_DISABLE\ + | PINCTRL_CONFIG_BIAS_HIGH_IMPEDANCE\ + | PINCTRL_CONFIG_BIAS_PULL_DOWN\ + | PINCTRL_CONFIG_BIAS_PULL_PIN_DEFAULT\ + | PINCTRL_CONFIG_BIAS_PULL_UP) + +/** + * @def PINCTRL_CONFIG_INPUT_MASK + * @brief Mask for PINCTRL_CONFIG_INPUT_ENABLE/DISABLE values. + */ +#define PINCTRL_CONFIG_INPUT_MASK (PINCTRL_CONFIG_INPUT_ENABLE\ + | PINCTRL_CONFIG_INPUT_DISABLE) + +/** + * @def PINCTRL_CONFIG_OUTPUT_MASK + * @brief Mask for PINCTRL_CONFIG_OUTPUT_ENABLE/DISABLE values. + */ +#define PINCTRL_CONFIG_OUTPUT_MASK (PINCTRL_CONFIG_OUTPUT_ENABLE\ + | PINCTRL_CONFIG_OUTPUT_DISABLE) + +/** + * @def PINCTRL_CONFIG_DRIVE_MASK + * @brief Mask for PINCTRL_CONFIG_DRIVE_x values. + */ +#define PINCTRL_CONFIG_DRIVE_MASK (PINCTRL_CONFIG_DRIVE_PUSH_PULL\ + | PINCTRL_CONFIG_DRIVE_OPEN_DRAIN\ + | PINCTRL_CONFIG_DRIVE_OPEN_SOURCE) + + +/** + * @def PINCTRL_CONFIG_DRIVE_STRENGTH_MASK + * @brief Mask for PINCTRL_CONFIG_DRIVE_STRENGTH_x values. + */ +#define PINCTRL_CONFIG_DRIVE_STRENGTH_MASK PINCTRL_CONFIG_DRIVE_STRENGTH_7 + +/**@} pinctrl_interface_pin_configurations */ + +/** + * @brief PINCTRL Functions + * @defgroup pinctrl_interface_functions PINCTRL Functions + * @ingroup pinctrl_interface + * @{ + */ + +#define PINCTRL_FUNCTION_HARDWARE_BASE 0 +#define PINCTRL_FUNCTION_HARDWARE_0 (PINCTRL_FUNCTION_HARDWARE_BASE + 0) +#define PINCTRL_FUNCTION_HARDWARE_1 (PINCTRL_FUNCTION_HARDWARE_BASE + 1) +#define PINCTRL_FUNCTION_HARDWARE_2 (PINCTRL_FUNCTION_HARDWARE_BASE + 2) +#define PINCTRL_FUNCTION_HARDWARE_3 (PINCTRL_FUNCTION_HARDWARE_BASE + 3) +#define PINCTRL_FUNCTION_HARDWARE_4 (PINCTRL_FUNCTION_HARDWARE_BASE + 4) +#define PINCTRL_FUNCTION_HARDWARE_5 (PINCTRL_FUNCTION_HARDWARE_BASE + 5) +#define PINCTRL_FUNCTION_HARDWARE_6 (PINCTRL_FUNCTION_HARDWARE_BASE + 6) +#define PINCTRL_FUNCTION_HARDWARE_7 (PINCTRL_FUNCTION_HARDWARE_BASE + 7) +#define PINCTRL_FUNCTION_HARDWARE_8 (PINCTRL_FUNCTION_HARDWARE_BASE + 8) +#define PINCTRL_FUNCTION_HARDWARE_9 (PINCTRL_FUNCTION_HARDWARE_BASE + 9) +#define PINCTRL_FUNCTION_HARDWARE_10 (PINCTRL_FUNCTION_HARDWARE_BASE + 10) +#define PINCTRL_FUNCTION_HARDWARE_11 (PINCTRL_FUNCTION_HARDWARE_BASE + 11) +#define PINCTRL_FUNCTION_HARDWARE_12 (PINCTRL_FUNCTION_HARDWARE_BASE + 12) +#define PINCTRL_FUNCTION_HARDWARE_13 (PINCTRL_FUNCTION_HARDWARE_BASE + 13) +#define PINCTRL_FUNCTION_HARDWARE_14 (PINCTRL_FUNCTION_HARDWARE_BASE + 14) +#define PINCTRL_FUNCTION_HARDWARE_15 (PINCTRL_FUNCTION_HARDWARE_BASE + 15) +#define PINCTRL_FUNCTION_HARDWARE_16 (PINCTRL_FUNCTION_HARDWARE_BASE + 16) +#define PINCTRL_FUNCTION_HARDWARE_17 (PINCTRL_FUNCTION_HARDWARE_BASE + 17) +#define PINCTRL_FUNCTION_HARDWARE_18 (PINCTRL_FUNCTION_HARDWARE_BASE + 18) +#define PINCTRL_FUNCTION_HARDWARE_19 (PINCTRL_FUNCTION_HARDWARE_BASE + 19) +#define PINCTRL_FUNCTION_HARDWARE_20 (PINCTRL_FUNCTION_HARDWARE_BASE + 20) +#define PINCTRL_FUNCTION_HARDWARE_21 (PINCTRL_FUNCTION_HARDWARE_BASE + 21) +#define PINCTRL_FUNCTION_HARDWARE_22 (PINCTRL_FUNCTION_HARDWARE_BASE + 22) +#define PINCTRL_FUNCTION_HARDWARE_23 (PINCTRL_FUNCTION_HARDWARE_BASE + 23) +#define PINCTRL_FUNCTION_HARDWARE_24 (PINCTRL_FUNCTION_HARDWARE_BASE + 24) +#define PINCTRL_FUNCTION_HARDWARE_25 (PINCTRL_FUNCTION_HARDWARE_BASE + 25) +#define PINCTRL_FUNCTION_HARDWARE_26 (PINCTRL_FUNCTION_HARDWARE_BASE + 26) +#define PINCTRL_FUNCTION_HARDWARE_27 (PINCTRL_FUNCTION_HARDWARE_BASE + 27) +#define PINCTRL_FUNCTION_HARDWARE_28 (PINCTRL_FUNCTION_HARDWARE_BASE + 28) +#define PINCTRL_FUNCTION_HARDWARE_29 (PINCTRL_FUNCTION_HARDWARE_BASE + 29) +#define PINCTRL_FUNCTION_HARDWARE_30 (PINCTRL_FUNCTION_HARDWARE_BASE + 30) +#define PINCTRL_FUNCTION_HARDWARE_31 (PINCTRL_FUNCTION_HARDWARE_BASE + 31) +#define PINCTRL_FUNCTION_DEVICE_BASE 32 +#define PINCTRL_FUNCTION_DEVICE_0 (PINCTRL_FUNCTION_DEVICE_BASE + 0) + +/**@} pinctrl_interface_functions */ + +#endif /* _PINCTRL_COMMON_H_ */ diff --git a/include/pinmux.h b/include/pinmux.h index b3c3ef2e9a9313..198b134c0ea7e7 100644 --- a/include/pinmux.h +++ b/include/pinmux.h @@ -12,6 +12,12 @@ #ifndef __INCLUDE_PINMUX_H #define __INCLUDE_PINMUX_H +#if CONFIG_PINCTRL +/* PINMUX is provided by PINCTRL */ +#include +#else +/* Legacy Pinmux Interface */ + /** * @brief Pinmux Interface * @defgroup pinmux_interface Pinmux Interface @@ -111,4 +117,6 @@ static inline int pinmux_pin_input_enable(struct device *dev, u32_t pin, * @} */ +#endif /* !defined(CONFIG_PINCTRL) */ + #endif /* __INCLUDE_PINMUX_H */ diff --git a/samples/basic/blink_led/src/main.c b/samples/basic/blink_led/src/main.c index 558a458e8a140b..dbfcbe7aa60e97 100644 --- a/samples/basic/blink_led/src/main.c +++ b/samples/basic/blink_led/src/main.c @@ -19,10 +19,10 @@ #if defined(CONFIG_SOC_STM32F401XE) || defined(CONFIG_SOC_STM32F412ZG) || \ defined(CONFIG_SOC_STM32F413XH) || defined(CONFIG_SOC_STM32L476XG) || \ defined(CONFIG_SOC_STM32F407XG) -#define PWM_DRIVER CONFIG_PWM_STM32_2_DEV_NAME +#define PWM_DRIVER "PWM_2" #define PWM_CHANNEL 1 #elif CONFIG_SOC_STM32F103XB -#define PWM_DRIVER CONFIG_PWM_STM32_1_DEV_NAME +#define PWM_DRIVER "PWM_1" #define PWM_CHANNEL 1 #elif defined(CONFIG_SOC_QUARK_SE_C1000) || defined(CONFIG_SOC_QUARK_D2000) #define PWM_DRIVER CONFIG_PWM_QMSI_DEV_NAME diff --git a/samples/basic/button/README.rst b/samples/basic/button/README.rst index d49117db0ea2a0..6c67c0a69c3912 100644 --- a/samples/basic/button/README.rst +++ b/samples/basic/button/README.rst @@ -29,6 +29,7 @@ The following boards currently define the above variables: - nrf51_pca10028 - nrf52840_pca10056 - nrf52_pca10040 +- nucleo_f091rc - nucleo_f103rb - :ref:`quark_d2000_devboard` - quark_se_c1000_devboard diff --git a/samples/basic/button/src/main.c b/samples/basic/button/src/main.c index 50604bc5043679..8bcb25d942807b 100644 --- a/samples/basic/button/src/main.c +++ b/samples/basic/button/src/main.c @@ -23,7 +23,12 @@ /* change this to use another GPIO pin */ #ifdef SW0_GPIO_PIN -#define PIN SW0_GPIO_PIN +#define PIN SW0_GPIO_PIN +#if CONFIG_PINCTRL +#define PIN_MASK SW0_GPIO_PIN +#else +#define PIN_MASK BIT(SW0_GPIO_PIN) +#endif #else #error SW0_GPIO_PIN needs to be set in board.h #endif @@ -72,7 +77,7 @@ void main(void) gpio_pin_configure(gpiob, PIN, GPIO_DIR_IN | GPIO_INT | PULL_UP | EDGE); - gpio_init_callback(&gpio_cb, button_pressed, BIT(PIN)); + gpio_init_callback(&gpio_cb, button_pressed, PIN_MASK); gpio_add_callback(gpiob, &gpio_cb); gpio_pin_enable_callback(gpiob, PIN); diff --git a/samples/basic/fade_led/src/main.c b/samples/basic/fade_led/src/main.c index ab3ccdc674f695..3458d90b69a2fe 100644 --- a/samples/basic/fade_led/src/main.c +++ b/samples/basic/fade_led/src/main.c @@ -17,10 +17,10 @@ #include #if defined(CONFIG_SOC_STM32F401XE) || defined(CONFIG_SOC_STM32L476XG) -#define PWM_DRIVER CONFIG_PWM_STM32_2_DEV_NAME +#define PWM_DRIVER "PWM_2" #define PWM_CHANNEL 1 #elif CONFIG_SOC_STM32F103XB -#define PWM_DRIVER CONFIG_PWM_STM32_1_DEV_NAME +#define PWM_DRIVER "PWM_1" #define PWM_CHANNEL 1 #elif defined(CONFIG_SOC_QUARK_SE_C1000) || defined(CONFIG_SOC_QUARK_D2000) #define PWM_DRIVER CONFIG_PWM_QMSI_DEV_NAME diff --git a/samples/drivers/CAN/src/main.c b/samples/drivers/CAN/src/main.c index 9a0e1dbf5d14b2..bb40e5f93109bd 100644 --- a/samples/drivers/CAN/src/main.c +++ b/samples/drivers/CAN/src/main.c @@ -142,8 +142,8 @@ void led_thread(void *msgq, void *can_dev_param, void *gpio_dev_param) int ret; int filter_id; - ret = gpio_pin_configure(gpio_dev, CONFIG_PIN_LED_1, GPIO_DIR_OUT); - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0); + ret = gpio_pin_configure(gpio_dev, LED0_GPIO_PIN, GPIO_DIR_OUT); + gpio_pin_write(gpio_dev, LED0_GPIO_PIN, 0); if (ret) { printk("ERROR configure pins\n"); @@ -162,11 +162,11 @@ void led_thread(void *msgq, void *can_dev_param, void *gpio_dev_param) switch (msg.data[0]) { case SET_LED: - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 1); + gpio_pin_write(gpio_dev, LED0_GPIO_PIN, 1); break; case RESET_LED: - gpio_pin_write(gpio_dev, CONFIG_PIN_LED_1, 0); + gpio_pin_write(gpio_dev, LED0_GPIO_PIN, 0); break; } } @@ -201,7 +201,7 @@ void main(void) can_configure(can_dev, CAN_LOOPBACK_MODE, 250000); #endif - led_gpio_dev = device_get_binding(CONFIG_GPIO_LED_DEV); + led_gpio_dev = device_get_binding(LED0_GPIO_CONTROLLER); if (!led_gpio_dev) { printk("LED: Device driver not found.\n"); return; @@ -209,28 +209,32 @@ void main(void) k_sem_init(&tx_sem, 0, INT_MAX); - button_gpio_dev = device_get_binding(CONFIG_GPIO_BUTTON_DEV); + button_gpio_dev = device_get_binding(SW0_GPIO_CONTROLLER); if (!button_gpio_dev) { printk("Button: Device driver not found.\n"); return; } - ret = gpio_pin_configure(button_gpio_dev, CONFIG_PIN_USER_BUTTON, + ret = gpio_pin_configure(button_gpio_dev, SW0_GPIO_PIN, (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE)); if (ret) { printk("Error configuring button pin\n"); } +#ifdef CONFIG_PINCTRL + gpio_init_callback(&gpio_cb, button_callback, SW0_GPIO_PIN); +#else gpio_init_callback(&gpio_cb, button_callback, - BIT(CONFIG_PIN_USER_BUTTON)); - + BIT(SW0_GPIO_PIN)); +#endif ret = gpio_add_callback(button_gpio_dev, &gpio_cb); if (ret) { printk("Cannot setup callback!\n"); } - ret = gpio_pin_enable_callback(button_gpio_dev, CONFIG_PIN_USER_BUTTON); + + ret = gpio_pin_enable_callback(button_gpio_dev, SW0_GPIO_PIN); if (ret) { printk("Error enabling callback!\n"); } diff --git a/scripts/codegen/cmake.py b/scripts/codegen/cmake.py new file mode 100644 index 00000000000000..eedc0be56c07fa --- /dev/null +++ b/scripts/codegen/cmake.py @@ -0,0 +1,191 @@ +# Copyright (c) 2018 Open Source Foundries Limited. +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 +# +# CMakeCacheEntry and CMakeCache are taken from scripts/zephyr_run.py. +# + +import os +import sys +import re +from collections import OrderedDict +from pathlib import Path + + +class CMakeCacheEntry: + '''Represents a CMake cache entry. + This class understands the type system in a CMakeCache.txt, and + converts the following cache types to Python types: + Cache Type Python type + ---------- ------------------------------------------- + FILEPATH str + PATH str + STRING str OR list of str (if ';' is in the value) + BOOL bool + INTERNAL str OR list of str (if ';' is in the value) + ---------- ------------------------------------------- + ''' + + # Regular expression for a cache entry. + # + # CMake variable names can include escape characters, allowing a + # wider set of names than is easy to match with a regular + # expression. To be permissive here, use a non-greedy match up to + # the first colon (':'). This breaks if the variable name has a + # colon inside, but it's good enough. + CACHE_ENTRY = re.compile( + r'''(?P.*?) # name + :(?PFILEPATH|PATH|STRING|BOOL|INTERNAL) # type + =(?P.*) # value + ''', re.X) + + @classmethod + def _to_bool(cls, val): + # Convert a CMake BOOL string into a Python bool. + # + # "True if the constant is 1, ON, YES, TRUE, Y, or a + # non-zero number. False if the constant is 0, OFF, NO, + # FALSE, N, IGNORE, NOTFOUND, the empty string, or ends in + # the suffix -NOTFOUND. Named boolean constants are + # case-insensitive. If the argument is not one of these + # constants, it is treated as a variable." + # + # https://cmake.org/cmake/help/v3.0/command/if.html + val = val.upper() + if val in ('ON', 'YES', 'TRUE', 'Y'): + return True + elif val in ('OFF', 'NO', 'FALSE', 'N', 'IGNORE', 'NOTFOUND', ''): + return False + elif val.endswith('-NOTFOUND'): + return False + else: + try: + v = int(val) + return v != 0 + except ValueError as exc: + raise ValueError('invalid bool {}'.format(val)) from exc + + @classmethod + def from_line(cls, line, line_no): + # Comments can only occur at the beginning of a line. + # (The value of an entry could contain a comment character). + if line.startswith('//') or line.startswith('#'): + return None + + # Whitespace-only lines do not contain cache entries. + if not line.strip(): + return None + + m = cls.CACHE_ENTRY.match(line) + if not m: + return None + + name, type_, value = (m.group(g) for g in ('name', 'type', 'value')) + if type_ == 'BOOL': + try: + value = cls._to_bool(value) + except ValueError as exc: + args = exc.args + ('on line {}: {}'.format(line_no, line),) + raise ValueError(args) from exc + elif type_ == 'STRING' or type_ == 'INTERNAL': + # If the value is a CMake list (i.e. is a string which + # contains a ';'), convert to a Python list. + if ';' in value: + value = value.split(';') + + return CMakeCacheEntry(name, value) + + def __init__(self, name, value): + self.name = name + self.value = value + + def __str__(self): + fmt = 'CMakeCacheEntry(name={}, value={})' + return fmt.format(self.name, self.value) + + +class CMakeCache: + '''Parses and represents a CMake cache file.''' + + def __init__(self, cache_file): + self.load(cache_file) + + def load(self, cache_file): + entries = [] + with open(str(cache_file), 'r') as cache: + for line_no, line in enumerate(cache): + entry = CMakeCacheEntry.from_line(line, line_no) + if entry: + entries.append(entry) + self._entries = OrderedDict((e.name, e) for e in entries) + + def get(self, name, default=None): + entry = self._entries.get(name) + if entry is not None: + return entry.value + else: + return default + + def get_list(self, name, default=None): + if default is None: + default = [] + entry = self._entries.get(name) + if entry is not None: + value = entry.value + if isinstance(value, list): + return value + elif isinstance(value, str): + return [value] + else: + msg = 'invalid value {} type {}' + raise RuntimeError(msg.format(value, type(value))) + else: + return default + + def __getitem__(self, name): + return self._entries[name].value + + def __setitem__(self, name, entry): + if not isinstance(entry, CMakeCacheEntry): + msg = 'improper type {} for value {}, expecting CMakeCacheEntry' + raise TypeError(msg.format(type(entry), entry)) + self._entries[name] = entry + + def __delitem__(self, name): + del self._entries[name] + + def __iter__(self): + return iter(self._entries.values()) + + +class CMakeMixin(object): + __slots__ = [] + + _cmake_cache = None + + def cmake_variable(self, variable_name, default=""): + variable_value = self.options.defines.get(variable_name, default) + if variable_value == "": + raise self._get_error_exception( + "CMake variable '{}' not defined.".format(variable_name), 1) + return variable_value + + def cmake_cache_variable(self, variable_name, default=""): + if self._cmake_cache is None: + cache_file = self.cmake_variable("CMAKE_BINARY_DIR") + cache_file = Path(cache_file).joinpath("CMakeCache.txt") + if not cache_file.is_file(): + raise self._get_error_exception( + "CMake cache file '{}' does not exist or is no file.". + format(cache_file), 1) + self._cmake_cache = CMakeCache(cache_file) + try: + return self._cmake_cache.get(variable_name) + except: + if default == "": + raise self._get_error_exception( + "CMake variable '{}' not defined in cache file.". + format(variable_name), 1) + return default + diff --git a/scripts/codegen/codegen.py b/scripts/codegen/codegen.py new file mode 100644 index 00000000000000..296ae8101d66ad --- /dev/null +++ b/scripts/codegen/codegen.py @@ -0,0 +1,630 @@ +# Copyright 2004-2016, Ned Batchelder. +# http://nedbatchelder.com/code/cog +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: MIT + +import sys +import os +import imp +import inspect +import re +from traceback import TracebackException + +from .whiteutils import * +from .filereader import NumberedFileReader +from .options import Options, OptionsMixin +from .generic import GenericMixin +from .guard import GuardMixin +from .config import ConfigMixin +from .cmake import CMakeMixin +from .zephyr import ZephyrMixin +from .edts import EDTSMixin +from .include import IncludeMixin +from .log import LogMixin +from .error import ErrorMixin, Error +from .output import OutputMixin +from .importmodule import ImportMixin +from .redirectable import Redirectable, RedirectableMixin + +class CodeGenerator(OptionsMixin, GenericMixin, ConfigMixin, + CMakeMixin, ZephyrMixin, EDTSMixin, GuardMixin, + IncludeMixin, LogMixin, ErrorMixin, OutputMixin, + ImportMixin, RedirectableMixin): + + code_start_marker = b'@code{.codegen}' + code_end_marker = b'@endcode{.codegen}' + code_insert_marker = b'@code{.codeins}@endcode' + + def __init__(self, processor, globals={}, + output_file=None, snippet_file = None): + self._stdout = sys.stdout + self._stderr = sys.stderr + self._outstring = '' + # code snippet markers and lines + self._start_marker = self.code_start_marker.decode('utf-8') + self._end_marker = self.code_end_marker.decode('utf-8') + self._insert_marker = self.code_insert_marker.decode('utf-8') + self.markers = [] + self.lines = [] + # The processor that is using this generator + self.processor = processor + self.options = processor.options + # All generators of a file usually work on the same global namespace + self.generator_globals = globals + self._output_file = output_file + # The file that contains the snippet + self._snippet_file = snippet_file + # The snippet this generator works on + self._snippet = None + # the snippet start offset in original file + self._snippet_offset = None + # the tab size in the snippet + self._snippet_tabsize = 8 + # the current evaluation start offset in the original file + # may be different to snippet offset during evaluation + self._eval_offset = None + # the previous output + self._previous = '' + + def line_is_start_marker(self, s): + return self._start_marker in s + + def line_is_end_marker(self, s): + return self._end_marker in s and not self.line_is_insert_marker(s) + + def line_is_insert_marker(self, s): + return self._insert_marker in s + + def parse_start_marker(self, l, snippet_offset): + self._snippet_offset = snippet_offset + self._eval_offset = snippet_offset + self.markers.append(l.expandtabs(self._snippet_tabsize)) + + def parse_end_marker(self, l): + self.markers.append(l.expandtabs(self._snippet_tabsize)) + + def parse_line(self, l, single_line_snippet=False): + l = l.expandtabs(self._snippet_tabsize).strip('\n') + if single_line_snippet: + # single line snippets contain the markers - remove them + beg = l.find(self._start_marker) + end = l.find(self._end_marker) + if beg > end: + self.lines.append(l) + self.error("Codegen code markers inverted", + frame_index = -2) + else: + l = l[beg+len(self._start_marker):end].strip() + self.lines.append(l) + + def _out(self, output='', dedent=False, trimblanklines=False): + if trimblanklines and ('\n' in output): + lines = output.split('\n') + if lines[0].strip() == '': + del lines[0] + if lines and lines[-1].strip() == '': + del lines[-1] + output = '\n'.join(lines)+'\n' + if dedent: + output = reindentBlock(output) + self._outstring += output + + ## + # @brief Re-indent a code block. + # + # Take a block of text as a string or list of lines. + # Remove any common prefix and whitespace indentation. + # Re-indent using new_indent + # + # @param lines + # @param common_prefix + # @param new_indent + # @return indented code block as a single string. + def _reindent_code(self, lines, common_prefix = '', new_indent=''): + if not isinstance(lines, list): + lines = lines.split('\n') + # remove common prefix + code_lines = [] # all code lines + code_no_white_lines = [] # code lines excluding white space lines + for line in lines: + line = line.expandtabs() + if common_prefix: + line = line.replace(common_prefix, '', 1) + code_lines.append(line) + if line and not line.isspace(): + code_no_white_lines.append(line) + # remove common white space and re-indent + out_lines = [] + common_white = os.path.commonprefix(code_no_white_lines) + common_white = re.search(r'\s*', common_white).group(0) + for line in code_lines: + if common_white: + line = line.replace(common_white, '', 1) + if line and new_indent: + line = new_indent + line + out_lines.append(line) + return '\n'.join(out_lines) + + ## + # @brief Extract the executable Python code from the generator. + # + def _get_code(self, fname, snippet_offset): + # If the markers and lines all have the same prefix + # (end-of-line comment chars, for example), + # then remove it from all the lines. + common_prefix = os.path.commonprefix(self.markers + self.lines) + if not common_prefix: + # there may be a prefix error + # just do some heuristics + if fname.endswith( + ('.h', '.hxx', '.c', '.cpp', '.cxx')): + # assume C/C++ comments + for line in (self.markers + self.lines): + if line.strip().startswith('*'): + common_prefix = '*' + break + elif line.strip().startswith('//'): + common_prefix = '//' + break + if common_prefix: + # there should be a common prefix -> error + lines = list() # lines with correct prefix + for lineno, line in enumerate(self.lines): + if not line.strip().startswith(common_prefix): + print("Codegen: Comment prefix may miss in codegen snippet (+{}) in '{}'.".format( + snippet_offset, fname)) + line_start = lineno - 5 + if line_start < 0: + line_start = 0 + line_end = lineno + 5 + if line_end > len(self.lines): + line_end = len(self.lines) + for i in range(line_start, line_end): + snippet_lineno = i + 2 + input_lineno = snippet_offset + snippet_lineno + print("#{} (+{}, line {}): {}".format( + input_lineno, snippet_offset, snippet_lineno, self.lines[i])) + else: + lines.append(line) + if len(lines) >= int(len(self.lines) / 2): + common_prefix = os.path.commonprefix(lines) + print("Codegen: Assuming comment prefix '{}' for codegen snippet (+{}) in '{}'.".format( + common_prefix, snippet_offset, fname)) + else: + common_prefix = '' + if common_prefix: + self.markers = [ line.replace(common_prefix, '', 1) for line in self.markers ] + code = self._reindent_code(self.lines, common_prefix) + return code + + # Make sure the "codegen" (alias cog) module has our state. + def _set_module_state(self): + restore_state = {} + module_states = self.processor.module_states + module = self.processor.cogmodule + # General module values + restore_state['inFile'] = getattr(module, 'inFile', None) + module.inFile = self._snippet_file + restore_state['outFile'] = getattr(module, 'outFile', None) + module.outFile = self._output_file + restore_state['firstLineNum'] = getattr(module, 'firstLineNum', None) + module.firstLineNum = self._snippet_offset + restore_state['previous'] = getattr(module, 'previous', None) + module.previous = self._previous + # CodeGenerator access + restore_state['options'] = getattr(module, 'options', None) + module.options = self.options + restore_state['Error'] = getattr(module, 'Error', None) + module.Error = self._get_error_exception + # Look for the Mixin classes + for base_cls in inspect.getmro(CodeGenerator): + if "Mixin" in base_cls.__name__: + for member_name, member_value in inspect.getmembers(base_cls): + if member_name.startswith('_'): + continue + if inspect.isroutine(member_value): + restore_state[member_name] = \ + getattr(module, member_name, None) + setattr(module, member_name, + getattr(self, member_name)) + module_states.append(restore_state) + + def _restore_module_state(self): + module_states = self.processor.module_states + module = self.processor.cogmodule + restore_state = module_states.pop() + # General module values + module.inFile = restore_state['inFile'] + module.outFile = restore_state['outFile'] + module.firstLineNum = restore_state['firstLineNum'] + module.previous = restore_state['previous'] + # CodeGenerator access + module.options = restore_state['options'] + module.Error = restore_state['Error'] + # Look for the Mixin classes + for base_cls in inspect.getmro(CodeGenerator): + if "Mixin" in base_cls.__name__: + for member_name, member_value in inspect.getmembers(base_cls): + if member_name.startswith('_'): + continue + if inspect.isroutine(member_value): + setattr(module, member_name, restore_state[member_name]) + + ## + # @brief snippet id to be used in logging and error reporting + # + # Accounts for extra lines added during evaluation + # + def _get_snippet_id(self): + return "+{}".format(self._eval_offset) + + ## + # @brief get snippet line number from evaluation line number + # + # Accounts for extra lines added during evaluation + # + # @param eval_lineno line number as reported from python code eval + def _get_snippet_lineno(self, eval_lineno): + return int(eval_lineno) + self._eval_offset - self._snippet_offset + + def _list_snippet(self): + if not self._snippet: + return None + listing = "" + for i, line in enumerate(self._snippet.splitlines()): + eval_lineno = i + 2 + input_lineno = self._eval_offset + eval_lineno + if i > 0: + listing += "\n" + listing += "#{} ({}, line {}): {}".format( + input_lineno, self._get_snippet_id(), eval_lineno, line) + return listing + + def _list_lines(self): + if len(self.lines) == 0: + return None + listing = "" + for i, line in enumerate(self.lines): + eval_lineno = i + 2 + input_lineno = self._eval_offset + eval_lineno + if i > 0: + listing += "\n" + listing += "#{} ({}, line {}): {}".format( + input_lineno, self._get_snippet_id(), eval_lineno, line) + return listing + + ## + # @brief evaluate + # + def evaluate(self): + self._snippet = self._get_code(self._snippet_file, self._snippet_offset) + if not self._snippet: + return '' + + # we add an extra line 'import codegen' + # to snippet so account for that + self._eval_offset = self._snippet_offset - 1 + + # In Python 2.2, the last line has to end in a newline. + eval_code = "import codegen\n" + self._snippet + "\n" + eval_fname = "{} {}".format(self._snippet_file, self._get_snippet_id()) + + try: + code = compile(eval_code, eval_fname, 'exec') + except: + exc_type, exc_value, exc_tb = sys.exc_info() + exc_traceback = TracebackException(exc_type, exc_value, exc_tb) + self.error( + "compile exception '{}' within snippet in {}".format( + exc_value, self._snippet_file), + frame_index = -2, + snippet_lineno = exc_traceback.lineno) + + # Make sure the "codegen" (alias cog) module has our state. + self._set_module_state() + + self._outstring = '' + try: + eval(code, self.generator_globals) + except: + exc_type, exc_value, exc_tb = sys.exc_info() + if exc_type is Error: + # Exception raise by CodeGen means + raise + # Not raised by Codegen means - add some info + print("Codegen: eval exception within codegen snippet ({}) in {}".format( + self._get_snippet_id(), self._snippet_file)) + for i, line in enumerate(self._snippet.splitlines()): + eval_lineno = i + 2 + input_lineno = self._eval_offset + eval_lineno + print("#{} ({}, line {}): {}".format(input_lineno, self._get_snippet_id(), eval_lineno, line)) + raise + finally: + self._restore_module_state() + + # We need to make sure that the last line in the output + # ends with a newline, or it will be joined to the + # end-output line, ruining cog's idempotency. + if self._outstring and self._outstring[-1] != '\n': + self._outstring += '\n' + + # end of evaluation - no extra offset anymore + self._eval_offset = self._snippet_offset + + # figure out the right whitespace prefix for the output + prefOut = whitePrefix(self.markers) + self._previous = reindentBlock(self._outstring, prefOut) + return self._previous + +## +# @brief The code generation processor +# +class CodeGen(Redirectable): + + def __init__(self): + Redirectable.__init__(self) + # Stack of module states + self.module_states = [] + self.options = Options() + # assure codegen module is installed + self._install_codegen_module() + + ## + # @brief Is this a trailing line after an end spec marker. + # + # @todo Make trailing end spec line detection dependent on + # type of text or file type. + # + # @param s line + # + def _is_end_spec_trailer(self, s): + return '*/' in s + + def _install_codegen_module(self): + """ Magic mumbo-jumbo so that imported Python modules + can say "import codegen" and get our state. + + Make us the module, and not our parent cog. + """ + self.cogmodule = imp.new_module('codegen') + self.cogmodule.path = [] + sys.modules['codegen'] = self.cogmodule + + def openOutputFile(self, fname): + """ Open an output file, taking all the details into account. + """ + opts = {} + mode = "w" + opts['encoding'] = self.options.sEncoding + if self.options.bNewlines: + opts['newline'] = "\n" + fdir = os.path.dirname(fname) + if os.path.dirname(fdir) and not os.path.exists(fdir): + os.makedirs(fdir) + return open(fname, mode, **opts) + + def openInputFile(self, fname): + """ Open an input file. """ + if fname == "-": + return sys.stdin + else: + opts = {} + opts['encoding'] = self.options.sEncoding + return open(fname, "r", **opts) + + ## + # @brief Process an input file object to an output file object. + # + # May be called recursively + # + # @param fIn input file object, or file name + # @param fOut output file object, or file name + # @param fname [optional] + # @param globals [optional] + # + def process_file(self, fIn, fOut, fname=None, globals=None): + + fInToClose = fOutToClose = None + # Convert filenames to files. + if isinstance(fIn, (str, bytes)): + # Open the input file. + sFileIn = fIn + fIn = fInToClose = self.openInputFile(fIn) + elif hasattr(fIn, 'name'): + sFileIn = fIn.name + else: + sFileIn = fname or '' + if isinstance(fOut, (str, bytes)): + # Open the output file. + sFileOut = fOut + fOut = fOutToClose = self.openOutputFile(fOut) + elif hasattr(fOut, 'name'): + sFileOut = fOut.name + else: + sFileOut = fname or '' + + try: + fIn = NumberedFileReader(fIn) + + bSawCog = False + + # The globals dict we will use for this file. + if globals is None: + globals = {} + # list of include files that are guarded against inclusion + globals['_guard_include'] = [] + + # If there are any global defines, put them in the globals. + globals.update(self.options.defines) + + # global flag for code generation + globals['_generate_code'] = True + + # loop over generator chunks + l = fIn.readline() + gen = None + while l and globals['_generate_code']: + + if gen is None: + # have a generator ready + # for marker check and error reporting + gen = CodeGenerator(self, globals, sFileOut, str(sFileIn)) + gen.setOutput(stdout=self._stdout) + + # Find the next spec begin + while l and not gen.line_is_start_marker(l): + if gen.line_is_end_marker(l): + gen._snippet_offset = fIn.linenumber() + gen.error("Unexpected '%s'" % gen._end_marker, + frame_index=-1, snippet_lineno=0) + if gen.line_is_insert_marker(l): + gen._snippet_offset = fIn.linenumber() + gen.error("Unexpected '%s'" % gen._insert_marker, + frame_index=-1, snippet_lineno=0) + fOut.write(l) + l = fIn.readline() + if not l: + break + if not self.options.bDeleteCode: + fOut.write(l) + + # l is the begin spec + firstLineNum = fIn.linenumber() + # Start parsing the inline code spec + # Assure a new generator is in use + gen = CodeGenerator(self, globals, sFileOut, str(sFileIn)) + gen.setOutput(stdout=self._stdout) + gen.parse_start_marker(l, firstLineNum) + + gen.log('s{}: process {} #{}'.format(len(self.module_states), sFileIn, firstLineNum)) + # If the spec begin is also a spec end, then process the single + # line of code inside. + if gen.line_is_end_marker(l): + gen.parse_line(l, True) + # next line + l = fIn.readline() + else: + # Deal with an ordinary code block. + l = fIn.readline() + + # Get all the lines in the spec + while l and not gen.line_is_end_marker(l): + gen.parse_line(l) + if gen.line_is_start_marker(l): + gen.error("Code followed by unexpected '%s'" % gen._start_marker, + frame_index = -2, + snippet_lineno = fIn.linenumber() - firstLineNum) + if gen.line_is_insert_marker(l): + gen.error("Code followed by unexpected '%s'" % gen._insert_marker, + frame_index = -2, + snippet_lineno = fIn.linenumber() - firstLineNum) + if not self.options.bDeleteCode: + fOut.write(l) + l = fIn.readline() + if not l: + gen.error("Codegen block begun but never ended.", + frame_index = -2, snippet_lineno = 0) + # write out end spec line + if not self.options.bDeleteCode: + fOut.write(l) + gen.parse_end_marker(l) + # next line - may be trailing end spec line + l = fIn.readline() + if self._is_end_spec_trailer(l) and not gen.line_is_insert_marker(l): + fOut.write(l) + l = fIn.readline() + + # Eat all the lines in the output section. + while l and not gen.line_is_insert_marker(l): + if gen.line_is_start_marker(l): + gen.error("Unexpected '%s'" % gen._start_marker, + frame_index = -2, + snippet_lineno = fIn.linenumber() - firstLineNum) + if gen.line_is_end_marker(l): + gen.error("Unexpected '%s'" % gen._end_marker, + frame_index = -2, + snippet_lineno = fIn.linenumber() - firstLineNum) + l = fIn.readline() + + if not l: + # We reached end of file before we found the end output line. + gen.error("Missing '%s' before end of file." % gen._insert_marker, + frame_index = -2, + snippet_lineno = fIn.linenumber() - firstLineNum) + + # Write the output of the spec to be the new output if we're + # supposed to generate code. + if not self.options.bNoGenerate: + sGen = gen.evaluate() + fOut.write(sGen) + if not globals['_generate_code']: + # generator code snippet stopped code generation + break + + bSawCog = True + + if not self.options.bDeleteCode: + fOut.write(l) + l = fIn.readline() + + if not bSawCog and self.options.bWarnEmpty: + self.warning("no codegen code found in %s" % sFileIn) + finally: + if fInToClose: + fInToClose.close() + if fOutToClose: + fOutToClose.close() + + def saveIncludePath(self): + self.savedInclude = self.options.includePath[:] + self.savedSysPath = sys.path[:] + + def restoreIncludePath(self): + self.options.includePath = self.savedInclude + self.cogmodule.path = self.options.includePath + sys.path = self.savedSysPath + + def addToIncludePath(self, includePath): + self.cogmodule.path.extend(includePath) + sys.path.extend(includePath) + + ## + # @brief process one file through CodeGen + # + # @param sFile file name + # + def _process_one_file(self, sFile): + """ Process one filename through cog. + """ + + self.saveIncludePath() + bNeedNewline = False + + try: + self.addToIncludePath(self.options.includePath) + # Since we know where the input file came from, + # push its directory onto the include path. + self.addToIncludePath([os.path.dirname(sFile)]) + + # How we process the file depends on where the output is going. + if self.options.sOutputName: + self.process_file(sFile, self.options.sOutputName, sFile) + else: + self.process_file(sFile, self.stdout, sFile) + finally: + self.restoreIncludePath() + + def callableMain(self, argv): + """ All of command-line codegen, but in a callable form. + This is used by main. + argv is the equivalent of sys.argv. + """ + argv = argv[1:] + + self.options.parse_args(argv) + + if self.options.input_file is None: + raise FileNotFoundError("No files to process") + + self._process_one_file(self.options.input_file) diff --git a/scripts/codegen/config.py b/scripts/codegen/config.py new file mode 100644 index 00000000000000..d878fe809a3bb8 --- /dev/null +++ b/scripts/codegen/config.py @@ -0,0 +1,59 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import sys +import shlex +from pathlib import Path + +class ConfigMixin(object): + __slots__ = [] + + _autoconf = None + _autoconf_filename = None + + def _autoconf_assure(self): + if self._autoconf is None: + autoconf_file = self.cmake_variable("PROJECT_BINARY_DIR", None) + if autoconf_file is None: + if default == "": + raise self._get_error_exception( + "CMake variable PROJECT_BINARY_DIR not defined to codegen.", 2) + return default + autoconf_file = Path(autoconf_file).joinpath('include/generated/autoconf.h') + if not autoconf_file.is_file(): + if default == "": + default = \ + "Generated configuration {} not found/ no access.".format(autoconf_file) + return default + autoconf = {} + with open(str(autoconf_file)) as autoconf_fd: + for line in autoconf_fd: + if not line.startswith('#'): + continue + if " " not in line: + continue + key, value = shlex.split(line)[1:] + autoconf[key] = value + self._autoconf = autoconf + self._autoconf_filename = str(autoconf_file) + + def config_property(self, property_name, default=""): + self._autoconf_assure() + property_value = self._autoconf.get(property_name, default) + if property_value == "": + raise self._get_error_exception( + "Config property '{}' not defined.".format(property_name), 1) + return property_value + + ## + # @brief Get all config properties. + # + # The property names are the ones autoconf.conf. + # + # @return A dictionary of config properties. + # + def config_properties(self): + self._autoconf_assure() + return self._autoconf diff --git a/scripts/codegen/edts.py b/scripts/codegen/edts.py new file mode 100644 index 00000000000000..a89b4205b413cb --- /dev/null +++ b/scripts/codegen/edts.py @@ -0,0 +1,31 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path +from dts.edtsdatabase import EDTSDatabase + +class EDTSMixin(object): + __slots__ = [] + + _edts = None + + def _edts_assure(self): + if self._edts is None: + edts_file = self.cmake_variable("GENERATED_DTS_BOARD_EDTS") + edts_file = Path(edts_file) + if not edts_file.is_file(): + raise self._get_error_exception( + "Generated extended device tree database file '{}' not found/ no access.". + format(edts_file), 2) + self._edts = EDTSDatabase() + self._edts.load(str(edts_file)) + + ## + # @brief Get the extended device tree database. + # + # @return Extended device tree database. + # + def edts(self): + self._edts_assure() + return self._edts diff --git a/scripts/codegen/error.py b/scripts/codegen/error.py new file mode 100644 index 00000000000000..56cf4ddb2a6b53 --- /dev/null +++ b/scripts/codegen/error.py @@ -0,0 +1,68 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +import inspect +from pathlib import Path + +class Error(Exception): + pass + +class ErrorMixin(object): + __slots__ = [] + + ## + # @brief Get code generation error exception + # + # @note only for 'raise codegen.Error(msg)' in snippet + # + # @param msg exception message + # @param frame_index [optional] call frame index + # @param snippet_lineno [optional] line number within snippet + # @return code generation exception object + # + def _get_error_exception(self, msg, frame_index = 0, + snippet_lineno = 0): + if frame_index >= 0: + # There are frames to get data from + frame_index += 1 + frame = inspect.currentframe() + try: + while frame_index > 0: + frame = frame.f_back + frame_index -= 1 + (filename, snippet_lineno, function, code_context, index) = \ + inspect.getframeinfo(frame) + except: + pass + finally: + del frame + input_lineno = self._snippet_offset + self._get_snippet_lineno(snippet_lineno) + error_msg = "{} #{} ({}, line {}): {}".format( + Path(self._snippet_file).name, + input_lineno, self._get_snippet_id(), + snippet_lineno, msg) + listing = self._list_snippet() + if listing: + error_msg = listing + '\n' + error_msg + else: + listing = self._list_lines() + if listing: + error_msg= listing + '\n' + error_msg + return Error(error_msg) + + ## + # @brief Raise Error exception. + # + # Extra information is added that maps the python snippet + # line seen by the Python interpreter to the line of the file + # that inlines the python snippet. + # + # @param msg [optional] exception message + # @param frame_index [optional] call frame index + # @param snippet_lineno [optional] line number within snippet + # + def error(self, msg = 'Error raised by codegen generator.', + frame_index = 0, snippet_lineno = 0): + frame_index += 1 + raise self._get_error_exception(msg, frame_index, snippet_lineno) diff --git a/scripts/codegen/filereader.py b/scripts/codegen/filereader.py new file mode 100644 index 00000000000000..c567a5ca24dfc1 --- /dev/null +++ b/scripts/codegen/filereader.py @@ -0,0 +1,20 @@ +# Copyright 2004-2016, Ned Batchelder. +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: MIT + +class NumberedFileReader: + """ A decorator for files that counts the readline()'s called. + """ + def __init__(self, f): + self.f = f + self.n = 0 + + def readline(self): + l = self.f.readline() + if l: + self.n += 1 + return l + + def linenumber(self): + return self.n diff --git a/scripts/codegen/generic.py b/scripts/codegen/generic.py new file mode 100644 index 00000000000000..07e89bcaeed570 --- /dev/null +++ b/scripts/codegen/generic.py @@ -0,0 +1,51 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path + +class GenericMixin(object): + __slots__ = [] + + @staticmethod + def path_walk(top, topdown = False, followlinks = False): + """ + See Python docs for os.walk, exact same behavior but it yields Path() + instances instead + + Form: http://ominian.com/2016/03/29/os-walk-for-pathlib-path/ + """ + names = list(top.iterdir()) + + dirs = (node for node in names if node.is_dir() is True) + nondirs = (node for node in names if node.is_dir() is False) + + if topdown: + yield top, dirs, nondirs + + for name in dirs: + if followlinks or name.is_symlink() is False: + for x in path_walk(name, topdown, followlinks): + yield x + + if topdown is not True: + yield top, dirs, nondirs + + # + # @param marker Marker as b'my-marker' + # + @staticmethod + def template_files(top, marker, suffix='.c'): + sources = [] + for path, directory_names, file_names in CodeGen.path_walk(top): + sources.extend([x for x in file_names if x.suffix == suffix]) + + templates = [] + for source_file in sources: + if os.stat(source_file).st_size == 0: + continue + with open(source_file, 'rb', 0) as source_file_fd: + s = mmap.mmap(source_file_fd.fileno(), 0, access=mmap.ACCESS_READ) + if s.find(marker) != -1: + templates.append(source_file) + return templates diff --git a/scripts/codegen/guard.py b/scripts/codegen/guard.py new file mode 100644 index 00000000000000..0cf8a11a22eb6b --- /dev/null +++ b/scripts/codegen/guard.py @@ -0,0 +1,16 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +class GuardMixin(object): + __slots__ = [] + + + def outl_guard_config(self, property_name): + is_config = self.config_property(property_name, 0) + self.outl("#if {} // Guard({}) {}".format( + is_config, is_config, property_name)) + + def outl_unguard_config(self, property_name): + is_config = self.config_property(property_name, 0) + self.outl("#endif // Guard({}) {}".format(is_config, property_name)) diff --git a/scripts/codegen/importmodule.py b/scripts/codegen/importmodule.py new file mode 100644 index 00000000000000..3f4e632059d9eb --- /dev/null +++ b/scripts/codegen/importmodule.py @@ -0,0 +1,37 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +import sys +import os +import importlib +from pathlib import Path + +class ImportMixin(object): + __slots__ = [] + + ## + # @brief Import a CodeGen module. + # + # Import a module from the codegen/modules package. + # + # @param name Module to import. Specified without any path. + # + def import_module(self, name): + try: + module_file = self.zephyr_path().joinpath( + "scripts/codegen/modules/{}.py".format(name)).resolve() + except FileNotFoundError: + # Python 3.4/3.5 will throw this exception + # Python >= 3.6 will not throw this exception + module_file = self.zephyr_path().joinpath( + "scripts/codegen/modules/{}.py".format(name)) + if not module_file.is_file(): + raise self._get_error_exception( + "Module file '{}' of module '{}' does not exist or is no file.". + format(module_file, name), 1) + sys.path.append(os.path.dirname(str(module_file))) + module = importlib.import_module(name) + sys.path.pop() + self.generator_globals[name] = module + diff --git a/scripts/codegen/include.py b/scripts/codegen/include.py new file mode 100644 index 00000000000000..54ea51d48eba9a --- /dev/null +++ b/scripts/codegen/include.py @@ -0,0 +1,67 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path +import io + +from .error import Error + +class IncludeMixin(object): + __slots__ = [] + + def out_include(self, include_file): + try: + input_file = Path(include_file).resolve() + except FileNotFoundError: + # Python 3.4/3.5 will throw this exception + # Python >= 3.6 will not throw this exception + input_file = Path(include_file) + if not input_file.is_file(): + # don't resolve upfront + input_file = Path(include_file) + # try to find the file in the templates directory + expanded_file_path = self.zephyr_path().joinpath( + "scripts/codegen/templates") + if 'templates' in input_file.parts: + templates_seen = False + else: + # assume the path starts after templates + templates_seen = True + # append the remaining part behind templates + for part in input_file.parts: + if templates_seen: + expanded_file_path = expanded_file_path.joinpath(part) + elif part is 'templates': + templates_seen = True + if expanded_file_path.is_file(): + input_file = expanded_file_path + if not input_file.is_file(): + raise self._get_error_exception( + "Include file '{}' does not exist or is no file.". + format(input_file), 1) + if str(input_file) in self.generator_globals['_guard_include']: + self.log('------- include guarded {} - multiple inclusion of include file.'. + format(str(input_file))) + else: + output_fd = io.StringIO() + # delete inline code in included files + delete_code = self.processor.options.bDeleteCode + self.processor.options.bDeleteCode = True + self.log('------- include start {}'.format(input_file)) + self.processor.process_file(str(input_file), output_fd, + globals=self.generator_globals) + self.log(output_fd.getvalue()) + self.log('------- include end {}'.format(input_file)) + self.processor.options.bDeleteCode = delete_code + self.out(output_fd.getvalue()) + + def guard_include(self): + if self._snippet_file in self.generator_globals['_guard_include']: + # This should never happen + raise self._get_error_exception( + "Multiple inclusion of guarded include file '{}'.". + format(self._snippet_file), 1) + self.log('------- include guard {}'.format(self._snippet_file)) + self.generator_globals['_guard_include'].append(self._snippet_file) + diff --git a/scripts/codegen/log.py b/scripts/codegen/log.py new file mode 100644 index 00000000000000..7ee81bad6ac6ec --- /dev/null +++ b/scripts/codegen/log.py @@ -0,0 +1,41 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path + +class LogMixin(object): + __slots__ = [] + + _log_fd = None + + def log(self, message, message_type=None, end="\n", logonly=True): + if self._log_fd is None: + if self.options.log_file is not None: + log_file = Path(self.options.log_file) + if not log_file.is_file(): + # log file will be created + # add preamble + preamble = "My preamble\n{}".format(message) + self._log_fd = open(str(log_file), 'a') + if message_type is None: + message_type = '' + else: + message_type = message_type+': ' + if self._log_fd is not None: + for line in message.splitlines(): + self._log_fd.write("{}{}{}".format(message_type, line, end)) + if not logonly: + print(message_type+message, file=self._stderr, end=end) + + def msg(self, s): + self.log(s, message_type='message', logonly=False) + + def warning(self, s): + self.log(s, message_type='warning', logonly=False) + + def prout(self, s, end="\n"): + self.log(s, message_type=None, end=end, logonly=False) + + def prerr(self, s, end="\n"): + self.log(s, message_type='error', end=end, logonly=False) diff --git a/scripts/codegen/modules/__init__.py b/scripts/codegen/modules/__init__.py new file mode 100644 index 00000000000000..270dcebaa5f4e7 --- /dev/null +++ b/scripts/codegen/modules/__init__.py @@ -0,0 +1 @@ +from .modules import * diff --git a/scripts/codegen/modules/devicedeclare.py b/scripts/codegen/modules/devicedeclare.py new file mode 100644 index 00000000000000..0c0024e4ec9a6a --- /dev/null +++ b/scripts/codegen/modules/devicedeclare.py @@ -0,0 +1,389 @@ +# Copyright (c) 2018 Linaro Limited +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 + +import pprint +import re +import codegen + +from string import Template + +_device_and_api_init_tmpl = \ + 'DEVICE_AND_API_INIT( \\\n' + \ + '\t${device-name}, \\\n' + \ + '\t"${driver-name}", \\\n' + \ + '\t${device-init}, \\\n' + \ + '\t&${device-data}, \\\n' + \ + '\t&${device-config-info}, \\\n' + \ + '\t${device-level}, \\\n' + \ + '\t${device-prio}, \\\n' + \ + '\t&${device-api});' + +## +# Aliases for EDTS property paths. +_property_path_aliases = [ + ('reg/0/address/0', 'reg/address'), + ('reg/0/size/0', 'reg/size'), +] + +## +# @brief Get device name +# +# Device name is generated from +# - device compatible +# - bus master address if the device is connected to a bus master +# - device address +# - parent device address if the device does not have a device address +def _device_name(device_id): + device_name = codegen.edts().device_property(device_id, 'compatible/0', None) + if device_name is None: + codegen.error("No compatible property for device id '{}'." + .format(device_id)) + + bus_master_device_id = codegen.edts().device_property(device_id, 'bus/master', None) + if bus_master_device_id is not None: + reg = codegen.edts().device_property(bus_master_device_id, 'reg') + try: + # use always the first key to get first address inserted into dict + # because reg_index may be number or name + # reg//address/ : address + for reg_index in reg: + for address_index in reg[reg_index]['address']: + bus = reg[reg_index]['address'][address_index] + device_name += '_' + hex(bus)[2:].zfill(8) + break + break + except: + # this device is missing the register directive + codegen.error("No bus master register address property for device id '{}'." + .format(bus_master_device_id)) + + reg = codegen.edts().device_property(device_id, 'reg', None) + if reg is None: + # no reg property - take the reg property of the parent device + parent_device_id = codegen.edts().device_property( + device_id, 'parent-device', None) + if parent_device_id: + reg = codegen.edts().device_property(parent_device_id, 'reg', None) + device_address = None + if reg is not None: + try: + # use always the first key to get first address inserted into dict + # because reg_index may be number or name + # reg//address/ : address + for reg_index in reg: + for address_index in reg[reg_index]['address']: + address = reg[reg_index]['address'][address_index] + device_address = hex(address)[2:].zfill(8) + break + break + except: + # this device is missing the register directive + pass + if device_address is None: + # use label instead of address + device_address = codegen.edts().device_property(device_id, 'label', + '') + # Warn about missing reg property + codegen.log("No register address property for device id '{}'." + .format(device_id), "warning", "\n") + device_name += '_' + device_address + + device_name = device_name.replace("-", "_"). \ + replace(",", "_"). \ + replace(";", "_"). \ + replace("@", "_"). \ + replace("#", "_"). \ + replace("&", "_"). \ + replace("/", "_"). \ + lower() + return device_name + +class _DeviceLocalTemplate(Template): + # pattern is ${} + # never starts with / + # extend default pattern by '-' '/' ',' + idpattern = r'[_a-z][_a-z0-9\-/,]*' + + +class _DeviceGlobalTemplate(Template): + # pattern is ${:} + # device ID is the same as node address + # always starts with / + # extend default pattern by '-', '@', '/', ':' + idpattern = r'/[_a-z0-9\-/,@:]*' + +## +# @brief Substitude values in device template +# +def _device_template_substitute(template, device_id, preset={}): + # substitute device local placeholders ${}, config, ... + mapping = {} + # add preset mapping + mapping.update(preset) + # add device properties from device tree + mapping.update(codegen.edts().device_properties_flattened(device_id)) + # add specific device declaration vars/ constants + mapping['device-name'] = mapping.get('device-name', + _device_name(device_id)) + mapping['driver-name'] = mapping.get('driver-name', + codegen.edts().device_property(device_id, 'label').strip('"')) + mapping['device-data'] = mapping.get('device-data', + "{}_data".format(mapping['device-name']).lower()) + mapping['device-config-info'] = mapping.get('device-config-info', + "{}_config".format(mapping['device-name']).lower()) + mapping['device-config-irq'] = mapping.get('device-config-irq', + "{}_config_irq".format(mapping['device-name']).lower()) + substituted = _DeviceLocalTemplate(template).safe_substitute(mapping) + + # substitute device global placeholders ${:} + # + # we need a second substitude to allow for device indirections + # ${${}:} + mapping = {} + for device_id in codegen.edts()['devices']: + path_prefix = device_id + ':' + mapping.update(codegen.edts().device_properties_flattened(device_id, + path_prefix)) + # add specific device declaration vars/ constants + try: + mapping[path_prefix + 'device-name'] = _device_name(device_id) + mapping[path_prefix + 'driver-name'] = \ + codegen.edts().device_property(device_id, 'label').strip('"') + except: + # will be obvious if any of this is needed, just skip here + pass + + # add aliases to mapping + aliases_mapping = {} + for property_path, property_value in mapping.items(): + for alias_property_path, alias in _property_path_aliases: + if property_path.endswith(alias_property_path): + property_path = property_path[:-len(alias_property_path)] \ + + alias + aliases_mapping[property_path] = property_value + mapping.update(aliases_mapping) + + substituted = _DeviceGlobalTemplate(substituted).safe_substitute(mapping) + + return substituted + + +# +# @return True if device is declared, False otherwise +def device_declare_single(device_config, + driver_name, + device_init, + device_level, + device_prio, + device_api, + device_info, + device_defaults = {}): + device_configured = codegen.config_property(device_config, '') + if device_configured == '' or device_configured[-1] == '0': + # Not configured - do not generate + # + # The generation decision must be taken by codegen here + # (vs. #define CONFIG_xxx) to cope with the following situation: + # + # If config is not set the device may also be not activated in the + # device tree. No device tree info is available in this case. + # An attempt to generate code without the DTS info + # will lead to an exception for a valid situation. + codegen.outl("/* !!! '{}' not configured !!! */".format(driver_name)) + return False + + device_id = codegen.edts().device_id_by_label(driver_name) + if device_id is None: + # this should not happen + raise codegen.Error("Did not find driver name '{}'.".format(driver_name)) + + # Presets for mapping this device data to template + preset = device_defaults + preset['device-init'] = device_init + preset['device-level'] = device_level + preset['device-prio'] = device_prio + preset['device-api'] = device_api + preset['device-config'] = device_config + preset['driver-name'] = driver_name.strip('"') + + # + # device info + if device_info: + device_info = _device_template_substitute(device_info, device_id, + preset) + codegen.outl(device_info) + # + # device init + codegen.outl(_device_template_substitute(_device_and_api_init_tmpl, + device_id, preset)) + return True + +## +# @param device_configs +# A list of configuration variables for device instantiation. +# (e.g. ['CONFIG_SPI_0', 'CONFIG_SPI_1']) +# @param driver_names +# A list of driver names for device instantiation. The list shall be ordered +# as the list of device configs. +# (e.g. ['SPI_0', 'SPI_1']) +# @param device_inits +# A list of device initialisation functions or a one single function. The +# list shall be ordered as the list of device configs. +# (e.g. 'spi_stm32_init') +# @param device_levels +# A list of driver initialisation levels or one single level definition. The +# list shall be ordered as the list of device configs. +# (e.g. 'PRE_KERNEL_1') +# @param device_prios +# A list of driver initialisation priorities or one single priority +# definition. The list shall be ordered as the list of device configs. +# (e.g. 32) +# @param device_api +# Identifier of the device api. +# (e.g. 'spi_stm32_driver_api') +# @param device_info +# Device info template for device driver config, data and interrupt +# initialisation. +# @param device_defaults +# Device default property values. `device_defaults` is a dictionary of +# property path : property value. +# +def device_declare_multi(device_configs, + driver_names, + device_inits, + device_levels, + device_prios, + device_api, + device_info, + device_defaults = {}): + devices_declared = [] + for i, device_config in enumerate(device_configs): + driver_name = driver_names[i] + if isinstance(device_inits, str): + device_init = device_inits + else: + try: + device_init = device_inits[i] + except: + device_init = device_inits + if isinstance(device_levels, str): + device_level = device_levels + else: + try: + device_level = device_levels[i] + except: + device_level = device_levels + if isinstance(device_prios, str): + device_prio = device_prios + else: + try: + device_prio = device_prios[i] + except: + device_prio = device_prios + + device_declared = device_declare_single(device_config, + driver_name, + device_init, + device_level, + device_prio, + device_api, + device_info, + device_defaults) + devices_declared.append(device_declared) + + if True not in devices_declared: + err = "No active device found for {} = {} and {}.".format( + ', '.join(device_configs), ', '.join(devices_declared), + ', '.join(driver_names)) + codegen.log(err) + raise codegen.Error(err) + + +def _device_generate_struct(type_of_struct, _struct): + if _struct is None and type_of_struct == 'config': + return 'static const int ${device-config-info}[] = {};\n' + elif _struct is None and type_of_struct == 'data': + return 'static int ${device-data}[] = {};\n' + + struct = "" + # convert _struct into a list. Struct might have only one element + if type(_struct) is str: + _struct = [_struct] + else: + _struct = list(_struct) + + if type_of_struct == 'config': + struct += 'static const struct {} ${{device-config-info}} = {{\n'.format(_struct[0]) + elif type_of_struct == 'data': + struct += 'static struct {} ${{device-data}} = {{\n'.format(_struct[0]) + else: + msg("Not expected") + + if len(_struct) > 1: + struct += _struct[1] + + struct += '};\n\n' + return struct + + +def _device_generate_irq_bootstrap(irq_names, irq_flag, irq_func): + irq_bootstrap_info = \ + '#ifdef {}\n'.format(irq_flag) + \ + 'DEVICE_DECLARE(${device-name});\n' + \ + 'static void ${device-config-irq}(struct device *dev)\n' + \ + '{\n' + for irq_name in irq_names: + irq_num = '${{interrupts/{}/irq}}'.format(irq_name) + irq_prio = '${{interrupts/{}/priority}}'.format(irq_name) + irq_bootstrap_info += \ + '\tIRQ_CONNECT({},\n'.format(irq_num) + \ + '\t\t{},\n'.format(irq_prio) + if len(irq_names) == 1 and irq_name == '0': + # Only one irq and no name associated. Keep it simple name + irq_bootstrap_info += '\t\t{},\n'.format(irq_func) + else: + irq_bootstrap_info += '\t\t{}_{},\n'.format(irq_func, irq_name) + irq_bootstrap_info += \ + '\t\tDEVICE_GET(${device-name}),\n' + \ + '\t\t0);\n' + \ + '\tirq_enable({});\n\n'.format(irq_num) + irq_bootstrap_info += \ + '}\n' + \ + '#endif /* {} */\n\n'.format(irq_flag) + return irq_bootstrap_info + + +def device_declare(compatibles, init_prio_flag, kernel_level, irq_func, + init_func, api, data_struct, config_struct): + + config_struct = _device_generate_struct('config', config_struct) + data_struct = _device_generate_struct('data', data_struct) + if api is None: + api = "(*(const int *)0)" + + for device_id in codegen.edts().device_ids_by_compatible(compatibles): + driver_name = codegen.edts().device_property(device_id, 'label') + device_config = "CONFIG_{}".format(driver_name.strip('"')) + interrupts = codegen.edts().device_property( + device_id, 'interrupts', None) + if interrupts is not None: + irq_names = list(interrupts.keys()) + else: + irq_names = None + + device_info = "" + if irq_func is not None: + device_info += _device_generate_irq_bootstrap( + irq_names, irq_func['irq_flag'], irq_func['irq_func']) + device_info += config_struct + device_info += data_struct + + device_declare_single(device_config, + driver_name, + init_func, + kernel_level, + init_prio_flag, + api, + device_info) diff --git a/scripts/codegen/modules/pincontroller.py b/scripts/codegen/modules/pincontroller.py new file mode 100644 index 00000000000000..ada3715263514f --- /dev/null +++ b/scripts/codegen/modules/pincontroller.py @@ -0,0 +1,298 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +## +# @file +# Code generation module for pinctrl. +# + +import codegen + +## +# @brief pin controller +# +class PinController(object): + + ## functions below are for pinmux hardware access + _pinctrl_function_device_base = 32 + + ## list of all pin controllers + _pin_controllers = [] + + ## + # @brief Get list of compatible pin controllers + # + # @param compatible + # @return list of compatible controllers + # + @classmethod + def create_all_compatible(cls, compatible): + # assure there is nothing left from last call + cls._pin_controllers = [] + + for device_id in codegen.edts().device_ids_by_compatible(compatible): + controller = cls(device_id) + cls._pin_controllers.append(controller) + return cls._pin_controllers + + ## + # @brief Get the maximum function count of all compatible pin controllers + # + # Includes the offset by PINCTRL_FUNCTION_DEVICE_BASE + # + # @return maximum function count + # + @classmethod + def max_function_count(cls): + max_count = 0 + for controller in cls._pin_controllers: + count = controller.function_count() + if count > max_count: + max_count = count + return max_count + cls._pinctrl_function_device_base + + ## + # @brief Get the maximum state name count of all compatible pin controllers + # + # @return maximum state name count + # + @classmethod + def max_state_name_count(cls): + max_count = 0 + for controller in cls._pin_controllers: + count = controller.state_name_count() + if count > max_count: + max_count = count + return max_count + + ## + # @brief Get the maximum state count of all compatible pin controllers + # + # @return maximum state count + # + @classmethod + def max_state_count(cls): + max_count = 0 + for controller in cls._pin_controllers: + count = controller.state_count() + if count > max_count: + max_count = count + return max_count + + ## + # @brief Get the maximum pinctrl count of all compatible pin controllers + # + # @return maximum pinctrl count + # + @classmethod + def max_pinctrl_count(cls): + max_count = 0 + for controller in cls._pin_controllers: + count = controller.pinctrl_count() + if count > max_count: + max_count = count + return max_count + + # Get the maximum pin count of all compatible pin controllers + @classmethod + def max_pin_count(cls): + max_count = 0 + for controller in cls._pin_controllers: + count = controller.pin_count() + if count > max_count: + max_count = count + return max_count + + def __init__(self, device_id): + self._device_id = device_id + self._state_name_data = [] + self._function_data = [] + self._state_data = [] + self._pinctrl_data = [] + self._gpio_range_data = [] + self._init_pinctrl() + self._init_gpio_ranges() + + def _init_pinctrl(self): + for device_id, device in codegen.edts()['devices'].items(): + if 'pinctrl' in device: + for pinctrl_idx, pinctrl in device['pinctrl'].items(): + pinctrl_name = pinctrl['name'] + for pinconf_index in pinctrl['pinconf']: + if pinctrl['pinconf'][pinconf_index]['pin-controller'] != self._device_id: + # other pin controller + continue + # pinconf is for us + # assure state is available + state = dict() + if pinctrl_name not in self._state_name_data: + self._state_name_data.append(pinctrl_name) + state['state-name-id'] = self._state_name_data.index(pinctrl_name) + if device['label'] not in self._function_data: + self._function_data.append(device['label']) + state['function-id'] = self._function_data.index(device['label']) + if state not in self._state_data: + self._state_data.append(state) + # setup pin control data + name = None + pins = [] + muxes = [] + config = dict() + for pinconf_prop, pinconf_value in pinctrl['pinconf'][pinconf_index].items(): + if pinconf_prop == 'name': + name = pinconf_value + elif pinconf_prop == 'pin-controller': + continue + elif pinconf_prop == 'pinmux': + for i in range(0, len(pinconf_value), 2): + pins.append(pinconf_value[i]) + muxes.append(pinconf_value[i + 1]) + elif pinconf_prop == 'pins': + for pin in pinconf_value: + pins.append(int(pin)) + muxes.append(None) + elif pinconf_prop == 'group': + codegen.error("Pinctrl does not support 'group'.") + else: + config[pinconf_prop] = pinconf_value + for i, pin in enumerate(pins): + control = dict() + control['name'] = name + control['pin'] = pin + control['mux'] = muxes[i] + control['config'] = config + control['state-id'] = self._state_data.index(state) + self._pinctrl_data.append(control) + + + def _init_gpio_ranges(self): + for device_id, device in codegen.edts()['devices'].items(): + if 'gpio-ranges' in device: + for gpio_range_idx, gpio_range in device['gpio-ranges'].items(): + if gpio_range['pin-controller'] == self._device_id: + control = dict() + control['name'] = device['label'] + control['base'] = gpio_range['pin-controller-base'] + control['gpio-base-idx'] = gpio_range['base'] + control['npins'] = gpio_range['npins'] + self._gpio_range_data.append(control) + + + def device_id(self): + return self._device_id + + def function_data(self): + return self._function_data + + def function_id(self, device_label): + return self._function_data.index(device_label) + + ## + # @brief Get the function count of a pin controller + # + # @return function count + def function_count(self): + return len(self._function_data) + + def state_name_data(self): + return self._state_name_data + + def state_name_id(self, state_name): + return self._state_name_data.index(state_name) + + def state_name(self, state_name_id): + return self._state_name_data[state_name_id] + + ## + # @brief Get the state name count of a pin controller + # + # @return state name count + def state_name_count(self): + return len(self._state_name_data) + + def state_data(self): + return self._state_data + + ## + # @brief Get the state count of a pin controller + # + # @return state count + def state_count(self): + return len(self._state_data) + + ## + # @brief Get the state id + # + # @param device_label + # @param state_name + # @return state id + def state_id(self, device_label, state_name): + state_name_id = self.state_name_id(state_name) + function_id = self.function_id(device_label) + for state_id, state in enumerate(self._state_data): + if state['state-name-id'] == state_name_id and state['function-id'] == function_id: + return state_id + return None + + def state_desc(self, state_id): + state = self._state_data[state_id] + state_name = self._state_name_data[state['state-name-id']] + function = self._function_data[state['function-id']] + return "{} {}".format(function, state_name) + + def pinctrl_data(self, state_name = None): + if state_name is None: + return self._pinctrl_data + data = [] + state_name_id = self.state_name_id(state_name) + for pinctrl in self._pinctrl_data: + state = self._state_data[pinctrl['state-id']] + if state['state-name-id'] == state_name_id: + data.append(pinctrl) + return data + + ## + # @brief Get the pinctrl count of a pin controller + # + # @return pinctrl count + def pinctrl_count(self): + return len(self._pinctrl_data) + + def gpio_range_data(self): + return self._gpio_range_data + + ## + # @brief Get the gpio range of a pin controller + # + # @return gpio range count + def gpio_range_count(self): + return len(self._gpio_range_data) + + ## + # @brief Get the the number of pins the pin controller controls + # + # @return pin count + # + def pin_count(self): + pin_low = 9999999 + pin_high = 0 + for control in self._gpio_range_data: + low = control['base'] + high = control['base'] + control['npins'] + if low < pin_low: + pin_low = low + if high > pin_high: + pin_high = high + pin_count = pin_high - pin_low + if pin_count < 0: + pin_count = 0 + return pin_count + + + + + + diff --git a/scripts/codegen/options.py b/scripts/codegen/options.py new file mode 100644 index 00000000000000..312509353852db --- /dev/null +++ b/scripts/codegen/options.py @@ -0,0 +1,139 @@ +# Copyright 2004-2016, Ned Batchelder. +# http://nedbatchelder.com/code/cog +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: MIT + +import os +import argparse + +class Options(object): + + @staticmethod + def is_valid_directory(parser, arg): + if not os.path.isdir(arg): + parser.error('The directory {} does not exist!'.format(arg)) + else: + # File directory so return the directory + return arg + + @staticmethod + def is_valid_file(parser, arg): + if not os.path.isfile(arg): + parser.error('The file {} does not exist!'.format(arg)) + else: + # File exists so return the file + return arg + + def __init__(self): + # Defaults for argument values. + self.args = [] + self.includePath = [] + self.defines = {} + self.bNoGenerate = False + self.sOutputName = None + self.bWarnEmpty = False + self.bDeleteCode = False + self.bNewlines = False + self.sEncoding = "utf-8" + self.verbosity = 2 + + self._parser = argparse.ArgumentParser( + description='Generate code with inlined Python code.') + self._parser.add_argument('-d', '--delete-code', + dest='bDeleteCode', action='store_true', + help='Delete the generator code from the output file.') + self._parser.add_argument('-D', '--define', nargs=1, metavar='DEFINE', + dest='defines', action='append', + help='Define a global string available to your generator code.') + self._parser.add_argument('-e', '--warn-empty', + dest='bWarnEmpty', action='store_true', + help='Warn if a file has no generator code in it.') + self._parser.add_argument('-U', '--unix-newlines', + dest='bNewlines', action='store_true', + help='Write the output with Unix newlines (only LF line-endings).') + self._parser.add_argument('-I', '--include', nargs=1, metavar='DIR', + dest='includePath', action='append', + type=lambda x: self.is_valid_directory(self._parser, x), + help='Add DIR to the list of directories for data files and modules.') + self._parser.add_argument('-n', '--encoding', nargs=1, + dest='sEncoding', action='store', metavar='ENCODING', + type=lambda x: self.is_valid_file(self._parser, x), + help='Use ENCODING when reading and writing files.') + self._parser.add_argument('-i', '--input', nargs=1, metavar='FILE', + dest='input_file', action='store', + type=lambda x: self.is_valid_file(self._parser, x), + help='Get the input from FILE.') + self._parser.add_argument('-o', '--output', nargs=1, metavar='FILE', + dest='sOutputName', action='store', + help='Write the output to FILE.') + self._parser.add_argument('-l', '--log', nargs=1, metavar='FILE', + dest='log_file', action='store', + help='Log to FILE.') + + def __str__(self): + sb = [] + for key in self.__dict__: + sb.append("{key}='{value}'".format(key=key, value=self.__dict__[key])) + return ', '.join(sb) + + def __repr__(self): + return self.__str__() + + + def __eq__(self, other): + """ Comparison operator for tests to use. + """ + return self.__dict__ == other.__dict__ + + def clone(self): + """ Make a clone of these options, for further refinement. + """ + return copy.deepcopy(self) + + def parse_args(self, argv): + args = self._parser.parse_args(argv) + # set options + self.bDeleteCode = args.bDeleteCode + self.bWarnEmpty = args.bWarnEmpty + self.bNewlines = args.bNewlines + if args.includePath is None: + self.includePath = [] + else: + self.includePath = args.includePath + self.sEncoding = args.sEncoding + if args.input_file is None: + self.input_file = None + else: + self.input_file = args.input_file[0] + if args.sOutputName is None: + self.sOutputName = None + else: + self.sOutputName = args.sOutputName[0] + if args.log_file is None: + self.log_file = None + else: + self.log_file = args.log_file[0] + self.defines = {} + if args.defines is not None: + for define in args.defines: + d = define[0].split('=') + if len(d) > 1: + value = d[1] + else: + value = None + self.defines[d[0]] = value + + def addToIncludePath(self, dirs): + """ Add directories to the include path. + """ + dirs = dirs.split(os.pathsep) + self.includePath.extend(dirs) + + + +class OptionsMixin(object): + __slots__ = [] + + def option(self, option_name): + return getattr(self.options, option_name) diff --git a/scripts/codegen/output.py b/scripts/codegen/output.py new file mode 100644 index 00000000000000..647002b3ed53f8 --- /dev/null +++ b/scripts/codegen/output.py @@ -0,0 +1,19 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + + +class OutputMixin(object): + __slots__ = [] + + def msg(self, s): + self.prout("Message: "+s) + + def out(self, sOut='', dedent=False, trimblanklines=False): + self._out(sOut, dedent, trimblanklines) + + def outl(self, sOut='', **kw): + """ The cog.outl function. + """ + self._out(sOut, **kw) + self._out('\n') diff --git a/scripts/codegen/redirectable.py b/scripts/codegen/redirectable.py new file mode 100644 index 00000000000000..3cdc49b25e5f28 --- /dev/null +++ b/scripts/codegen/redirectable.py @@ -0,0 +1,31 @@ +# Copyright 2004-2016, Ned Batchelder. +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: MIT + +import sys + +class RedirectableMixin(object): + __slots__ = [] + + def setOutput(self, stdout=None, stderr=None): + """ Assign new files for standard out and/or standard error. + """ + if stdout: + self._stdout = stdout + if stderr: + self._stderr = stderr + + def prout(self, s, end="\n"): + print(s, file=self._stdout, end=end) + + def prerr(self, s, end="\n"): + print(s, file=self._stderr, end=end) + + +class Redirectable(RedirectableMixin): + """ An object with its own stdout and stderr files. + """ + def __init__(self): + self._stdout = sys.stdout + self._stderr = sys.stderr diff --git a/scripts/codegen/templates/drivers/pinctrl_tmpl.c b/scripts/codegen/templates/drivers/pinctrl_tmpl.c new file mode 100644 index 00000000000000..86c92e06a24b63 --- /dev/null +++ b/scripts/codegen/templates/drivers/pinctrl_tmpl.c @@ -0,0 +1,1144 @@ +/* + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Code generation template for PINCTRL drivers + */ + +/** + * @brief PINCTRL template. + * @defgroup pinctrl_template PINCTRL template. + * @ingroup device_driver_support + * + * Code generation template for PINCTRL drivers. + * + * Usage example: + * compatible = 'st,stm32-pinctrl' + * data_info = 'struct pinctrl_stm32_data' + * config_get = 'pinctrl_stm32_config_get' + * config_set = 'pinctrl_stm32_config_set' + * mux_get = 'pinctrl_stm32_mux_get' + * mux_set = 'pinctrl_stm32_mux_set' + * device_init = 'pinctrl_stm32_device_init' + * codegen.out_include('templates/drivers/pinctrl_tmpl.c') + * + * The template expects the following globals to be set: + * - compatible + * The compatible string of the driver (e.g. 'st,stm32-pinctrl') + * - data_info + * device data type definition (e.g. 'struct pinctrl_stm32_data') + * - config_get + * C function name of device config_get function. + * - mux_free + * C function name of device mux_free function. + * - mux_get + * C function name of device mux_get function. + * - mux_set + * C function name of device mux_set function. + * - device_init + * C function name of device init function + * + * @{ + */ + +/** Helper functions for code generation + * @code{.codegen} + * + * # template shall only be included once + * codegen.guard_include() + * + * # Pin controller device tree data access + * codegen.import_module('pincontroller') + * + * _pin_controllers = \ + * pincontroller.PinController.create_all_compatible(compatible) + * + * codegen.outl("/" + "* {} x '{}' pin controller devices *" \ + * .format(len(_pin_controllers), compatible) + "/") + * + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +#undef SYS_LOG_LEVEL +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_PINCTRL_LEVEL +#include + +#include +#include +#include + +/** Define template types for minimum footprint. + * @code{.codegen} + * + * if pincontroller.PinController.max_pin_count() < 256: + * codegen.outl("typedef u8_t pinctrl_tmpl_pin_t;") + * else: + * codegen.outl("typedef u16_t pinctrl_tmpl_pin_t;") + * if pincontroller.PinController.max_function_count() < 256: + * codegen.outl("typedef u8_t pinctrl_tmpl_mux_t;") + * codegen.outl("typedef u8_t pinctrl_tmpl_function_id_t;") + * else: + * codegen.outl("typedef u16_t pinctrl_tmpl_mux_t;") + * codegen.outl("typedef u16_t pinctrl_tmpl_function_id_t;") + * if pincontroller.PinController.max_state_name_count() < 256: + * codegen.outl("typedef u8_t pinctrl_tmpl_state_name_id_t;") + * else: + * codegen.outl("typedef u16_t pinctrl_tmpl_state_name_id_t;") + * if pincontroller.PinController.max_state_count() < 256: + * codegen.outl("typedef u8_t pinctrl_tmpl_state_id_t;") + * else: + * codegen.outl("typedef u16_t pinctrl_tmpl_state_id_t;") + * if pincontroller.PinController.max_pinctrl_count() < 256: + * codegen.outl("typedef u8_t pinctrl_tmpl_pinctrl_id_t;") + * else: + * codegen.outl("typedef u16_t pinctrl_tmpl_pinctrl_id_t;") + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +#if CONFIG_PINCTRL_RUNTIME_DTS + +/** + * @brief Device function info. + */ +struct pinctrl_tmpl_device_function { + const char *name; +}; + +/** + * @brief State name info. + */ +struct pinctrl_tmpl_state_name { + const char *name; +}; + +/** + * @brief Pinctrl state info. + */ +struct pinctrl_tmpl_pinctrl_state { + pinctrl_tmpl_function_id_t device_function; + pinctrl_tmpl_state_name_id_t name; +}; + +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + +/** + * @brief Pinctrl info. + */ +struct pinctrl_tmpl_pinctrl { + u32_t config; + pinctrl_tmpl_pin_t pin; /* pin ID */ + pinctrl_tmpl_mux_t mux; +#if CONFIG_PINCTRL_RUNTIME_DTS + pinctrl_tmpl_state_id_t state; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ +}; + +/** + * @brief GPIO range info. + */ +struct pinctrl_tmpl_gpio_range { + const char *name; + pinctrl_tmpl_pin_t base; + u8_t gpio_base_idx; + u8_t npins; +}; + +/** + * @brief Pin controller configuration info. + */ +struct pinctrl_tmpl_config { +#if CONFIG_PINCTRL_RUNTIME_DTS + const struct pinctrl_tmpl_device_function *device_function_data; + const struct pinctrl_tmpl_state_name *state_name_data; + const struct pinctrl_tmpl_pinctrl_state *pinctrl_state_data; + u8_t *mux_pinmap; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + const struct pinctrl_tmpl_pinctrl *pinctrl_data; + const struct pinctrl_tmpl_gpio_range *gpio_range_data; + int (*device_init)(struct device *dev); + int (*mux_set)(struct device *dev, u16_t pin, u16_t func); + pinctrl_tmpl_pin_t pin_count; +#if CONFIG_PINCTRL_RUNTIME_DTS + pinctrl_tmpl_function_id_t device_function_count; + pinctrl_tmpl_state_name_id_t state_name_count; + pinctrl_tmpl_state_id_t pinctrl_state_count; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + pinctrl_tmpl_pinctrl_id_t pinctrl_count; + u8_t gpio_range_count; +}; + +static inline const struct pinctrl_tmpl_config + *pinctrl_tmpl_device_config_info(struct device *dev) +{ + return (const struct pinctrl_tmpl_config *) dev->config->config_info; +} + +#if CONFIG_PINCTRL_RUNTIME_DTS + +static inline pinctrl_tmpl_function_id_t + pinctrl_tmpl_device_function_id(u16_t func) +{ + return func - PINCTRL_FUNCTION_DEVICE_BASE; +} + +static int pinctrl_tmpl_is_device_function(struct device *dev, u16_t func) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (func < PINCTRL_FUNCTION_DEVICE_BASE) { + return 0; + } + func = pinctrl_tmpl_device_function_id(func); + if (func >= config->device_function_count) { + return 0; + } + return 1; +} + +/** + * @brief Pin multiplex owner info + */ +struct pinctrl_tmpl_mux_owner { + const char *name; +}; + +/** + * @brief Pin multiplex owner data + */ +struct pinctrl_tmpl_mux_owner pinctrl_tmpl_mux_owner_data[15]; + +static const char *pinctrl_tmpl_mux_owner_get(struct device *dev, u16_t pin) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + int pinmap_idx = pin >> 1; + u8_t owner_idx = config->mux_pinmap[pinmap_idx]; + + if (pin & 0x01) { + owner_idx = owner_idx >> 4; + } else { + owner_idx &= 0x0F; + } + if (owner_idx >= 15) { + /* no owner */ + return 0; + } + return pinctrl_tmpl_mux_owner_data[owner_idx].name; +} + +static int pinctrl_tmpl_mux_owner_set(struct device *dev, u16_t pin, + const char *owner) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + int pinmap_idx = pin >> 1; + u8_t owner_idx; + + if (owner == 0) { + /* No owner */ + owner_idx = 15; + } else { + for (owner_idx = 0; owner_idx < 15; owner_idx++) { + const char *name = + pinctrl_tmpl_mux_owner_data[owner_idx].name; + if (name && (strcmp(name, owner) == 0)) { + break; + } + } + if (owner_idx >= 15) { + /* owner unknown - add it */ + for (owner_idx = 0; owner_idx < 15; owner_idx++) { + if (pinctrl_tmpl_mux_owner_data[owner_idx] + .name == 0) { + pinctrl_tmpl_mux_owner_data[owner_idx] + .name = owner; + break; + } + } + } + if (owner_idx >= 15) { + /* no more memory for owner info */ + return -ENOMEM; + } + } + if (pin & 0x01) { + config->mux_pinmap[pinmap_idx] = + (config->mux_pinmap[pinmap_idx] & 0x0F) | + (owner_idx << 4); + } else { + config->mux_pinmap[pinmap_idx] = + (config->mux_pinmap[pinmap_idx] & 0xF0) | owner_idx; + } + return 0; +} + +static void pinctrl_tmpl_mux_owner_init(void) +{ + for (int owner_idx = 0; owner_idx < 15; owner_idx++) { + pinctrl_tmpl_mux_owner_data[owner_idx].name = 0; + } +} + +static u8_t pinctrl_tmpl_mux_owner_initialized; /* initialized to 0 */ + +static int pinctrl_tmpl_mux_request_init(struct device *dev) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (!pinctrl_tmpl_mux_owner_initialized) { + pinctrl_tmpl_mux_owner_init(); + pinctrl_tmpl_mux_owner_initialized = 1; + } + for (int i = 0; i < config->pin_count / 2; i++) { + config->mux_pinmap[i] = 0xFF; + } + return 0; +} + +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + +/* --- API --- */ + +static u16_t pinctrl_tmpl_control_get_pins_count(struct device *dev) +{ + return pinctrl_tmpl_device_config_info(dev)->pin_count; +} + +#if CONFIG_PINCTRL_RUNTIME_DTS + +static int pinctrl_tmpl_control_get_groups_count(struct device *dev) +{ + return pinctrl_tmpl_device_config_info(dev)->pinctrl_state_count; +} + +/* + * @note The pin group is defined by the pinctrl state. + * The group number equals the pinctrl state index. + */ +static int pinctrl_tmpl_control_get_group_pins(struct device *dev, u16_t group, + u16_t *pins, u16_t *num_pins) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + pinctrl_tmpl_pin_t num_pins_found = 0; + + for (int i = 0; i < config->pinctrl_count; i++) { + if (config->pinctrl_data[i].state == group) { + if (num_pins_found < *num_pins) { + pins[num_pins_found] = + config->pinctrl_data[i].pin; + } + num_pins_found++; + } + } + if (num_pins_found == 0) { + *num_pins = 0; + return -ENOTSUP; + } + if (num_pins_found > *num_pins) { + *num_pins = num_pins_found; + return -EINVAL; + } + *num_pins = num_pins_found; + return 0; +} + +static u16_t pinctrl_tmpl_control_get_states_count(struct device *dev) +{ + return pinctrl_tmpl_device_config_info(dev)->pinctrl_state_count; +} + +/* + * @note Every state is regarded a group. Resulting multi definition + * of the same set of pins is accepted for the sake of code simplicity. + */ +static int pinctrl_tmpl_control_get_state_group(struct device *dev, + u16_t state, u16_t *group) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (state >= config->pinctrl_state_count) { + return -ENOTSUP; + } + *group = state; + return 0; +} + +static u16_t pinctrl_tmpl_control_get_functions_count(struct device *dev) +{ + return pinctrl_tmpl_device_config_info(dev)->device_function_count; +} + +static int pinctrl_tmpl_control_get_function_group(struct device *dev, + u16_t func, + const char *name, + u16_t *group) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (!pinctrl_tmpl_is_device_function(dev, func)) { + return -ENODEV; + } + + func = pinctrl_tmpl_device_function_id(func); + for (u16_t i = 0; i < config->pinctrl_state_count; i++) { + /* state name is name also used as group name */ + const char *group_name = + config->state_name_data[config->pinctrl_state_data[i] + .name].name; + + if ((func == config->pinctrl_state_data[i].device_function) && + (strcmp(name, group_name) == 0)) { + *group = i; + return 0; + } + } + return -ENOTSUP; +} + +static int pinctrl_tmpl_control_get_function_groups(struct device *dev, + u16_t func, u16_t *groups, + u16_t *num_groups) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (!pinctrl_tmpl_is_device_function(dev, func)) { + *num_groups = 0; + return -ENODEV; + } + + func = pinctrl_tmpl_device_function_id(func); + u16_t num_groups_found = 0; + + for (u16_t i = 0; i < config->pinctrl_state_count; i++) { + if (func == config->pinctrl_state_data[i].device_function) { + if (num_groups_found < *num_groups) { + groups[num_groups_found] = i; + } + num_groups_found++; + } + } + if (num_groups_found == 0) { + *num_groups = 0; + return -ENOTSUP; + } + if (num_groups_found > *num_groups) { + *num_groups = num_groups_found; + return -EINVAL; + } + *num_groups = num_groups_found; + return 0; +} + +static int pinctrl_tmpl_control_get_function_state(struct device *dev, + u16_t func, + const char *name, + u16_t *state) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (!pinctrl_tmpl_is_device_function(dev, func)) { + return -ENODEV; + } + + func = pinctrl_tmpl_device_function_id(func); + + for (pinctrl_tmpl_state_id_t i = 0; + i < config->pinctrl_state_count; i++) { + u16_t function = config->pinctrl_state_data[i].device_function; + const char *state_name = + config->state_name_data[config->pinctrl_state_data[i] + .name].name; + + if ((func == function) && (strcmp(name, state_name) == 0)) { + *state = i; + return 0; + } + } + + return -ENOTSUP; +} + +static int pinctrl_tmpl_control_get_function_states(struct device *dev, + u16_t func, u16_t *states, + u16_t *num_states) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (!pinctrl_tmpl_is_device_function(dev, func)) { + *num_states = 0; + return -ENODEV; + } + + func = pinctrl_tmpl_device_function_id(func); + pinctrl_tmpl_state_id_t num_states_found = 0; + + for (u16_t i = 0; i < config->pinctrl_state_count; i++) { + if (func == config->pinctrl_state_data[i].device_function) { + if (num_states_found < *num_states) { + states[num_states_found] = i; + } + num_states_found++; + } + } + + if (num_states_found == 0) { + *num_states = 0; + return -ENOTSUP; + } + if (num_states_found > *num_states) { + *num_states = num_states_found; + return -EINVAL; + } + *num_states = num_states_found; + return 0; +} + +static int pinctrl_tmpl_control_get_device_function(struct device *dev, + struct device *client, + u16_t *func) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + for (u32_t i = 0; i < config->device_function_count; i++) { + if (strcmp(client->config->name, + config->device_function_data[i].name) == 0) { + *func = i + PINCTRL_FUNCTION_DEVICE_BASE; + return 0; + } + } + + return -ENOTSUP; +} + +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + +static int pinctrl_tmpl_control_get_gpio_range(struct device *dev, + struct device *gpio, + u32_t gpio_pin, u16_t *pin, + u16_t *base_pin, + u8_t *num_pins) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + int gpio_pin_idx = gpio_port_pin_idx(gpio_pin); + + if (gpio_pin_idx < 0) { + /* invalid gpio_pin */ + return gpio_pin_idx; + } + for (u8_t i = 0; i < config->gpio_range_count; i++) { + if ((strcmp(gpio->config->name, + config->gpio_range_data[i].name) == 0) && + (gpio_pin_idx >= + config->gpio_range_data[i].gpio_base_idx) && + (gpio_pin_idx < config->gpio_range_data[i].npins)) { + *pin = config->gpio_range_data[i].base + + (gpio_pin_idx - + config->gpio_range_data[i].gpio_base_idx); + *base_pin = config->gpio_range_data[i].base; + *num_pins = config->gpio_range_data[i].npins; + return 0; + } + } + + return -ENOTSUP; +} + +/* Wrapper to access externally provided function */ +static inline int pinctrl_tmpl_config_get(struct device *dev, u16_t pin, + u32_t *config) +{ + /** + * @code{.codegen} + * codegen.out('return {}(dev, pin, config);'.format(config_get)) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ +} + +/* Wrapper to access externally provided function */ +static inline int pinctrl_tmpl_config_set(struct device *dev, u16_t pin, + u32_t config) +{ + /** + * @code{.codegen} + * codegen.out('return {}(dev, pin, config);'.format(config_set)) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ +} + +#if CONFIG_PINCTRL_RUNTIME_DTS + +static int pinctrl_tmpl_config_group_get(struct device *dev, u16_t group, + u32_t *configs, u16_t *num_configs) +{ + int err; + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (group >= config->pinctrl_state_count) { + *num_configs = 0; + return -ENOTSUP; + } + + u16_t num_pins_found = 0; + + for (int i = 0; i < config->pinctrl_count; i++) { + if (config->pinctrl_data[i].state == group) { + if (num_pins_found < *num_configs) { + err = pinctrl_tmpl_config_get(dev, i, + &configs + [num_pins_found]); + if (err) { + *num_configs = num_pins_found; + return err; + } + } + num_pins_found++; + } + } + if (num_pins_found == 0) { + *num_configs = 0; + return -ENOTSUP; + } + if (num_pins_found > *num_configs) { + *num_configs = num_pins_found; + return -EINVAL; + } + *num_configs = num_pins_found; + return 0; +} + +static int pinctrl_tmpl_config_group_set(struct device *dev, u16_t group, + const u32_t *configs, + u16_t num_configs) +{ + int err; + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (group >= config->pinctrl_state_count) { + return -ENOTSUP; + } + + u16_t num_pins_found = 0; + + for (int i = 0; i < config->pinctrl_count; i++) { + if (config->pinctrl_data[i].state == group) { + if (num_pins_found < num_configs) { + err = pinctrl_tmpl_config_set(dev, i, + configs + [num_pins_found]); + if (err) { + return err; + } + } + num_pins_found++; + } + } + if (num_pins_found == 0) { + return -ENOTSUP; + } + if (num_pins_found != num_configs) { + return -EINVAL; + } + return 0; +} + +static int pinctrl_tmpl_mux_request(struct device *dev, u16_t pin, + const char *owner) +{ + const char *current_owner; + + if (pin >= pinctrl_tmpl_device_config_info(dev)->pin_count) { + SYS_LOG_ERR("Invalid pin %d of %s on mux request by %s.", + (int)pin, dev->config->name, owner); + return -ENOTSUP; + } + current_owner = pinctrl_tmpl_mux_owner_get(dev, pin); + if (current_owner == 0) { + return pinctrl_tmpl_mux_owner_set(dev, pin, owner); + } + if (current_owner != owner) { + SYS_LOG_WRN("Pin %d of %s owned by %s but mux requested by %s.", + (int)pin, dev->config->name, current_owner, owner); + return -EBUSY; + } + return 0; +} + +static int pinctrl_tmpl_mux_free(struct device *dev, u16_t pin, + const char *owner) +{ + const char *current_owner; + + if (pin >= pinctrl_tmpl_device_config_info(dev)->pin_count) { + SYS_LOG_ERR("Invalid pin %d of %s on mux free by %s.", + (int)pin, dev->config->name, owner); + return -ENOTSUP; + } + current_owner = pinctrl_tmpl_mux_owner_get(dev, pin); + if (current_owner != owner) { + SYS_LOG_WRN( + "Pin %d of %s owned by %s but mux free tried by %s.", + (int)pin, dev->config->name, current_owner, owner); + return -EACCES; + } + return pinctrl_tmpl_mux_owner_set(dev, pin, 0); +} + +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + +/* Wrapper to access externally provided function */ +static inline int pinctrl_tmpl_mux_get(struct device *dev, u16_t pin, + u16_t *func) +{ +/** + * @code{.codegen} + * codegen.outl('\treturn {}(dev, pin, func);'.format(mux_get)) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ +} + +static int pinctrl_tmpl_mux_set(struct device *dev, u16_t pin, + u16_t func) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + + if (pin >= pinctrl_tmpl_control_get_pins_count(dev)) { + return -ENOTSUP; + } + + if (pinctrl_is_device_function(func)) { +#if CONFIG_PINCTRL_RUNTIME_DTS + pinctrl_tmpl_function_id_t device_function = + pinctrl_tmpl_device_function_id(func); + + /* Get hardware pinmux control for pin + * from a pinctrl for the device function. + */ + for (int i = 0; i < config->pinctrl_count; i++) { + u16_t pinctrl_state = config->pinctrl_data[i].state; + u16_t pinctrl_func = + config->pinctrl_state_data[pinctrl_state] + .device_function; + u16_t pinctrl_pin = config->pinctrl_data[i].pin; + + if ((pinctrl_func == device_function) + && (pinctrl_pin == pin)) { + func = config->pinctrl_data[i].mux; + break; + } + } +#else + return -ENOTSUP; +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + } + if (!pinctrl_is_pinmux_function(func)) { + return -EINVAL; + } + + return config->mux_set(dev, pin, func); +} + +#if CONFIG_PINCTRL_RUNTIME_DTS + +static int pinctrl_tmpl_mux_group_set(struct device *dev, u16_t group, + u16_t func) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + int err; + + if (!pinctrl_tmpl_is_device_function(dev, func)) { + /* function does not denote a device */ + return -ENOTSUP; + } + if (group >= config->pinctrl_state_count) { + /* pin group does not correspond to a pinctrl state */ + return -ENOTSUP; + } + func = pinctrl_tmpl_device_function_id(func); + if (config->pinctrl_state_data[group].device_function != func) { + /* Group (aka pinctrl state) was defined by a different + * function (aka. device) + */ + return -EINVAL; + } + u16_t num_pins_found = 0; + + for (u16_t i = 0; i < config->pinctrl_count; i++) { + if (config->pinctrl_data[i].state == group) { + err = pinctrl_tmpl_mux_set(dev, + config->pinctrl_data[i].pin, + config->pinctrl_data[i].mux); + if (err) { + return err; + } + num_pins_found++; + } + } + if (num_pins_found == 0) { + /* no pins found to mux pin group to function */ + return -ENOTSUP; + } + return 0; +} + +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + +static int pinctrl_tmpl_state_set(struct device *dev, u16_t state) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + int err = -ENOTSUP; /* Returned if no corresponding state is found */ + +#if CONFIG_PINCTRL_RUNTIME_DTS + if (state >= config->pinctrl_state_count) { + return err; + } + + SYS_LOG_DBG("Set '%s' state.", + config->state_name_data[ + config->pinctrl_state_data[state] + .name].name); + + for (pinctrl_tmpl_pinctrl_id_t i = 0; i < config->pinctrl_count; i++) { + if (config->pinctrl_data[i].state == state) { + const char *owner = config->device_function_data[ + config->pinctrl_state_data[state] + .device_function].name; + + err = pinctrl_tmpl_mux_request( + dev, config->pinctrl_data[i].pin, owner); + if (err) { + return err; + } + err = pinctrl_tmpl_config_set(dev, + config->pinctrl_data[i].pin, + config->pinctrl_data[i].config); + if (err) { + return err; + } + err = pinctrl_tmpl_mux_set(dev, + config->pinctrl_data[i].pin, + config->pinctrl_data[i].mux); + if (err) { + return err; + } + } + } +#else + SYS_LOG_DBG("Set 'default' state."); + + /* all pinctrl data belongs to the "default" state */ + for (pinctrl_tmpl_pinctrl_id_t i = 0; i < config->pinctrl_count; i++) { + err = pinctrl_tmpl_config_set(dev, + config->pinctrl_data[i].pin, + config->pinctrl_data[i].config); + if (err) { + return err; + } + err = pinctrl_tmpl_mux_set(dev, + config->pinctrl_data[i].pin, + config->pinctrl_data[i].mux); + if (err) { + return err; + } + } +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + return err; +} + +/** + * @brief Initialise pin controller. + * + * @param dev Pointer to the device structure for the driver instance. + */ +static int pinctrl_tmpl_init(struct device *dev) +{ + const struct pinctrl_tmpl_config *config = + pinctrl_tmpl_device_config_info(dev); + int err; + + err = config->device_init(dev); + if (err) { + return err; + } +#if CONFIG_PINCTRL_RUNTIME_DTS + err = pinctrl_tmpl_mux_request_init(dev); + if (err) { + return err; + } + for (pinctrl_tmpl_state_id_t state = 0; + (state < config->pinctrl_state_count) && !err; + state++) { + const char *state_name = + config->state_name_data + [config->pinctrl_state_data[state].name] + .name; + + if (strcmp(state_name, "default") == 0) { + err = pinctrl_tmpl_state_set(dev, state); + } + } +#else + /* all pinctrl data belongs to the "default" state */ + err = pinctrl_tmpl_state_set(dev, 0); +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + return err; +} + +static const struct pinctrl_driver_api pinctrl_tmpl_driver_api = { + .control = { + .get_pins_count = pinctrl_tmpl_control_get_pins_count, + .get_gpio_range = pinctrl_tmpl_control_get_gpio_range, +#if CONFIG_PINCTRL_RUNTIME_DTS + .get_groups_count = pinctrl_tmpl_control_get_groups_count, + .get_group_pins = pinctrl_tmpl_control_get_group_pins, + .get_states_count = pinctrl_tmpl_control_get_states_count, + .get_state_group = pinctrl_tmpl_control_get_state_group, + .get_functions_count = + pinctrl_tmpl_control_get_functions_count, + .get_function_group = + pinctrl_tmpl_control_get_function_group, + .get_function_groups = + pinctrl_tmpl_control_get_function_groups, + .get_function_state = + pinctrl_tmpl_control_get_function_state, + .get_function_states = + pinctrl_tmpl_control_get_function_states, + .get_device_function = + pinctrl_tmpl_control_get_device_function, +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + }, + .config = { + /** + * @code{.codegen} + * codegen.outl('.get = {},'.format(config_get)) + * codegen.outl('.set = {},'.format(config_set)) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ +#if CONFIG_PINCTRL_RUNTIME_DTS + .group_get = pinctrl_tmpl_config_group_get, + .group_set = pinctrl_tmpl_config_group_set, +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + }, + .mux = { + /** + * @code{.codegen} + * codegen.outl('.get = {},'.format(mux_get)) + * @endcode{.codegen} + */ + /** @code{.codeins}@endcode */ + .set = pinctrl_tmpl_mux_set, +#if CONFIG_PINCTRL_RUNTIME_DTS + .group_set = pinctrl_tmpl_mux_group_set, + .request = pinctrl_tmpl_mux_request, + .free = pinctrl_tmpl_mux_free, +#endif /* CONFIG_PINCTRL_RUNTIME_DTS */ + }, + .state = { + .set = pinctrl_tmpl_state_set, + }, +}; + +/** + * @code{.codegen} + * + * codegen.import_module('devicedeclare') + * + * _device_init = 'pinctrl_tmpl_init' + * _device_level = 'PRE_KERNEL_1' + * _device_prio = codegen.config_property('PINCTRL_INIT_PRIORITY', 2) + * _device_api = 'pinctrl_tmpl_driver_api' + * + * for _pin_controller in _pin_controllers: + * _device_id = _pin_controller.device_id() + * _driver_name = codegen.edts().device_property(_device_id, 'label') + * _device_config = "CONFIG_{}".format(_driver_name.strip('"')) + * _device_info = "" + * + * _pin_count = _pin_controller.pin_count() + * _mux_pinmap = '${device-name}_mux_pinmap' + * _device_function_data = '${device-name}_function' + * _device_function_count = _pin_controller.function_count() + * _state_name_data = '${device-name}_state_name' + * _state_name_count = _pin_controller.state_name_count() + * _pinctrl_state_data = '${device-name}_pinctrl_state' + * _pinctrl_state_count = _pin_controller.state_count() + * _pinctrl_data = '${device-name}_pinctrl' + * _pinctrl_count = _pin_controller.pinctrl_count() + * _gpio_range_data = '${device-name}_gpio_range' + * _gpio_range_count = _pin_controller.gpio_range_count() + * _config_info = '${device-name}_config' + * _data = '${device-name}_data' + * + * if codegen.config_property('CONFIG_PINCTRL_RUNTIME_DTS', 0): + * # + * # mux_pinmap data + * _device_info += 'static u8_t {}[{}];\n' \ + * .format(_mux_pinmap, (_pin_count + 1) >> 1) + * # + * # function data + * _device_info += \ + * 'static const struct pinctrl_tmpl_device_function {}[{}] = {{\n'\ + * .format(_device_function_data, _device_function_count) + * for function in _pin_controller.function_data(): + * _device_info += '\t{{\n\t\t.name = "{}",\n\t}},\n' \ + * .format(function) + * _device_info += "};\n" + * # + * # state name data + * _device_info += \ + * 'static const struct pinctrl_tmpl_state_name {}[{}] = {{\n' \ + * .format(_state_name_data, _state_name_count) + * for state_name in _pin_controller.state_name_data(): + * _device_info += '\t{{\n\t\t.name = "{}",\n\t}},\n' \ + * .format(state_name) + * _device_info += "};\n" + * # + * # pinctrl state data + * _device_info += \ + * 'static const struct pinctrl_tmpl_pinctrl_state {}[{}] = {{\n' \ + * .format(_pinctrl_state_data, _pinctrl_state_count) + * for pinctrl_state in _pin_controller.state_data(): + * _device_info += \ + * '\t{\n' + \ + * '\t\t.device_function = {},\n' \ + * .format(pinctrl_state['function-id']) + \ + * '\t\t.name = {},\n' \ + * .format(pinctrl_state['state-name-id']) + \ + * '\t},\n' + * _device_info += "};\n" + * # + * # pinctrl data + * # only "default" state data if no CONFIG_PINCTRL_RUNTIME_DTS + * if codegen.config_property('CONFIG_PINCTRL_RUNTIME_DTS', 0) == 0: + * _pinctrl_state_name = 'default' + * else: + * _pinctrl_state_name = None + * _pinctrl_data_list = _pin_controller.pinctrl_data(_pinctrl_state_name) + * _pinctrl_data_count = len(_pinctrl_data_list) + * _device_info += \ + * 'static const struct pinctrl_tmpl_pinctrl {}[{}] = {{ \n' \ + * .format(_pinctrl_data, _pinctrl_data_count) + * for pinctrl_id, pinctrl in enumerate(_pinctrl_data_list): + * _pin = pinctrl['pin'] + * _mux = pinctrl['mux'] + * _state_id = pinctrl['state-id'] + * _device_info += ('\t{{ /' '* {}: {} {} *' '/\n') \ + * .format(pinctrl_id, + * _pin_controller.state_desc(_state_id), + * pinctrl['name']) + * _device_info += '\t.pin = {},\n'.format(_pin) + * _device_info += '\t.mux = {},\n'.format(_mux) + * if codegen.config_property('CONFIG_PINCTRL_RUNTIME_DTS', 0): + * _device_info += '\t.state = {},\n'.format(_state_id) + * _device_info += '\t.config = \\\n' + * _config = [] + * for config_x in ('bias-disable', 'bias-high-impedance', + * 'bias-bus-hold', 'bias-pull-up', 'bias-pull-down', + * 'bias-pull-pin-default', 'drive-push-pull', + * 'drive-open_drain', 'drive-open-source', + * 'input-enable', 'input-disable', + * 'input-schmitt-enable', 'input-schmitt-disable', + * 'low-power-enable', 'low-power-disable', + * 'output-enable', 'output-disable', + * 'output-low', 'output-high'): + * _config.append('({} * PINCTRL_CONFIG_{})'.format( \ + * pinctrl['config'].get(config_x, 0), + * config_x.replace('-', '_').upper())) + * _config.append('({} & PINCTRL_CONFIG_DRIVE_STRENGTH_7)'.format( \ + * pinctrl['config'].get('drive-strength', 0))) + * _config.append('({} & PINCTRL_CONFIG_POWER_SOURCE_3)'.format( \ + * pinctrl['config'].get('power-source', 0))) + * _config.append('({} & PINCTRL_CONFIG_SLEW_RATE_FAST)'.format( \ + * pinctrl['config'].get('slew-rate', 0))) + * _config.append('({} & PINCTRL_CONFIG_SPEED_HIGH)'.format( \ + * pinctrl['config'].get('speed', 0))) + * for config_x in _config: + * _device_info += '\t\t{} |\\\n'.format(config_x) + * _device_info += '\t\t0,\n' + * _device_info += '\t},\n' + * _device_info += '};\n' + * # + * # gpio range data + * _device_info += \ + * 'static const struct pinctrl_tmpl_gpio_range {}[{}] = {{\n' \ + * .format(_gpio_range_data, _gpio_range_count) + * for gpio_range in _pin_controller.gpio_range_data(): + * _device_info += '\t{\n' + * _device_info += '\t.gpio_base_idx = {},\n'.format( \ + * gpio_range['gpio-base-idx']) + * _device_info += '\t.npins = {},\n'.format(gpio_range['npins']) + * _device_info += '\t.base = {},\n'.format(gpio_range['base']) + * _device_info += '\t.name = "{}",\n'.format(gpio_range['name']) + * _device_info += '\t},\n' + * _device_info += '};\n' + * # + * # config info + * _device_info += 'static const struct pinctrl_tmpl_config {} = {{\n' \ + * .format(_config_info) + * _device_info += '\t.pin_count = {},\n'.format(_pin_count) + * if codegen.config_property('CONFIG_PINCTRL_RUNTIME_DTS', 0): + * _device_info += '\t.device_function_count = {},\n' \ + * .format(_device_function_count) + * _device_info += '\t.device_function_data = {},\n' \ + * .format(_device_function_data) + * _device_info += '\t.state_name_count = {},\n' \ + * .format(_state_name_count) + * _device_info += '\t.state_name_data = {},\n' \ + * .format(_state_name_data) + * _device_info += '\t.pinctrl_state_count = {},\n' \ + * .format(_pinctrl_state_count) + * _device_info += '\t.pinctrl_state_data = {},\n' \ + * .format(_pinctrl_state_data) + * _device_info += '\t.mux_pinmap = {},\n' \ + * .format(_mux_pinmap) + * _device_info += '\t.pinctrl_count = {},\n'.format(_pinctrl_count) + * _device_info += '\t.pinctrl_data = {},\n'.format(_pinctrl_data) + * _device_info += '\t.gpio_range_count = {},\n'.format(_gpio_range_count) + * _device_info += '\t.gpio_range_data = {},\n'.format(_gpio_range_data) + * _device_info += '\t.device_init = {},\n'.format(device_init) + * _device_info += '\t.mux_set = {},\n'.format(mux_set) + * _device_info += '};\n' + * # + * # data + * _device_info += 'static {} {};\n'.format(data_info ,_data) + * # + * devicedeclare.device_declare_single(_device_config, + * _driver_name, + * _device_init, + * _device_level, + * _device_prio, + * _device_api, + * _device_info) + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +/** @} pinctrl_template */ diff --git a/scripts/codegen/whiteutils.py b/scripts/codegen/whiteutils.py new file mode 100644 index 00000000000000..2a128e4ab88f79 --- /dev/null +++ b/scripts/codegen/whiteutils.py @@ -0,0 +1,72 @@ +# Copyright 2004-2016, Ned Batchelder. +# http://nedbatchelder.com/code/cog +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: MIT + +import re + +def b(s): + return s.encode("latin-1") + +def whitePrefix(strings): + """ Determine the whitespace prefix common to all non-blank lines + in the argument list. + """ + # Remove all blank lines from the list + strings = [s for s in strings if s.strip() != ''] + + if not strings: return '' + + # Find initial whitespace chunk in the first line. + # This is the best prefix we can hope for. + pat = r'\s*' + if isinstance(strings[0], (bytes, )): + pat = pat.encode("utf8") + prefix = re.match(pat, strings[0]).group(0) + + # Loop over the other strings, keeping only as much of + # the prefix as matches each string. + for s in strings: + for i in range(len(prefix)): + if prefix[i] != s[i]: + prefix = prefix[:i] + break + return prefix + +def reindentBlock(lines, newIndent=''): + """ Take a block of text as a string or list of lines. + Remove any common whitespace indentation. + Re-indent using newIndent, and return it as a single string. + """ + sep, nothing = '\n', '' + if isinstance(lines, (bytes, )): + sep, nothing = b('\n'), b('') + if isinstance(lines, (str, bytes)): + lines = lines.split(sep) + oldIndent = whitePrefix(lines) + outLines = [] + for l in lines: + if oldIndent: + l = l.replace(oldIndent, nothing, 1) + if l and newIndent: + l = newIndent + l + outLines.append(l) + return sep.join(outLines) + +def commonPrefix(strings): + """ Find the longest string that is a prefix of all the strings. + """ + if not strings: + return '' + prefix = strings[0] + for s in strings: + if len(s) < len(prefix): + prefix = prefix[:len(s)] + if not prefix: + return '' + for i in range(len(prefix)): + if prefix[i] != s[i]: + prefix = prefix[:i] + break + return prefix diff --git a/scripts/codegen/zephyr.py b/scripts/codegen/zephyr.py new file mode 100644 index 00000000000000..3366b2643ba870 --- /dev/null +++ b/scripts/codegen/zephyr.py @@ -0,0 +1,12 @@ +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +from pathlib import Path + +class ZephyrMixin(object): + __slots__ = [] + + @staticmethod + def zephyr_path(): + return Path(__file__).resolve().parents[2] diff --git a/scripts/dts/edtsdatabase.py b/scripts/dts/edtsdatabase.py new file mode 100644 index 00000000000000..baab6a63fd6d0e --- /dev/null +++ b/scripts/dts/edtsdatabase.py @@ -0,0 +1,257 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from collections.abc import Mapping +import json + +## +# @brief ETDS Database consumer +# +# Methods for ETDS database usage. +# +class EDTSConsumerMixin(object): + __slots__ = [] + + ## + # @brief Get all activated compatible devices. + # + # @param compatibles compatible(s) + # @return list of devices that are compatible + def devices_by_compatible(self, compatibles): + devices = dict() + if not isinstance(compatibles, list): + compatibles = [compatibles, ] + for compatible in compatibles: + for device_id in self._edts['compatibles'].get(compatible, []): + devices[device_id] = self._edts['devices'][device_id] + return list(devices.values()) + + ## + # @brief Get device ids of all activated compatible devices. + # + # @param compatibles compatible(s) + # @return list of device ids of activated devices that are compatible + def device_ids_by_compatible(self, compatibles): + device_ids = dict() + if not isinstance(compatibles, list): + compatibles = [compatibles, ] + for compatible in compatibles: + for device_id in self._edts['compatibles'].get(compatible, []): + device_ids[device_id] = 1 + return list(device_ids.keys()) + + + ## + # @brief Get device ids of all activated devices of given device type. + # + # @return list of device ids + def device_ids_by_type(self, device_type): + return self._edts['device-types'].get(device_type, []) + + ## + # @brief Get device id of activated device with given label. + # + # @return device id + def device_id_by_label(self, label): + for device_id, device in self._edts['devices'].items(): + if label == device.get('label', None): + return device_id + return None + + ## + # @brief Get device tree property value for the device of the given device id. + # + # @param device_id + # @param property_path Path of the property to access + # (e.g. 'reg/0', 'interrupts/prio', 'device_id', ...) + # @return property value + # + def device_property(self, device_id, property_path, default=""): + property_value = self._edts['devices'].get(device_id, None) + property_path_elems = property_path.strip("'").split('/') + for elem_index, key in enumerate(property_path_elems): + if isinstance(property_value, dict): + property_value = property_value.get(key, None) + elif isinstance(property_value, list): + if int(key) < len(property_value): + property_value = property_value[int(key)] + else: + property_value = None + else: + property_value = None + if property_value is None: + if default == "": + default = "Device tree property {} not available in {}" \ + .format(property_path, device_id) + return default + return property_value + + def _device_properties_flattened(self, properties, path, flattened, path_prefix): + if isinstance(properties, dict): + for prop_name in properties: + super_path = "{}/{}".format(path, prop_name).strip('/') + self._device_properties_flattened(properties[prop_name], + super_path, flattened, + path_prefix) + elif isinstance(properties, list): + for i, prop in enumerate(properties): + super_path = "{}/{}".format(path, i).strip('/') + self._device_properties_flattened(prop, super_path, flattened, + path_prefix) + else: + flattened[path_prefix + path] = properties + + ## + # @brief Get the device tree properties for the device of the given device id. + # + # @param device_id + # @param path_prefix + # @return dictionary of proerty_path and property_value + def device_properties_flattened(self, device_id, path_prefix = ""): + flattened = dict() + self._device_properties_flattened(self._edts['devices'][device_id], + '', flattened, path_prefix) + return flattened + + def load(self, file_path): + with open(file_path, "r") as load_file: + self._edts = json.load(load_file) + +## +# @brief ETDS Database provider +# +# Methods for ETDS database creation. +# +class EDTSProviderMixin(object): + __slots__ = [] + + def _update_device_compatible(self, device_id, compatible): + if compatible not in self._edts['compatibles']: + self._edts['compatibles'][compatible] = list() + if device_id not in self._edts['compatibles'][compatible]: + self._edts['compatibles'][compatible].append(device_id) + self._edts['compatibles'][compatible].sort() + + def _update_device_type(self, device_id, device_type): + if device_type not in self._edts['device-types']: + self._edts['device-types'][device_type] = list() + if device_id not in self._edts['device-types'][device_type]: + self._edts['device-types'][device_type].append(device_id) + self._edts['device-types'][device_type].sort() + + ## + # @brief Insert property value for the device of the given device id. + # + # @param device_id + # @param property_path Path of the property to access + # (e.g. 'reg/0', 'interrupts/prio', 'label', ...) + # @param property_value value + # + def insert_device_property(self, device_id, property_path, property_value): + # special properties + if property_path.startswith('compatible'): + self._update_device_compatible(device_id, property_value) + elif property_path == 'device-type': + self._update_device_type(device_id, property_value) + + # normal property management + if device_id not in self._edts['devices']: + self._edts['devices'][device_id] = dict() + self._edts['devices'][device_id]['device-id'] = device_id + if property_path == 'device-id': + # already set + return + keys = property_path.strip("'").split('/') + property_access_point = self._edts['devices'][device_id] + for i in range(0, len(keys)): + if i < len(keys) - 1: + # there are remaining keys + if keys[i] not in property_access_point: + property_access_point[keys[i]] = dict() + property_access_point = property_access_point[keys[i]] + else: + # we have to set the property value + if keys[i] in property_access_point: + # There is already a value set + current_value = property_access_point[keys[i]] + if not isinstance(current_value, list): + current_value = [current_value, ] + if isinstance(property_value, list): + property_value = current_value.extend(property_value) + else: + property_value = current_value.append(property_value) + property_access_point[keys[i]] = property_value + + + def save(self, file_path): + with open(file_path, "w") as save_file: + json.dump(self._edts, save_file, indent = 4) + +## +# @brief Extended DTS database +# +# Database schema: +# +# _edts dict( +# 'devices': dict(device-id : device-struct), +# 'compatibles': dict(compatible : sorted list(device-id)), +# 'device-types': dict(device-type : sorted list(device-id)), +# ... +# ) +# +# device-struct dict( +# 'device-id' : device-id, +# 'device-type' : list(device-type) or device-type, +# 'compatible' : list(compatible) or compatible, +# 'label' : label, +# property-name : property-value ... +# ) +# +# Database types: +# +# device-id: opaque id for a device (do not use for other purposes), +# compatible: any of ['st,stm32-spi-fifo', ...] - 'compatibe' from .yaml +# device-type: any of ['GPIO', 'SPI', 'CAN', ...] - 'id' from .yaml +# label: any of ['UART_0', 'SPI_11', ...] - label directive from DTS +# +class EDTSDatabase(EDTSConsumerMixin, EDTSProviderMixin, Mapping): + + ## + # @brief Boolean type properties for pin configuration by pinctrl. + pinconf_bool_props = [ + "bias-disable", "bias-high-impedance", "bias-bus-hold", + "drive-push-pull", "drive-open-drain", "drive-open-source", + "input-enable", "input-disable", "input-schmitt-enable", + "input-schmitt-disable", "low-power-enable", "low-power-disable", + "output-disable", "output-enable", "output-low","output-high"] + ## + # @brief Boolean or value type properties for pin configuration by pinctrl. + pinconf_bool_or_value_props = [ + "bias-pull-up", "bias-pull-down", "bias-pull-pin-default"] + ## + # @brief List type properties for pin configuration by pinctrl. + pinconf_list_props = [ + "pinmux", "pins", "group", "drive-strength", "input-debounce", + "power-source", "slew-rate", "speed"] + + def __init__(self, *args, **kw): + self._edts = dict(*args, **kw) + # setup basic database schema + for edts_key in ('devices', 'compatibles', 'device-types'): + if not edts_key in self._edts: + self._edts[edts_key] = dict() + + def __getitem__(self, key): + return self._edts[key] + + def __iter__(self): + return iter(self._edts) + + def __len__(self): + return len(self._edts) + + + diff --git a/scripts/dts/extract/clocks.py b/scripts/dts/extract/clocks.py index 72ed9e21768e36..b125679d19df52 100644 --- a/scripts/dts/extract/clocks.py +++ b/scripts/dts/extract/clocks.py @@ -5,30 +5,168 @@ # from extract.globals import * +from extract.edts import * from extract.directive import DTDirective +from extract.default import default ## # @brief Manage clocks related directives. # # Handles: # - clocks -# directives. +# - clock-names +# - clock-output-names +# - clock-indices +# - clock-ranges +# - clock-frequency +# - clock-accuracy +# - oscillator +# - assigned-clocks +# - assigned-clock-parents +# - assigned-clock-rates +# +# Generates in EDTS: +# +# Clock provider +# -------------- +# - clock-output//name : clock output name +# - clock-output//clock-frequency : fixed clock output frequency in Hz +# - clock-output//clock-accuracy : accuracy of clock in ppb (parts per billion). +# - clock-output//oscillator : True +# +# Clock consumer +# -------------- +# - clocks//name : name of clock input +# - clocks//provider : device id of clock provider +# - clocks//clock-ranges : True +# - clocks// : +# (cell-name from cell-names of provider) +# - assigned-clocks//provider : device id of provider of assigned clock +# - assigned-clocks//rate : selected rate of assigned clock in Hz +# - assigned-clocks// : +# (cell-name from cell-names of provider) +# - assigned-clocks//parent/provider : provider of parent clock of assigned clock +# - assigned-clocks//parent/ : +# (cell-name from cell-names of provider) # class DTClocks(DTDirective): def __init__(self): - pass + ## + # Dictionary of all clocks + # primary key is the top node + # secondary key is is the clock name, + # value is the clock id + self._clocks = {} + + ## + # @brief Get output clock names of clock provider + # + def _clock_output_names(self, clock_provider): + names = clock_provider['props'].get('clock-output-names', []) + if len(names) == 0: + names = [clock_provider['props'].get('label', '')] + elif not isinstance(names, list): + names = [names] + return names + + ## + # @brief Get clock id of output clock of clock provider + # + # @param clock_provider + # @param clock_output_name + # @return clock id + # + def _clock_output_id(self, clock_provider, clock_output_name): + clock_output_names = self._clock_output_names(clock_provider) + clock_indices = clock_provider['props'].get('clock-indices', None) + if clock_indices: + if len(clock_output_names) != len(clock_indices): + raise Exception( + ("clock-output-names count ({}) does not match" + " clock-indices count ({}) in clock provider {}.") + .format(len(clock_output_names), len(clock_indices), + str(clock_provider['name']))) + for i, name in enumerate(clock_output_names): + if name == clock_output_name: + if clock_indices: + return clock_indices[i] + return i + return None + + ## + # @brief Get clock name of output clock of clock provider + # + # @param clock_provider + # @param clock_output_name + # @return clock id + # + def _clock_output_name(self, clock_provider, clock_output_id): + clock_output_names = self._clock_output_names(clock_provider) + clock_indices = clock_provider['props'].get('clock-indices', None) + if clock_indices: + for i, clock_id in enumerate(clock_indices): + if clock_id == clock_output_id: + clock_output_id = i + break + return clock_output_names[clock_output_id] + + ## + # @brief Get clock name of input clock of clock consumer + # + def _clock_input_name(self, clock_consumer, clock_input_index): + clock_names = clock_consumer['props'].get('clock-names', None) + if clock_names is None: + return "clk{}".format(clock_input_index) + if not isinstance(clock_names, list): + clock_names = [clock_names] + if len(clock_names) <= clock_input_index: + return "clk{}".format(clock_input_index) + return clock_names[clock_input_index] + + ## + # @brief Insert clock cells into EDTS + # + # @param clock_consumer + # @param yaml + # @param clock_provider + # @param clock_cells + # @param property_path_templ "xxx/yyy/{}" + # + def _edts_insert_clock_cells(self, clock_consumer_node_address, yaml, + clock_provider_node_address, clock_cells, + property_path_templ): + if len(clock_cells) == 0: + return + clock_consumer_device_id = edts_device_id(clock_consumer_node_address) + clock_provider_device_id = edts_device_id(clock_provider_node_address) + clock_provider = reduced[clock_provider_node_address] + clock_provider_compat = get_compat(clock_provider_node_address) + clock_provider_bindings = yaml[clock_provider_compat] + clock_nr_cells = int(clock_provider['props'].get('#clock-cells', 0)) + clock_cells_names = clock_provider_bindings.get( + '#cells', ['ID', 'CELL1', "CELL2", "CELL3"]) + for i, cell in enumerate(clock_cells): + if i >= len(clock_cells_names): + clock_cell_name = 'CELL{}'.format(i).lower() + else: + clock_cell_name = clock_cells_names[i].lower() + edts_insert_device_property(clock_consumer_device_id, + property_path_templ.format(clock_cell_name), cell) + def _extract_consumer(self, node_address, yaml, clocks, names, def_label): + clock_consumer_device_id = edts_device_id(node_address) clock_consumer = reduced[node_address] clock_consumer_compat = get_compat(node_address) clock_consumer_bindings = yaml[clock_consumer_compat] clock_consumer_label = self.get_node_label_string(node_address) + clock_consumer_clock_names = clock_consumer['props'].get('clock-names', None) clock_index = 0 clock_cell_index = 0 - nr_clock_cells = 0 + clock_nr_cells = 0 clock_provider_node_address = '' clock_provider = {} for cell in clocks: @@ -42,27 +180,45 @@ def _extract_consumer(self, node_address, yaml, clocks, names, def_label): str(clock_provider))) clock_provider_node_address = phandles[cell] clock_provider = reduced[clock_provider_node_address] - clock_provider_compat = get_compat(clock_provider_node_address) - clock_provider_bindings = yaml[clock_provider_compat] - clock_provider_label = self.get_node_label_string( \ - clock_provider_node_address) - nr_clock_cells = int(clock_provider['props'].get( - '#clock-cells', 0)) - clock_cells_string = clock_provider_bindings.get( - 'cell_string', 'CLOCK') - clock_cells_names = clock_provider_bindings.get( - '#cells', ['ID', 'CELL1', "CELL2", "CELL3"]) + clock_nr_cells = int(clock_provider['props'].get('#clock-cells', 0)) clock_cells = [] else: clock_cells.append(cell) clock_cell_index += 1 - if clock_cell_index > nr_clock_cells: - # clock consumer device - clocks info - ##################################### + if clock_cell_index > clock_nr_cells: + + # generate EDTS + edts_insert_device_property(clock_consumer_device_id, + 'clocks/{}/name'.format(clock_index), + self._clock_input_name(clock_consumer, clock_index)) + edts_insert_device_property(clock_consumer_device_id, + 'clocks/{}/provider'.format(clock_index), + edts_device_id(clock_provider_node_address)) + for prop in ('clock-ranges',): + value = clock_consumer['props'].get(prop, None) + if value is not None: + edts_insert_device_property(clock_consumer_device_id, + 'clocks/{}/{}'.format(clock_index, prop), value) + self._edts_insert_clock_cells(node_address, yaml, + clock_provider_node_address, + clock_cells, + "clocks/{}/{{}}".format(clock_index)) + + # generate defines prop_def = {} prop_alias = {} + # legacy definitions for backwards compatibility + # @todo remove legacy definitions + # Legacy clocks definitions by extract_cells + clock_provider_compat = get_compat(clock_provider_node_address) + clock_provider_bindings = yaml[clock_provider_compat] + clock_cells_string = clock_provider_bindings.get( + 'cell_string', 'CLOCK') + clock_cells_names = clock_provider_bindings.get( + '#cells', ['ID', 'CELL1', "CELL2", "CELL3"]) + for i, cell in enumerate(clock_cells): if i >= len(clock_cells_names): clock_cell_name = 'CELL{}'.format(i) @@ -78,13 +234,13 @@ def _extract_consumer(self, node_address, yaml, clocks, names, def_label): clock_cell_name, str(clock_index)]) prop_def[clock_label] = str(cell) # alias - if i < nr_clock_cells: + if i < clock_nr_cells: # clocks info for first clock clock_alias_label = self.get_label_string([ clock_consumer_label, clock_cells_string, clock_cell_name]) prop_alias[clock_alias_label] = clock_label - # Legacy clocks definitions by extract_controller + # ----- legacy clocks definitions clock_provider_label_str = clock_provider['props'].get('label', None) if clock_provider_label_str is not None: @@ -113,10 +269,91 @@ def _extract_consumer(self, node_address, yaml, clocks, names, def_label): prop_alias[clock_alias_label] = clock_label insert_defs(node_address, prop_def, prop_alias) + # ------ legacy end clock_cell_index = 0 clock_index += 1 + def _extract_assigned(self, node_address, yaml, clocks, names, def_label): + + clock_consumer = reduced[node_address] + clocks = clock_consumer['props'].get('assigned-clocks', None) + clock_parents = clock_consumer['props'].get('assigned-clock-parents', None) + clock_rates = clock_consumer['props'].get('assigned-clock-rates', None) + + # generate EDTS + clock_consumer_device_id = edts_device_id(node_address) + clock_index = 0 + clock_parents_index = 0 + clock_cell_index = 0 + clock_nr_cells = 1 # [phandle, clock specifier] -> 1 specifier + clock_provider_node_address = '' + clock_provider = {} + for cell in clocks: + if clock_cell_index == 0: + if cell not in phandles: + raise Exception( + ("Could not find the clock provider node {} for assigned-clocks" + " = {} in clock consumer node {}. Did you activate" + " the clock node?. Last clock provider: {}.") + .format(str(cell), str(clocks), node_address, + str(clock_provider))) + clock_provider_node_address = phandles[cell] + clock_provider = reduced[clock_provider_node_address] + clock_nr_cells = int(clock_provider['props'].get('#clock-cells', clock_nr_cells)) + clock_cells = [] + else: + clock_cells.append(cell) + clock_cell_index += 1 + if clock_cell_index > clock_nr_cells: + # - assigned clock provider + edts_insert_device_property(clock_consumer_device_id, + 'assigned-clock/{}/provider'.format(clock_index), + edts_device_id(clock_provider_node_address)) + # - assigned clock provider output index + self._edts_insert_clock_cells(node_address, yaml, + clock_provider_node_address, clock_cells, + 'assigned-clock/{}/\{\}'.format(clock_index)) + # - assigned clock rate + if len(clock_rates) > clock_index: + edts_insert_device_property(clock_consumer_device_id, + 'assigned-clock/{}/rate'.format(clock_index), + clock_rates[clock_index]) + # - assigned clock parent + if len(clock_parents) > clock_parents_index + 1: + clock_parent_node_address = phandles[clock_parents[clock_parents_index]] + clock_parent = reduced[clock_parent_node_address] + clock_parent_nr_cells = int(clock_parent['props'].get('#clock-cells', 0)) + clock_parent_cells = clock_parents[ + clock_parents_index + 1 : + clock_parents_index + 1 + clock_parent_nr_cells] + edts_insert_device_property(clock_consumer_device_id, + 'assigned-clock/{}/parent/provider'.format(clock_index), + edts_device_id(clock_parent_node_address)) + self._edts_insert_clock_cells(node_address, yaml, + clock_parent_node_address, clock_parent_cells, + 'assigned-clock/{}/parent/\{\}'.format(clock_index)) + clock_parents_index += clock_parent_nr_cells + 1 + + clock_cell_index = 0 + clock_index += 1 + + def _extract_provider(self, node_address, yaml, prop_list, names, def_label): + + clock_provider = reduced[node_address] + + # generate EDTS + clock_provider_device_id = edts_device_id(node_address) + for output_name in self._clock_output_names(clock_provider): + output_id = self._clock_output_id(clock_provider, output_name) + edts_insert_device_property(clock_provider_device_id, + 'output-clock/{}/name'.format(output_id), output_name) + for prop in ('clock-frequency', 'clock-accuracy', 'oscillator'): + value = clock_provider['props'].get(prop, None) + if value is not None: + edts_insert_device_property(clock_provider_device_id, + 'output-clock/{}/{}'.format(output_id, prop), value) + ## # @brief Extract clocks related directives # @@ -139,6 +376,24 @@ def extract(self, node_address, yaml, prop, names, def_label): if prop == 'clocks': # indicator for clock consumers self._extract_consumer(node_address, yaml, prop_list, names, def_label) + elif prop in ('clock-names', 'clock-ranges'): + # covered by _extract_consumer + pass + elif prop == '#clock-cells': + # indicator for clock providers + self._extract_provider(node_address, yaml, prop_list, names, def_label) + elif prop in ('clock-output-names', 'clock-indices', 'clock-frequency', + 'clock-accuracy', 'oscillator'): + # covered by _extract_provider + # legacy definitions for backwards compatibility + if prop in ('clock-frequency',): + default.extract(node_address, yaml, prop, names, def_label) + elif prop in 'assigned-clocks': + # indicator for assigned clocks + self._extract_assigned(node_address, yaml, prop_list, names, def_label) + elif prop in ('assigned-clock-parents', 'assigned-clock-rates'): + # covered by _extract_assigned + pass else: raise Exception( "DTClocks.extract called with unexpected directive ({})." diff --git a/scripts/dts/extract/compatible.py b/scripts/dts/extract/compatible.py new file mode 100644 index 00000000000000..7bfb3bbe70134a --- /dev/null +++ b/scripts/dts/extract/compatible.py @@ -0,0 +1,50 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from extract.globals import * +from extract.edts import * +from extract.directive import DTDirective + +## +# @brief Manage compatible directives. +# +# Handles: +# - compatible +# +# Generates in EDTS: +# - compatible/ : compatible +class DTCompatible(DTDirective): + + def __init__(self): + pass + + ## + # @brief Extract compatible + # + # @param node_address Address of node owning the + # compatible definition. + # @param yaml YAML definition for the owning node. + # @param prop compatible property name + # @param names (unused) + # @param def_label Define label string of node owning the + # compatible definition. + # + def extract(self, node_address, yaml, prop, names, def_label): + + # compatible definition + compatible = reduced[node_address]['props'][prop] + if not isinstance(compatible, list): + compatible = [compatible, ] + + # generate EDTS + device_id = edts_device_id(node_address) + for i, comp in enumerate(compatible): + edts_insert_device_property(device_id, 'compatible/{}'.format(i), + comp) + +## +# @brief Management information for compatible. +compatible = DTCompatible() diff --git a/scripts/dts/extract/controller.py b/scripts/dts/extract/controller.py new file mode 100644 index 00000000000000..03e5f0654fad1b --- /dev/null +++ b/scripts/dts/extract/controller.py @@ -0,0 +1,43 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from extract.globals import * +from extract.edts import * +from extract.directive import DTDirective + +## +# @brief Manage -controller directives. +# +# Handles: +# - -controller +# +# Generates in EDTS: +# - -controller : True +class DTController(DTDirective): + + def __init__(self): + pass + + ## + # @brief Extract -controller + # + # @param node_address Address of node owning the + # -controller definition. + # @param yaml YAML definition for the owning node. + # @param prop -controller property name + # @param names (unused) + # @param def_label Define label string of node owning the + # -controller definition. + # + def extract(self, node_address, yaml, prop, names, def_label): + + # generate EDTS + device_id = edts_device_id(node_address) + edts_insert_device_property(device_id, prop, True) + +## +# @brief Management information for [device]-controller. +controller = DTController() diff --git a/scripts/dts/extract/default.py b/scripts/dts/extract/default.py index f66c0dd496a413..1319d2a3883107 100644 --- a/scripts/dts/extract/default.py +++ b/scripts/dts/extract/default.py @@ -5,6 +5,7 @@ # from extract.globals import * +from extract.edts import * from extract.directive import DTDirective ## @@ -18,17 +19,21 @@ def __init__(self): ## # @brief Extract directives in a default way # - # @param node_address Address of node owning the clockxxx definition. + # @param node_address Address of node owning the directive definition. # @param yaml YAML definition for the owning node. # @param prop property name # @param names (unused) # @param def_label Define label string of node owning the directive. # def extract(self, node_address, yaml, prop, names, def_label): - prop_def = {} - prop_alias = {} prop_values = reduced[node_address]['props'][prop] + # generate EDTS + edts_insert_device_property(node_address, prop, prop_values) + + # generate defines + prop_def = {} + prop_alias = {} if isinstance(prop_values, list): for i, prop_value in enumerate(prop_values): prop_name = convert_string_to_label(prop) diff --git a/scripts/dts/extract/edts.py b/scripts/dts/extract/edts.py new file mode 100644 index 00000000000000..02268c869af65d --- /dev/null +++ b/scripts/dts/extract/edts.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from .globals import * +import edtsdatabase + +edts = edtsdatabase.EDTSDatabase() + +## +# @brief Get EDTS device id associated to node address. +# +# @return ETDS device id +def edts_device_id(node_address): + return node_address + +## +# @brief Insert device property into EDTS +# +def edts_insert_device_property(node_address, property_path, property_value): + device_id = edts_device_id(node_address) + edts.insert_device_property(device_id, property_path, property_value) + +## +# @brief Insert device parent-device property into EDTS +# +def edts_insert_device_parent_device_property(node_address): + # Check for a parent device this device is subordinated + parent_device_id = None + parent_node_address = '' + for comp in node_address.split('/')[1:-1]: + parent_node_address += '/' + comp + compatibles = reduced[parent_node_address]['props'] \ + .get('compatible', None) + if compatibles: + # there is a parent device, + # only use the ones that have a minimum control on the child + if 'simple-bus' not in compatibles: + parent_device_id = edts_device_id(parent_node_address) + if parent_device_id: + edts_insert_device_property(edts_device_id(node_address), + 'parent-device', parent_device_id) diff --git a/scripts/dts/extract/flash.py b/scripts/dts/extract/flash.py index 312e79842ec323..54ab4908c94dfe 100644 --- a/scripts/dts/extract/flash.py +++ b/scripts/dts/extract/flash.py @@ -6,6 +6,7 @@ from extract.globals import * from extract.directive import DTDirective +from extract.edts import * from extract.default import default from extract.reg import reg @@ -20,13 +21,43 @@ def __init__(self): self._flash_node = None def _extract_partition(self, node_address, yaml, prop, names, def_label): - prop_def = {} - prop_alias = {} node = reduced[node_address] - partition_name = node['props']['label'] partition_sectors = node['props']['reg'] + nr_address_cells = reduced['/']['props'].get('#address-cells') + nr_size_cells = reduced['/']['props'].get('#size-cells') + address = '' + for comp in node_address.split('/')[1:-1]: + address += '/' + comp + nr_address_cells = reduced[address]['props'].get( + '#address-cells', nr_address_cells) + nr_size_cells = reduced[address]['props'].get('#size-cells', nr_size_cells) + + # generate EDTS + sector_index = 0 + sector_cell_index = 0 + sector_nr_cells = nr_address_cells + nr_size_cells + for cell in partition_sectors: + if sector_cell_index < nr_address_cells: + edts_insert_device_property(node_address, + 'sector/{}/offset/{}'.format(sector_index, sector_cell_index), + cell) + else: + size_cell_index = sector_cell_index - nr_address_cells + edts_insert_device_property(node_address, + 'sector/{}/size/{}'.format(sector_index, size_cell_index), + cell) + sector_cell_index += 1 + if sector_cell_index >= sector_nr_cells: + sector_cell_index = 0 + sector_index += 1 + edts_insert_device_parent_device_property(node_address) + + # generate defines + prop_def = {} + prop_alias = {} + label_prefix = ["FLASH_AREA", partition_name] label = self.get_label_string(label_prefix + ["LABEL",]) prop_def[label] = '"{}"'.format(partition_name) @@ -54,6 +85,7 @@ def _extract_partition(self, node_address, yaml, prop, names, def_label): insert_defs(node_address, prop_def, prop_alias) def _extract_flash(self, node_address, yaml, prop, names, def_label): + # generate defines load_defs = {} if node_address == 'dummy-flash': @@ -65,19 +97,24 @@ def _extract_flash(self, node_address, yaml, prop, names, def_label): } insert_defs(node_address, load_defs, {}) self._flash_base_address = 0 - return - - self._flash_node = reduced[node_address] + else: + self._flash_node = reduced[node_address] - flash_props = ["label", "write-block-size", "erase-block-size"] - for prop in flash_props: - if prop in self._flash_node['props']: - default.extract(node_address, None, prop, None, def_label) - insert_defs(node_address, load_defs, {}) + flash_props = ["label", "write-block-size", "erase-block-size"] + for prop in flash_props: + if prop in self._flash_node['props']: + default.extract(node_address, yaml, prop, None, def_label) + insert_defs(node_address, load_defs, {}) - #for address in reduced: - # if address.startswith(node_address) and 'partition@' in address: - # self._extract_partition(address, yaml, 'partition', None, def_label) + # generate EDTS + # - keep behind define generation to overwrite values + # done by default.extract() generation + device_id = edts_device_id(node_address) + if node_address == 'dummy-flash': + edts_insert_device_property(device_id, 'reg/0/address/0', "0") + edts_insert_device_property(device_id, 'reg/0/size/0', "0") + else: + pass def _extract_code_partition(self, node_address, yaml, prop, names, def_label): load_defs = {} diff --git a/scripts/dts/extract/globals.py b/scripts/dts/extract/globals.py index cf59ebcacbadcf..bb3b5c288e4fe2 100644 --- a/scripts/dts/extract/globals.py +++ b/scripts/dts/extract/globals.py @@ -1,10 +1,11 @@ # # Copyright (c) 2017 Linaro -# Copyright (c) 2017 Bobby Noelte +# Copyright (c) 2018 Bobby Noelte # # SPDX-License-Identifier: Apache-2.0 # +import sys from collections import defaultdict # globals @@ -13,7 +14,6 @@ chosen = {} reduced = {} defs = {} -structs = {} regs_config = { 'zephyr,flash' : 'CONFIG_FLASH', @@ -182,3 +182,7 @@ def find_parent_prop(node_address, prop): " has no " + prop + " property") return parent_prop + +def node_top_address(node_address): + address = node_address.split('/')[1] + return address diff --git a/scripts/dts/extract/gpioranges.py b/scripts/dts/extract/gpioranges.py new file mode 100644 index 00000000000000..3f5d8aa426bd07 --- /dev/null +++ b/scripts/dts/extract/gpioranges.py @@ -0,0 +1,88 @@ +# +# Copyright (c) 2017 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from extract.globals import * +from extract.directive import DTDirective +from extract.edts import * + +## +# @brief Manage gpio-ranges directive. +# +# Handles: +# - gpio-ranges +# +# Generates in EDTS: +# - gpio-ranges//base : base pin of gpio +# - gpio-ranges//npins : number of pins +# - gpio-ranges//pin-controller : device_id of pin controller +# - gpio-ranges//pin-controller-base : base pin of pin controller +# +class DTGpioRanges(DTDirective): + + def __init__(self): + self._data = {} + + ## + # @brief Extract GPIO ranges + # + # @param node_address Address of node owning the gpio-ranges definition. + # @param yaml YAML definition for the owning node. + # @param prop gpio-ranges property name + # @param names (unused) + # @param def_label Define label string of node owning the gio-ranges definition. + # + def extract(self, node_address, yaml, prop, names, def_label): + + # gpio-ranges definition + gpio_ranges = reduced[node_address]['props'][prop] + + gpio_range_cells = 3 + prop_list = [] + if not isinstance(gpio_ranges, list): + prop_list.append(gpio_ranges) + else: + prop_list = list(gpio_ranges) + + gpio_device_id = edts_device_id(node_address) + gpio_range_index = 0 + gpio_range_cell = 0 + gpio_pin_start = 0 + gpio_pin_count = 0 + pin_controller_node_address = '' + pin_controller_pin_start = 0 + for p in prop_list: + if gpio_range_cell == 0: + pin_controller_node_address = phandles[p] + elif gpio_range_cell == 1: + gpio_pin_start = p + elif gpio_range_cell == 2: + pin_controller_pin_start = p + elif gpio_range_cell == 3: + gpio_pin_count = p + if gpio_range_cell < gpio_range_cells: + gpio_range_cell += 1 + else: + # generate EDTS + edts_insert_device_property(gpio_device_id, + 'gpio-ranges/{}/pin-controller'.format(gpio_range_index), + edts_device_id(pin_controller_node_address)) + edts_insert_device_property(gpio_device_id, + 'gpio-ranges/{}/pin-controller-base'.format(gpio_range_index), + int(pin_controller_pin_start)) + edts_insert_device_property(gpio_device_id, + 'gpio-ranges/{}/base'.format(gpio_range_index), + int(gpio_pin_start)) + edts_insert_device_property(gpio_device_id, + 'gpio-ranges/{}/npins'.format(gpio_range_index), + int(gpio_pin_count)) + + gio_range_cell = 0 + gpio_range_index += 1 + +## +# @brief Management information for gpio-ranges. +gpioranges = DTGpioRanges() + diff --git a/scripts/dts/extract/heuristics.py b/scripts/dts/extract/heuristics.py new file mode 100644 index 00000000000000..9a65039440f9c8 --- /dev/null +++ b/scripts/dts/extract/heuristics.py @@ -0,0 +1,73 @@ +# +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 +# + +from extract.globals import * +from extract.edts import * +from extract.directive import DTDirective + +from extract.default import default + +## +# @brief Generate device tree information based on heuristics. +# +# Generates in EDTS: +# - bus/master : device id of bus master for a bus device +# - parent-device : device id of parent device +class DTHeuristics(DTDirective): + + def __init__(self): + pass + + ## + # @brief Generate device tree information based on heuristics. + # + # Device tree properties may have to be deduced by heuristics + # as the property definitions are not always consistent across + # different node types. + # + # @param node_address Address of node owning the + # compatible definition. + # @param yaml YAML definition for the owning node. + # @param prop compatible property name + # @param names (unused) + # @param def_label Define label string of node owning the + # compatible definition. + # + def extract(self, node_address, yaml, prop, names, def_label): + compatible = reduced[node_address]['props']['compatible'] + if not isinstance(compatible, list): + compatible = [compatible] + + # Check for -device that is connected to a bus + for compat in compatible: + for device_type in yaml[compat].get('node_type', []): + if not device_type.endswith('-device'): + continue + + bus_master_device_type = device_type.replace('-device', '') + + # get parent + parent_node_address = '' + for comp in node_address.split('/')[1:-1]: + parent_node_address += '/' + comp + + # get parent yaml + parent_yaml = yaml[reduced[parent_node_address] \ + ['props']['compatible']] + + if bus_master_device_type not in parent_yaml['node_type']: + continue + + # generate EDTS + edts_insert_device_property(node_address, 'bus/master', + edts_device_id(parent_node_address)) + + # Check for a parent device this device is subordinated + edts_insert_device_parent_device_property(node_address) + +## +# @brief Management information for heuristics. +heuristics = DTHeuristics() diff --git a/scripts/dts/extract/interrupts.py b/scripts/dts/extract/interrupts.py index d79cbb5e91d5e2..1f69675e314e81 100644 --- a/scripts/dts/extract/interrupts.py +++ b/scripts/dts/extract/interrupts.py @@ -6,6 +6,7 @@ from extract.globals import * from extract.directive import DTDirective +from extract.edts import * ## # @brief Manage interrupts directives. @@ -47,7 +48,35 @@ def extract(self, node_address, yaml, prop, names, def_label): props = [node['props'].get(prop)] irq_parent = self._find_parent_irq_node(node_address) - + irq_nr_cells = reduced[irq_parent]['props']['#interrupt-cells'] + irq_cell_yaml = yaml[get_compat(irq_parent)] + irq_cell_names = irq_cell_yaml.get('#cells', []) + irq_names = node['props'].get('interrupt-names', []) + if not isinstance(irq_names, list): + irq_names = [irq_names, ] + + # generate EDTS + device_id = edts_device_id(node_address) + irq_index = 0 + irq_cell_index = 0 + for cell in props: + if len(irq_names) > irq_index: + irq_name = irq_names[irq_index] + else: + irq_name = str(irq_index) + if len(irq_cell_names) > irq_cell_index: + irq_cell_name = irq_cell_names[irq_cell_index] + else: + irq_cell_name = str(irq_cell_index) + edts_insert_device_property(device_id, + 'interrupts/{}/{}'.format(irq_name, irq_cell_name), + cell) + irq_cell_index += 1 + if irq_cell_index >= irq_nr_cells: + irq_cell_index = 0 + irq_index += 1 + + # generate defines l_base = def_label.split('/') index = 0 @@ -61,11 +90,10 @@ def extract(self, node_address, yaml, prop, names, def_label): except: name = [] - cell_yaml = yaml[get_compat(irq_parent)] l_cell_prefix = ['IRQ'] - for i in range(reduced[irq_parent]['props']['#interrupt-cells']): - l_cell_name = [cell_yaml['#cells'][i].upper()] + for i in range(irq_nr_cells): + l_cell_name = [irq_cell_names[i].upper()] if l_cell_name == l_cell_prefix: l_cell_name = [] diff --git a/scripts/dts/extract/pinctrl.py b/scripts/dts/extract/pinctrl.py index 7ca63dccd8e543..693ac897116978 100644 --- a/scripts/dts/extract/pinctrl.py +++ b/scripts/dts/extract/pinctrl.py @@ -5,10 +5,23 @@ # from extract.globals import * +from extract.edts import * from extract.directive import DTDirective ## -# @brief Manage pinctrl-x directive. +# @brief Manage pinctrl related directives. +# +# Handles: +# - pinctrl-x +# - pinctrl-names +# +# Generates in EDTS: +# - pinctrl//name : name of the pinctrl +# - pinctrl//pinconf//pin-controller : device_id of +# pin controller +# - pinctrl//pinconf//bias-disable : pinconf value +# - pinctrl//pinconf//bias-high-impedance : .. +# - pinctrl//pinconf//bias-bus-hold : .. # class DTPinCtrl(DTDirective): @@ -27,45 +40,99 @@ def __init__(self): # def extract(self, node_address, yaml, prop, names, def_label): - pinconf = reduced[node_address]['props'][prop] - - prop_list = [] - if not isinstance(pinconf, list): - prop_list.append(pinconf) + # Get pinctrl index from pinctrl- directive + pinctrl_index = int(prop.split('-')[1]) + # Pinctrl definition + pinctrl = reduced[node_address]['props'][prop] + # Name of this pinctrl state. Use directive if there is no name. + if pinctrl_index >= len(names): + pinctrl_name = prop else: - prop_list = list(pinconf) - - def_prefix = def_label.split('_') + pinctrl_name = names[pinctrl_index] - prop_def = {} - for p in prop_list: - pin_node_address = phandles[p] - pin_subnode = '/'.join(pin_node_address.split('/')[-1:]) - cell_yaml = yaml[get_compat(pin_node_address)] - cell_prefix = 'PINMUX' - post_fix = [] - - if cell_prefix is not None: - post_fix.append(cell_prefix) - - for subnode in reduced.keys(): - if pin_subnode in subnode and pin_node_address != subnode: - # found a subnode underneath the pinmux handle - pin_label = def_prefix + post_fix + subnode.split('/')[-2:] + pin_config_handles = [] + if not isinstance(pinctrl, list): + pin_config_handles.append(pinctrl) + else: + pin_config_handles = list(pinctrl) - for i, cells in enumerate(reduced[subnode]['props']): - key_label = list(pin_label) + \ - [cell_yaml['#cells'][0]] + [str(i)] - func_label = key_label[:-2] + \ - [cell_yaml['#cells'][1]] + [str(i)] - key_label = convert_string_to_label('_'.join(key_label)) - func_label = convert_string_to_label('_'.join(func_label)) + # generate EDTS pinctrl + pinctrl_client_device_id = edts_device_id(node_address) + edts_insert_device_property(pinctrl_client_device_id, + 'pinctrl/{}/name'.format(pinctrl_index), pinctrl_name) - prop_def[key_label] = cells - prop_def[func_label] = \ - reduced[subnode]['props'][cells] + client_prop_def = {} + pinconf_index = 0 + for pin_config_handle in pin_config_handles: + pin_config_node_address = phandles[pin_config_handle] + pin_controller_node_address = \ + '/'.join(pin_config_node_address.split('/')[:-1]) + pin_config_subnode_prefix = \ + '/'.join(pin_config_node_address.split('/')[-1:]) + pin_controller_device_id = edts_device_id(pin_controller_node_address) + for subnode_address in reduced: + if pin_config_subnode_prefix in subnode_address \ + and pin_config_node_address != subnode_address: + # Found a subnode underneath the pin configuration node + # Create pinconf defines and EDTS + edts_insert_device_property(pinctrl_client_device_id, + 'pinctrl/{}/pinconf/{}/name' \ + .format(pinctrl_index, pinconf_index), + subnode_address.split('/')[-1]) + edts_insert_device_property(pinctrl_client_device_id, + 'pinctrl/{}/pinconf/{}/pin-controller' \ + .format(pinctrl_index, pinconf_index), + pin_controller_device_id) + pinconf_props = reduced[subnode_address]['props'].keys() + for pinconf_prop in pinconf_props: + pinconf_value = reduced[subnode_address]['props'][pinconf_prop] + if pinconf_prop in edts.pinconf_bool_props: + pinconf_value = 1 if pinconf_value else 0 + elif pinconf_prop in edts.pinconf_bool_or_value_props: + if isinstance(pinconf_value, bool): + pinconf_value = 1 if pinconf_value else 0 + elif pinconf_prop in edts.pinconf_list_props: + if not isinstance(pinconf_value, list): + pinconf_value = [pinconf_value, ] + else: + # generate defines - insert_defs(node_address, prop_def, {}) + # use cell names if available + # (for a pinmux node these are: pin, function) + controller_compat = get_compat(pin_controller_node_address) + if controller_compat is None: + raise Exception("No binding or compatible missing for {}." + .format(pin_controller_node_address)) + controller_yaml = yaml.get(controller_compat, None) + if controller_yaml is None: + raise Exception("No binding for {}." + .format(controller_compat)) + if 'pinmux' in controller_compat: + cell_prefix = 'PINMUX' + else: + cell_prefix = 'PINCTRL' + cell_names = controller_yaml.get('#cells', None) + if cell_names is None: + # No cell names - use default names for pinctrl + cell_names = ['pin', 'function'] + pin_label = self.get_label_string([def_label, \ + cell_prefix] + subnode_address.split('/')[-2:] \ + + [cell_names[0], str(pinconf_index)]) + func_label = self.get_label_string([def_label, \ + cell_prefix] + subnode_address.split('/')[-2:] \ + + [cell_names[1], str(pinconf_index)]) + client_prop_def[pin_label] = pinconf_prop + client_prop_def[func_label] = pinconf_value + continue + # generate EDTS pinconf value + edts_insert_device_property(pinctrl_client_device_id, + 'pinctrl/{}/pinconf/{}/{}'.format(pinctrl_index, + pinconf_index, + pinconf_prop), + pinconf_value) + pinconf_index += 1 + # update property definitions of owning node + insert_defs(node_address, client_prop_def, {}) ## # @brief Management information for pinctrl-[x]. diff --git a/scripts/dts/extract/reg.py b/scripts/dts/extract/reg.py index aeec78ab2d64e7..57dee545a0691c 100644 --- a/scripts/dts/extract/reg.py +++ b/scripts/dts/extract/reg.py @@ -6,6 +6,7 @@ from extract.globals import * from extract.directive import DTDirective +from extract.edts import * ## # @brief Manage reg directive. @@ -32,18 +33,43 @@ def extract(self, node_address, yaml, prop, names, def_label): node_compat = get_compat(node_address) reg = reduced[node_address]['props']['reg'] - if type(reg) is not list: reg = [ reg ] - props = list(reg) + if type(reg) is not list: reg = [ reg, ] + reg_names = node['props'].get('reg-names', []) - address_cells = reduced['/']['props'].get('#address-cells') - size_cells = reduced['/']['props'].get('#size-cells') + nr_address_cells = reduced['/']['props'].get('#address-cells') + nr_size_cells = reduced['/']['props'].get('#size-cells') address = '' for comp in node_address.split('/')[1:-1]: address += '/' + comp - address_cells = reduced[address]['props'].get( - '#address-cells', address_cells) - size_cells = reduced[address]['props'].get('#size-cells', size_cells) - + nr_address_cells = reduced[address]['props'].get( + '#address-cells', nr_address_cells) + nr_size_cells = reduced[address]['props'].get('#size-cells', nr_size_cells) + + # generate EDTS + device_id = edts_device_id(node_address) + reg_index = 0 + reg_cell_index = 0 + reg_nr_cells = nr_address_cells + nr_size_cells + for cell in reg: + if len(reg_names) > reg_index: + reg_name = reg_names[reg_index] + else: + reg_name = str(reg_index) + if reg_cell_index < nr_address_cells: + edts_insert_device_property(device_id, + 'reg/{}/address/{}'.format(reg_name, reg_cell_index), + cell) + else: + size_cell_index = reg_cell_index - nr_address_cells + edts_insert_device_property(device_id, + 'reg/{}/size/{}'.format(reg_name, size_cell_index), + cell) + reg_cell_index += 1 + if reg_cell_index >= reg_nr_cells: + reg_cell_index = 0 + reg_index += 1 + + # generate defines post_label = "BASE_ADDRESS" if yaml[node_compat].get('use-property-label', False): label = node['props'].get('label', None) @@ -55,6 +81,7 @@ def extract(self, node_address, yaml, prop, names, def_label): l_addr = [convert_string_to_label(post_label)] l_size = ["SIZE"] + props = list(reg) while props: prop_def = {} prop_alias = {} @@ -72,21 +99,21 @@ def extract(self, node_address, yaml, prop, names, def_label): except: name = [] - for x in range(address_cells): + for x in range(nr_address_cells): addr += props.pop(0) << (32 * x) - for x in range(size_cells): + for x in range(nr_size_cells): size += props.pop(0) << (32 * x) l_addr_fqn = '_'.join(l_base + l_addr + l_idx) l_size_fqn = '_'.join(l_base + l_size + l_idx) - if address_cells: + if nr_address_cells: prop_def[l_addr_fqn] = hex(addr) - if size_cells: + if nr_size_cells: prop_def[l_size_fqn] = int(size) if len(name): - if address_cells: + if nr_address_cells: prop_alias['_'.join(l_base + name + l_addr)] = l_addr_fqn - if size_cells: + if nr_size_cells: prop_alias['_'.join(l_base + name + l_size)] = l_size_fqn # generate defs for node aliases diff --git a/scripts/dts/extract_dts_includes.py b/scripts/dts/extract_dts_includes.py index 2e8b24a88693cc..4aae62abe8605c 100755 --- a/scripts/dts/extract_dts_includes.py +++ b/scripts/dts/extract_dts_includes.py @@ -19,12 +19,17 @@ from devicetree import parse_file from extract.globals import * +from extract.edts import edts from extract.clocks import clocks +from extract.compatible import compatible +from extract.controller import controller from extract.interrupts import interrupts from extract.reg import reg from extract.flash import flash from extract.pinctrl import pinctrl +from extract.heuristics import heuristics +from extract.gpioranges import gpioranges from extract.default import default class Loader(yaml.Loader): @@ -385,9 +390,18 @@ def extract_property(node_compat, yaml, node_address, prop, prop_val, names, reg.extract(node_address, yaml, prop, names, def_label) elif prop == 'interrupts' or prop == 'interrupts-extended': interrupts.extract(node_address, yaml, prop, names, def_label) + elif prop == 'compatible': + compatible.extract(node_address, yaml, prop, names, def_label) + # do extra property definition based on heuristics + # do it here as the compatible property is mandatory + heuristics.extract(node_address, yaml, prop, names, def_label) + elif '-controller' in prop: + controller.extract(node_address, yaml, prop, names, def_label) elif 'pinctrl-' in prop: pinctrl.extract(node_address, yaml, prop, names, def_label) - elif 'clocks' in prop: + elif 'gpio-ranges' in prop: + gpioranges.extract(node_address, yaml, prop, names, def_label) + elif prop.startswith(('clock', '#clock', 'assigned-clock', 'oscillator')): clocks.extract(node_address, yaml, prop, names, def_label) elif 'gpios' in prop: try: @@ -737,6 +751,8 @@ def parse_arguments(): parser.add_argument("-d", "--dts", nargs=1, required=True, help="DTS file") parser.add_argument("-y", "--yaml", nargs=1, required=True, help="YAML file") + parser.add_argument("-e", "--edts", nargs=1, required=True, + help="Generate EDTS database file for the build system") parser.add_argument("-f", "--fixup", nargs='+', help="Fixup file(s), we allow multiple") parser.add_argument("-i", "--include", nargs=1, required=True, @@ -765,6 +781,7 @@ def main(): generate_keyvalue_file(args.keyvalue[0]) generate_include_file(args.include[0], args.fixup) + edts.save(args.edts[0]) if __name__ == '__main__': diff --git a/scripts/gen_code.py b/scripts/gen_code.py new file mode 100755 index 00000000000000..36719134ef7401 --- /dev/null +++ b/scripts/gen_code.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2018 Bobby Noelte. +# +# SPDX-License-Identifier: Apache-2.0 + +import sys + +from codegen.codegen import CodeGen + +if __name__ == '__main__': + ret = CodeGen().callableMain(sys.argv) + sys.exit(ret) diff --git a/scripts/gen_kobject_list.py b/scripts/gen_kobject_list.py index 9937edc8134f7b..33a7f46903f63f 100755 --- a/scripts/gen_kobject_list.py +++ b/scripts/gen_kobject_list.py @@ -45,6 +45,7 @@ "i2s_driver_api", "ipm_driver_api", "led_driver_api", + "pinctrl_driver_api", "pinmux_driver_api", "pwm_driver_api", "entropy_driver_api", diff --git a/scripts/sanitycheck b/scripts/sanitycheck index d6e2a9e0c4adb9..804701ba4933c1 100755 --- a/scripts/sanitycheck +++ b/scripts/sanitycheck @@ -1076,7 +1076,11 @@ class MakeGenerator: cmd = ["make", "-k", "-j", str(JOBS), "-f", tf.name, "all"] - p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=devnull) + # assure language neutral environemnt + make_env = os.environ.copy() + make_env['LC_MESSAGES'] = 'C.UTF-8' + p = subprocess.Popen(cmd, stderr=subprocess.PIPE, + stdout=devnull, env=make_env) for line in iter(p.stderr.readline, b''): line = line.decode("utf-8") diff --git a/tests/drivers/gpio/gpio_basic_api/prj.conf b/tests/drivers/gpio/gpio_basic_api/prj.conf index 505646e546992c..2565e1660f440b 100644 --- a/tests/drivers/gpio/gpio_basic_api/prj.conf +++ b/tests/drivers/gpio/gpio_basic_api/prj.conf @@ -2,3 +2,4 @@ CONFIG_GPIO=y CONFIG_ZTEST=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_PINCTRL_RUNTIME_DTS=n diff --git a/tests/drivers/gpio/gpio_basic_api/src/main.c b/tests/drivers/gpio/gpio_basic_api/src/main.c index 3bf2b02a49328f..8b0c808fc60d26 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/main.c +++ b/tests/drivers/gpio/gpio_basic_api/src/main.c @@ -41,19 +41,35 @@ * * 1. PIN_OUT is GPIO_8 * 2. PIN_IN is GPIO_9 + * + * nucleo_f091rc - arm STM32F0 + * -------------------- + * + * 1. PIN_OUT is GPIO B5 + * 2. PIN_IN is GPIO B4 */ #include "test_gpio.h" void test_main(void) { +#ifndef CONFIG_SOC_SERIES_STM32F0X ztest_test_suite(gpio_basic_test, ztest_unit_test(test_gpio_pin_read_write), ztest_unit_test(test_gpio_callback_edge_high), ztest_unit_test(test_gpio_callback_edge_low), ztest_unit_test(test_gpio_callback_level_high), + ztest_unit_test(test_gpio_callback_level_low), ztest_unit_test(test_gpio_callback_add_remove), - ztest_unit_test(test_gpio_callback_enable_disable), - ztest_unit_test(test_gpio_callback_level_low)); + ztest_unit_test(test_gpio_callback_enable_disable)); ztest_run_test_suite(gpio_basic_test); +#else + ztest_test_suite(gpio_basic_test_no_level, + ztest_unit_test(test_gpio_pin_read_write), + ztest_unit_test(test_gpio_callback_edge_high), + ztest_unit_test(test_gpio_callback_edge_low), + ztest_unit_test(test_gpio_callback_add_remove), + ztest_unit_test(test_gpio_callback_enable_disable)); + ztest_run_test_suite(gpio_basic_test_no_level); +#endif } diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c index afbd6cb02ea777..161548b02e41e8 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c @@ -44,10 +44,18 @@ static void init_callback(struct device *dev) GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | \ GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE); +#if CONFIG_PINCTRL + gpio_init_callback(&cb_data[0].gpio_cb, callback_1, PIN_IN); +#else gpio_init_callback(&cb_data[0].gpio_cb, callback_1, BIT(PIN_IN)); +#endif gpio_add_callback(dev, &cb_data[0].gpio_cb); +#if CONFIG_PINCTRL + gpio_init_callback(&cb_data[1].gpio_cb, callback_2, PIN_IN); +#else gpio_init_callback(&cb_data[1].gpio_cb, callback_2, BIT(PIN_IN)); +#endif gpio_add_callback(dev, &cb_data[1].gpio_cb); } diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c index 70908bae230cfd..c349459b2238f1 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_trigger.c @@ -18,6 +18,7 @@ static struct drv_data data; static int cb_cnt; +#if !CONFIG_PINCTRL static int pin_num(u32_t pins) { int ret = 0; @@ -27,12 +28,17 @@ static int pin_num(u32_t pins) } return ret; } +#endif static void callback(struct device *dev, struct gpio_callback *gpio_cb, u32_t pins) { /*= checkpoint: pins should be marked with correct pin number bit =*/ +#if CONFIG_PINCTRL + zassert_true(pins == PIN_IN, NULL); +#else zassert_true(pin_num(pins) == PIN_IN, NULL); +#endif TC_PRINT("callback triggered: %d\n", ++cb_cnt); if (cb_cnt >= MAX_INT_CNT) { struct drv_data *drv_data = CONTAINER_OF(gpio_cb, @@ -70,7 +76,11 @@ static int test_callback(int mode) } drv_data->mode = mode; +#if CONFIG_PINCTRL + gpio_init_callback(&drv_data->gpio_cb, callback, PIN_IN); +#else gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN)); +#endif if (gpio_add_callback(dev, &drv_data->gpio_cb) != 0) { TC_ERROR("set PIN_IN callback fail\n"); return TC_FAIL; diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h b/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h index 9b3ca7aebdf105..0ce60d4f539544 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h +++ b/tests/drivers/gpio/gpio_basic_api/src/test_gpio.h @@ -52,6 +52,14 @@ #define DEV_NAME CONFIG_GPIO_P0_DEV_NAME #define PIN_OUT 12 /* P0.12 */ #define PIN_IN 13 /* P0.13 */ +#elif CONFIG_PINCTRL && defined(CONFIG_BOARD_NUCLEO_F091RC) +#define DEV_NAME "GPIOB" +#define PIN_OUT GPIO_PORT_PIN5 +#define PIN_IN GPIO_PORT_PIN4 +#elif CONFIG_PINCTRL && defined(CONFIG_BOARD_NUCLEO_F030R8) +#define DEV_NAME "GPIOB" +#define PIN_OUT GPIO_PORT_PIN5 +#define PIN_IN GPIO_PORT_PIN4 #else #error Unsupported board #endif diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_pin_rw.c b/tests/drivers/gpio/gpio_basic_api/src/test_pin_rw.c index a796cd3f694342..ce91d38cdca2b8 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_pin_rw.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_pin_rw.c @@ -21,11 +21,19 @@ void test_gpio_pin_read_write(void) struct device *dev = device_get_binding(DEV_NAME); /* set PIN_OUT as writer */ +#if CONFIG_PINCTRL + TC_PRINT("device=%s, pin1=%d, pin2=%d\n", DEV_NAME, + GPIO_PORT_PIN_IDX(PIN_OUT), GPIO_PORT_PIN_IDX(PIN_IN)); +#else TC_PRINT("device=%s, pin1=%d, pin2=%d\n", DEV_NAME, PIN_OUT, PIN_IN); - gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT); +#endif + zassert_true(gpio_pin_configure(dev, PIN_OUT, GPIO_DIR_OUT) == 0, + "configure pin out fail"); /* set PIN_IN as reader */ - gpio_pin_configure(dev, PIN_IN, GPIO_DIR_IN); - gpio_pin_disable_callback(dev, PIN_IN); + zassert_true(gpio_pin_configure(dev, PIN_IN, GPIO_DIR_IN) == 0, + "configure pin in fail"); + zassert_true(gpio_pin_disable_callback(dev, PIN_IN) == 0, + "disable pin in callback fail"); u32_t val_write, val_read = 0; int i = 0; diff --git a/tests/drivers/gpio/gpio_basic_api/testcase.yaml b/tests/drivers/gpio/gpio_basic_api/testcase.yaml index 2fa1e8cb158ba5..e099f0aadcfb2d 100644 --- a/tests/drivers/gpio/gpio_basic_api/testcase.yaml +++ b/tests/drivers/gpio/gpio_basic_api/testcase.yaml @@ -3,5 +3,5 @@ tests: tags: drivers gpio depends_on: gpio # FIXME: code is board specific, it should be generalised - platform_whitelist: quark_se_c1000_devboard quark_d2000_crb esp32 + platform_whitelist: quark_se_c1000_devboard quark_d2000_crb esp32 nucleo_f091rc nucleo_f030r8 harness: loopback # see documentation diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_f030r8.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_f030r8.conf new file mode 100644 index 00000000000000..9059fb218dbd38 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_f030r8.conf @@ -0,0 +1 @@ +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_1" diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_f070rb.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_f070rb.conf new file mode 100644 index 00000000000000..9059fb218dbd38 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_f070rb.conf @@ -0,0 +1 @@ +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_1" diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_f091rc.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_f091rc.conf new file mode 100644 index 00000000000000..9c772265859269 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_f091rc.conf @@ -0,0 +1,3 @@ +CONFIG_SPI_LOOPBACK_DRV_NAME="SPI_1" +CONFIG_SPI_LOOPBACK_SLOW_FREQ=550000 +CONFIG_SPI_LOOPBACK_FAST_FREQ=2000000 diff --git a/tests/unit/drivers/pinctrl/CMakeLists.txt b/tests/unit/drivers/pinctrl/CMakeLists.txt new file mode 100644 index 00000000000000..b5741ad9943419 --- /dev/null +++ b/tests/unit/drivers/pinctrl/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (c) 2018 Bobby Noelte +# +# SPDX-License-Identifier: Apache-2.0 + +# Prepare generic unit test environment +# +# parameters: +# - INCLUDE is relative to zephyr base +# - SOURCES defaults to main.c +# +# target: +# - testbinary (default) + +# for ztest +list(APPEND INCLUDE subsys) +# for code generation +set(template_file ${CMAKE_CURRENT_SOURCE_DIR}/main.c) +set(SOURCES "") # prevent default +include($ENV{ZEPHYR_BASE}/tests/unit/unittest.cmake) + +# Fake zephyr environment to prepare the +# generation of include/generated/generated_dts_board.h from DTS +set(ZEPHYR_BASE $ENV{ZEPHYR_BASE}) +set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(PROJECT_SOURCE_DIR ${ZEPHYR_BASE}) +set(ARCH arm) +set(BOARD_FAMILY nucleo_f091rc) +set(BOARD nucleo_f091rc) +set(CONFIG_HAS_DTS True) +set(APPLICATION_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +include(${ZEPHYR_BASE}/cmake/extensions.cmake) + +# Get the tools for DTS - python and DTC +find_package(PythonInterp 3.4) +include(${ZEPHYR_BASE}/cmake/host-tools.cmake) + +# fake autconf.h generation +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/generated) +file(COPY autoconf.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/generated) + +# Generate include/generated/generated_dts_board.h from DTS +set(AUTOCONF_H ${CMAKE_CURRENT_SOURCE_DIR}/autoconf.h) +set(DTS_SOURCE ${PROJECT_SOURCE_DIR}/boards/arm/nucleo_f091rc/nucleo_f091rc.dts) +include(${ZEPHYR_BASE}/cmake/dts.cmake) + +# fake syscall generation for header files that are needed +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/syscalls) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/include/syscalls/pinctrl.h "/* test only */") +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/include/syscalls/gpio.h "/* test only */") + +# Prepare for inline code generation +target_sources_codegen(testbinary ${template_file}) + +# Make test aware of +# - dts bindings header files +# - generated include file +target_include_directories(testbinary PRIVATE + ${DTS_BINDINGS_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include/generated + ) + +project(none) # switches PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR diff --git a/tests/unit/drivers/pinctrl/autoconf.h b/tests/unit/drivers/pinctrl/autoconf.h new file mode 100644 index 00000000000000..7408fc8f456584 --- /dev/null +++ b/tests/unit/drivers/pinctrl/autoconf.h @@ -0,0 +1,128 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Zephyr Kernel Configuration + * + */ +#define CONFIG_APPLICATION_INIT_PRIORITY 90 +#define CONFIG_ARCH "arm" +#define CONFIG_ARCH_DEFCONFIG "arch/arm/defconfig" +#define CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN 1 +#define CONFIG_ARCH_HAS_THREAD_ABORT 1 +#define CONFIG_ARM 1 +#define CONFIG_ARMV6_M 1 +#define CONFIG_ATOMIC_OPERATIONS_C 1 +#define CONFIG_BOARD "nucleo_f091rc" +#define CONFIG_BOARD_NUCLEO_F091RC 1 +#define CONFIG_BOOT_BANNER 1 +#define CONFIG_BOOT_DELAY 0 +#define CONFIG_BUILD_OUTPUT_BIN 1 +#define CONFIG_BUILD_TIMESTAMP 1 +#define CONFIG_CHAOS 1 +#define CONFIG_CHECK_LINK_MAP 1 +#define CONFIG_CLOCK_CONTROL 1 +#define CONFIG_CLOCK_CONTROL_STM32_CUBE 1 +#define CONFIG_CLOCK_CONTROL_STM32_DEVICE_INIT_PRIORITY 1 +#define CONFIG_CLOCK_STM32_AHB_PRESCALER 1 +#define CONFIG_CLOCK_STM32_APB1_PRESCALER 1 +#define CONFIG_CLOCK_STM32_HSE_CLOCK 8000000 +#define CONFIG_CLOCK_STM32_PLL_MULTIPLIER 6 +#define CONFIG_CLOCK_STM32_PLL_PREDIV 1 +#define CONFIG_CLOCK_STM32_PLL_PREDIV1 1 +#define CONFIG_CLOCK_STM32_PLL_SRC_HSE 1 +#define CONFIG_CLOCK_STM32_SYSCLK_SRC_PLL 1 +#define CONFIG_COMPILER_OPT "" +#define CONFIG_CONSOLE 1 +#define CONFIG_CONSOLE_HAS_DRIVER 1 +#define CONFIG_CONSOLE_INPUT_MAX_LINE_LEN 128 +#define CONFIG_COOP_ENABLED 1 +#define CONFIG_CORTEX_M_SYSTICK 1 +#define CONFIG_COVERAGE 1 +#define CONFIG_CPU_CORTEX 1 +#define CONFIG_CPU_CORTEX_M 1 +#define CONFIG_CPU_CORTEX_M0 1 +#define CONFIG_CPU_HAS_SYSTICK 1 +#define CONFIG_CROSS_COMPILE "" +#define CONFIG_DATA_ENDIANNESS_LITTLE 1 +#define CONFIG_EARLY_CONSOLE 1 +#define CONFIG_ERRNO 1 +#define CONFIG_EXTI_STM32 1 +#define CONFIG_EXTI_STM32_EXTI15_4_IRQ_PRI 0 +#define CONFIG_EXTI_STM32_EXTI1_0_IRQ_PRI 0 +#define CONFIG_EXTI_STM32_EXTI3_2_IRQ_PRI 0 +#define CONFIG_FAULT_DUMP 2 +#define CONFIG_FLASH_PAGE_SIZE 0x800 +#define CONFIG_GEN_IRQ_START_VECTOR 0 +#define CONFIG_GEN_IRQ_VECTOR_TABLE 1 +#define CONFIG_GEN_ISR_TABLES 1 +#define CONFIG_GEN_SW_ISR_TABLE 1 +#define CONFIG_GPIO 1 +#define CONFIG_GPIO_PINCTRL 1 +#define CONFIG_GPIO_PINCTRL_STM32 1 +#define CONFIG_GPIO_STM32 1 +#define CONFIG_HAS_CMSIS 1 +#define CONFIG_HAS_DTS 1 +#define CONFIG_HAS_FLASH_LOAD_OFFSET 1 +#define CONFIG_HAS_STM32CUBE 1 +#define CONFIG_HEAP_MEM_POOL_SIZE 0 +#define CONFIG_IDLE_STACK_SIZE 256 +#define CONFIG_ISA_THUMB2 1 +#define CONFIG_ISR_STACK_SIZE 2048 +#define CONFIG_KERNEL_BIN_NAME "zephyr" +#define CONFIG_KERNEL_ENTRY "__start" +#define CONFIG_KERNEL_INIT_PRIORITY_DEFAULT 40 +#define CONFIG_KERNEL_INIT_PRIORITY_DEVICE 50 +#define CONFIG_KERNEL_INIT_PRIORITY_OBJECTS 30 +#define CONFIG_LDREX_STREX_AVAILABLE 1 +#define CONFIG_MAIN_STACK_SIZE 1024 +#define CONFIG_MAIN_THREAD_PRIORITY 0 +#define CONFIG_MULTITHREADING 1 +#define CONFIG_NUM_COOP_PRIORITIES 16 +#define CONFIG_NUM_IRQS 32 +#define CONFIG_NUM_MBOX_ASYNC_MSGS 10 +#define CONFIG_NUM_PIPE_ASYNC_MSGS 10 +#define CONFIG_NUM_PREEMPT_PRIORITIES 15 +#define CONFIG_OFFLOAD_WORKQUEUE_PRIORITY -1 +#define CONFIG_OFFLOAD_WORKQUEUE_STACK_SIZE 1024 +#define CONFIG_OUTPUT_DISASSEMBLY 1 +#define CONFIG_OUTPUT_PRINT_MEMORY_USAGE 1 +#define CONFIG_OUTPUT_STAT 1 +#define CONFIG_PINCTRL 1 +#define CONFIG_PINCTRL_INIT_PRIORITY 2 +#define CONFIG_PINCTRL_RUNTIME_DTS 1 +#define CONFIG_PINCTRL_NAME "PINCTRL" +#define CONFIG_PINCTRL_PINMUX 1 +#define CONFIG_PINCTRL_STM32 1 +#define CONFIG_PREEMPT_ENABLED 1 +#define CONFIG_PRINTK 1 +#define CONFIG_PRIORITY_CEILING 0 +#define CONFIG_SERIAL 1 +#define CONFIG_SERIAL_HAS_DRIVER 1 +#define CONFIG_SERIAL_SUPPORT_INTERRUPT 1 +#define CONFIG_SOC "stm32f091xc" +#define CONFIG_SOC_FAMILY "st_stm32" +#define CONFIG_SOC_FAMILY_STM32 1 +#define CONFIG_SOC_SERIES "stm32f0" +#define CONFIG_SOC_SERIES_STM32F0X 1 +#define CONFIG_SOC_STM32F091XC 1 +#define CONFIG_SPI_LEGACY_API 1 +#define CONFIG_STACK_ALIGN_DOUBLE_WORD 1 +#define CONFIG_SYSTEM_CLOCK_INIT_PRIORITY 0 +#define CONFIG_SYSTEM_WORKQUEUE_PRIORITY -1 +#define CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE 1024 +#define CONFIG_SYS_CLOCK_EXISTS 1 +#define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 48000000 +#define CONFIG_SYS_CLOCK_TICKS_PER_SEC 100 +#define CONFIG_SYS_POWER_LOW_POWER_STATE_SUPPORTED 1 +#define CONFIG_TEST_EXTRA_STACKSIZE 0 +#define CONFIG_TEXT_SECTION_OFFSET 0x0 +#define CONFIG_TIMESLICE_PRIORITY 0 +#define CONFIG_TIMESLICE_SIZE 0 +#define CONFIG_TIMESLICING 1 +#define CONFIG_TOOLCHAIN_VARIANT "" +#define CONFIG_UART_CONSOLE 1 +#define CONFIG_UART_CONSOLE_INIT_PRIORITY 60 +#define CONFIG_UART_INTERRUPT_DRIVEN 1 +#define CONFIG_UART_STM32 1 +#define CONFIG_UART_STM32_PORT_2 1 +#define CONFIG_XIP 1 diff --git a/tests/unit/drivers/pinctrl/main.c b/tests/unit/drivers/pinctrl/main.c new file mode 100644 index 00000000000000..3366eae589204e --- /dev/null +++ b/tests/unit/drivers/pinctrl/main.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2018 Bobby Noelte + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "autoconf.h" +#include "include/generated/generated_dts_board.h" + +#include +#include +#include + +/* data as produced by inline code generation */ +#define TEST_DEVICE_NAME st_stm32_pinctrl_48000000 +#define TEST_DATA st_stm32_pinctrl_48000000_data +#define TEST_CONFIG st_stm32_pinctrl_48000000_config +#define TEST_FUNCTION_DATA st_stm32_pinctrl_48000000_function +#define TEST_STATE_NAME_DATA st_stm32_pinctrl_48000000_state_name +#define TEST_PINCTRL_STATE_DATA st_stm32_pinctrl_48000000_pinctrl_state +#define TEST_PINCTRL_DATA st_stm32_pinctrl_48000000_pinctrl + +/* device functions have an offset of PINCTRL_FUNCTION_DEVICE_BASE */ +#define TEST_CLIENT_FUNCTION_DEVICE \ + (TEST_CLIENT_FUNCTION + PINCTRL_FUNCTION_DEVICE_BASE) + +/* Test mock */ +struct mock_info { + int config_get_invocation; + int config_set_invocation; + int mux_get_invocation; + int mux_set_invocation; + u32_t mux_set_pin; + u16_t mux_set_func; + int device_init_invocation; + struct device_config client_config; + struct device client; +}; + +/* forward declarations */ +static int mock_config_get(struct device *dev, u16_t pin, u32_t *config); +static int mock_config_set(struct device *dev, u16_t pin, u32_t config); +static int mock_mux_get(struct device *dev, u16_t pin, u16_t *func); +static int mock_mux_set(struct device *dev, u16_t pin, u16_t func); +static int mock_device_init(struct device *dev); + +/** + * @code{.codegen} + * compatible = 'st,stm32-pinctrl' + * config_get = 'mock_config_get' + * config_set = 'mock_config_set' + * mux_get = 'mock_mux_get' + * mux_set = 'mock_mux_set' + * data_info = 'struct mock_info' + * device_init = 'mock_device_init' + * codegen.out_include('templates/drivers/pinctrl_tmpl.c') + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +/** Defines for values from Device Tree + * @code{.codegen} + * test_device_id = codegen.edts().device_ids_by_compatible(compatible)[0] + * codegen.outl('#define TEST_DRIVER_NAME "{}"'.format( \ + * codegen.edts().device_property(test_device_id, 'label'))) + * codegen.outl('#define TEST_PIN_COUNT {}'.format( \ + * _pin_controllers[0].pin_count())) + * codegen.outl('#define TEST_FUNCTION_COUNT {}'.format( \ + * _pin_controllers[0].function_count())) + * codegen.outl('#define TEST_STATE_NAME_COUNT {}'.format( \ + * _pin_controllers[0].state_name_count())) + * codegen.outl('#define TEST_STATE_COUNT {}'.format( \ + * _pin_controllers[0].state_count())) + * codegen.outl('#define TEST_PINCTRL_COUNT {}'.format( \ + * _pin_controllers[0].pinctrl_count())) + * + * test_client_name = "UART_1" + * test_client_device_id = codegen.edts().device_id_by_label(test_client_name) + * codegen.outl('#define TEST_CLIENT_NAME "{}"'.format(test_client_name)) + * codegen.outl('#define TEST_CLIENT_FUNCTION {}'.format( \ + * _pin_controllers[0].function_id(test_client_name))) + * codegen.outl('#define TEST_CLIENT_DEFAULT_STATE {}'.format( \ + * _pin_controllers[0].state_id(test_client_name, 'default'))) + * + * @endcode{.codegen} + */ +/** @code{.codeins}@endcode */ + +/* UART_1 default tx */ +#define TEST_CLIENT_PINCTRL_PINCONF_PIN 22 +#define TEST_CLIENT_PINCTRL_PINCONF_MUX 0 +#define TEST_CLIENT_GROUP TEST_CLIENT_DEFAULT_STATE +#define TEST_CLIENT_GROUP_PINS 2 /* rx, tx */ + +static int mock_config_get(struct device *dev, u16_t pin, u32_t *config) +{ + TEST_DATA.config_get_invocation++; + return 0; +} + +static int mock_config_set(struct device *dev, u16_t pin, u32_t config) +{ + TEST_DATA.config_set_invocation++; + return 0; +} + +static int mock_mux_get(struct device *dev, u16_t pin, u16_t *func) +{ + TEST_DATA.mux_get_invocation++; + return 0; +} + +static int mock_mux_set(struct device *dev, u16_t pin, u16_t func) +{ + TEST_DATA.mux_set_invocation++; + TEST_DATA.mux_set_pin = pin; + TEST_DATA.mux_set_func = func; + return 0; +} + +static int mock_device_init(struct device *dev) +{ + TEST_DATA.device_init_invocation++; + return 0; +} + +/* Defines for what DEVICE_API_INIT generates */ +#define TEST_DEVICE DEVICE_NAME_GET(TEST_DEVICE_NAME) + +/* Access pinctrl template data structures */ +#define TEST_API pinctrl_tmpl_driver_api +#define TEST_DEVICE_CONFIG_INFO(_device_name) \ + _TEST_DEVICE_CONFIG_INFO1(_device_name) +#define _TEST_DEVICE_CONFIG_INFO1(_device_name) \ + ((const struct pinctrl_tmpl_config *)_device_name.config->config_info) + +/* Replace Pinctrl API syscall interface */ +__syscall u16_t pinctrl_get_pins_count(struct device *dev) +{ + return _impl_pinctrl_get_pins_count(dev); +} + +__syscall u16_t pinctrl_get_groups_count(struct device *dev) +{ + return _impl_pinctrl_get_groups_count(dev); +} + +__syscall int pinctrl_get_group_pins(struct device *dev, u16_t group, + u16_t *pins, u16_t *num_pins) +{ + return _impl_pinctrl_get_group_pins(dev, group, pins, num_pins); +} + +__syscall u16_t pinctrl_get_states_count(struct device *dev) +{ + return _impl_pinctrl_get_states_count(dev); +} + +__syscall int pinctrl_get_state_group(struct device *dev, u16_t state, + u16_t *group) +{ + return _impl_pinctrl_get_state_group(dev, state, group); +} + +__syscall u16_t pinctrl_get_functions_count(struct device *dev) +{ + return _impl_pinctrl_get_functions_count(dev); +} + +__syscall int pinctrl_get_function_group(struct device *dev, u16_t func, + const char *name, u16_t *group) +{ + return _impl_pinctrl_get_function_group(dev, func, name, group); +} + +__syscall int pinctrl_get_function_groups(struct device *dev, u16_t func, + u16_t *groups, u16_t *num_groups) +{ + return _impl_pinctrl_get_function_groups(dev, func, groups, num_groups); +} + +__syscall int pinctrl_get_function_state(struct device *dev, u16_t func, + const char *name, u16_t *state) +{ + return _impl_pinctrl_get_function_state(dev, func, name, state); +} + +__syscall int pinctrl_get_function_states(struct device *dev, u16_t func, + u16_t *states, u16_t *num_states) +{ + return _impl_pinctrl_get_function_states(dev, func, states, num_states); +} + +__syscall int pinctrl_get_device_function(struct device *dev, + struct device *other, u16_t *func) +{ + return _impl_pinctrl_get_device_function(dev, other, func); +} + +__syscall int pinctrl_get_gpio_range(struct device *dev, struct device *gpio, + u32_t gpio_pin, u16_t *pin, + u16_t *base_pin, u8_t *num_pins) +{ + return _impl_pinctrl_get_gpio_range( + dev, gpio, gpio_pin, pin, base_pin, num_pins); +} + +__syscall int pinctrl_config_get(struct device *dev, u16_t pin, u32_t *config) +{ + return _impl_pinctrl_config_get(dev, pin, config); +} + +__syscall int pinctrl_config_set(struct device *dev, u16_t pin, u32_t config) +{ + return _impl_pinctrl_config_set(dev, pin, config); +} + +__syscall int pinctrl_config_group_get(struct device *dev, u16_t group, + u32_t *configs, u16_t *num_configs) +{ + return _impl_pinctrl_config_group_get(dev, group, configs, num_configs); +} + +__syscall int pinctrl_config_group_set(struct device *dev, u16_t group, + const u32_t *configs, u16_t num_configs) +{ + return _impl_pinctrl_config_group_set(dev, group, configs, num_configs); +} + +__syscall int pinctrl_mux_request(struct device *dev, u16_t pin, + const char *owner) +{ + return _impl_pinctrl_mux_request(dev, pin, owner); +} + +__syscall int pinctrl_mux_free(struct device *dev, u16_t pin, const char *owner) +{ + return _impl_pinctrl_mux_free(dev, pin, owner); +} + +__syscall int pinctrl_mux_get(struct device *dev, u16_t pin, u16_t *func) +{ + return _impl_pinctrl_mux_get(dev, pin, func); +} + +__syscall int pinctrl_mux_set(struct device *dev, u16_t pin, u16_t func) +{ + return _impl_pinctrl_mux_set(dev, pin, func); +} + +__syscall int pinctrl_mux_group_set(struct device *dev, u16_t group, u16_t func) +{ + return _impl_pinctrl_mux_group_set(dev, group, func); +} + +__syscall int pinctrl_state_set(struct device *dev, u16_t state) +{ + return _impl_pinctrl_state_set(dev, state); +} + + +static _Bool assert_strcmp(const char *s1, const char *s2) +{ + const char *_s1 = s1; + const char *_s2 = s2; + + for (int i = 0; i <= 1000; i++) { + if ((*s1 == 0) && (*s2 == 0)) { + return 1; + } + if (*s1 != *s2) { + TC_PRINT("%s: %s, %s failed - char %c != %c (%d)\n", + __func__, _s1, _s2, *s1, *s2, i); + return 0; + } + if (((*s1 == 0) && (*s2 != 0)) || ((*s1 != 0) && (*s2 == 0))) { + TC_PRINT("%s: %s, %s failed - end of string (%d)\n", + __func__, _s1, _s2, i); + return 0; + } + if (i >= 1000) { + TC_PRINT("%s: %s, %s failed - no end of string (%d)\n", + __func__, _s1, _s2, i); + return 0; + } + s1++; + s2++; + }; + return 1; +} + +const char *error(int err) +{ + if (err == 0) { + return "OK"; + } + if (err == EINVAL) { + return "EINVAL"; + } + if (err == ENOTSUP) { + return "ENOTSUP"; + } + return strerror(err); + +} + +static void mock_reset(void) +{ + TEST_DATA.config_get_invocation = 0; + TEST_DATA.config_set_invocation = 0; + TEST_DATA.mux_get_invocation = 0; + TEST_DATA.mux_set_invocation = 0; + TEST_DATA.mux_set_pin = 0xFFFF; + TEST_DATA.mux_set_func = 0xFFFF; + TEST_DATA.device_init_invocation = 0; + TEST_DATA.client_config.name = TEST_CLIENT_NAME; + TEST_DATA.client_config.init = 0; + TEST_DATA.client_config.config_info = 0; + TEST_DATA.client.config = &TEST_DATA.client_config, + TEST_DATA.client.driver_api = 0; + TEST_DATA.client.driver_data = 0; + + /* fake init of mux_request data */ + pinctrl_tmpl_mux_owner_initialized = 0; + zassert_equal(0, + pinctrl_tmpl_mux_request_init(&TEST_DEVICE), + "init: pinctrl_tmpl_mux_request_init failed"); +} + +void test_pinctrl_tmpl_test_data(void) +{ + assert_strcmp(TEST_DRIVER_NAME, "PINCTRL"); + assert_strcmp(TEST_CLIENT_NAME, "UART_1"); + zassert_true((TEST_PIN_COUNT > 0), + "test data: TEST_PIN_COUNT == 0"); + zassert_true((TEST_FUNCTION_COUNT > 0), + "test data: TEST_FUNCTION_COUNT == 0"); + zassert_true((TEST_STATE_NAME_COUNT > 0), + "test data: TEST_STATE_NAME_COUNT == 0"); + zassert_true((TEST_STATE_COUNT > 0), + "test data: TEST_STATE_COUNT == 0"); + zassert_true((TEST_PINCTRL_COUNT > 0), + "test data: TEST_PINCTRL_COUNT == 0"); +} + +void test_pinctrl_tmpl_init(void) +{ + zassert_equal(TEST_API.config.get, + mock_config_get, + "init: pinctrl_config_get API init failed"); + zassert_equal(TEST_API.mux.get, + mock_mux_get, + "init: pinctrl_mux_get API init failed"); + zassert_equal(TEST_CONFIG.mux_set, + mock_mux_set, + "init: pinctrl_mux_set API init failed"); + zassert_equal(TEST_API.state.set, + pinctrl_tmpl_state_set, + "init: pinctrl_state_set API init failed"); + zassert_equal((const void *)&TEST_CONFIG, + TEST_DEVICE.config->config_info, + "init: driver config_info init failed"); + zassert_equal(1, + assert_strcmp(TEST_DRIVER_NAME, TEST_DEVICE.config->name), + "init: driver name init failed"); + zassert_equal(TEST_PIN_COUNT, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->pin_count, + "init: driver config_info->pin_count init failed"); + zassert_equal(TEST_FUNCTION_COUNT, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE) + ->device_function_count, + "init: driver config_info->device_function_count init failed"); + zassert_equal(TEST_STATE_NAME_COUNT, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->state_name_count, + "init: driver config_info->state_name_count init failed"); + zassert_equal(TEST_STATE_COUNT, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->pinctrl_state_count, + "init: driver config_info->pinctrl_state_count init failed"); + zassert_equal(TEST_PINCTRL_COUNT, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->pinctrl_count, + "init: driver config_info->pinctrl_count init failed"); + zassert_equal(TEST_FUNCTION_DATA, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE) + ->device_function_data, + "init: driver config_info->device_function_data init failed"); + zassert_equal(TEST_STATE_NAME_DATA, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->state_name_data, + "init: driver config_info->state_name_data init failed"); + zassert_equal(TEST_PINCTRL_STATE_DATA, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->pinctrl_state_data, + "init: driver config_info->pinctrl_state_data " + "init failed"); + zassert_equal(TEST_PINCTRL_DATA, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->pinctrl_data, + "init: driver config_info->pinctrl_data " + "init failed"); + zassert_equal(mock_device_init, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->device_init, + "init: driver config_info->device_init init failed"); + zassert_equal(mock_mux_set, + TEST_DEVICE_CONFIG_INFO(TEST_DEVICE)->mux_set, + "init: driver config_info->mux_set init failed"); + + /* Assure pinctrl pins are in valid range */ + for (int pinctrl = 0; pinctrl < TEST_PINCTRL_COUNT; pinctrl++) { + int pin = TEST_DEVICE_CONFIG_INFO(TEST_DEVICE) + ->pinctrl_data[pinctrl].pin; + + zassert_equal(1, (pin < TEST_PIN_COUNT), + "init: driver config_info->pinctrl_data failed: " + "pinctrl %d pin %d", pinctrl, pin); + } + + /* call device init function provided by driver writer (our mock) */ + mock_reset(); + int ret = TEST_DEVICE_CONFIG_INFO(TEST_DEVICE) + ->device_init(&TEST_DEVICE); + + zassert_equal(0, ret, + "init: device_init() failed return: %d %s", + ret, error(-ret)); + zassert_equal(1, + TEST_DATA.device_init_invocation, + "init: device_init() not called"); + + /* call mux request init function (part of initialization) */ + mock_reset(); + ret = pinctrl_tmpl_mux_request_init(&TEST_DEVICE); + zassert_equal(0, ret, + "init: pinctrl_tmpl_mux_request_init() " + "failed return: %d %s", ret, error(-ret)); + + /* call device init function provided by template*/ + mock_reset(); + ret = TEST_DEVICE.config->init(&TEST_DEVICE); + zassert_equal(0, ret, + "init: init() failed return: %d %s", ret, error(-ret)); + zassert_equal(1, + TEST_DATA.device_init_invocation, + "init: device_init() not called"); + zassert_equal(TEST_PINCTRL_COUNT, + TEST_DATA.config_set_invocation, + "init: default initialisation (config) not called"); + zassert_equal(TEST_PINCTRL_COUNT, + TEST_DATA.mux_set_invocation, + "init: default initialisation (mux) not called"); +} + +void test_pinctrl_tmpl_control_get_pins_count(void) +{ + mock_reset(); + + zassert_equal(TEST_PIN_COUNT, + pinctrl_get_pins_count(&TEST_DEVICE), + "api: pinctrl_get_pins_count failed"); +} + +void test_pinctrl_tmpl_control_get_function_state(void) +{ + u16_t state = 0; + int ret; + + mock_reset(); + ret = pinctrl_get_function_state( + &TEST_DEVICE, TEST_CLIENT_FUNCTION_DEVICE, "default", &state), + zassert_equal(0, ret, + "api: pinctrl_get_function_state failed (%d %s)", + (int)ret, error(ret)); + zassert_equal(TEST_CLIENT_DEFAULT_STATE, + state, + "api: pinctrl_get_function_state wrong state %d (expected %d).", + (int)state, (int)TEST_CLIENT_DEFAULT_STATE); +} + +void test_pinctrl_tmpl_control_get_function_states(void) +{ + u16_t states[TEST_STATE_COUNT]; + u16_t num_states; + + mock_reset(); + /* Only default state configured */ + num_states = TEST_STATE_COUNT; + states[0] = 0; + states[1] = 0; + zassert_equal(0, + pinctrl_get_function_states(&TEST_DEVICE, + TEST_CLIENT_FUNCTION_DEVICE, + &states[0], + &num_states), + "api: pinctrl_get_function_states failed"); + zassert_equal(1, + num_states, + "api: pinctrl_get_function_states wrong state count"); + zassert_equal(TEST_CLIENT_DEFAULT_STATE, + states[0], + "api: pinctrl_get_function_state wrong state"); + /* error - not sufficent array space */ + num_states = 0; + states[0] = 0; + states[1] = 0; + zassert_equal(-EINVAL, + pinctrl_get_function_states(&TEST_DEVICE, + TEST_CLIENT_FUNCTION_DEVICE, + &states[0], + &num_states), + "api: pinctrl_get_function_states failed"); + zassert_equal(1, + num_states, + "api: pinctrl_get_function_states wrong state count"); + zassert_equal( + 0, states[0], "api: pinctrl_get_function_state wrong state"); + /* error - unknown function */ + num_states = 2; + states[0] = 0; + states[1] = 0; + zassert_equal(-ENODEV, + pinctrl_get_function_states(&TEST_DEVICE, + TEST_FUNCTION_COUNT, + &states[0], + &num_states), + "api: pinctrl_get_function_states failed"); + zassert_equal(0, + num_states, + "api: pinctrl_get_function_states wrong state count"); + zassert_equal( + 0, states[0], "api: pinctrl_get_function_state wrong state"); +} + +void test_pinctrl_tmpl_control_get_device_function(void) +{ + u16_t func = 0; + + mock_reset(); + zassert_equal(0, + pinctrl_get_device_function( + &TEST_DEVICE, &TEST_DATA.client, &func), + "api: pinctrl_get_device_function failed"); + zassert_equal(TEST_CLIENT_FUNCTION_DEVICE, + func, + "api: pinctrl_get_device_function wrong function"); +} + +void test_pinctrl_tmpl_config_group_get(void) +{ + u16_t group; + u16_t num_configs; + u32_t configs[TEST_PIN_COUNT]; + + /* normal case */ + mock_reset(); + group = TEST_CLIENT_GROUP; + num_configs = TEST_PIN_COUNT; + zassert_equal(0, + pinctrl_tmpl_config_group_get( + &TEST_DEVICE, group, &configs[0], &num_configs), + "api: pinctrl_tmpl_config_group_get failed"); + zassert_equal( + TEST_CLIENT_GROUP_PINS, + num_configs, + "api: pinctrl_tmpl_config_group_get wrong config count: %d", + (int)num_configs); + zassert_equal( + TEST_CLIENT_GROUP_PINS, + TEST_DATA.config_get_invocation, + "api: pinctrl_tmpl_config_group_get " + "config_get called: %d times", + (int)TEST_DATA.config_get_invocation); + /* error - configs array (aka. num_configs) to small */ + mock_reset(); + group = TEST_CLIENT_GROUP; + num_configs = TEST_CLIENT_GROUP_PINS - 1; + zassert_equal(-EINVAL, + pinctrl_tmpl_config_group_get( + &TEST_DEVICE, group, &configs[0], &num_configs), + "api: pinctrl_tmpl_config_group_get failed"); + zassert_equal( + TEST_CLIENT_GROUP_PINS, + num_configs, + "api: pinctrl_tmpl_config_group_get wrong config count: %d", + (int)num_configs); + zassert_equal( + TEST_CLIENT_GROUP_PINS - 1, + TEST_DATA.config_get_invocation, + "api: pinctrl_tmpl_config_group_get " + "config_get called: %d times", + (int)TEST_DATA.config_get_invocation); + /* error - unknown group */ + mock_reset(); + group = TEST_STATE_COUNT; + num_configs = TEST_PIN_COUNT; + zassert_equal(-ENOTSUP, + pinctrl_tmpl_config_group_get( + &TEST_DEVICE, group, &configs[0], &num_configs), + "api: pinctrl_tmpl_config_group_get failed"); + zassert_equal( + 0, + num_configs, + "api: pinctrl_tmpl_config_group_get wrong config count: %d", + (int)num_configs); + zassert_equal( + 0, + TEST_DATA.config_get_invocation, + "api: pinctrl_tmpl_config_group_get " + "config_get called: %d times", + (int)TEST_DATA.config_get_invocation); +} + +void test_pinctrl_tmpl_config_group_set(void) +{ + u16_t group; + u16_t num_configs; + u32_t configs[TEST_PIN_COUNT]; + + /* normal case */ + mock_reset(); + group = TEST_CLIENT_GROUP; + num_configs = TEST_CLIENT_GROUP_PINS; + zassert_equal(0, + pinctrl_tmpl_config_group_set( + &TEST_DEVICE, group, &configs[0], num_configs), + "api: pinctrl_tmpl_config_group_set failed"); + zassert_equal( + TEST_CLIENT_GROUP_PINS, + TEST_DATA.config_set_invocation, + "api: pinctrl_tmpl_config_group_set " + "config_set called: %d times", + (int)TEST_DATA.config_set_invocation); + /* error - configs array (aka. num_configs) to small */ + mock_reset(); + group = TEST_CLIENT_GROUP; + num_configs = TEST_CLIENT_GROUP_PINS - 1; + zassert_equal(-EINVAL, + pinctrl_tmpl_config_group_set( + &TEST_DEVICE, group, &configs[0], num_configs), + "api: pinctrl_tmpl_config_group_set failed"); + zassert_equal( + TEST_CLIENT_GROUP_PINS - 1, + TEST_DATA.config_set_invocation, + "api: pinctrl_tmpl_config_group_set " + "config_set called: %d times", + (int)TEST_DATA.config_set_invocation); + /* error - unknown group */ + mock_reset(); + group = TEST_STATE_COUNT; + num_configs = TEST_PIN_COUNT; + zassert_equal(-ENOTSUP, + pinctrl_tmpl_config_group_set( + &TEST_DEVICE, group, &configs[0], num_configs), + "api: pinctrl_tmpl_config_group_set failed"); + zassert_equal( + 0, + TEST_DATA.config_set_invocation, + "api: pinctrl_tmpl_config_group_set " + "config_set called: %d times", + (int)TEST_DATA.config_set_invocation); +} + +void test_pinctrl_tmpl_mux_request_free(void) +{ + const char *owner1 = "xxxx"; + const char *owner2 = "yyyy"; + + mock_reset(); + + /* owner1 requests all pins - all pins should be available */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(0, + pinctrl_mux_request(&TEST_DEVICE, pin, owner1), + "api: pinctrl_mux_request failed (pin: %d)", + (int)pin); + } + /* owner2 requests all pins - none should be available */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal( + -EBUSY, + pinctrl_mux_request(&TEST_DEVICE, pin, owner2), + "api: pinctrl_mux_request wrongly passed (pin: %d)", + (int)pin); + } + /* owner1 frees all pins - all pins should be available afterwards */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(0, + pinctrl_mux_free(&TEST_DEVICE, pin, owner1), + "api: pinctrl_mux_free failed (pin: %d)", + (int)pin); + } + /* owner2 requests all pins - all pins should be available */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(0, + pinctrl_mux_request(&TEST_DEVICE, pin, owner2), + "api: pinctrl_mux_request failed (pin: %d)", + (int)pin); + } + /* owner1 tries to free all pins - should not be possible - not owner */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(-EACCES, + pinctrl_mux_free(&TEST_DEVICE, pin, owner1), + "api: pinctrl_mux_free wrongly passed (pin: %d)", + (int)pin); + } + /* owner2 frees all pins - all pins should be available afterwards */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(0, + pinctrl_mux_free(&TEST_DEVICE, pin, owner2), + "api: pinctrl_mux_free failed (pin: %d)", + (int)pin); + } + /* owner1 requests all pins - all pins should be available */ + for (u16_t pin = 0; pin < TEST_PIN_COUNT; + pin++) { + zassert_equal(0, + pinctrl_mux_request(&TEST_DEVICE, pin, owner1), + "api: pinctrl_mux_request failed (pin: %d)", + (int)pin); + } + zassert_equal( + -ENOTSUP, + pinctrl_mux_request(&TEST_DEVICE, + TEST_PIN_COUNT, + owner2), + "api: pinctrl_mux_request wrongly passed (pin: %d)", + (int)TEST_PIN_COUNT); +} + +void test_pinctrl_tmpl_mux_set(void) +{ + u16_t pin; + u16_t func; + int ret; + + /* hardware pinmux*/ + mock_reset(); + pin = TEST_CLIENT_PINCTRL_PINCONF_PIN; + func = TEST_CLIENT_PINCTRL_PINCONF_MUX; + + ret = pinctrl_mux_set(&TEST_DEVICE, pin, func); + zassert_equal(0, ret, + "api: pinctrl_tmpl_mux_set failed %d %s\n", + ret, error(-ret)); + zassert_equal( + 1, + TEST_DATA.mux_set_invocation, + "api: pinctrl_tmpl_mux_set called: %d times", + (int)TEST_DATA.mux_set_invocation); + zassert_equal( + pin, + TEST_DATA.mux_set_pin, + "api: pinctrl_tmpl_mux_set unexpected pin: %d", + (int)TEST_DATA.mux_set_pin); + zassert_equal( + func, + TEST_DATA.mux_set_func, + "api: pinctrl_tmpl_mux_set unexpected func: %d", + (int)TEST_DATA.mux_set_func); + + /* device pinmux*/ + mock_reset(); + pin = TEST_CLIENT_PINCTRL_PINCONF_PIN; + func = TEST_CLIENT_FUNCTION_DEVICE; + zassert_false((func == TEST_CLIENT_PINCTRL_PINCONF_MUX), + "api: pinctrl_tmpl_mux_set wrong test setup\n"); + + ret = pinctrl_mux_set(&TEST_DEVICE, pin, func); + zassert_equal(0, ret, + "api: pinctrl_tmpl_mux_set failed %d %s\n", + ret, error(-ret)); + func = TEST_CLIENT_PINCTRL_PINCONF_MUX; + zassert_equal( + 1, + TEST_DATA.mux_set_invocation, + "api: pinctrl_tmpl_mux_set called: %d times", + (int)TEST_DATA.mux_set_invocation); + zassert_equal( + pin, + TEST_DATA.mux_set_pin, + "api: pinctrl_tmpl_mux_set unexpected pin: %d", + (int)TEST_DATA.mux_set_pin); + zassert_equal( + func, + TEST_DATA.mux_set_func, + "api: pinctrl_tmpl_mux_set unexpected func: %d", + (int)TEST_DATA.mux_set_func); +} + +void test_pinctrl_tmpl_mux_group_set(void) +{ + u16_t group; + u16_t func; + + /* normal case */ + mock_reset(); + group = TEST_CLIENT_GROUP; + func = TEST_CLIENT_FUNCTION_DEVICE; + zassert_equal(0, + pinctrl_tmpl_mux_group_set(&TEST_DEVICE, group, func), + "api: pinctrl_tmpl_mux_group_set failed"); + zassert_equal( + TEST_CLIENT_GROUP_PINS, + TEST_DATA.mux_set_invocation, + "api: pinctrl_tmpl_mux_group_set config_set called: %d times", + (int)TEST_DATA.mux_set_invocation); + /* error - unknown function */ + mock_reset(); + group = TEST_CLIENT_GROUP; + func = TEST_FUNCTION_COUNT; + zassert_equal(-ENOTSUP, + pinctrl_tmpl_mux_group_set(&TEST_DEVICE, group, func), + "api: pinctrl_tmpl_mux_group_set failed"); + zassert_equal( + 0, + TEST_DATA.mux_set_invocation, + "api: pinctrl_tmpl_mux_group_set config_set called: %d times", + (int)TEST_DATA.mux_set_invocation); + /* error - unknown group */ + mock_reset(); + group = TEST_STATE_COUNT; + func = TEST_CLIENT_FUNCTION_DEVICE; + zassert_equal(-ENOTSUP, + pinctrl_tmpl_mux_group_set(&TEST_DEVICE, group, func), + "api: pinctrl_tmpl_mux_group_set failed"); + zassert_equal( + 0, + TEST_DATA.mux_set_invocation, + "api: pinctrl_tmpl_mux_group_set config_set called: %d times", + (int)TEST_DATA.mux_set_invocation); +} + +void test_pinctrl_tmpl_state_set(void) +{ + mock_reset(); + int ret = pinctrl_state_set(&TEST_DEVICE, TEST_CLIENT_DEFAULT_STATE); + + zassert_equal( + 0, ret, + "api: pinctrl_state_set failed: %d %s\n", + ret, error(-ret)); +} + +void test_pinctrl_pinmux(void) +{ + mock_reset(); + int ret = pinmux_pin_set(&TEST_DEVICE, 1, 2); + + zassert_equal(0, ret, + "pinctrl_pinmux: pinmux_pin_set() failed: %d %s", + ret, error(-ret)); + zassert_equal(1, + TEST_DATA.mux_set_invocation, + "pinctrl_pinmux: mux_set not called"); +} + +void test_main(void) +{ + ztest_test_suite( + test_pinctrl_tmpl, + ztest_unit_test(test_pinctrl_tmpl_test_data), + ztest_unit_test(test_pinctrl_tmpl_init), + ztest_unit_test(test_pinctrl_tmpl_control_get_pins_count), + ztest_unit_test(test_pinctrl_tmpl_control_get_function_state), + ztest_unit_test(test_pinctrl_tmpl_control_get_function_states), + ztest_unit_test(test_pinctrl_tmpl_control_get_device_function), + ztest_unit_test(test_pinctrl_tmpl_config_group_get), + ztest_unit_test(test_pinctrl_tmpl_config_group_set), + ztest_unit_test(test_pinctrl_tmpl_mux_request_free), + ztest_unit_test(test_pinctrl_tmpl_mux_set), + ztest_unit_test(test_pinctrl_tmpl_mux_group_set), + ztest_unit_test(test_pinctrl_tmpl_state_set), + ztest_unit_test(test_pinctrl_pinmux)); + ztest_run_test_suite(test_pinctrl_tmpl); +} diff --git a/tests/unit/drivers/pinctrl/testcase.yaml b/tests/unit/drivers/pinctrl/testcase.yaml new file mode 100644 index 00000000000000..1df914ff1de016 --- /dev/null +++ b/tests/unit/drivers/pinctrl/testcase.yaml @@ -0,0 +1,5 @@ +tests: + test: + tags: pinctrl_lib + timeout: 5 + type: unit