svn commit: r273650 - stable/10/sys/arm/rockchip

Ian Lepore ian at FreeBSD.org
Sun Oct 26 01:15:17 UTC 2014


Author: ian
Date: Sun Oct 26 01:15:16 2014
New Revision: 273650
URL: https://svnweb.freebsd.org/changeset/base/273650

Log:
  MFC r257200, r259121, r261410, r265853:
  
   - Remove #include <machine/frame.h>.
   - Add gpio parse routines according to sys/boot/fdt/dts/bindings-gpio.txt.
   - Follow r261352 by updating all drivers which are children of simplebus
     to check the status property in their probe routines.
   - Rename platform_gpio_init to be SoC specific, and make it static as it's
     only called from this file.
  
  This is mostly catching up on some old MFCs that were done before this file
  existed in the 10 branch.

Modified:
  stable/10/sys/arm/rockchip/rk30xx_gpio.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/arm/rockchip/rk30xx_gpio.c
==============================================================================
--- stable/10/sys/arm/rockchip/rk30xx_gpio.c	Sat Oct 25 22:53:08 2014	(r273649)
+++ stable/10/sys/arm/rockchip/rk30xx_gpio.c	Sun Oct 26 01:15:16 2014	(r273650)
@@ -86,6 +86,26 @@ struct rk30_gpio_softc {
 	struct gpio_pin		sc_gpio_pins[RK30_GPIO_PINS];
 };
 
+static struct rk30_gpio_softc *rk30_gpio_sc = NULL;
+
+typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
+
+struct gpio_ctrl_entry {
+	const char		*compat;
+	gpios_phandler_t	handler;
+};
+
+int rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len);
+static int rk30_gpio_init(void);
+
+struct gpio_ctrl_entry gpio_controllers[] = {
+	{ "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+	{ "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+	{ "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+	{ "rockchip,rk30xx-gpio", &rk30_gpios_prop_handle },
+	{ NULL, NULL }
+};
+
 #define	RK30_GPIO_LOCK(_sc)		mtx_lock(&_sc->sc_mtx)
 #define	RK30_GPIO_UNLOCK(_sc)		mtx_unlock(&_sc->sc_mtx)
 #define	RK30_GPIO_LOCK_ASSERT(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED)
@@ -439,6 +459,9 @@ rk30_gpio_attach(device_t dev)
 	int i, rid;
 	phandle_t gpio;
 
+	if (rk30_gpio_sc)
+		return (ENXIO);
+
 	sc->sc_dev = dev;
 
 	mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
@@ -483,6 +506,11 @@ rk30_gpio_attach(device_t dev)
 
 	device_add_child(dev, "gpioc", device_get_unit(dev));
 	device_add_child(dev, "gpiobus", device_get_unit(dev));
+
+	rk30_gpio_sc = sc;
+
+	rk30_gpio_init();
+	
 	return (bus_generic_attach(dev));
 
 fail:
@@ -528,3 +556,121 @@ static driver_t rk30_gpio_driver = {
 };
 
 DRIVER_MODULE(rk30_gpio, simplebus, rk30_gpio_driver, rk30_gpio_devclass, 0, 0);
+
+int
+rk30_gpios_prop_handle(phandle_t ctrl, pcell_t *gpios, int len)
+{
+	struct rk30_gpio_softc *sc;
+	pcell_t gpio_cells;
+	int inc, t, tuples, tuple_size;
+	int dir, flags, pin, i;
+	u_long gpio_ctrl, size;
+
+	sc = rk30_gpio_sc;
+	if (sc == NULL)
+		return ENXIO;
+
+	if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
+		return (ENXIO);
+
+	gpio_cells = fdt32_to_cpu(gpio_cells);
+	if (gpio_cells != 2)
+		return (ENXIO);
+
+	tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t);
+	tuples = len / tuple_size;
+
+	if (fdt_regsize(ctrl, &gpio_ctrl, &size))
+		return (ENXIO);
+
+	/*
+	 * Skip controller reference, since controller's phandle is given
+	 * explicitly (in a function argument).
+	 */
+	inc = sizeof(ihandle_t) / sizeof(pcell_t);
+	gpios += inc;
+	for (t = 0; t < tuples; t++) {
+		pin = fdt32_to_cpu(gpios[0]);
+		dir = fdt32_to_cpu(gpios[1]);
+		flags = fdt32_to_cpu(gpios[2]);
+
+		for (i = 0; i < sc->sc_gpio_npins; i++) {
+			if (sc->sc_gpio_pins[i].gp_pin == pin)
+				break;
+		}
+		if (i >= sc->sc_gpio_npins)
+			return (EINVAL);
+
+		rk30_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+
+		if (dir == 1) {
+			/* Input. */
+			rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_INPUT);
+		} else {
+			/* Output. */
+			rk30_gpio_pin_set(sc->sc_dev, pin, RK30_GPIO_OUTPUT);
+		}
+		gpios += gpio_cells + inc;
+	}
+
+	return (0);
+}
+
+#define	MAX_PINS_PER_NODE	5
+#define	GPIOS_PROP_CELLS	4
+
+static int
+rk30_gpio_init(void)
+{
+	phandle_t child, parent, root, ctrl;
+	pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
+	struct gpio_ctrl_entry *e;
+	int len, rv;
+
+	root = OF_finddevice("/");
+	len = 0;
+	parent = root;
+
+	/* Traverse through entire tree to find nodes with 'gpios' prop */
+	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+		/* Find a 'leaf'. Start the search from this node. */
+		while (OF_child(child)) {
+			parent = child;
+			child = OF_child(child);
+		}
+		if ((len = OF_getproplen(child, "gpios")) > 0) {
+
+			if (len > sizeof(gpios))
+				return (ENXIO);
+
+			/* Get 'gpios' property. */
+			OF_getprop(child, "gpios", &gpios, len);
+
+			e = (struct gpio_ctrl_entry *)&gpio_controllers;
+
+			/* Find and call a handler. */
+			for (; e->compat; e++) {
+				/*
+				 * First cell of 'gpios' property should
+				 * contain a ref. to a node defining GPIO
+				 * controller.
+				 */
+				ctrl = OF_xref_phandle(fdt32_to_cpu(gpios[0]));
+
+				if (fdt_is_compatible(ctrl, e->compat))
+					/* Call a handler. */
+					if ((rv = e->handler(ctrl,
+					    (pcell_t *)&gpios, len)))
+						return (rv);
+			}
+		}
+
+		if (OF_peer(child) == 0) {
+			/* No more siblings. */
+			child = parent;
+			parent = OF_parent(child);
+		}
+	}
+	return (0);
+}


More information about the svn-src-stable-10 mailing list