Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Dec 2018 22:02:57 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342013 - in head/sys: arm/mv arm64/conf conf
Message-ID:  <201812122202.wBCM2vV2009769@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Wed Dec 12 22:02:57 2018
New Revision: 342013
URL: https://svnweb.freebsd.org/changeset/base/342013

Log:
  arm64: mv_gpio: Add Marvell 8K support
  
  While here put the interrupts setup in it's own function
  
  Sponsored by:	Rubicon Communications, LCC ("Netgate")

Modified:
  head/sys/arm/mv/gpio.c
  head/sys/arm64/conf/GENERIC
  head/sys/conf/files.arm64

Modified: head/sys/arm/mv/gpio.c
==============================================================================
--- head/sys/arm/mv/gpio.c	Wed Dec 12 22:01:06 2018	(r342012)
+++ head/sys/arm/mv/gpio.c	Wed Dec 12 22:02:57 2018	(r342013)
@@ -60,6 +60,10 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 
+#ifdef __aarch64__
+#include "opt_soc.h"
+#endif
+
 #define GPIO_MAX_INTR_COUNT	8
 #define GPIO_PINS_PER_REG	32
 #define GPIO_GENERIC_CAP	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |		\
@@ -74,6 +78,7 @@ __FBSDID("$FreeBSD$");
 #define DEBOUNCE_CHECK_TICKS	((hz / 1000) * DEBOUNCE_CHECK_MS)
 
 struct mv_gpio_softc {
+	device_t		dev;
 	device_t		sc_busdev;
 	struct resource	*	mem_res;
 	int			mem_rid;
@@ -83,6 +88,7 @@ struct mv_gpio_softc {
 	void			*ih_cookie[GPIO_MAX_INTR_COUNT];
 	bus_space_tag_t		bst;
 	bus_space_handle_t	bsh;
+	uint32_t		offset;
 	struct mtx		mutex;
 	uint8_t			pin_num;	/* number of GPIO pins */
 	uint8_t			irq_num;	/* number of real IRQs occupied by GPIO controller */
@@ -189,9 +195,12 @@ static devclass_t mv_gpio_devclass;
 
 DRIVER_MODULE(mv_gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
 
-struct ofw_compat_data gpio_controllers[] = {
-	{ "mrvl,gpio", (uintptr_t)true },
-	{ "marvell,orion-gpio", (uintptr_t)true },
+struct ofw_compat_data compat_data[] = {
+	{ "mrvl,gpio", 1 },
+	{ "marvell,orion-gpio", 1 },
+#ifdef SOC_MARVELL_8K
+	{ "marvell,armada-8k-gpio", 1 },
+#endif
 	{ NULL, 0 }
 };
 
@@ -201,7 +210,7 @@ mv_gpio_probe(device_t dev)
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (ofw_bus_search_compatible(dev, gpio_controllers)->ocd_data == 0)
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
 		return (ENXIO);
 
 	device_set_desc(dev, "Marvell Integrated GPIO Controller");
@@ -209,61 +218,75 @@ mv_gpio_probe(device_t dev)
 }
 
 static int
-mv_gpio_attach(device_t dev)
+mv_gpio_setup_interrupts(struct mv_gpio_softc *sc, phandle_t node)
 {
-	int i, size;
-	struct mv_gpio_softc *sc;
-	pcell_t pincnt = 0;
-	pcell_t irq_cells = 0;
 	phandle_t iparent;
+	pcell_t irq_cells;
+	int i, size;
 
-	sc = (struct mv_gpio_softc *)device_get_softc(dev);
-	if (sc == NULL)
-		return (ENXIO);
-
-	if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt,
-	    sizeof(pcell_t)) >= 0 ||
-	    OF_getencprop(ofw_bus_get_node(dev), "ngpios", &pincnt,
-	    sizeof(pcell_t)) >= 0) {
-		sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
-		if (bootverbose)
-			device_printf(dev, "%d pins available\n", sc->pin_num);
-	} else {
-		device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
-		return (ENXIO);
-	}
-
-	/* Assign generic capabilities to every gpio pin */
-	for(i = 0; i < sc->pin_num; i++)
-		sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
-
 	/* Find root interrupt controller */
-	iparent = ofw_bus_find_iparent(ofw_bus_get_node(dev));
+	iparent = ofw_bus_find_iparent(node);
 	if (iparent == 0) {
-		device_printf(dev, "No interrupt-parrent found. "
+		device_printf(sc->dev, "No interrupt-parrent found. "
 				"Error in DTB\n");
 		return (ENXIO);
 	} else {
 		/* While at parent - store interrupt cells prop */
 		if (OF_searchencprop(OF_node_from_xref(iparent),
 		    "#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) {
-			device_printf(dev, "DTB: Missing #interrupt-cells "
+			device_printf(sc->dev, "DTB: Missing #interrupt-cells "
 			    "property in interrupt parent node\n");
 			return (ENXIO);
 		}
 	}
 
-	size = OF_getproplen(ofw_bus_get_node(dev), "interrupts");
+	size = OF_getproplen(node, "interrupts");
 	if (size != -1) {
 		size = size / sizeof(pcell_t);
 		size = size / irq_cells;
 		sc->irq_num = size;
-		device_printf(dev, "%d IRQs available\n", sc->irq_num);
+		device_printf(sc->dev, "%d IRQs available\n", sc->irq_num);
 	} else {
-		device_printf(dev, "ERROR: no interrupts entry found!\n");
+		device_printf(sc->dev, "ERROR: no interrupts entry found!\n");
 		return (ENXIO);
 	}
 
+	for (i = 0; i < sc->irq_num; i++) {
+		sc->irq_rid[i] = i;
+		sc->irq_res[i] = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
+			&sc->irq_rid[i], RF_ACTIVE);
+		if (!sc->irq_res[i]) {
+			mtx_destroy(&sc->mutex);
+			device_printf(sc->dev,
+			    "could not allocate gpio%d interrupt\n", i+1);
+			return (ENXIO);
+		}
+	}
+
+	device_printf(sc->dev, "Disable interrupts (offset = %x + EDGE(0x18)\n", sc->offset);
+	/* Disable all interrupts */
+	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_EDGE_MASK, 0);
+	device_printf(sc->dev, "Disable interrupts (offset = %x + LEV(0x1C))\n", sc->offset);
+	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_LEV_MASK, 0);
+
+	for (i = 0; i < sc->irq_num; i++) {
+		device_printf(sc->dev, "Setup intr %d\n", i);
+		if (bus_setup_intr(sc->dev, sc->irq_res[i],
+		    INTR_TYPE_MISC,
+		    (driver_filter_t *)mv_gpio_intr, NULL,
+		    sc, &sc->ih_cookie[i]) != 0) {
+			mtx_destroy(&sc->mutex);
+			bus_release_resource(sc->dev, SYS_RES_IRQ,
+				sc->irq_rid[i], sc->irq_res[i]);
+			device_printf(sc->dev, "could not set up intr %d\n", i);
+			return (ENXIO);
+		}
+	}
+
+	/* Clear interrupt status. */
+	device_printf(sc->dev, "Clear int status (offset = %x)\n", sc->offset);
+	bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_CAUSE, 0);
+
 	sc->debounce_callouts = (struct callout **)malloc(sc->pin_num *
 	    sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (sc->debounce_callouts == NULL)
@@ -274,11 +297,46 @@ mv_gpio_attach(device_t dev)
 	if (sc->debounce_counters == NULL)
 		return (ENOMEM);
 
+	return (0);
+}
+
+static int
+mv_gpio_attach(device_t dev)
+{
+	int i, rv;
+	struct mv_gpio_softc *sc;
+	phandle_t node;
+	pcell_t pincnt = 0;
+
+	sc = (struct mv_gpio_softc *)device_get_softc(dev);
+	if (sc == NULL)
+		return (ENXIO);
+
+	node = ofw_bus_get_node(dev);
+	sc->dev = dev;
+
+	if (OF_getencprop(node, "pin-count", &pincnt, sizeof(pcell_t)) >= 0 ||
+	    OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t)) >= 0) {
+		sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
+		if (bootverbose)
+			device_printf(dev, "%d pins available\n", sc->pin_num);
+	} else {
+		device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
+		return (ENXIO);
+	}
+
+	if (OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset)) == -1)
+		sc->offset = 0;
+
+	/* Assign generic capabilities to every gpio pin */
+	for(i = 0; i < sc->pin_num; i++)
+		sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
+
 	mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);
 
 	sc->mem_rid = 0;
 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
-		 RF_ACTIVE);
+		 RF_ACTIVE | RF_SHAREABLE );
 
 	if (!sc->mem_res) {
 		mtx_destroy(&sc->mutex);
@@ -289,38 +347,10 @@ mv_gpio_attach(device_t dev)
 	sc->bst = rman_get_bustag(sc->mem_res);
 	sc->bsh = rman_get_bushandle(sc->mem_res);
 
-	for (i = 0; i < sc->irq_num; i++) {
-		sc->irq_rid[i] = i;
-		sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-			&sc->irq_rid[i], RF_ACTIVE);
-		if (!sc->irq_res[i]) {
-			mtx_destroy(&sc->mutex);
-			device_printf(dev,
-			    "could not allocate gpio%d interrupt\n", i+1);
-			return (ENXIO);
-		}
-	}
+	rv = mv_gpio_setup_interrupts(sc, node);
+	if (rv != 0)
+		return (rv);
 
-	/* Disable all interrupts */
-	bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0);
-	bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0);
-
-	for (i = 0; i < sc->irq_num; i++) {
-		if (bus_setup_intr(dev, sc->irq_res[i],
-		    INTR_TYPE_MISC,
-		    (driver_filter_t *)mv_gpio_intr, NULL,
-		    sc, &sc->ih_cookie[i]) != 0) {
-			mtx_destroy(&sc->mutex);
-			bus_release_resource(dev, SYS_RES_IRQ,
-				sc->irq_rid[i], sc->irq_res[i]);
-			device_printf(dev, "could not set up intr %d\n", i);
-			return (ENXIO);
-		}
-	}
-
-	/* Clear interrupt status. */
-	bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
-
 	sc->sc_busdev = gpiobus_attach_bus(dev);
 	if (sc->sc_busdev == NULL) {
 		mtx_destroy(&sc->mutex);
@@ -540,6 +570,8 @@ mv_gpio_configure(device_t dev, uint32_t pin, uint32_t
 		return (EINVAL);
 
 	if (mask & MV_GPIO_IN_DEBOUNCE) {
+		if (sc->irq_num == 0)
+			return (EINVAL);
 		error = mv_gpio_debounce_prepare(dev, pin);
 		if (error != 0)
 			return (error);
@@ -845,7 +877,7 @@ mv_gpio_reg_read(device_t dev, uint32_t reg)
 	struct mv_gpio_softc *sc;
 	sc = (struct mv_gpio_softc *)device_get_softc(dev);
 
-	return (bus_space_read_4(sc->bst, sc->bsh, reg));
+	return (bus_space_read_4(sc->bst, sc->bsh, sc->offset + reg));
 }
 
 static void
@@ -854,7 +886,7 @@ mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t
 	struct mv_gpio_softc *sc;
 	sc = (struct mv_gpio_softc *)device_get_softc(dev);
 
-	bus_space_write_4(sc->bst, sc->bsh, reg, val);
+	bus_space_write_4(sc->bst, sc->bsh, sc->offset + reg, val);
 }
 
 static void

Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC	Wed Dec 12 22:01:06 2018	(r342012)
+++ head/sys/arm64/conf/GENERIC	Wed Dec 12 22:02:57 2018	(r342013)
@@ -204,6 +204,7 @@ device		aw_gpio		# Allwinner GPIO controller
 device		gpio
 device		gpioled
 device		fdt_pinctrl
+device		mv_gpio		# Marvell GPIO controller
 device		mvebu_pinctrl	# Marvell Pinmux Controller
 
 # I2C

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64	Wed Dec 12 22:01:06 2018	(r342012)
+++ head/sys/conf/files.arm64	Wed Dec 12 22:02:57 2018	(r342013)
@@ -89,6 +89,7 @@ arm/broadcom/bcm2835/bcm2835_vcio.c		optional soc_brcm
 arm/broadcom/bcm2835/bcm2835_wdog.c		optional soc_brcm_bcm2837 fdt
 arm/broadcom/bcm2835/bcm2836.c			optional soc_brcm_bcm2837 fdt
 arm/broadcom/bcm2835/bcm283x_dwc_fdt.c		optional dwcotg fdt soc_brcm_bcm2837
+arm/mv/gpio.c					optional mv_gpio fdt
 arm/mv/mvebu_pinctrl.c				optional mvebu_pinctrl fdt
 arm/mv/mv_ap806_clock.c				optional SOC_MARVELL_8K fdt
 arm/mv/armada38x/armada38x_rtc.c		optional mv_rtc fdt



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812122202.wBCM2vV2009769>