svn commit: r303577 - head/sys/mips/atheros

Adrian Chadd adrian at FreeBSD.org
Sun Jul 31 06:51:35 UTC 2016


Author: adrian
Date: Sun Jul 31 06:51:34 2016
New Revision: 303577
URL: https://svnweb.freebsd.org/changeset/base/303577

Log:
  [ar71xx_gpio] handle AR934x and QCA953x GPIO OE polarity.
  
  For reasons I won't comment on, the AR934x and QCA953x GPIO_OE register
  value is inverted - bit set == input, bit clear == output.
  
  So, fix this in the output setting, in reading the initial state from
  the boot loader, and also setting any gpiofunc pins that are necessary.

Modified:
  head/sys/mips/atheros/ar71xx_gpio.c

Modified: head/sys/mips/atheros/ar71xx_gpio.c
==============================================================================
--- head/sys/mips/atheros/ar71xx_gpio.c	Sun Jul 31 06:34:49 2016	(r303576)
+++ head/sys/mips/atheros/ar71xx_gpio.c	Sun Jul 31 06:51:34 2016	(r303577)
@@ -138,13 +138,56 @@ ar71xx_gpio_function_disable(struct ar71
 		GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
 }
 
+/*
+ * On most platforms, GPIO_OE is a bitmap where the bit set
+ * means "enable output."
+ *
+ * On AR934x and QCA953x, it's the opposite - the bit set means
+ * "input enable".
+ */
+static int
+ar71xx_gpio_oe_is_high(void)
+{
+	switch (ar71xx_soc) {
+	case AR71XX_SOC_AR9344:
+	case AR71XX_SOC_QCA9533:
+	case AR71XX_SOC_QCA9533_V2:
+		return 0;
+	default:
+		return 1;
+	}
+}
+
 static void
-ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
-    unsigned int flags)
+ar71xx_gpio_oe_set_output(struct ar71xx_gpio_softc *sc, int b)
+{
+	uint32_t mask;
+
+	mask = 1 << b;
+
+	if (ar71xx_gpio_oe_is_high())
+		GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
+	else
+		GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
+}
+
+static void
+ar71xx_gpio_oe_set_input(struct ar71xx_gpio_softc *sc, int b)
 {
 	uint32_t mask;
 
-	mask = 1 << pin->gp_pin;
+	mask = 1 << b;
+
+	if (ar71xx_gpio_oe_is_high())
+		GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
+	else
+		GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
+}
+
+static void
+ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
+    unsigned int flags)
+{
 
 	/*
 	 * Manage input/output
@@ -153,11 +196,10 @@ ar71xx_gpio_pin_configure(struct ar71xx_
 		pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
 		if (flags & GPIO_PIN_OUTPUT) {
 			pin->gp_flags |= GPIO_PIN_OUTPUT;
-			GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
-		}
-		else {
+			ar71xx_gpio_oe_set_output(sc, pin->gp_pin);
+		} else {
 			pin->gp_flags |= GPIO_PIN_INPUT;
-			GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
+			ar71xx_gpio_oe_set_input(sc, pin->gp_pin);
 		}
 	}
 }
@@ -455,6 +497,14 @@ ar71xx_gpio_attach(device_t dev)
 	}
 	/* Iniatilize the GPIO pins, keep the loader settings. */
 	oe = GPIO_READ(sc, AR71XX_GPIO_OE);
+	/*
+	 * For AR934x and QCA953x, the meaning of oe is inverted;
+	 * so flip it the right way around so we can parse the GPIO
+	 * state.
+	 */
+	if (!ar71xx_gpio_oe_is_high())
+		oe = ~oe;
+
 	sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins,
 	    M_DEVBUF, M_WAITOK | M_ZERO);
 	for (i = 0, j = 0; j <= maxpin; j++) {
@@ -515,16 +565,14 @@ ar71xx_gpio_attach(device_t dev)
 		    gpiofunc,
 		    gpiomode);
 
-		/* Set output (bit == 0) */
-		oe = GPIO_READ(sc, AR71XX_GPIO_OE);
-		oe &= ~ (1 << i);
-		GPIO_WRITE(sc, AR71XX_GPIO_OE, oe);
-
 		/* Set pin value = 0, so it stays low by default */
 		oe = GPIO_READ(sc, AR71XX_GPIO_OUT);
 		oe &= ~ (1 << i);
 		GPIO_WRITE(sc, AR71XX_GPIO_OUT, oe);
 
+		/* Set output */
+		ar71xx_gpio_oe_set_output(sc, i);
+
 		/* Finally: Set the output config */
 		ar71xx_gpio_ouput_configure(i, gpiofunc);
 	}


More information about the svn-src-head mailing list