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