1 /*
2  * Copyright (c) 2012 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 <assert.h>
10 #include <dev/gpio.h>
11 #include <platform/stm32.h>
12 #include <platform/gpio.h>
13 #include <stm32f4xx_gpio.h>
14 #include <stm32f4xx_rcc.h>
15 
port_to_pointer(unsigned int port)16 static GPIO_TypeDef *port_to_pointer(unsigned int port) {
17     switch (port) {
18         default:
19         case GPIO_PORT_A:
20             return GPIOA;
21         case GPIO_PORT_B:
22             return GPIOB;
23         case GPIO_PORT_C:
24             return GPIOC;
25         case GPIO_PORT_D:
26             return GPIOD;
27         case GPIO_PORT_E:
28             return GPIOE;
29         case GPIO_PORT_F:
30             return GPIOF;
31         case GPIO_PORT_G:
32             return GPIOG;
33         case GPIO_PORT_H:
34             return GPIOH;
35         case GPIO_PORT_I:
36             return GPIOI;
37     }
38 }
39 
enable_port(unsigned int port)40 static void enable_port(unsigned int port) {
41     DEBUG_ASSERT(port <= GPIO_PORT_I);
42 
43     /* happens to be the RCC ids are sequential bits, so we can start from A and shift */
44     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA << port, ENABLE);
45 }
46 
stm32_gpio_early_init(void)47 void stm32_gpio_early_init(void) {
48 }
49 
gpio_config(unsigned nr,unsigned flags)50 int gpio_config(unsigned nr, unsigned flags) {
51 
52     uint port = GPIO_PORT(nr);
53     uint pin = GPIO_PIN(nr);
54 
55     enable_port(port);
56 
57     GPIO_InitTypeDef init;
58     init.GPIO_Speed = GPIO_Speed_50MHz;
59     init.GPIO_Pin = (1 << pin);
60     init.GPIO_PuPd = GPIO_PuPd_NOPULL;
61 
62     if (flags & GPIO_INPUT) {
63         init.GPIO_Mode = GPIO_Mode_IN;
64     } else if  (flags & GPIO_OUTPUT) {
65         init.GPIO_Mode = GPIO_Mode_OUT;
66     } else if  (flags & GPIO_STM32_AF) {
67         init.GPIO_Mode = GPIO_Mode_AF;
68         GPIO_PinAFConfig(port_to_pointer(port), pin, GPIO_AFNUM(flags));
69     }
70 
71     if (flags & GPIO_PULLUP) {
72         init.GPIO_PuPd = GPIO_PuPd_UP;
73     } else if (flags & GPIO_PULLDOWN) {
74         init.GPIO_PuPd = GPIO_PuPd_DOWN;
75     }
76 
77     if (flags & GPIO_STM32_OD) {
78         init.GPIO_OType = GPIO_OType_OD;
79     } else {
80         init.GPIO_OType = GPIO_OType_PP;
81     }
82 
83     GPIO_Init(port_to_pointer(port), &init);
84 
85     return 0;
86 }
87 
gpio_set(unsigned nr,unsigned on)88 void gpio_set(unsigned nr, unsigned on) {
89     GPIO_WriteBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr), on);
90 }
91 
gpio_get(unsigned nr)92 int gpio_get(unsigned nr) {
93     return GPIO_ReadInputDataBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
94 }
95 
96