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