blob: d264d8b3182288aa2e4321eb87d99df7d8d3aee1 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2012 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <debug.h>
24#include <assert.h>
25#include <dev/gpio.h>
26#include <platform/stm32.h>
27#include <platform/gpio.h>
28#include <stm32f10x_gpio.h>
29#include <stm32f10x_rcc.h>
30
31static GPIO_TypeDef *port_to_pointer(unsigned int port)
32{
33 switch (port) {
34 default:
35 case GPIO_PORT_A:
36 return GPIOA;
37 case GPIO_PORT_B:
38 return GPIOB;
39 case GPIO_PORT_C:
40 return GPIOC;
41 case GPIO_PORT_D:
42 return GPIOD;
43 case GPIO_PORT_E:
44 return GPIOE;
45 case GPIO_PORT_F:
46 return GPIOF;
47 case GPIO_PORT_G:
48 return GPIOG;
49 }
50}
51
52static void enable_port(unsigned int port)
53{
54 DEBUG_ASSERT(port <= GPIO_PORT_G);
55
56 /* happens to be the RCC ids are sequential bits, so we can start from A and shift */
57 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << port, ENABLE);
58}
59
60void stm32_gpio_early_init(void)
61{
62 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
63}
64
65int gpio_config(unsigned nr, unsigned flags)
66{
67 uint port = GPIO_PORT(nr);
68 uint pin = GPIO_PIN(nr);
69
70 enable_port(port);
71
72 GPIO_InitTypeDef init;
73 init.GPIO_Speed = GPIO_Speed_50MHz;
74
75 init.GPIO_Pin = (1 << pin);
76
77 if (flags & GPIO_STM32_AF) {
78 if (flags & GPIO_STM32_OD)
79 init.GPIO_Mode = GPIO_Mode_Out_OD;
80 else
81 init.GPIO_Mode = GPIO_Mode_AF_PP;
82 } else if (flags & GPIO_OUTPUT) {
83 if (flags & GPIO_STM32_OD)
84 init.GPIO_Mode = GPIO_Mode_Out_OD;
85 else
86 init.GPIO_Mode = GPIO_Mode_Out_PP;
87 } else { // GPIO_INPUT
88 if (flags & GPIO_PULLUP) {
89 init.GPIO_Mode = GPIO_Mode_IPU;
90 } else if (flags & GPIO_PULLDOWN) {
91 init.GPIO_Mode = GPIO_Mode_IPD;
92 } else {
93 init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
94 }
95 }
96
97 GPIO_Init(port_to_pointer(port), &init);
98
99 return 0;
100}
101
102void gpio_set(unsigned nr, unsigned on)
103{
104 GPIO_WriteBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr), on);
105}
106
107int gpio_get(unsigned nr)
108{
109 return GPIO_ReadInputDataBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
110}
111