Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Mar 2014 07:06:36 +0000 (UTC)
From:      Ruslan Bukin <br@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262885 - in head/sys: arm/freescale/vybrid boot/fdt/dts/arm
Message-ID:  <201403070706.s2776anJ081598@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: br
Date: Fri Mar  7 07:06:36 2014
New Revision: 262885
URL: http://svnweb.freebsd.org/changeset/base/262885

Log:
  Add driver for Port control and interrupts (PORT).
  
  PORT is responsible for external interrupts management,
  so move IRQ lines from GPIO driver.

Added:
  head/sys/arm/freescale/vybrid/vf_port.c   (contents, props changed)
  head/sys/arm/freescale/vybrid/vf_port.h   (contents, props changed)
Modified:
  head/sys/arm/freescale/vybrid/files.vybrid
  head/sys/arm/freescale/vybrid/vf_gpio.c
  head/sys/boot/fdt/dts/arm/vybrid.dtsi

Modified: head/sys/arm/freescale/vybrid/files.vybrid
==============================================================================
--- head/sys/arm/freescale/vybrid/files.vybrid	Fri Mar  7 06:23:37 2014	(r262884)
+++ head/sys/arm/freescale/vybrid/files.vybrid	Fri Mar  7 07:06:36 2014	(r262885)
@@ -23,6 +23,7 @@ arm/freescale/vybrid/vf_mscm.c			standar
 arm/freescale/vybrid/vf_src.c			standard
 arm/freescale/vybrid/vf_edma.c			standard
 arm/freescale/vybrid/vf_dmamux.c		standard
+arm/freescale/vybrid/vf_port.c			standard
 arm/freescale/vybrid/vf_i2c.c			optional	iicbus
 arm/freescale/vybrid/vf_tcon.c			optional	vt
 arm/freescale/vybrid/vf_dcu4.c			optional	vt

Modified: head/sys/arm/freescale/vybrid/vf_gpio.c
==============================================================================
--- head/sys/arm/freescale/vybrid/vf_gpio.c	Fri Mar  7 06:23:37 2014	(r262884)
+++ head/sys/arm/freescale/vybrid/vf_gpio.c	Fri Mar  7 07:06:36 2014	(r262885)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include "gpio_if.h"
 
 #include <arm/freescale/vybrid/vf_common.h>
+#include <arm/freescale/vybrid/vf_port.h>
 
 #define	GPIO_PDOR(n)	(0x00 + 0x40 * (n >> 5))
 #define	GPIO_PSOR(n)	(0x04 + 0x40 * (n >> 5))
@@ -68,8 +69,6 @@ __FBSDID("$FreeBSD$");
 #define	GPIO_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	GPIO_UNLOCK(_sc)	mtx_unlock(&(_sc)->sc_mtx)
 
-#define	NPORTS		5
-#define	NGPIO		(NPORTS * 32)
 #define	DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
 
 /*
@@ -85,41 +84,23 @@ static int vf_gpio_pin_get(device_t, uin
 static int vf_gpio_pin_toggle(device_t, uint32_t pin);
 
 struct vf_gpio_softc {
-	struct resource		*res[6];
+	struct resource		*res[1];
 	bus_space_tag_t		bst;
 	bus_space_handle_t	bsh;
 
 	struct mtx		sc_mtx;
 	int			gpio_npins;
 	struct gpio_pin		gpio_pins[NGPIO];
-	void			*gpio_ih[NPORTS];
 };
 
 struct vf_gpio_softc *gpio_sc;
 
 static struct resource_spec vf_gpio_spec[] = {
 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
-	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
-	{ SYS_RES_IRQ,		1,	RF_ACTIVE },
-	{ SYS_RES_IRQ,		2,	RF_ACTIVE },
-	{ SYS_RES_IRQ,		3,	RF_ACTIVE },
-	{ SYS_RES_IRQ,		4,	RF_ACTIVE },
 	{ -1, 0 }
 };
 
 static int
-vf_gpio_intr(void *arg)
-{
-	struct vf_gpio_softc *sc;
-	sc = arg;
-
-	/* TODO: interrupt handling */
-
-	return (FILTER_HANDLED);
-}
-
-
-static int
 vf_gpio_probe(device_t dev)
 {
 
@@ -137,7 +118,7 @@ static int
 vf_gpio_attach(device_t dev)
 {
 	struct vf_gpio_softc *sc;
-	int irq, i;
+	int i;
 
 	sc = device_get_softc(dev);
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
@@ -147,22 +128,13 @@ vf_gpio_attach(device_t dev)
 		return (ENXIO);
 	}
 
-	gpio_sc = sc;
-
 	/* Memory interface */
 	sc->bst = rman_get_bustag(sc->res[0]);
 	sc->bsh = rman_get_bushandle(sc->res[0]);
 
-	sc->gpio_npins = NGPIO;
+	gpio_sc = sc;
 
-	for (irq = 0; irq < NPORTS; irq ++) {
-		if ((bus_setup_intr(dev, sc->res[1 + irq], INTR_TYPE_MISC,
-		    vf_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) {
-			device_printf(dev,
-			    "WARNING: unable to register interrupt handler\n");
-			return (ENXIO);
-		}
-	}
+	sc->gpio_npins = NGPIO;
 
 	for (i = 0; i < sc->gpio_npins; i++) {
 		sc->gpio_pins[i].gp_pin = i;

Added: head/sys/arm/freescale/vybrid/vf_port.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_port.c	Fri Mar  7 07:06:36 2014	(r262885)
@@ -0,0 +1,250 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Vybrid Family Port control and interrupts (PORT)
+ * Chapter 6, Vybrid Reference Manual, Rev. 5, 07/2013
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/freescale/vybrid/vf_port.h>
+#include <arm/freescale/vybrid/vf_common.h>
+
+/* Pin Control Register */
+#define PORT_PCR(n)		(0x1000 * (n >> 5) + 0x4 * (n % 32))
+#define	 PCR_IRQC_S	16
+#define	 PCR_IRQC_M	0xF
+#define	 PCR_DMA_RE	0x1
+#define	 PCR_DMA_FE	0x2
+#define	 PCR_DMA_EE	0x3
+#define	 PCR_INT_LZ	0x8
+#define	 PCR_INT_RE	0x9
+#define	 PCR_INT_FE	0xA
+#define	 PCR_INT_EE	0xB
+#define	 PCR_INT_LO	0xC
+#define	 PCR_ISF	(1 << 24)
+#define	PORT0_ISFR	0xA0	/* Interrupt Status Flag Register */
+#define	PORT0_DFER	0xC0	/* Digital Filter Enable Register */
+#define	PORT0_DFCR	0xC4	/* Digital Filter Clock Register */
+#define	PORT0_DFWR	0xC8	/* Digital Filter Width Register */
+
+struct port_event {
+	uint32_t	enabled;
+	uint32_t	mux_num;
+	uint32_t	mux_src;
+	uint32_t	mux_chn;
+	void		(*ih) (void *);
+	void		*ih_user;
+	enum ev_type	pevt;
+};
+
+static struct port_event event_map[NGPIO];
+
+struct port_softc {
+	struct resource		*res[6];
+	bus_space_tag_t		bst;
+	bus_space_handle_t	bsh;
+	void			*gpio_ih[NGPIO];
+};
+
+struct port_softc *port_sc;
+
+static struct resource_spec port_spec[] = {
+	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		1,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		2,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		3,	RF_ACTIVE },
+	{ SYS_RES_IRQ,		4,	RF_ACTIVE },
+	{ -1, 0 }
+};
+
+static int
+port_intr(void *arg)
+{
+	struct port_event *pev;
+	struct port_softc *sc;
+	int reg;
+	int i;
+
+	sc = arg;
+
+	for (i = 0; i < NGPIO; i++) {
+		reg = READ4(sc, PORT_PCR(i));
+		if (reg & PCR_ISF) {
+
+			/* Clear interrupt */
+			WRITE4(sc, PORT_PCR(i), reg);
+
+			/* Handle event */
+			pev = &event_map[i];
+			if (pev->enabled == 1) {
+				if (pev->ih != NULL) {
+					pev->ih(pev->ih_user);
+				}
+			}
+		}
+	}
+
+	return (FILTER_HANDLED);
+}
+
+int
+port_setup(int pnum, enum ev_type pevt, void (*ih)(void *), void *ih_user)
+{
+	struct port_event *pev;
+	struct port_softc *sc;
+	int reg;
+	int val;
+
+	sc = port_sc;
+
+	switch (pevt) {
+	case DMA_RISING_EDGE:
+		val = PCR_DMA_RE;
+		break;
+	case DMA_FALLING_EDGE:
+		val = PCR_DMA_FE;
+		break;
+	case DMA_EITHER_EDGE:
+		val = PCR_DMA_EE;
+		break;
+	case INT_LOGIC_ZERO:
+		val = PCR_INT_LZ;
+		break;
+	case INT_RISING_EDGE:
+		val = PCR_INT_RE;
+		break;
+	case INT_FALLING_EDGE:
+		val = PCR_INT_FE;
+		break;
+	case INT_EITHER_EDGE:
+		val = PCR_INT_RE;
+		break;
+	case INT_LOGIC_ONE:
+		val = PCR_INT_LO;
+		break;
+	default:
+		return (-1);
+	};
+
+	reg = READ4(sc, PORT_PCR(pnum));
+	reg &= ~(PCR_IRQC_M << PCR_IRQC_S);
+	reg |= (val << PCR_IRQC_S);
+	WRITE4(sc, PORT_PCR(pnum), reg);
+
+	pev = &event_map[pnum];
+	pev->ih = ih;
+	pev->ih_user = ih_user;
+	pev->pevt = pevt;
+	pev->enabled = 1;
+
+	return (0);
+}
+
+static int
+port_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "fsl,mvf600-port"))
+		return (ENXIO);
+
+	device_set_desc(dev, "Vybrid Family Port control and interrupts");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+port_attach(device_t dev)
+{
+	struct port_softc *sc;
+	int irq;
+
+	sc = device_get_softc(dev);
+
+	if (bus_alloc_resources(dev, port_spec, sc->res)) {
+		device_printf(dev, "could not allocate resources\n");
+		return (ENXIO);
+	}
+
+	/* Memory interface */
+	sc->bst = rman_get_bustag(sc->res[0]);
+	sc->bsh = rman_get_bushandle(sc->res[0]);
+
+	port_sc = sc;
+
+	for (irq = 0; irq < NPORTS; irq ++) {
+		if ((bus_setup_intr(dev, sc->res[1 + irq], INTR_TYPE_MISC,
+		    port_intr, NULL, sc, &sc->gpio_ih[irq]))) {
+			device_printf(dev,
+			    "ERROR: Unable to register interrupt handler\n");
+			return (ENXIO);
+		}
+	}
+
+	return (0);
+}
+
+static device_method_t port_methods[] = {
+	DEVMETHOD(device_probe,		port_probe),
+	DEVMETHOD(device_attach,	port_attach),
+	{ 0, 0 }
+};
+
+static driver_t port_driver = {
+	"port",
+	port_methods,
+	sizeof(struct port_softc),
+};
+
+static devclass_t port_devclass;
+
+DRIVER_MODULE(port, simplebus, port_driver, port_devclass, 0, 0);

Added: head/sys/arm/freescale/vybrid/vf_port.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/freescale/vybrid/vf_port.h	Fri Mar  7 07:06:36 2014	(r262885)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define	NPORTS		5
+#define	NGPIO		(NPORTS * 32)
+
+enum ev_type {
+	DMA_RISING_EDGE,
+	DMA_FALLING_EDGE,
+	DMA_EITHER_EDGE,
+	INT_LOGIC_ZERO,
+	INT_RISING_EDGE,
+	INT_FALLING_EDGE,
+	INT_EITHER_EDGE,
+	INT_LOGIC_ONE,
+};
+
+int port_setup(int, enum ev_type, void (*ih)(void *), void *ih_user);

Modified: head/sys/boot/fdt/dts/arm/vybrid.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/arm/vybrid.dtsi	Fri Mar  7 06:23:37 2014	(r262884)
+++ head/sys/boot/fdt/dts/arm/vybrid.dtsi	Fri Mar  7 07:06:36 2014	(r262885)
@@ -146,13 +146,18 @@
 			reg = <0x40048000 0x1000>;
 		};
 
+		port@40049000 {
+			compatible = "fsl,mvf600-port";
+			reg = <0x40049000 0x5000>;
+			interrupts = < 139 140 141 142 143 >;
+			interrupt-parent = <&GIC>;
+		};
+
 		gpio@400FF000 {
 			compatible = "fsl,mvf600-gpio";
 			reg = <0x400FF000 0x200>;
 			#gpio-cells = <3>;
 			gpio-controller;
-			interrupts = < 139 140 141 142 143 >;
-			interrupt-parent = <&GIC>;
 		};
 
 		nand@400E0000 {



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