123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /*
- * Copyright (c) 2019, Linaro Limited
- * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <string.h>
- #include <assert.h>
- #include <lib/mmio.h>
- #include <drivers/delay_timer.h>
- #include <drivers/rpi3/gpio/rpi3_gpio.h>
- #include <platform_def.h>
- static uintptr_t reg_base;
- static int rpi3_gpio_get_direction(int gpio);
- static void rpi3_gpio_set_direction(int gpio, int direction);
- static int rpi3_gpio_get_value(int gpio);
- static void rpi3_gpio_set_value(int gpio, int value);
- static void rpi3_gpio_set_pull(int gpio, int pull);
- static const gpio_ops_t rpi3_gpio_ops = {
- .get_direction = rpi3_gpio_get_direction,
- .set_direction = rpi3_gpio_set_direction,
- .get_value = rpi3_gpio_get_value,
- .set_value = rpi3_gpio_set_value,
- .set_pull = rpi3_gpio_set_pull,
- };
- /**
- * Get selection of GPIO pinmux settings.
- *
- * @param gpio The pin number of GPIO. From 0 to 53.
- * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
- * RPI3_GPIO_FUNC_OUTPUT: output,
- * RPI3_GPIO_FUNC_ALT0: alt-0,
- * RPI3_GPIO_FUNC_ALT1: alt-1,
- * RPI3_GPIO_FUNC_ALT2: alt-2,
- * RPI3_GPIO_FUNC_ALT3: alt-3,
- * RPI3_GPIO_FUNC_ALT4: alt-4,
- * RPI3_GPIO_FUNC_ALT5: alt-5
- */
- int rpi3_gpio_get_select(int gpio)
- {
- int ret;
- int regN = gpio / 10;
- int shift = 3 * (gpio % 10);
- uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
- uint32_t sel = mmio_read_32(reg_sel);
- ret = (sel >> shift) & 0x07;
- return ret;
- }
- /**
- * Set selection of GPIO pinmux settings.
- *
- * @param gpio The pin number of GPIO. From 0 to 53.
- * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
- * RPI3_GPIO_FUNC_OUTPUT: output,
- * RPI3_GPIO_FUNC_ALT0: alt-0,
- * RPI3_GPIO_FUNC_ALT1: alt-1,
- * RPI3_GPIO_FUNC_ALT2: alt-2,
- * RPI3_GPIO_FUNC_ALT3: alt-3,
- * RPI3_GPIO_FUNC_ALT4: alt-4,
- * RPI3_GPIO_FUNC_ALT5: alt-5
- */
- void rpi3_gpio_set_select(int gpio, int fsel)
- {
- int regN = gpio / 10;
- int shift = 3 * (gpio % 10);
- uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
- uint32_t sel = mmio_read_32(reg_sel);
- uint32_t mask = U(0x07) << shift;
- sel = (sel & (~mask)) | ((fsel << shift) & mask);
- mmio_write_32(reg_sel, sel);
- }
- static int rpi3_gpio_get_direction(int gpio)
- {
- int result = rpi3_gpio_get_select(gpio);
- if (result == RPI3_GPIO_FUNC_INPUT)
- return GPIO_DIR_IN;
- else if (result == RPI3_GPIO_FUNC_OUTPUT)
- return GPIO_DIR_OUT;
- return GPIO_DIR_IN;
- }
- static void rpi3_gpio_set_direction(int gpio, int direction)
- {
- switch (direction) {
- case GPIO_DIR_IN:
- rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT);
- break;
- case GPIO_DIR_OUT:
- rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT);
- break;
- }
- }
- static int rpi3_gpio_get_value(int gpio)
- {
- int regN = gpio / 32;
- int shift = gpio % 32;
- uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN);
- uint32_t value = mmio_read_32(reg_lev);
- if ((value >> shift) & 0x01)
- return GPIO_LEVEL_HIGH;
- return GPIO_LEVEL_LOW;
- }
- static void rpi3_gpio_set_value(int gpio, int value)
- {
- int regN = gpio / 32;
- int shift = gpio % 32;
- uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN);
- uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN);
- switch (value) {
- case GPIO_LEVEL_LOW:
- mmio_write_32(reg_clr, U(1) << shift);
- break;
- case GPIO_LEVEL_HIGH:
- mmio_write_32(reg_set, U(1) << shift);
- break;
- }
- }
- static void rpi3_gpio_set_pull(int gpio, int pull)
- {
- int regN = gpio / 32;
- int shift = gpio % 32;
- uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD;
- uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN);
- switch (pull) {
- case GPIO_PULL_NONE:
- mmio_write_32(reg_pud, 0x0);
- break;
- case GPIO_PULL_UP:
- mmio_write_32(reg_pud, 0x2);
- break;
- case GPIO_PULL_DOWN:
- mmio_write_32(reg_pud, 0x1);
- break;
- }
- mdelay(150);
- mmio_write_32(reg_clk, U(1) << shift);
- mdelay(150);
- mmio_write_32(reg_clk, 0x0);
- mmio_write_32(reg_pud, 0x0);
- }
- void rpi3_gpio_init(void)
- {
- reg_base = RPI3_GPIO_BASE;
- gpio_init(&rpi3_gpio_ops);
- }
|