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 <stm32f10x_gpio.h>
14 #include <stm32f10x_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     }
34 }
35 
enable_port(unsigned int port)36 static void enable_port(unsigned int port) {
37     DEBUG_ASSERT(port <= GPIO_PORT_G);
38 
39     /* happens to be the RCC ids are sequential bits, so we can start from A and shift */
40     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << port, ENABLE);
41 }
42 
stm32_gpio_early_init(void)43 void stm32_gpio_early_init(void) {
44     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
45 }
46 
gpio_config(unsigned nr,unsigned flags)47 int gpio_config(unsigned nr, unsigned flags) {
48     uint port = GPIO_PORT(nr);
49     uint pin = GPIO_PIN(nr);
50 
51     enable_port(port);
52 
53     GPIO_InitTypeDef init;
54     init.GPIO_Speed = GPIO_Speed_50MHz;
55 
56     init.GPIO_Pin = (1 << pin);
57 
58     if (flags & GPIO_STM32_AF) {
59         if (flags & GPIO_STM32_OD)
60             init.GPIO_Mode = GPIO_Mode_Out_OD;
61         else
62             init.GPIO_Mode = GPIO_Mode_AF_PP;
63     } else if (flags & GPIO_OUTPUT) {
64         if (flags & GPIO_STM32_OD)
65             init.GPIO_Mode = GPIO_Mode_Out_OD;
66         else
67             init.GPIO_Mode = GPIO_Mode_Out_PP;
68     } else { // GPIO_INPUT
69         if (flags & GPIO_PULLUP) {
70             init.GPIO_Mode = GPIO_Mode_IPU;
71         } else if (flags & GPIO_PULLDOWN) {
72             init.GPIO_Mode = GPIO_Mode_IPD;
73         } else {
74             init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
75         }
76     }
77 
78     GPIO_Init(port_to_pointer(port), &init);
79 
80     return 0;
81 }
82 
gpio_set(unsigned nr,unsigned on)83 void gpio_set(unsigned nr, unsigned on) {
84     GPIO_WriteBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr), on);
85 }
86 
gpio_get(unsigned nr)87 int gpio_get(unsigned nr) {
88     return GPIO_ReadInputDataBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
89 }
90 
91