aboutsummaryrefslogtreecommitdiff
path: root/src/soc/broadcom/cygnus/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/broadcom/cygnus/gpio.c')
-rw-r--r--src/soc/broadcom/cygnus/gpio.c501
1 files changed, 0 insertions, 501 deletions
diff --git a/src/soc/broadcom/cygnus/gpio.c b/src/soc/broadcom/cygnus/gpio.c
deleted file mode 100644
index 9c4ef24079..0000000000
--- a/src/soc/broadcom/cygnus/gpio.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
-* Copyright (C) 2015 Broadcom Corporation
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation version 2.
-*
-* This program is distributed "as is" WITHOUT ANY WARRANTY of any
-* kind, whether express or implied; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*/
-
-#include <arch/io.h>
-#include <console/console.h>
-#include <gpio.h>
-#include <stdlib.h>
-#include <delay.h>
-
-#define dev_dbg(chip, fmt, args...) printk(BIOS_DEBUG, "[%s] " fmt, \
- chip->label, args)
-
-#define CYGNUS_GPIO_DATA_IN_OFFSET 0x00
-#define CYGNUS_GPIO_DATA_OUT_OFFSET 0x04
-#define CYGNUS_GPIO_OUT_EN_OFFSET 0x08
-#define CYGNUS_GPIO_IN_TYPE_OFFSET 0x0c
-#define CYGNUS_GPIO_INT_DE_OFFSET 0x10
-#define CYGNUS_GPIO_INT_EDGE_OFFSET 0x14
-#define CYGNUS_GPIO_INT_MSK_OFFSET 0x18
-#define CYGNUS_GPIO_INT_STAT_OFFSET 0x1c
-#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
-#define CYGNUS_GPIO_INT_CLR_OFFSET 0x24
-#define CYGNUS_GPIO_PAD_RES_OFFSET 0x34
-#define CYGNUS_GPIO_RES_EN_OFFSET 0x38
-
-/* drive strength control for ASIU GPIO */
-#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
-
-/* drive strength control for CCM/CRMU (AON) GPIO */
-#define CYGNUS_GPIO_DRV0_CTRL_OFFSET 0x00
-
-#define GPIO_BANK_SIZE 0x200
-#define NGPIOS_PER_BANK 32
-#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
-
-#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
-#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
-
-#define GPIO_DRV_STRENGTH_BIT_SHIFT 20
-#define GPIO_DRV_STRENGTH_BITS 3
-#define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
-
-/*
- * Cygnus GPIO core
- *
- * @base: I/O register base for Cygnus GPIO controller
- * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
- * has the PINCONF support implemented outside of the GPIO block
- * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
- * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
- * that can be individually muxed to GPIO
- * @pctl_priv: pointer to pinctrl handle
- */
-struct cygnus_gpio {
- void *base;
- void *io_ctrl;
- const char *label;
- int gpio_base;
- u16 ngpio;
- unsigned num_banks;
- int pinmux_is_supported;
- void *pctl_priv;
-};
-
-/*
- * GPIO cores table
- *
- * Cygnus has 3 gpio cores. The tables contains descriptors of those cores.
- */
-struct cygnus_gpio cygnus_gpio_table[] = {
- {
- .base = (void *)0x03024800,
- .io_ctrl = (void *)0x03024008,
- .label = "gpio_crmu",
- .gpio_base = 170,
- .ngpio = 6,
- },
- {
- .base = (void *)0x1800a000,
- .io_ctrl = (void *)0x0301d164,
- .label = "gpio_ccm",
- .gpio_base = 0,
- .ngpio = 24,
- },
- {
- .base = (void *)0x180a5000,
- .label = "gpio_asiu",
- .gpio_base = 24,
- .ngpio = 146,
- .pinmux_is_supported = 1
- }
-};
-
-/*
- * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
- * pinctrl pin space
- */
-struct cygnus_gpio_pin_range {
- unsigned offset;
- unsigned pin_base;
- unsigned num_pins;
-};
-
-#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
-
-/*
- * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins.
- * This is for ASIU gpio. The offset is based on ASIU gpios.
- */
-static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
- CYGNUS_PINRANGE(0, 42, 1),
- CYGNUS_PINRANGE(1, 44, 3),
- CYGNUS_PINRANGE(4, 48, 1),
- CYGNUS_PINRANGE(5, 50, 3),
- CYGNUS_PINRANGE(8, 126, 1),
- CYGNUS_PINRANGE(9, 155, 1),
- CYGNUS_PINRANGE(10, 152, 1),
- CYGNUS_PINRANGE(11, 154, 1),
- CYGNUS_PINRANGE(12, 153, 1),
- CYGNUS_PINRANGE(13, 127, 3),
- CYGNUS_PINRANGE(16, 140, 1),
- CYGNUS_PINRANGE(17, 145, 7),
- CYGNUS_PINRANGE(24, 130, 10),
- CYGNUS_PINRANGE(34, 141, 4),
- CYGNUS_PINRANGE(38, 54, 1),
- CYGNUS_PINRANGE(39, 56, 3),
- CYGNUS_PINRANGE(42, 60, 3),
- CYGNUS_PINRANGE(45, 64, 3),
- CYGNUS_PINRANGE(48, 68, 2),
- CYGNUS_PINRANGE(50, 84, 6),
- CYGNUS_PINRANGE(56, 94, 6),
- CYGNUS_PINRANGE(62, 72, 1),
- CYGNUS_PINRANGE(63, 70, 1),
- CYGNUS_PINRANGE(64, 80, 1),
- CYGNUS_PINRANGE(65, 74, 3),
- CYGNUS_PINRANGE(68, 78, 1),
- CYGNUS_PINRANGE(69, 82, 1),
- CYGNUS_PINRANGE(70, 156, 17),
- CYGNUS_PINRANGE(87, 104, 12),
- CYGNUS_PINRANGE(99, 102, 2),
- CYGNUS_PINRANGE(101, 90, 4),
- CYGNUS_PINRANGE(105, 116, 10),
- CYGNUS_PINRANGE(123, 11, 1),
- CYGNUS_PINRANGE(124, 38, 4),
- CYGNUS_PINRANGE(128, 43, 1),
- CYGNUS_PINRANGE(129, 47, 1),
- CYGNUS_PINRANGE(130, 49, 1),
- CYGNUS_PINRANGE(131, 53, 1),
- CYGNUS_PINRANGE(132, 55, 1),
- CYGNUS_PINRANGE(133, 59, 1),
- CYGNUS_PINRANGE(134, 63, 1),
- CYGNUS_PINRANGE(135, 67, 1),
- CYGNUS_PINRANGE(136, 71, 1),
- CYGNUS_PINRANGE(137, 73, 1),
- CYGNUS_PINRANGE(138, 77, 1),
- CYGNUS_PINRANGE(139, 79, 1),
- CYGNUS_PINRANGE(140, 81, 1),
- CYGNUS_PINRANGE(141, 83, 1),
- CYGNUS_PINRANGE(142, 10, 1)
-};
-
-static unsigned cygnus_gpio_to_pin(unsigned gpio)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
- const struct cygnus_gpio_pin_range *range = cygnus_gpio_pintable
- + i;
-
- if ((gpio < range->offset) ||
- (gpio >= (range->offset + range->num_pins)))
- continue;
-
- return range->pin_base + (gpio - range->offset);
- }
- return -1;
-}
-
-static struct cygnus_gpio *cygnus_get_gpio_core(unsigned gpio,
- unsigned *gpio_offset)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cygnus_gpio_table); i++) {
- struct cygnus_gpio *chip = cygnus_gpio_table + i;
-
- if ((gpio < chip->gpio_base) ||
- (gpio >= (chip->gpio_base + chip->ngpio)))
- continue;
-
- *gpio_offset = gpio - chip->gpio_base;
- return chip;
- }
-
- return NULL;
-}
-
-static u32 cygnus_readl(struct cygnus_gpio *chip, unsigned int offset)
-{
- return read32(chip->base + offset);
-}
-
-static void cygnus_writel(struct cygnus_gpio *chip, unsigned int offset,
- u32 val)
-{
- write32(chip->base + offset, val);
-}
-
-/**
- * cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
- * Cygnus GPIO register
- *
- * @cygnus_gpio: Cygnus GPIO device
- * @reg: register offset
- * @gpio: GPIO pin
- * @set: set or clear. 1 - set; 0 -clear
- */
-static void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
- unsigned gpio, int set)
-{
- unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
- u32 val;
-
- val = cygnus_readl(chip, offset);
- if (set)
- val |= BIT(shift);
- else
- val &= ~BIT(shift);
- cygnus_writel(chip, offset, val);
-}
-
-static int cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
- unsigned gpio)
-{
- unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
- u32 val;
-
- val = cygnus_readl(chip, offset) & BIT(shift);
- if (val)
- return 1;
- else
- return 0;
-}
-
-/*
- * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
- */
-static int cygnus_gpio_request(struct cygnus_gpio *chip, unsigned offset)
-{
- /* not all Cygnus GPIO pins can be muxed individually */
- if (!chip->pinmux_is_supported || (chip->pctl_priv == NULL))
- return 0;
-
- return cygnus_gpio_request_enable(chip->pctl_priv,
- cygnus_gpio_to_pin(offset));
-}
-
-static void cygnus_gpio_free(struct cygnus_gpio *chip, unsigned offset)
-{
- if (!chip->pinmux_is_supported || (chip->pctl_priv == NULL))
- return;
-
- cygnus_gpio_disable_free(chip->pctl_priv, cygnus_gpio_to_pin(offset));
-}
-
-static int cygnus_gpio_direction_input(struct cygnus_gpio *chip, unsigned gpio)
-{
- cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, 0);
-
- dev_dbg(chip, "gpio:%u set input\n", gpio);
-
- return 0;
-}
-
-static int cygnus_gpio_direction_output(struct cygnus_gpio *chip, unsigned gpio,
- int value)
-{
- cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, 1);
- cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, value);
-
- dev_dbg(chip, "gpio:%u set output, value:%d\n", gpio, value);
-
- return 0;
-}
-
-static void cygnus_gpio_set(struct cygnus_gpio *chip, unsigned gpio, int value)
-{
- cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, value);
-
- dev_dbg(chip, "gpio:%u set, value:%d\n", gpio, value);
-}
-
-static int cygnus_gpio_get(struct cygnus_gpio *chip, unsigned gpio)
-{
- return cygnus_get_bit(chip, CYGNUS_GPIO_DATA_IN_OFFSET, gpio);
-}
-
-static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
- int disable, int pull_up)
-{
- if (disable) {
- cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, 0);
- } else {
- cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio, pull_up);
- cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, 1);
- }
-
- dev_dbg(chip, "gpio:%u set pullup:%d\n", gpio, pull_up);
-
- return 0;
-}
-
-#define CYGNUS_GPIO_TEST_AON_GPIO0 170
-#define CYGNUS_GPIO_TEST_SPI2_MISO 69
-#define CYGNUS_GPIO_TEST_DELAY_S 3
-
-static void cygnus_gpio_test(void)
-{
- gpio_t gpio_in;
- gpio_t gpio_out;
- unsigned val;
-
- printk(BIOS_INFO, "Start gpio test...\n");
-
- gpio_in = CYGNUS_GPIO_TEST_AON_GPIO0; /* AON_GPIO0 */
- gpio_input(gpio_in);
- gpio_input_pulldown(gpio_in);
- printk(BIOS_INFO, "GPIO get %d=%d\n", gpio_in, gpio_get(gpio_in));
-
- gpio_in = CYGNUS_GPIO_TEST_SPI2_MISO; /* SPI2_MISO */
- gpio_input(gpio_in);
- gpio_input_pullup(gpio_in);
- printk(BIOS_INFO, "GPIO get %d=%d\n", gpio_in, gpio_get(gpio_in));
- val = 0;
- gpio_out = CYGNUS_GPIO_TEST_SPI2_MISO;
-
- gpio_output(gpio_out, val);
- printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
- delay(CYGNUS_GPIO_TEST_DELAY_S);
-
- val = 1;
- gpio_set(gpio_out, val);
- printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
- delay(CYGNUS_GPIO_TEST_DELAY_S);
-
- val = 0;
- gpio_set(gpio_out, val);
- printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
- delay(CYGNUS_GPIO_TEST_DELAY_S);
-
- val = 1;
- gpio_set(gpio_out, val);
- printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
- delay(CYGNUS_GPIO_TEST_DELAY_S);
-
- val = 0;
- gpio_set(gpio_out, val);
- printk(BIOS_INFO, "GPIO set %d=%d\n", gpio_out, val);
- delay(CYGNUS_GPIO_TEST_DELAY_S);
-
- gpio_free(CYGNUS_GPIO_TEST_AON_GPIO0);
- gpio_free(CYGNUS_GPIO_TEST_SPI2_MISO);
- printk(BIOS_INFO, "Gpio test completed...\n");
-}
-
-void gpio_init(void)
-{
- int i;
-
- printk(BIOS_INFO, "Setting up the gpio...\n");
-
- for (i = 0; i < ARRAY_SIZE(cygnus_gpio_table); i++) {
- struct cygnus_gpio *chip = cygnus_gpio_table + i;
-
- chip->num_banks = (chip->ngpio+NGPIOS_PER_BANK - 1)
- / NGPIOS_PER_BANK;
- if (chip->pinmux_is_supported)
- chip->pctl_priv = cygnus_pinmux_init();
- }
-
- if (IS_ENABLED(CONFIG_CYGNUS_GPIO_TEST))
- cygnus_gpio_test();
-}
-
-void gpio_free(gpio_t gpio)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- cygnus_gpio_free(chip, gpio_num);
-}
-
-void gpio_input(gpio_t gpio)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- if (cygnus_gpio_request(chip, gpio_num) != 0) {
- printk(BIOS_ERR, "Cannot mux GPIO %d\n", gpio);
- return;
- }
- cygnus_gpio_direction_input(chip, gpio_num);
-}
-
-void gpio_input_pulldown(gpio_t gpio)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- cygnus_gpio_set_pull(chip, gpio_num, 0, 0);
-}
-
-void gpio_input_pullup(gpio_t gpio)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- cygnus_gpio_set_pull(chip, gpio_num, 0, 1);
-}
-
-int gpio_get(gpio_t gpio)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return -1;
- }
-
- return cygnus_gpio_get(chip, gpio_num);
-}
-
-void gpio_set(gpio_t gpio, int value)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- cygnus_gpio_set(chip, gpio_num, value);
-}
-
-void gpio_output(gpio_t gpio, int value)
-{
- struct cygnus_gpio *chip;
- unsigned gpio_num;
-
- chip = cygnus_get_gpio_core(gpio, &gpio_num);
- if (chip == NULL) {
- dev_dbg(chip, "unable to find chip for gpio %d", gpio);
- return;
- }
-
- if (cygnus_gpio_request(chip, gpio_num) != 0) {
- printk(BIOS_ERR, "Cannot mux GPIO %d\n", gpio);
- return;
- }
- cygnus_gpio_direction_output(chip, gpio_num, value);
-}