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