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 | /* * 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 <pinmux.h> #include <gpio/gpio_stm32.h> #include <clock_control/stm32_clock_control.h> #include <pinmux/stm32/pinmux_stm32.h> #include "pinmux.h" static const u32_t ports_enable[STM32_PORTS_MAX] = { STM32_PERIPH_GPIOA, STM32_PERIPH_GPIOB, STM32_PERIPH_GPIOC, #ifdef GPIOD_BASE STM32_PERIPH_GPIOD, #endif #ifdef GPIOE_BASE STM32_PERIPH_GPIOE, #endif #ifdef GPIOF_BASE STM32_PERIPH_GPIOF, #endif #ifdef GPIOG_BASE STM32_PERIPH_GPIOG, #endif #ifdef GPIOH_BASE STM32_PERIPH_GPIOH, #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]; 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 stm32_gpio_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 _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++) { _pinmux_stm32_set(pinconf[i].pin_num, pinconf[i].mode, clk); } } |