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>