From owner-svn-src-projects@freebsd.org Wed Apr 6 01:44:23 2016 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5B589B04DA7 for ; Wed, 6 Apr 2016 01:44:23 +0000 (UTC) (envelope-from gjb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1C66B17F8; Wed, 6 Apr 2016 01:44:23 +0000 (UTC) (envelope-from gjb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u361iMUe034209; Wed, 6 Apr 2016 01:44:22 GMT (envelope-from gjb@FreeBSD.org) Received: (from gjb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u361iLKD034200; Wed, 6 Apr 2016 01:44:21 GMT (envelope-from gjb@FreeBSD.org) Message-Id: <201604060144.u361iLKD034200@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gjb set sender to gjb@FreeBSD.org using -f From: Glen Barber Date: Wed, 6 Apr 2016 01:44:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r297605 - in projects/release-pkg: . share/man/man4 sys/amd64/linux sys/amd64/linux32 sys/arm/broadcom/bcm2835 sys/arm/conf sys/arm/nvidia sys/arm/nvidia/tegra124 sys/arm/ti sys/boot/fd... X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Apr 2016 01:44:23 -0000 Author: gjb Date: Wed Apr 6 01:44:21 2016 New Revision: 297605 URL: https://svnweb.freebsd.org/changeset/base/297605 Log: MFH Sponsored by: The FreeBSD Foundation Modified: projects/release-pkg/Makefile.inc1 projects/release-pkg/Makefile.libcompat projects/release-pkg/share/man/man4/usb_quirk.4 projects/release-pkg/sys/amd64/linux/linux_sysvec.c projects/release-pkg/sys/amd64/linux32/linux32_sysvec.c projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_gpio.c projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_intr.c projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836.c projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836.h projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836_mp.c projects/release-pkg/sys/arm/conf/RPI-B projects/release-pkg/sys/arm/conf/RPI2 projects/release-pkg/sys/arm/nvidia/tegra124/tegra124_clk_pll.c projects/release-pkg/sys/arm/nvidia/tegra124/tegra124_clk_super.c projects/release-pkg/sys/arm/nvidia/tegra124/tegra124_cpufreq.c projects/release-pkg/sys/arm/nvidia/tegra_ehci.c projects/release-pkg/sys/arm/ti/aintc.c projects/release-pkg/sys/boot/fdt/dts/arm/bcm2835.dtsi projects/release-pkg/sys/boot/fdt/dts/arm/bcm2836.dtsi projects/release-pkg/sys/dev/fdc/fdc.c projects/release-pkg/sys/dev/iicbus/ds1307.c projects/release-pkg/sys/dev/iicbus/ds1307reg.h projects/release-pkg/sys/dev/urtwn/if_urtwn.c projects/release-pkg/sys/dev/urtwn/if_urtwnvar.h projects/release-pkg/sys/dev/usb/controller/ehci_fsl.c projects/release-pkg/sys/dev/usb/controller/ehci_imx.c projects/release-pkg/sys/dev/usb/controller/musb_otg.c projects/release-pkg/sys/dev/usb/serial/uftdi.c projects/release-pkg/sys/dev/usb/wlan/if_rsu.c projects/release-pkg/sys/dev/xen/control/control.c projects/release-pkg/sys/i386/linux/linux_sysvec.c projects/release-pkg/sys/kern/kern_racct.c projects/release-pkg/sys/kern/kern_rctl.c projects/release-pkg/sys/kern/subr_smp.c projects/release-pkg/sys/net/netisr.c projects/release-pkg/sys/net80211/ieee80211.c projects/release-pkg/sys/net80211/ieee80211_freebsd.h projects/release-pkg/sys/net80211/ieee80211_hostap.c projects/release-pkg/sys/net80211/ieee80211_ht.h projects/release-pkg/sys/net80211/ieee80211_node.c projects/release-pkg/sys/net80211/ieee80211_output.c projects/release-pkg/sys/net80211/ieee80211_phy.c projects/release-pkg/sys/net80211/ieee80211_phy.h projects/release-pkg/sys/net80211/ieee80211_sta.c projects/release-pkg/sys/net80211/ieee80211_superg.c projects/release-pkg/sys/net80211/ieee80211_superg.h projects/release-pkg/sys/net80211/ieee80211_var.h projects/release-pkg/sys/powerpc/mpc85xx/i2c.c projects/release-pkg/sys/sys/param.h projects/release-pkg/sys/x86/x86/mp_x86.c projects/release-pkg/usr.bin/sed/compile.c projects/release-pkg/usr.sbin/bhyve/pci_ahci.c projects/release-pkg/usr.sbin/bhyveload/bhyveload.c Directory Properties: projects/release-pkg/ (props changed) projects/release-pkg/share/ (props changed) projects/release-pkg/share/man/man4/ (props changed) projects/release-pkg/sys/ (props changed) projects/release-pkg/sys/boot/ (props changed) projects/release-pkg/usr.sbin/bhyve/ (props changed) projects/release-pkg/usr.sbin/bhyveload/ (props changed) Modified: projects/release-pkg/Makefile.inc1 ============================================================================== --- projects/release-pkg/Makefile.inc1 Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/Makefile.inc1 Wed Apr 6 01:44:21 2016 (r297605) @@ -470,7 +470,7 @@ LIBCOMPAT= SOFT WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP} -IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*} +IMAKEENV= ${CROSSENV} IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \ ${IMAKE_INSTALL} ${IMAKE_MTREE} .if empty(.MAKEFLAGS:M-n) Modified: projects/release-pkg/Makefile.libcompat ============================================================================== --- projects/release-pkg/Makefile.libcompat Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/Makefile.libcompat Wed Apr 6 01:44:21 2016 (r297605) @@ -97,7 +97,7 @@ LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCO MK_TESTS=no LIBCOMPATWMAKE+= ${LIBCOMPATWMAKEENV} ${MAKE} ${LIBCOMPATWMAKEFLAGS} \ MK_MAN=no MK_HTML=no -LIBCOMPATIMAKE+= ${LIBCOMPATWMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} \ +LIBCOMPATIMAKE+= ${LIBCOMPATWMAKE:NINSTALL=*:NDESTDIR=*} \ MK_TOOLCHAIN=no ${IMAKE_INSTALL} \ -DLIBRARIES_ONLY Modified: projects/release-pkg/share/man/man4/usb_quirk.4 ============================================================================== --- projects/release-pkg/share/man/man4/usb_quirk.4 Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/share/man/man4/usb_quirk.4 Wed Apr 6 01:44:21 2016 (r297605) @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 26, 2015 +.Dd April 4, 2016 .Dt USB_QUIRK 4 .Os .Sh NAME @@ -234,6 +234,12 @@ device which appears as a USB device on usbconfig -d ugen0.3 add_quirk UQ_MSC_EJECT_WAIT .Ed .Pp +Enable a Holtec/Keep Out F85 gaming keyboard on +.Pa ugen1.4 : +.Bd -literal -offset indent +usbconfig -d ugen1.4 add_quirk UQ_KBD_BOOTPROTO +.Ed +.Pp To install a quirk at boot time, place one or several lines like the following in .Xr loader.conf 5 : Modified: projects/release-pkg/sys/amd64/linux/linux_sysvec.c ============================================================================== --- projects/release-pkg/sys/amd64/linux/linux_sysvec.c Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/sys/amd64/linux/linux_sysvec.c Wed Apr 6 01:44:21 2016 (r297605) @@ -992,3 +992,4 @@ static moduledata_t linux64_elf_mod = { DECLARE_MODULE_TIED(linux64elf, linux64_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_DEPEND(linux64elf, linux_common, 1, 1, 1); +FEATURE(linux64, "Linux 64bit support"); Modified: projects/release-pkg/sys/amd64/linux32/linux32_sysvec.c ============================================================================== --- projects/release-pkg/sys/amd64/linux32/linux32_sysvec.c Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/sys/amd64/linux32/linux32_sysvec.c Wed Apr 6 01:44:21 2016 (r297605) @@ -1205,3 +1205,4 @@ static moduledata_t linux_elf_mod = { DECLARE_MODULE_TIED(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_DEPEND(linuxelf, linux_common, 1, 1, 1); +FEATURE(linux, "Linux 32bit support"); Modified: projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_gpio.c ============================================================================== --- projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_gpio.c Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_gpio.c Wed Apr 6 01:44:21 2016 (r297605) @@ -28,6 +28,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include @@ -37,10 +39,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include @@ -49,6 +53,10 @@ __FBSDID("$FreeBSD$"); #include "gpio_if.h" +#ifdef ARM_INTRNG +#include "pic_if.h" +#endif + #ifdef DEBUG #define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ printf(fmt,##args); } while (0) @@ -64,10 +72,10 @@ __FBSDID("$FreeBSD$"); static struct resource_spec bcm_gpio_res_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, 0, RF_ACTIVE }, /* bank 0 interrupt */ + { SYS_RES_IRQ, 1, RF_ACTIVE }, /* bank 1 interrupt */ + { SYS_RES_IRQ, 2, RF_ACTIVE }, /* bank 1 interrupt (mirrored) */ + { SYS_RES_IRQ, 3, RF_ACTIVE }, /* bank 0-1 interrupt (united) */ { -1, 0, 0 } }; @@ -76,6 +84,15 @@ struct bcm_gpio_sysctl { uint32_t pin; }; +#ifdef ARM_INTRNG +struct bcm_gpio_irqsrc { + struct intr_irqsrc bgi_isrc; + uint32_t bgi_irq; + uint32_t bgi_reg; + uint32_t bgi_mask; +}; +#endif + struct bcm_gpio_softc { device_t sc_dev; device_t sc_busdev; @@ -88,10 +105,16 @@ struct bcm_gpio_softc { int sc_ro_npins; int sc_ro_pins[BCM_GPIO_PINS]; struct gpio_pin sc_gpio_pins[BCM_GPIO_PINS]; +#ifndef ARM_INTRNG struct intr_event * sc_events[BCM_GPIO_PINS]; +#endif struct bcm_gpio_sysctl sc_sysctl[BCM_GPIO_PINS]; +#ifdef ARM_INTRNG + struct bcm_gpio_irqsrc sc_isrcs[BCM_GPIO_PINS]; +#else enum intr_trigger sc_irq_trigger[BCM_GPIO_PINS]; enum intr_polarity sc_irq_polarity[BCM_GPIO_PINS]; +#endif }; enum bcm_gpio_pud { @@ -130,6 +153,13 @@ enum bcm_gpio_pud { static struct bcm_gpio_softc *bcm_gpio_sc = NULL; +#ifdef ARM_INTRNG +static int bcm_gpio_intr_bank0(void *arg); +static int bcm_gpio_intr_bank1(void *arg); +static int bcm_gpio_pic_attach(struct bcm_gpio_softc *sc); +static int bcm_gpio_pic_detach(struct bcm_gpio_softc *sc); +#endif + static int bcm_gpio_pin_is_ro(struct bcm_gpio_softc *sc, int pin) { @@ -661,6 +691,7 @@ bcm_gpio_get_reserved_pins(struct bcm_gp return (0); } +#ifndef ARM_INTRNG static int bcm_gpio_intr(void *arg) { @@ -694,6 +725,7 @@ bcm_gpio_intr(void *arg) return (FILTER_HANDLED); } +#endif static int bcm_gpio_probe(device_t dev) @@ -709,6 +741,49 @@ bcm_gpio_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +#ifdef ARM_INTRNG +static int +bcm_gpio_intr_attach(device_t dev) +{ + struct bcm_gpio_softc *sc; + + /* + * Only first two interrupt lines are used. Third line is + * mirrored second line and forth line is common for all banks. + */ + sc = device_get_softc(dev); + if (sc->sc_res[1] == NULL || sc->sc_res[2] == NULL) + return (-1); + + if (bcm_gpio_pic_attach(sc) != 0) { + device_printf(dev, "unable to attach PIC\n"); + return (-1); + } + if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_MISC | INTR_MPSAFE, + bcm_gpio_intr_bank0, NULL, sc, &sc->sc_intrhand[0]) != 0) + return (-1); + if (bus_setup_intr(dev, sc->sc_res[2], INTR_TYPE_MISC | INTR_MPSAFE, + bcm_gpio_intr_bank1, NULL, sc, &sc->sc_intrhand[1]) != 0) + return (-1); + + return (0); +} + +static void +bcm_gpio_intr_detach(device_t dev) +{ + struct bcm_gpio_softc *sc; + + sc = device_get_softc(dev); + if (sc->sc_intrhand[0] != NULL) + bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intrhand[0]); + if (sc->sc_intrhand[1] != NULL) + bus_teardown_intr(dev, sc->sc_res[2], sc->sc_intrhand[1]); + + bcm_gpio_pic_detach(sc); +} + +#else static int bcm_gpio_intr_attach(device_t dev) { @@ -741,6 +816,7 @@ bcm_gpio_intr_detach(device_t dev) } } } +#endif static int bcm_gpio_attach(device_t dev) @@ -786,9 +862,11 @@ bcm_gpio_attach(device_t dev) sc->sc_gpio_pins[i].gp_pin = j; sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS; sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func); +#ifndef ARM_INTRNG /* The default is active-low interrupts. */ sc->sc_irq_trigger[i] = INTR_TRIGGER_LEVEL; sc->sc_irq_polarity[i] = INTR_POLARITY_LOW; +#endif i++; } sc->sc_gpio_npins = i; @@ -814,6 +892,289 @@ bcm_gpio_detach(device_t dev) return (EBUSY); } +#ifdef ARM_INTRNG +static inline void +bcm_gpio_isrc_eoi(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) +{ + uint32_t bank; + + /* Write 1 to clear. */ + bank = BCM_GPIO_BANK(bgi->bgi_irq); + BCM_GPIO_WRITE(sc, BCM_GPIO_GPEDS(bank), bgi->bgi_mask); +} + +static inline bool +bcm_gpio_isrc_is_level(struct bcm_gpio_irqsrc *bgi) +{ + uint32_t bank; + + bank = BCM_GPIO_BANK(bgi->bgi_irq); + return (bgi->bgi_reg == BCM_GPIO_GPHEN(bank) || + bgi->bgi_reg == BCM_GPIO_GPLEN(bank)); +} + +static inline void +bcm_gpio_isrc_mask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) +{ + + BCM_GPIO_LOCK(sc); + BCM_GPIO_CLEAR_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); + BCM_GPIO_UNLOCK(bcm_gpio_sc); +} + +static inline void +bcm_gpio_isrc_unmask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) +{ + + BCM_GPIO_LOCK(sc); + BCM_GPIO_SET_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); + BCM_GPIO_UNLOCK(sc); +} + +static int +bcm_gpio_intr_internal(struct bcm_gpio_softc *sc, uint32_t bank) +{ + u_int irq; + struct bcm_gpio_irqsrc *bgi; + uint32_t reg; + + /* Do not care of spurious interrupt on GPIO. */ + reg = BCM_GPIO_READ(sc, BCM_GPIO_GPEDS(bank)); + while (reg != 0) { + irq = BCM_GPIO_PINS_PER_BANK * bank + ffs(reg) - 1; + bgi = sc->sc_isrcs + irq; + if (!bcm_gpio_isrc_is_level(bgi)) + bcm_gpio_isrc_eoi(sc, bgi); + if (intr_isrc_dispatch(&bgi->bgi_isrc, + curthread->td_intr_frame) != 0) { + bcm_gpio_isrc_mask(sc, bgi); + if (bcm_gpio_isrc_is_level(bgi)) + bcm_gpio_isrc_eoi(sc, bgi); + device_printf(sc->sc_dev, "Stray irq %u disabled\n", + irq); + } + reg &= ~bgi->bgi_mask; + } + return (FILTER_HANDLED); +} + +static int +bcm_gpio_intr_bank0(void *arg) +{ + + return (bcm_gpio_intr_internal(arg, 0)); +} + +static int +bcm_gpio_intr_bank1(void *arg) +{ + + return (bcm_gpio_intr_internal(arg, 1)); +} + +static int +bcm_gpio_pic_attach(struct bcm_gpio_softc *sc) +{ + int error; + uint32_t irq; + const char *name; + + name = device_get_nameunit(sc->sc_dev); + for (irq = 0; irq < BCM_GPIO_PINS; irq++) { + sc->sc_isrcs[irq].bgi_irq = irq; + sc->sc_isrcs[irq].bgi_mask = BCM_GPIO_MASK(irq); + sc->sc_isrcs[irq].bgi_reg = 0; + + error = intr_isrc_register(&sc->sc_isrcs[irq].bgi_isrc, + sc->sc_dev, 0, "%s,%u", name, irq); + if (error != 0) + return (error); /* XXX deregister ISRCs */ + } + return (intr_pic_register(sc->sc_dev, + OF_xref_from_node(ofw_bus_get_node(sc->sc_dev)))); +} + +static int +bcm_gpio_pic_detach(struct bcm_gpio_softc *sc) +{ + + /* + * There has not been established any procedure yet + * how to detach PIC from living system correctly. + */ + device_printf(sc->sc_dev, "%s: not implemented yet\n", __func__); + return (EBUSY); +} + +static void +bcm_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct bcm_gpio_softc *sc = device_get_softc(dev); + struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; + + bcm_gpio_isrc_mask(sc, bgi); +} + +static void +bcm_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct bcm_gpio_softc *sc = device_get_softc(dev); + struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; + + arm_irq_memory_barrier(bgi->bgi_irq); + bcm_gpio_isrc_unmask(sc, bgi); +} + +static int +bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, + u_int *irqp, uint32_t *regp) +{ + u_int irq; + uint32_t reg, bank; + + /* + * The first cell is the interrupt number. + * The second cell is used to specify flags: + * bits[3:0] trigger type and level flags: + * 1 = low-to-high edge triggered. + * 2 = high-to-low edge triggered. + * 4 = active high level-sensitive. + * 8 = active low level-sensitive. + */ + if (ncells != 2) + return (EINVAL); + + irq = cells[0]; + if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq)) + return (EINVAL); + + /* + * All interrupt types could be set for an interrupt at one moment. + * At least, the combination of 'low-to-high' and 'high-to-low' edge + * triggered interrupt types can make a sense. However, no combo is + * supported now. + */ + bank = BCM_GPIO_BANK(irq); + if (cells[1] == 1) + reg = BCM_GPIO_GPREN(bank); + else if (cells[1] == 2) + reg = BCM_GPIO_GPFEN(bank); + else if (cells[1] == 4) + reg = BCM_GPIO_GPHEN(bank); + else if (cells[1] == 8) + reg = BCM_GPIO_GPLEN(bank); + else + return (EINVAL); + + *irqp = irq; + if (regp != NULL) + *regp = reg; + return (0); +} + +static int +bcm_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, + struct intr_irqsrc **isrcp) +{ + int error; + u_int irq; + struct bcm_gpio_softc *sc; + + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + + sc = device_get_softc(dev); + error = bcm_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, + &irq, NULL); + if (error == 0) + *isrcp = &sc->sc_isrcs[irq].bgi_isrc; + return (error); +} + +static void +bcm_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc) +{ + struct bcm_gpio_softc *sc = device_get_softc(dev); + struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; + + if (bcm_gpio_isrc_is_level(bgi)) + bcm_gpio_isrc_eoi(sc, bgi); +} + +static void +bcm_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + bcm_gpio_pic_enable_intr(dev, isrc); +} + +static void +bcm_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + struct bcm_gpio_softc *sc = device_get_softc(dev); + struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; + + bcm_gpio_isrc_mask(sc, bgi); + if (bcm_gpio_isrc_is_level(bgi)) + bcm_gpio_isrc_eoi(sc, bgi); +} + +static int +bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, + struct resource *res, struct intr_map_data *data) +{ + u_int irq; + uint32_t bank, reg; + struct bcm_gpio_softc *sc; + struct bcm_gpio_irqsrc *bgi; + + if (data == NULL || data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + + sc = device_get_softc(dev); + bgi = (struct bcm_gpio_irqsrc *)isrc; + + /* Get and check config for an interrupt. */ + if (bcm_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq, + ®) != 0 || bgi->bgi_irq != irq) + return (EINVAL); + + /* + * If this is a setup for another handler, + * only check that its configuration match. + */ + if (isrc->isrc_handlers != 0) + return (bgi->bgi_reg == reg ? 0 : EINVAL); + + bank = BCM_GPIO_BANK(irq); + BCM_GPIO_LOCK(sc); + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask); + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask); + bgi->bgi_reg = reg; + BCM_GPIO_SET_BITS(sc, reg, bgi->bgi_mask); + BCM_GPIO_UNLOCK(sc); + return (0); +} + +static int +bcm_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, + struct resource *res, struct intr_map_data *data) +{ + struct bcm_gpio_softc *sc = device_get_softc(dev); + struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; + + if (isrc->isrc_handlers == 0) { + BCM_GPIO_LOCK(sc); + BCM_GPIO_CLEAR_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); + bgi->bgi_reg = 0; + BCM_GPIO_UNLOCK(sc); + } + return (0); +} + +#else static uint32_t bcm_gpio_intr_reg(struct bcm_gpio_softc *sc, unsigned int irq, uint32_t bank) { @@ -984,6 +1345,7 @@ bcm_gpio_teardown_intr(device_t dev, dev return (err); } +#endif static phandle_t bcm_gpio_get_node(device_t bus, device_t dev) @@ -1010,13 +1372,24 @@ static device_method_t bcm_gpio_methods[ DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set), DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle), +#ifdef ARM_INTRNG + /* Interrupt controller interface */ + DEVMETHOD(pic_disable_intr, bcm_gpio_pic_disable_intr), + DEVMETHOD(pic_enable_intr, bcm_gpio_pic_enable_intr), + DEVMETHOD(pic_map_intr, bcm_gpio_pic_map_intr), + DEVMETHOD(pic_post_filter, bcm_gpio_pic_post_filter), + DEVMETHOD(pic_post_ithread, bcm_gpio_pic_post_ithread), + DEVMETHOD(pic_pre_ithread, bcm_gpio_pic_pre_ithread), + DEVMETHOD(pic_setup_intr, bcm_gpio_pic_setup_intr), + DEVMETHOD(pic_teardown_intr, bcm_gpio_pic_teardown_intr), +#else /* Bus interface */ DEVMETHOD(bus_activate_resource, bcm_gpio_activate_resource), DEVMETHOD(bus_deactivate_resource, bcm_gpio_deactivate_resource), DEVMETHOD(bus_config_intr, bcm_gpio_config_intr), DEVMETHOD(bus_setup_intr, bcm_gpio_setup_intr), DEVMETHOD(bus_teardown_intr, bcm_gpio_teardown_intr), - +#endif /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, bcm_gpio_get_node), Modified: projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_intr.c ============================================================================== --- projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_intr.c Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2835_intr.c Wed Apr 6 01:44:21 2016 (r297605) @@ -30,12 +30,15 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include #include #include #include +#include #include #include #include @@ -49,6 +52,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef ARM_INTRNG +#include "pic_if.h" +#endif + #define INTC_PENDING_BASIC 0x00 #define INTC_PENDING_BANK1 0x04 #define INTC_PENDING_BANK2 0x08 @@ -60,17 +67,55 @@ __FBSDID("$FreeBSD$"); #define INTC_DISABLE_BANK2 0x20 #define INTC_DISABLE_BASIC 0x24 +#define INTC_PENDING_BASIC_ARM 0x0000FF +#define INTC_PENDING_BASIC_GPU1_PEND 0x000100 +#define INTC_PENDING_BASIC_GPU2_PEND 0x000200 +#define INTC_PENDING_BASIC_GPU1_7 0x000400 +#define INTC_PENDING_BASIC_GPU1_9 0x000800 +#define INTC_PENDING_BASIC_GPU1_10 0x001000 +#define INTC_PENDING_BASIC_GPU1_18 0x002000 +#define INTC_PENDING_BASIC_GPU1_19 0x004000 +#define INTC_PENDING_BASIC_GPU2_21 0x008000 +#define INTC_PENDING_BASIC_GPU2_22 0x010000 +#define INTC_PENDING_BASIC_GPU2_23 0x020000 +#define INTC_PENDING_BASIC_GPU2_24 0x040000 +#define INTC_PENDING_BASIC_GPU2_25 0x080000 +#define INTC_PENDING_BASIC_GPU2_30 0x100000 +#define INTC_PENDING_BASIC_MASK 0x1FFFFF + +#define INTC_PENDING_BASIC_GPU1_MASK (INTC_PENDING_BASIC_GPU1_7 | \ + INTC_PENDING_BASIC_GPU1_9 | \ + INTC_PENDING_BASIC_GPU1_10 | \ + INTC_PENDING_BASIC_GPU1_18 | \ + INTC_PENDING_BASIC_GPU1_19) + +#define INTC_PENDING_BASIC_GPU2_MASK (INTC_PENDING_BASIC_GPU2_21 | \ + INTC_PENDING_BASIC_GPU2_22 | \ + INTC_PENDING_BASIC_GPU2_23 | \ + INTC_PENDING_BASIC_GPU2_24 | \ + INTC_PENDING_BASIC_GPU2_25 | \ + INTC_PENDING_BASIC_GPU2_30) + +#define INTC_PENDING_BANK1_MASK (~((1 << 7) | (1 << 9) | (1 << 10) | \ + (1 << 18) | (1 << 19))) +#define INTC_PENDING_BANK2_MASK (~((1 << 21) | (1 << 22) | (1 << 23) | \ + (1 << 24) | (1 << 25) | (1 << 30))) + #define BANK1_START 8 #define BANK1_END (BANK1_START + 32 - 1) #define BANK2_START (BANK1_START + 32) #define BANK2_END (BANK2_START + 32 - 1) +#ifndef ARM_INTRNG #define BANK3_START (BANK2_START + 32) #define BANK3_END (BANK3_START + 32 - 1) +#endif #define IS_IRQ_BASIC(n) (((n) >= 0) && ((n) < BANK1_START)) #define IS_IRQ_BANK1(n) (((n) >= BANK1_START) && ((n) <= BANK1_END)) #define IS_IRQ_BANK2(n) (((n) >= BANK2_START) && ((n) <= BANK2_END)) +#ifndef ARM_INTRNG #define ID_IRQ_BCM2836(n) (((n) >= BANK3_START) && ((n) <= BANK3_END)) +#endif #define IRQ_BANK1(n) ((n) - BANK1_START) #define IRQ_BANK2(n) ((n) - BANK2_START) @@ -80,11 +125,28 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif +#ifdef ARM_INTRNG +#define BCM_INTC_NIRQS 72 /* 8 + 32 + 32 */ + +struct bcm_intc_irqsrc { + struct intr_irqsrc bii_isrc; + u_int bii_irq; + uint16_t bii_disable_reg; + uint16_t bii_enable_reg; + uint32_t bii_mask; +}; +#endif + struct bcm_intc_softc { device_t sc_dev; struct resource * intc_res; bus_space_tag_t intc_bst; bus_space_handle_t intc_bsh; +#ifdef ARM_INTRNG + struct resource * intc_irq_res; + void * intc_irq_hdl; + struct bcm_intc_irqsrc intc_isrcs[BCM_INTC_NIRQS]; +#endif }; static struct bcm_intc_softc *bcm_intc_sc = NULL; @@ -94,6 +156,192 @@ static struct bcm_intc_softc *bcm_intc_s #define intc_write_4(_sc, reg, val) \ bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val)) +#ifdef ARM_INTRNG +static inline void +bcm_intc_isrc_mask(struct bcm_intc_softc *sc, struct bcm_intc_irqsrc *bii) +{ + + intc_write_4(sc, bii->bii_disable_reg, bii->bii_mask); +} + +static inline void +bcm_intc_isrc_unmask(struct bcm_intc_softc *sc, struct bcm_intc_irqsrc *bii) +{ + + intc_write_4(sc, bii->bii_enable_reg, bii->bii_mask); +} + +static inline int +bcm2835_intc_active_intr(struct bcm_intc_softc *sc) +{ + uint32_t pending, pending_gpu; + + pending = intc_read_4(sc, INTC_PENDING_BASIC) & INTC_PENDING_BASIC_MASK; + if (pending == 0) + return (-1); + if (pending & INTC_PENDING_BASIC_ARM) + return (ffs(pending) - 1); + if (pending & INTC_PENDING_BASIC_GPU1_MASK) { + if (pending & INTC_PENDING_BASIC_GPU1_7) + return (BANK1_START + 7); + if (pending & INTC_PENDING_BASIC_GPU1_9) + return (BANK1_START + 9); + if (pending & INTC_PENDING_BASIC_GPU1_10) + return (BANK1_START + 10); + if (pending & INTC_PENDING_BASIC_GPU1_18) + return (BANK1_START + 18); + if (pending & INTC_PENDING_BASIC_GPU1_19) + return (BANK1_START + 19); + } + if (pending & INTC_PENDING_BASIC_GPU2_MASK) { + if (pending & INTC_PENDING_BASIC_GPU2_21) + return (BANK2_START + 21); + if (pending & INTC_PENDING_BASIC_GPU2_22) + return (BANK2_START + 22); + if (pending & INTC_PENDING_BASIC_GPU2_23) + return (BANK2_START + 23); + if (pending & INTC_PENDING_BASIC_GPU2_24) + return (BANK2_START + 24); + if (pending & INTC_PENDING_BASIC_GPU2_25) + return (BANK2_START + 25); + if (pending & INTC_PENDING_BASIC_GPU2_30) + return (BANK2_START + 30); + } + if (pending & INTC_PENDING_BASIC_GPU1_PEND) { + pending_gpu = intc_read_4(sc, INTC_PENDING_BANK1); + pending_gpu &= INTC_PENDING_BANK1_MASK; + if (pending_gpu != 0) + return (BANK1_START + ffs(pending_gpu) - 1); + } + if (pending & INTC_PENDING_BASIC_GPU2_PEND) { + pending_gpu = intc_read_4(sc, INTC_PENDING_BANK2); + pending_gpu &= INTC_PENDING_BANK2_MASK; + if (pending_gpu != 0) + return (BANK2_START + ffs(pending_gpu) - 1); + } + return (-1); /* It shouldn't end here, but it's hardware. */ +} + +static int +bcm2835_intc_intr(void *arg) +{ + int irq, num; + struct bcm_intc_softc *sc = arg; + + for (num = 0; ; num++) { + irq = bcm2835_intc_active_intr(sc); + if (irq == -1) + break; + if (intr_isrc_dispatch(&sc->intc_isrcs[irq].bii_isrc, + curthread->td_intr_frame) != 0) { + bcm_intc_isrc_mask(sc, &sc->intc_isrcs[irq]); + device_printf(sc->sc_dev, "Stray irq %u disabled\n", + irq); + } + arm_irq_memory_barrier(0); /* XXX */ + } + if (num == 0) + device_printf(sc->sc_dev, "Spurious interrupt detected\n"); + + return (FILTER_HANDLED); +} + +static void +bcm_intc_enable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct bcm_intc_irqsrc *bii = (struct bcm_intc_irqsrc *)isrc; + + arm_irq_memory_barrier(bii->bii_irq); + bcm_intc_isrc_unmask(device_get_softc(dev), bii); +} + +static void +bcm_intc_disable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + + bcm_intc_isrc_mask(device_get_softc(dev), + (struct bcm_intc_irqsrc *)isrc); +} + +static int +bcm_intc_map_intr(device_t dev, struct intr_map_data *data, + struct intr_irqsrc **isrcp) +{ + u_int irq; + struct bcm_intc_softc *sc; + + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + if (data->fdt.ncells == 1) + irq = data->fdt.cells[0]; + else if (data->fdt.ncells == 2) + irq = data->fdt.cells[0] * 32 + data->fdt.cells[1]; + else + return (EINVAL); + + if (irq >= BCM_INTC_NIRQS) + return (EINVAL); + + sc = device_get_softc(dev); + *isrcp = &sc->intc_isrcs[irq].bii_isrc; + return (0); +} + +static void +bcm_intc_pre_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + bcm_intc_disable_intr(dev, isrc); +} + +static void +bcm_intc_post_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + bcm_intc_enable_intr(dev, isrc); +} + +static void +bcm_intc_post_filter(device_t dev, struct intr_irqsrc *isrc) +{ +} + +static int +bcm_intc_pic_register(struct bcm_intc_softc *sc, intptr_t xref) +{ + struct bcm_intc_irqsrc *bii; + int error; + uint32_t irq; + const char *name; + + name = device_get_nameunit(sc->sc_dev); + for (irq = 0; irq < BCM_INTC_NIRQS; irq++) { + bii = &sc->intc_isrcs[irq]; + bii->bii_irq = irq; + if (IS_IRQ_BASIC(irq)) { + bii->bii_disable_reg = INTC_DISABLE_BASIC; + bii->bii_enable_reg = INTC_ENABLE_BASIC; + bii->bii_mask = 1 << irq; + } else if (IS_IRQ_BANK1(irq)) { + bii->bii_disable_reg = INTC_DISABLE_BANK1; + bii->bii_enable_reg = INTC_ENABLE_BANK1; + bii->bii_mask = 1 << IRQ_BANK1(irq); + } else if (IS_IRQ_BANK2(irq)) { + bii->bii_disable_reg = INTC_DISABLE_BANK2; + bii->bii_enable_reg = INTC_ENABLE_BANK2; + bii->bii_mask = 1 << IRQ_BANK2(irq); + } else + return (ENXIO); + + error = intr_isrc_register(&bii->bii_isrc, sc->sc_dev, 0, + "%s,%u", name, irq); + if (error != 0) + return (error); + } + return (intr_pic_register(sc->sc_dev, xref)); +} +#endif + static int bcm_intc_probe(device_t dev) { @@ -112,7 +360,9 @@ bcm_intc_attach(device_t dev) { struct bcm_intc_softc *sc = device_get_softc(dev); int rid = 0; - +#ifdef ARM_INTRNG + intptr_t xref; +#endif sc->sc_dev = dev; if (bcm_intc_sc) @@ -124,6 +374,32 @@ bcm_intc_attach(device_t dev) return (ENXIO); } +#ifdef ARM_INTRNG + xref = OF_xref_from_node(ofw_bus_get_node(dev)); + if (bcm_intc_pic_register(sc, xref) != 0) { + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->intc_res); + device_printf(dev, "could not register PIC\n"); + return (ENXIO); + } + + rid = 0; + sc->intc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->intc_irq_res == NULL) { + if (intr_pic_claim_root(dev, xref, bcm2835_intc_intr, sc, 0) != 0) { + /* XXX clean up */ + device_printf(dev, "could not set PIC as a root\n"); + return (ENXIO); + } + } else { + if (bus_setup_intr(dev, sc->intc_irq_res, INTR_TYPE_CLK, + bcm2835_intc_intr, NULL, sc, &sc->intc_irq_hdl)) { + /* XXX clean up */ + device_printf(dev, "could not setup irq handler\n"); + return (ENXIO); + } + } +#endif sc->intc_bst = rman_get_bustag(sc->intc_res); sc->intc_bsh = rman_get_bushandle(sc->intc_res); @@ -135,6 +411,16 @@ bcm_intc_attach(device_t dev) static device_method_t bcm_intc_methods[] = { DEVMETHOD(device_probe, bcm_intc_probe), DEVMETHOD(device_attach, bcm_intc_attach), + +#ifdef ARM_INTRNG + DEVMETHOD(pic_disable_intr, bcm_intc_disable_intr), + DEVMETHOD(pic_enable_intr, bcm_intc_enable_intr), + DEVMETHOD(pic_map_intr, bcm_intc_map_intr), + DEVMETHOD(pic_post_filter, bcm_intc_post_filter), + DEVMETHOD(pic_post_ithread, bcm_intc_post_ithread), + DEVMETHOD(pic_pre_ithread, bcm_intc_pre_ithread), +#endif + { 0, 0 } }; @@ -148,6 +434,7 @@ static devclass_t bcm_intc_devclass; DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass, 0, 0); +#ifndef ARM_INTRNG int arm_get_next_irq(int last_irq) { @@ -247,3 +534,4 @@ intr_pic_init_secondary(void) { } #endif +#endif Modified: projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836.c ============================================================================== --- projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836.c Wed Apr 6 01:22:20 2016 (r297604) +++ projects/release-pkg/sys/arm/broadcom/bcm2835/bcm2836.c Wed Apr 6 01:44:21 2016 (r297605) @@ -1,5 +1,6 @@ /* * Copyright 2015 Andrew Turner. + * Copyright 2016 Svatopluk Kraus * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,19 +29,33 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include +#include #include #include +#include #include +#ifdef SMP +#include +#endif #include +#include #include +#ifdef SMP +#include +#endif #include #include +#ifdef ARM_INTRNG +#include "pic_if.h" +#else #include #define ARM_LOCAL_BASE 0x40000000 @@ -55,7 +70,703 @@ __FBSDID("$FreeBSD$"); #define INT_PENDING_MASK 0x011f #define MAILBOX0_IRQ 4 #define MAILBOX0_IRQEN (1 << 0) +#endif + +#ifdef ARM_INTRNG +#define BCM_LINTC_CONTROL_REG 0x00 +#define BCM_LINTC_PRESCALER_REG 0x08 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***