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 <b...@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 <b...@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 {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to