[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(&regs->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(&regs->bit_cfg[gpio]);
+	bit_cfg.s.pin_sel = 0;
+	bit_cfg.s.tx_oe = 0;
+	write64(&regs->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(&regs->tx_set, 1 << gpio);
+	else
+		write64(&regs->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(&regs->bit_cfg[gpio]);
+	bit_cfg.s.pin_sel = 0;
+	bit_cfg.s.tx_oe = 1;
+	write64(&regs->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(&regs->bit_cfg[gpio]);
+	bit_cfg.s.xor = !!value;
+	write64(&regs->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(&regs->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(&regs->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