[coreboot-gerrit] Change in coreboot[master]: soc/cavium: Add GPIO driver
Patrick Rudolph (Code Review)
gerrit at coreboot.org
Wed Feb 14 15:29:00 CET 2018
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/23753
Change subject: soc/cavium: Add GPIO driver
......................................................................
soc/cavium: Add GPIO driver
Change-Id: I77b83eaebc94b1e311e6834658074c2c7c5faf55
Signed-off-by: Patrick Rudolph <patrick.rudolph at 9elements.com>
---
M src/soc/cavium/cn81xx/Makefile.inc
M src/soc/cavium/common/Makefile.inc
M src/soc/cavium/common/gpio.c
M src/soc/cavium/common/include/soc/gpio.h
4 files changed, 169 insertions(+), 174 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/53/23753/1
diff --git a/src/soc/cavium/cn81xx/Makefile.inc b/src/soc/cavium/cn81xx/Makefile.inc
index 8fe8f44..6c129e8 100644
--- a/src/soc/cavium/cn81xx/Makefile.inc
+++ b/src/soc/cavium/cn81xx/Makefile.inc
@@ -70,7 +70,6 @@
romstage-y += ../common/lame_string.c
-
#verstage-y += ../common/cbmem.c
#verstage-y += ../common/gpio.c
#verstage-y += gpio.c
diff --git a/src/soc/cavium/common/Makefile.inc b/src/soc/cavium/common/Makefile.inc
index 48cc7bd..f51e13e 100644
--- a/src/soc/cavium/common/Makefile.inc
+++ b/src/soc/cavium/common/Makefile.inc
@@ -18,16 +18,19 @@
bootblock-$(CONFIG_BOOTBLOCK_CUSTOM) += bootblock.c
bootblock-y += twsi.c
bootblock-y += clock.c
+bootblock-y += gpio.c
romstage-y += twsi.c
romstage-y += clock.c
+romstage-y += gpio.c
ramstage-y += twsi.c
ramstage-y += clock.c
+ramstage-y += gpio.c
CPPFLAGS_common += -Isrc/soc/cavium/common/include
diff --git a/src/soc/cavium/common/gpio.c b/src/soc/cavium/common/gpio.c
index add2100..b7620e5 100644
--- a/src/soc/cavium/common/gpio.c
+++ b/src/soc/cavium/common/gpio.c
@@ -1,138 +1,183 @@
/*
- * This file is part of the coreboot project.
+ * Copyright 2018-present Facebook, Inc.
*
- * Copyright 2017-present Facebook, Inc.
- *
- * 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 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * SPDX-License-Identifier: GPL-2.0+
*/
-/* FIXME: scaffolding based on rk3399 */
-
-#include <arch/io.h>
-#include <assert.h>
#include <console/console.h>
-#include <gpio.h>
#include <soc/gpio.h>
-//#include <soc/grf.h>
-#include <soc/soc.h>
-#include <stdlib.h>
+#include <arch/io.h>
+#include <endian.h>
-static void gpio_set_dir(gpio_t gpio, enum gpio_dir dir)
+union gpio_const {
+ u64 u;
+ struct {
+ u64 gpios:8; /** Number of GPIOs implemented */
+ u64 pp:8; /** Number of PP vectors */
+ u64:48; /* Reserved */
+ } s;
+};
+union bit_cfg {
+ u64 u;
+ struct {
+ u64 tx_oe : 1; /* Output Enable */
+ u64 xor : 1; /* Invert */
+ u64 int_en : 1; /* Interrupt Enable */
+ u64 int_type : 1; /* Type of Interrupt */
+ u64 filt_cnt : 4; /* Glitch filter counter */
+ u64 filt_sel : 4; /* Glitch filter select */
+ u64 tx_od : 1; /* Set Output to Open Drain */
+ u64 : 3;
+ u64 pin_sel : 10; /* Select type of pin */
+ u64 : 38;
+ } s;
+};
+
+struct cavium_gpio {
+ u64 rx_dat;
+ u64 tx_set;
+ u64 tx_clr;
+ u64 multicast;
+ u64 ocla_exten_trg;
+ u64 strap;
+ u64 reserved[12];
+ union gpio_const gpio_const; /* Offset 90 */
+ u64 reserved2[109];
+ union bit_cfg bit_cfg[48]; /* Offset 400 */
+};
+
+/* Base address of GPIO BAR */
+static void *gpio_get_baseaddr(void)
{
-#if 0
- clrsetbits_le32(&gpio_port[gpio.port]->swporta_ddr,
- 1 << gpio.num, dir << gpio.num);
-#endif
+ return (void *)0x803000000000ULL;
}
-static void gpio_set_pull(gpio_t gpio, enum gpio_pull pull)
+/* Number of GPIO pins. Usually 48. */
+gpio_t gpio_pin_count(void)
{
-#if 0
- u32 pull_val = gpio_get_pull_val(gpio, pull);
- if (is_pmu_gpio(gpio) && IS_ENABLED(CONFIG_SOC_ROCKCHIP_RK3288))
- clrsetbits_le32(gpio_grf_reg(gpio), 3 << (gpio.idx * 2),
- pull_val << (gpio.idx * 2));
- else
- write32(gpio_grf_reg(gpio), RK_CLRSETBITS(3 << (gpio.idx * 2),
- pull_val << (gpio.idx * 2)));
-#endif
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+ union gpio_const gpio_const;
+
+ gpio_const.u = read64(®s->gpio_const.u);
+
+ if (gpio_const.s.gpios > 64)
+ return 64; // FIXME: Add support for more than 64 GPIOs
+ return gpio_const.s.gpios;
}
+/* Set GPIO to software control and direction INPUT */
void gpio_input(gpio_t gpio)
{
-#if 0
- gpio_set_pull(gpio, GPIO_PULLNONE);
- gpio_set_dir(gpio, GPIO_INPUT);
-#endif
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+ union bit_cfg bit_cfg;
+
+ if (gpio >= gpio_pin_count())
+ return;
+
+ printk(BIOS_SPEW, "GPIO(%u): direction input\n", gpio);
+
+ bit_cfg.u = read64(®s->bit_cfg[gpio]);
+ bit_cfg.s.pin_sel = 0;
+ bit_cfg.s.tx_oe = 0;
+ write64(®s->bit_cfg[gpio], bit_cfg.u);
+}
+
+/* Set GPIO of direction OUTPUT to level */
+void gpio_set(gpio_t gpio, int value)
+{
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+
+ if (gpio >= gpio_pin_count())
+ return;
+
+ printk(BIOS_SPEW, "GPIO(%u): level: %u\n", gpio, !!value);
+
+ if (value)
+ write64(®s->tx_set, 1 << gpio);
+ else
+ write64(®s->tx_clr, 1 << gpio);
+}
+
+/* Set GPIO direction to OUTPUT with level */
+void gpio_output(gpio_t gpio, int value)
+{
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+ union bit_cfg bit_cfg;
+
+ if (gpio >= gpio_pin_count())
+ return;
+
+ gpio_set(gpio, value);
+
+ printk(BIOS_SPEW, "GPIO(%u): direction output with level: %u\n", gpio,
+ !!value);
+
+ bit_cfg.u = read64(®s->bit_cfg[gpio]);
+ bit_cfg.s.pin_sel = 0;
+ bit_cfg.s.tx_oe = 1;
+ write64(®s->bit_cfg[gpio], bit_cfg.u);
+}
+
+/* Set GPIO invert flag, that affects INPUT and OUTPUT */
+void gpio_invert(gpio_t gpio, int value)
+{
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+ union bit_cfg bit_cfg;
+
+ if (gpio >= gpio_pin_count())
+ return;
+
+ bit_cfg.u = read64(®s->bit_cfg[gpio]);
+ bit_cfg.s.xor = !!value;
+ write64(®s->bit_cfg[gpio], bit_cfg.u);
+
+ printk(BIOS_SPEW, "GPIO(%u): invert: %s\n", gpio, value ? "ON" : "OFF");
+}
+
+/* Read GPIO level with direction set to INPUT */
+int gpio_get(gpio_t gpio)
+{
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+
+ if (gpio >= gpio_pin_count())
+ return 0;
+
+ const u64 reg = read64(®s->rx_dat);
+ printk(BIOS_SPEW, "GPIO(%u): input: %u\n", gpio, !!(reg & (1 << gpio)));
+
+ return !!(reg & (1 << gpio));
+}
+
+/* Read GPIO STRAP level sampled at cold boot */
+int gpio_strap_value(gpio_t gpio)
+{
+ struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
+
+ if (gpio >= gpio_pin_count())
+ return 0;
+
+ const u64 reg = read64(®s->strap);
+ printk(BIOS_SPEW, "GPIO(%u): strap: %u\n", gpio, !!(reg & (1 << gpio)));
+
+ return !!(reg & (1 << gpio));
+}
+
+/* FIXME: Parse devicetree ? */
+void gpio_init(void)
+{
+ const size_t pin_count = gpio_pin_count();
+
+ printk(BIOS_DEBUG, "GPIO: base address: %p, pin count: %d\n",
+ gpio_get_baseaddr(), pin_count);
+
+ if (!pin_count)
+ return;
}
void gpio_input_pulldown(gpio_t gpio)
{
-#if 0
- gpio_set_pull(gpio, GPIO_PULLDOWN);
- gpio_set_dir(gpio, GPIO_INPUT);
-#endif
}
void gpio_input_pullup(gpio_t gpio)
{
-#if 0
- gpio_set_pull(gpio, GPIO_PULLUP);
- gpio_set_dir(gpio, GPIO_INPUT);
-#endif
-}
-
-void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, enum gpio_pull pull)
-{
-#if 0
- uint32_t int_polarity, inttype_level;
- uint32_t mask = BIT(gpio.num);
-
- /* gpio pull only PULLNONE, PULLUP, PULLDOWN status */
- assert(pull <= GPIO_PULLDOWN);
-
- gpio_set_dir(gpio, GPIO_INPUT);
- gpio_set_pull(gpio, pull);
-
- int_polarity = inttype_level = 0;
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- int_polarity = mask;
- inttype_level = mask;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- inttype_level = mask;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- int_polarity = mask;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- break;
- }
- clrsetbits_le32(&gpio_port[gpio.port]->int_polarity,
- mask, int_polarity);
- clrsetbits_le32(&gpio_port[gpio.port]->inttype_level,
- mask, inttype_level);
-
- setbits_le32(&gpio_port[gpio.port]->inten, mask);
- clrbits_le32(&gpio_port[gpio.port]->intmask, mask);
-#endif
-}
-
-int gpio_irq_status(gpio_t gpio)
-{
-#if 0
- uint32_t mask = BIT(gpio.num);
- uint32_t int_status = read32(&gpio_port[gpio.port]->int_status);
-
- if (!(int_status & mask))
- return 0;
-
- setbits_le32(&gpio_port[gpio.port]->porta_eoi, mask);
- return 1;
-#endif
-}
-
-int gpio_get(gpio_t gpio)
-{
-#if 0
- return (read32(&gpio_port[gpio.port]->ext_porta) >> gpio.num) & 0x1;
-#endif
-}
-
-void gpio_output(gpio_t gpio, int value)
-{
-#if 0
- clrsetbits_le32(&gpio_port[gpio.port]->swporta_dr, 1 << gpio.num,
- !!value << gpio.num);
- gpio_set_dir(gpio, GPIO_OUTPUT);
- gpio_set_pull(gpio, GPIO_PULLNONE);
-#endif
}
diff --git a/src/soc/cavium/common/include/soc/gpio.h b/src/soc/cavium/common/include/soc/gpio.h
index 666f7bb..6986482 100644
--- a/src/soc/cavium/common/include/soc/gpio.h
+++ b/src/soc/cavium/common/include/soc/gpio.h
@@ -19,68 +19,16 @@
#include <types.h>
-typedef union {
- u32 raw;
-#if 0
- struct {
- union {
- struct {
- u32 num : 5;
- u32 reserved1 : 27;
- };
- struct {
- u32 idx : 3;
- u32 bank : 2;
- u32 port : 4;
- u32 reserved2 : 23;
- };
- };
- };
-#endif
-} gpio_t;
+typedef u32 gpio_t;
+#include <gpio.h>
-#if 0
-enum {
- GPIO_A = 0,
- GPIO_B,
- GPIO_C,
- GPIO_D,
-};
+/* The following functions must be implemented by SoC/board code. */
-extern struct rockchip_gpio_regs *gpio_port[];
-/* Check if the gpio port is a pmu gpio */
-int is_pmu_gpio(gpio_t gpio);
+gpio_t gpio_pin_count(void);
+void gpio_invert(gpio_t gpio, int value);
+int gpio_strap_value(gpio_t gpio);
-/* Return the io addr of gpio register */
-void *gpio_grf_reg(gpio_t gpio);
-
-enum gpio_pull {
- GPIO_PULLNONE = 0,
- GPIO_PULLUP = 1,
- GPIO_PULLDOWN = 2,
-};
-
-enum gpio_dir {
- GPIO_INPUT = 0,
- GPIO_OUTPUT = 1,
-};
-
-enum gpio_irq_type {
- IRQ_TYPE_EDGE_RISING = 0,
- IRQ_TYPE_EDGE_FALLING,
- IRQ_TYPE_LEVEL_HIGH,
- IRQ_TYPE_LEVEL_LOW,
-};
-
-/* Setup and enable irq */
-void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, enum gpio_pull pull);
-
-/* Check and clear irq status */
-int gpio_irq_status(gpio_t gpio);
-
-/* The gpio pull bias setting may be different between SoCs */
-u32 gpio_get_pull_val(gpio_t gpio, enum gpio_pull pull);
-#endif
+void gpio_init(void);
#endif
--
To view, visit https://review.coreboot.org/23753
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I77b83eaebc94b1e311e6834658074c2c7c5faf55
Gerrit-Change-Number: 23753
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph at 9elements.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180214/825ccc1a/attachment-0001.html>
More information about the coreboot-gerrit
mailing list