Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* * Copyright (c) 2016 Open-RnD Sp. z o.o. * * SPDX-License-Identifier: Apache-2.0 */ /** * @brief * * A common driver for STM32 pinmux. Each SoC must implement a SoC * specific part of the driver. */ #include <errno.h> #include <kernel.h> #include <device.h> #include <soc.h> #include <drivers/pinmux.h> #include <gpio/gpio_stm32.h> #include <drivers/clock_control/stm32_clock_control.h> #include <pinmux/stm32/pinmux_stm32.h> #ifdef CONFIG_SOC_SERIES_STM32MP1X #define GPIO_REG_SIZE 0x1000 /* 0x1000 between each port, 0x400 gpio registry 0xC00 reserved */ #else #define GPIO_REG_SIZE 0x400 #endif /* CONFIG_SOC_SERIES_STM32MP1X */ /* base address for where GPIO registers start */ #define GPIO_PORTS_BASE (GPIOA_BASE) static const u32_t ports_enable[STM32_PORTS_MAX] = { STM32_PERIPH_GPIOA, STM32_PERIPH_GPIOB, STM32_PERIPH_GPIOC, #ifdef GPIOD_BASE STM32_PERIPH_GPIOD, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOE_BASE STM32_PERIPH_GPIOE, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOF_BASE STM32_PERIPH_GPIOF, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOG_BASE STM32_PERIPH_GPIOG, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOH_BASE STM32_PERIPH_GPIOH, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOI_BASE STM32_PERIPH_GPIOI, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOJ_BASE STM32_PERIPH_GPIOJ, #else STM32_PORT_NOT_AVAILABLE, #endif #ifdef GPIOK_BASE STM32_PERIPH_GPIOK, #else STM32_PORT_NOT_AVAILABLE, #endif }; /** * @brief enable IO port clock * * @param port I/O port ID * @param clk optional clock device * * @return 0 on success, error otherwise */ static int enable_port(u32_t port, struct device *clk) { /* enable port clock */ if (!clk) { clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); } struct stm32_pclken pclken; pclken.bus = STM32_CLOCK_BUS_GPIO; pclken.enr = ports_enable[port]; if (pclken.enr == STM32_PORT_NOT_AVAILABLE) { return -EIO; } return clock_control_on(clk, (clock_control_subsys_t *) &pclken); } static int stm32_pin_configure(int pin, int func, int altf) { /* determine IO port registers location */ u32_t offset = STM32_PORT(pin) * GPIO_REG_SIZE; u8_t *port_base = (u8_t *)(GPIO_PORTS_BASE + offset); /* not much here, on STM32F10x the alternate function is * controller by setting up GPIO pins in specific mode. */ return gpio_stm32_configure((u32_t *)port_base, STM32_PIN(pin), func, altf); } /** * @brief pin setup * * @param pin STM32PIN() encoded pin ID * @param func SoC specific function assignment * @param clk optional clock device * * @return 0 on success, error otherwise */ int z_pinmux_stm32_set(u32_t pin, u32_t func, struct device *clk) { /* make sure to enable port clock first */ if (enable_port(STM32_PORT(pin), clk)) { return -EIO; } return stm32_pin_configure(pin, func, func & STM32_AFR_MASK); } /** * @brief setup pins according to their assignments * * @param pinconf board pin configuration array * @param pins array size */ void stm32_setup_pins(const struct pin_config *pinconf, size_t pins) { struct device *clk; int i; clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); for (i = 0; i < pins; i++) { z_pinmux_stm32_set(pinconf[i].pin_num, pinconf[i].mode, clk); } } |