/drivers/pinmux/stm32/pinmux_stm32.c

https://github.com/zephyrproject-rtos/zephyr · C · 158 lines · 99 code · 17 blank · 42 comment · 5 complexity · 5055706460f2ca073a37b5d8ee0d7360 MD5 · raw file

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