Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Jan 2015 19:15:12 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r276784 - head/sys/arm/rockchip
Message-ID:  <201501071915.t07JFCHW056354@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Wed Jan  7 19:15:11 2015
New Revision: 276784
URL: https://svnweb.freebsd.org/changeset/base/276784

Log:
  Fix the handling of pull-up and pull-down for RK3188.
  
  For this to work the driver needs to know the bank it has attached to since
  the registers for the first 12 pins are at a different location.
  
  Move the lock initialization to simplify the code.

Modified:
  head/sys/arm/rockchip/rk30xx_gpio.c

Modified: head/sys/arm/rockchip/rk30xx_gpio.c
==============================================================================
--- head/sys/arm/rockchip/rk30xx_gpio.c	Wed Jan  7 19:06:27 2015	(r276783)
+++ head/sys/arm/rockchip/rk30xx_gpio.c	Wed Jan  7 19:15:11 2015	(r276784)
@@ -79,10 +79,14 @@ struct rk30_gpio_softc {
 	bus_space_tag_t		sc_bst;
 	bus_space_handle_t	sc_bsh;
 	void *			sc_intrhand;
+	int			sc_bank;
 	int			sc_gpio_npins;
 	struct gpio_pin		sc_gpio_pins[RK30_GPIO_PINS];
 };
 
+/* We use our base address to find out our bank number. */
+static unsigned long rk30_gpio_base_addr[4] =
+	{ 0x2000a000, 0x2003c000, 0x2003e000, 0x20080000 };
 static struct rk30_gpio_softc *rk30_gpio_sc = NULL;
 
 typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
@@ -153,17 +157,28 @@ rk30_gpio_set_function(struct rk30_gpio_
 static void
 rk30_gpio_set_pud(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t state)
 {
-	uint32_t bank;
-
-	bank = pin / 32;
+	uint32_t pud;
 
 	/* Must be called with lock held. */
 	RK30_GPIO_LOCK_ASSERT(sc);
-
-	if (bank == 0 && pin < 12)
-		rk30_pmu_gpio_pud(pin, state);
+	switch (state) {
+	case GPIO_PIN_PULLUP:
+		pud = RK30_GPIO_PULLUP;
+		break;
+	case GPIO_PIN_PULLDOWN:
+		pud = RK30_GPIO_PULLDOWN;
+		break;
+	default:
+		pud = RK30_GPIO_NONE;
+	}
+	/*
+	 * The pull up/down registers for GPIO0A and half of GPIO0B
+	 * (the first 12 pins on bank 0) are at a different location.
+	 */
+	if (sc->sc_bank == 0 && pin < 12)
+		rk30_pmu_gpio_pud(pin, pud);
 	else
-		rk30_grf_gpio_pud(bank, pin, state);
+		rk30_grf_gpio_pud(sc->sc_bank, pin, pud);
 }
 
 static void
@@ -183,22 +198,15 @@ rk30_gpio_pin_configure(struct rk30_gpio
 			pin->gp_flags |= GPIO_PIN_INPUT;
 		rk30_gpio_set_function(sc, pin->gp_pin, pin->gp_flags);
 	}
-
 	/* Manage Pull-up/pull-down. */
-	pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
-	if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
-		if (flags & GPIO_PIN_PULLUP) {
+	pin->gp_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
+	if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
+		if (flags & GPIO_PIN_PULLUP)
 			pin->gp_flags |= GPIO_PIN_PULLUP;
-			rk30_gpio_set_pud(sc, pin->gp_pin, 
-			    RK30_GPIO_PULLUP);
-		} else {
+		else
 			pin->gp_flags |= GPIO_PIN_PULLDOWN;
-			rk30_gpio_set_pud(sc, pin->gp_pin, 
-			    RK30_GPIO_PULLDOWN);
-		}
-	} else
-		rk30_gpio_set_pud(sc, pin->gp_pin, RK30_GPIO_NONE);
-
+	}
+	rk30_gpio_set_pud(sc, pin->gp_pin, pin->gp_flags);
 	RK30_GPIO_UNLOCK(sc);
 }
 
@@ -386,14 +394,12 @@ rk30_gpio_attach(device_t dev)
 	struct rk30_gpio_softc *sc = device_get_softc(dev);
 	int i, rid;
 	phandle_t gpio;
+	unsigned long start;
 
 	if (rk30_gpio_sc)
 		return (ENXIO);
-
 	sc->sc_dev = dev;
 
-	mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
-
 	rid = 0;
 	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 	    RF_ACTIVE);
@@ -401,9 +407,23 @@ rk30_gpio_attach(device_t dev)
 		device_printf(dev, "cannot allocate memory window\n");
 		return (ENXIO);
 	}
-
 	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
 	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+	/* Check the unit we are attaching by our base address. */
+	sc->sc_bank = -1;
+	start = rman_get_start(sc->sc_mem_res);
+	for (i = 0; i < nitems(rk30_gpio_base_addr); i++) {
+		if (rk30_gpio_base_addr[i] == start) {
+			sc->sc_bank = i;
+			break;
+		}
+	}
+	if (sc->sc_bank == -1) {
+		device_printf(dev,
+		    "unsupported device unit (only GPIO0..3 are supported)\n");
+		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+		return (ENXIO);
+	}
 
 	rid = 0;
 	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
@@ -421,6 +441,8 @@ rk30_gpio_attach(device_t dev)
 		/* Node is not a GPIO controller. */
 		goto fail;
 
+	mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
+
 	/* Initialize the software controlled pins. */
 	for (i = 0; i < RK30_GPIO_PINS; i++) {
 		snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,



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