1 /*
2  * Copyright (c) 2012-2015 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/debug.h>
9 #include <lk/err.h>
10 #include <assert.h>
11 #include <dev/gpio.h>
12 #include <platform/stm32.h>
13 #include <platform/gpio.h>
14 
port_to_pointer(unsigned int port)15 static GPIO_TypeDef *port_to_pointer(unsigned int port) {
16     DEBUG_ASSERT(port <= GPIO_PORT_K);
17 
18     switch (port) {
19         default:
20         case GPIO_PORT_A:
21             return GPIOA;
22         case GPIO_PORT_B:
23             return GPIOB;
24         case GPIO_PORT_C:
25             return GPIOC;
26         case GPIO_PORT_D:
27             return GPIOD;
28         case GPIO_PORT_E:
29             return GPIOE;
30         case GPIO_PORT_F:
31             return GPIOF;
32         case GPIO_PORT_G:
33             return GPIOG;
34         case GPIO_PORT_H:
35             return GPIOH;
36         case GPIO_PORT_I:
37             return GPIOI;
38         case GPIO_PORT_J:
39             return GPIOJ;
40         case GPIO_PORT_K:
41             return GPIOK;
42     }
43 }
44 
enable_port(unsigned int port)45 static void enable_port(unsigned int port) {
46     DEBUG_ASSERT(port <= GPIO_PORT_K);
47 
48     switch (port) {
49         case GPIO_PORT_A:
50             __HAL_RCC_GPIOA_CLK_ENABLE();
51             break;
52         case GPIO_PORT_B:
53             __HAL_RCC_GPIOB_CLK_ENABLE();
54             break;
55         case GPIO_PORT_C:
56             __HAL_RCC_GPIOC_CLK_ENABLE();
57             break;
58         case GPIO_PORT_D:
59             __HAL_RCC_GPIOD_CLK_ENABLE();
60             break;
61         case GPIO_PORT_E:
62             __HAL_RCC_GPIOE_CLK_ENABLE();
63             break;
64         case GPIO_PORT_F:
65             __HAL_RCC_GPIOF_CLK_ENABLE();
66             break;
67         case GPIO_PORT_G:
68             __HAL_RCC_GPIOG_CLK_ENABLE();
69             break;
70         case GPIO_PORT_H:
71             __HAL_RCC_GPIOH_CLK_ENABLE();
72             break;
73         case GPIO_PORT_I:
74             __HAL_RCC_GPIOI_CLK_ENABLE();
75             break;
76         case GPIO_PORT_J:
77             __HAL_RCC_GPIOJ_CLK_ENABLE();
78             break;
79         case GPIO_PORT_K:
80             __HAL_RCC_GPIOK_CLK_ENABLE();
81             break;
82     }
83 }
84 
stm32_gpio_early_init(void)85 void stm32_gpio_early_init(void) {
86 }
87 
gpio_config(unsigned nr,unsigned flags)88 int gpio_config(unsigned nr, unsigned flags) {
89     uint port = GPIO_PORT(nr);
90     uint pin = GPIO_PIN(nr);
91 
92     enable_port(port);
93 
94     GPIO_InitTypeDef init;
95     init.Speed = GPIO_SPEED_HIGH;
96     init.Pin = (1 << pin);
97     init.Alternate = 0;
98 
99     if (flags & GPIO_INPUT) {
100         init.Mode = GPIO_MODE_INPUT;
101     } else if (flags & GPIO_OUTPUT) {
102         if (flags & GPIO_STM32_OD) {
103             init.Mode = GPIO_MODE_OUTPUT_OD;
104         } else {
105             init.Mode = GPIO_MODE_OUTPUT_PP;
106         }
107     } else if (flags & GPIO_STM32_AF) {
108         if (flags & GPIO_STM32_OD) {
109             init.Mode = GPIO_MODE_AF_OD;
110         } else {
111             init.Mode = GPIO_MODE_AF_PP;
112         }
113         init.Alternate = GPIO_AFNUM(flags);
114     } else {
115         panic("stm32f7: invalid args to gpio_config\n");
116         return ERR_INVALID_ARGS;
117     }
118 
119     if (flags & GPIO_PULLUP) {
120         init.Pull = GPIO_PULLUP;
121     } else if (flags & GPIO_PULLDOWN) {
122         init.Pull = GPIO_PULLDOWN;
123     } else {
124         init.Pull = GPIO_NOPULL;
125     }
126 
127     HAL_GPIO_Init(port_to_pointer(port), &init);
128 
129     return 0;
130 }
131 
gpio_set(unsigned nr,unsigned on)132 void gpio_set(unsigned nr, unsigned on) {
133     HAL_GPIO_WritePin(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr), on);
134 }
135 
gpio_get(unsigned nr)136 int gpio_get(unsigned nr) {
137     return HAL_GPIO_ReadPin(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
138 }
139 
140