1 /* 2 * Copyright (c) 2019, Linaro Limited 3 * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <string.h> 9 #include <assert.h> 10 #include <lib/mmio.h> 11 #include <drivers/delay_timer.h> 12 #include <drivers/rpi3/gpio/rpi3_gpio.h> 13 14 static uintptr_t reg_base; 15 16 static int rpi3_gpio_get_direction(int gpio); 17 static void rpi3_gpio_set_direction(int gpio, int direction); 18 static int rpi3_gpio_get_value(int gpio); 19 static void rpi3_gpio_set_value(int gpio, int value); 20 static void rpi3_gpio_set_pull(int gpio, int pull); 21 22 static const gpio_ops_t rpi3_gpio_ops = { 23 .get_direction = rpi3_gpio_get_direction, 24 .set_direction = rpi3_gpio_set_direction, 25 .get_value = rpi3_gpio_get_value, 26 .set_value = rpi3_gpio_set_value, 27 .set_pull = rpi3_gpio_set_pull, 28 }; 29 30 /** 31 * Get selection of GPIO pinmux settings. 32 * 33 * @param gpio The pin number of GPIO. From 0 to 53. 34 * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, 35 * RPI3_GPIO_FUNC_OUTPUT: output, 36 * RPI3_GPIO_FUNC_ALT0: alt-0, 37 * RPI3_GPIO_FUNC_ALT1: alt-1, 38 * RPI3_GPIO_FUNC_ALT2: alt-2, 39 * RPI3_GPIO_FUNC_ALT3: alt-3, 40 * RPI3_GPIO_FUNC_ALT4: alt-4, 41 * RPI3_GPIO_FUNC_ALT5: alt-5 42 */ 43 int rpi3_gpio_get_select(int gpio) 44 { 45 int ret; 46 int regN = gpio / 10; 47 int shift = 3 * (gpio % 10); 48 uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); 49 uint32_t sel = mmio_read_32(reg_sel); 50 51 ret = (sel >> shift) & 0x07; 52 53 return ret; 54 } 55 56 /** 57 * Set selection of GPIO pinmux settings. 58 * 59 * @param gpio The pin number of GPIO. From 0 to 53. 60 * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, 61 * RPI3_GPIO_FUNC_OUTPUT: output, 62 * RPI3_GPIO_FUNC_ALT0: alt-0, 63 * RPI3_GPIO_FUNC_ALT1: alt-1, 64 * RPI3_GPIO_FUNC_ALT2: alt-2, 65 * RPI3_GPIO_FUNC_ALT3: alt-3, 66 * RPI3_GPIO_FUNC_ALT4: alt-4, 67 * RPI3_GPIO_FUNC_ALT5: alt-5 68 */ 69 void rpi3_gpio_set_select(int gpio, int fsel) 70 { 71 int regN = gpio / 10; 72 int shift = 3 * (gpio % 10); 73 uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); 74 uint32_t sel = mmio_read_32(reg_sel); 75 uint32_t mask = U(0x07) << shift; 76 77 sel = (sel & (~mask)) | ((fsel << shift) & mask); 78 mmio_write_32(reg_sel, sel); 79 } 80 81 static int rpi3_gpio_get_direction(int gpio) 82 { 83 int result = rpi3_gpio_get_select(gpio); 84 85 if (result == RPI3_GPIO_FUNC_INPUT) 86 return GPIO_DIR_IN; 87 else if (result == RPI3_GPIO_FUNC_OUTPUT) 88 return GPIO_DIR_OUT; 89 90 return GPIO_DIR_IN; 91 } 92 93 static void rpi3_gpio_set_direction(int gpio, int direction) 94 { 95 switch (direction) { 96 case GPIO_DIR_IN: 97 rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT); 98 break; 99 case GPIO_DIR_OUT: 100 rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT); 101 break; 102 } 103 } 104 105 static int rpi3_gpio_get_value(int gpio) 106 { 107 int regN = gpio / 32; 108 int shift = gpio % 32; 109 uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN); 110 uint32_t value = mmio_read_32(reg_lev); 111 112 if ((value >> shift) & 0x01) 113 return GPIO_LEVEL_HIGH; 114 return GPIO_LEVEL_LOW; 115 } 116 117 static void rpi3_gpio_set_value(int gpio, int value) 118 { 119 int regN = gpio / 32; 120 int shift = gpio % 32; 121 uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN); 122 uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN); 123 124 switch (value) { 125 case GPIO_LEVEL_LOW: 126 mmio_write_32(reg_clr, U(1) << shift); 127 break; 128 case GPIO_LEVEL_HIGH: 129 mmio_write_32(reg_set, U(1) << shift); 130 break; 131 } 132 } 133 134 static void rpi3_gpio_set_pull(int gpio, int pull) 135 { 136 int regN = gpio / 32; 137 int shift = gpio % 32; 138 uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD; 139 uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN); 140 141 switch (pull) { 142 case GPIO_PULL_NONE: 143 mmio_write_32(reg_pud, 0x0); 144 break; 145 case GPIO_PULL_UP: 146 mmio_write_32(reg_pud, 0x2); 147 break; 148 case GPIO_PULL_DOWN: 149 mmio_write_32(reg_pud, 0x1); 150 break; 151 } 152 mdelay(150); 153 mmio_write_32(reg_clk, U(1) << shift); 154 mdelay(150); 155 mmio_write_32(reg_clk, 0x0); 156 mmio_write_32(reg_pud, 0x0); 157 } 158 159 void rpi3_gpio_init(void) 160 { 161 reg_base = RPI3_GPIO_BASE; 162 gpio_init(&rpi3_gpio_ops); 163 } 164