Index: head/sys/arm/conf/BEAGLEBONE =================================================================== --- head/sys/arm/conf/BEAGLEBONE (revision 297539) +++ head/sys/arm/conf/BEAGLEBONE (revision 297540) @@ -1,151 +1,153 @@ # # BEAGLEBONE -- Custom configuration for the BeagleBone ARM development # platforms, check out http://www.beagleboard.org/bone and # http://www.beagleboard.org/black. This kernel config file is used for the # original BeagleBone and the BeagleBone Black. # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident BEAGLEBONE include "std.armv6" include "../ti/am335x/std.am335x" makeoptions MODULES_EXTRA="dtb/am335x am335x_dmtpps" +options ARM_INTRNG + options HZ=100 options SCHED_4BSD # 4BSD scheduler options PLATFORM # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options ALT_BREAK_TO_DEBUGGER #options VERBOSE_SYSINIT # Enable verbose sysinit messages options KDB # Enable kernel debugger support # For minimum debugger support (stable branch) use: #options KDB_TRACE # Print a stack trace for a panic # For full debugger support use this instead: options DDB # Enable the kernel debugger options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS options WITNESS # Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed #options DIAGNOSTIC # NFS server support #options NFSD # NFS root from boopt/dhcp #options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=cpsw0 # Boot device is 2nd slice on MMC/SD card options ROOTDEVNAME=\"ufs:mmcsd0s2\" # MMC/SD/SDIO Card slot support device mmc # mmc/sd bus device mmcsd # mmc/sd flash cards device sdhci # mmc/sd host controller # I2C support device iicbus device iic device ti_i2c device am335x_pmic # AM335x Power Management IC (TPC65217) device am335x_rtc # RTC support (power management only) #define am335x_dmtpps # Pulse Per Second capture driver # Console and misc device uart device uart_ns8250 device pty device snp device md device random # Entropy device # GPIO device gpio device gpioled device gpiobacklight # SPI device ti_spi device spibus # ADC support device ti_adc # Watchdog support # If we don't enable the watchdog driver, the system could potentially # reboot automatically because the boot loader might have enabled the # watchdog. device ti_wdt # TI Programmable Realtime Unit support device ti_pruss # Mailbox support device ti_mbox # PMU support (for CCNT). device pmu # USB support device usb options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. options USB_DEBUG #options USB_REQ_DEBUG #options USB_VERBOSE device musb device umass device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) # Ethernet device loop device ether device mii device smscphy device cpsw device bpf # USB Ethernet support, requires miibus device miibus device axe # ASIX Electronics USB Ethernet # Device mode support and USFS template device usb_template # Control of the gadget device usfs # Pinmux device fdt_pinctrl # Flattened Device Tree options FDT # Configure using FDT/DTB data # Comment following lines for boot console on serial port device vt device videomode device hdmi device ums device ukbd device kbdmux Index: head/sys/arm/ti/aintc.c =================================================================== --- head/sys/arm/ti/aintc.c (revision 297539) +++ head/sys/arm/ti/aintc.c (revision 297540) @@ -1,202 +1,378 @@ /*- * Copyright (c) 2012 Damjan Marion * All rights reserved. * * Based on OMAP3 INTC code by Ben Gray * * 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. */ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include #include #include #include +#include #include #include #include #include #include #include #include +#ifdef ARM_INTRNG +#include "pic_if.h" +#endif + #define INTC_REVISION 0x00 #define INTC_SYSCONFIG 0x10 #define INTC_SYSSTATUS 0x14 #define INTC_SIR_IRQ 0x40 #define INTC_CONTROL 0x48 #define INTC_THRESHOLD 0x68 #define INTC_MIR_CLEAR(x) (0x88 + ((x) * 0x20)) #define INTC_MIR_SET(x) (0x8C + ((x) * 0x20)) #define INTC_ISR_SET(x) (0x90 + ((x) * 0x20)) #define INTC_ISR_CLEAR(x) (0x94 + ((x) * 0x20)) +#define INTC_SIR_SPURIOUS_MASK 0xffffff80 +#define INTS_SIR_ACTIVE_MASK 0x7f + +#define INTC_NIRQS 128 + +#ifdef ARM_INTRNG +struct ti_aintc_irqsrc { + struct intr_irqsrc tai_isrc; + u_int tai_irq; +}; +#endif + struct ti_aintc_softc { device_t sc_dev; struct resource * aintc_res[3]; bus_space_tag_t aintc_bst; bus_space_handle_t aintc_bsh; uint8_t ver; +#ifdef ARM_INTRNG + struct ti_aintc_irqsrc aintc_isrcs[INTC_NIRQS]; +#endif }; static struct resource_spec ti_aintc_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, 0 } }; static struct ti_aintc_softc *ti_aintc_sc = NULL; #define aintc_read_4(_sc, reg) \ bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg)) #define aintc_write_4(_sc, reg, val) \ bus_space_write_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg), (val)) /* List of compatible strings for FDT tree */ static struct ofw_compat_data compat_data[] = { {"ti,am33xx-intc", 1}, {"ti,omap2-intc", 1}, {NULL, 0}, }; +#ifdef ARM_INTRNG +static inline void +ti_aintc_irq_eoi(struct ti_aintc_softc *sc) +{ + + aintc_write_4(sc, INTC_CONTROL, 1); +} + +static inline void +ti_aintc_irq_mask(struct ti_aintc_softc *sc, u_int irq) +{ + + aintc_write_4(sc, INTC_MIR_SET(irq >> 5), (1UL << (irq & 0x1F))); +} + +static inline void +ti_aintc_irq_unmask(struct ti_aintc_softc *sc, u_int irq) +{ + + aintc_write_4(sc, INTC_MIR_CLEAR(irq >> 5), (1UL << (irq & 0x1F))); +} + +static int +ti_aintc_intr(void *arg) +{ + uint32_t irq; + struct ti_aintc_softc *sc = arg; + + /* Get active interrupt */ + irq = aintc_read_4(sc, INTC_SIR_IRQ); + if ((irq & INTC_SIR_SPURIOUS_MASK) != 0) { + device_printf(sc->sc_dev, + "Spurious interrupt detected (0x%08x)\n", irq); + ti_aintc_irq_eoi(sc); + return (FILTER_HANDLED); + } + + /* Only level-sensitive interrupts detection is supported. */ + irq &= INTS_SIR_ACTIVE_MASK; + if (intr_isrc_dispatch(&sc->aintc_isrcs[irq].tai_isrc, + curthread->td_intr_frame) != 0) { + ti_aintc_irq_mask(sc, irq); + ti_aintc_irq_eoi(sc); + device_printf(sc->sc_dev, "Stray irq %u disabled\n", irq); + } + + arm_irq_memory_barrier(irq); /* XXX */ + return (FILTER_HANDLED); +} + static void +ti_aintc_enable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq; + struct ti_aintc_softc *sc = device_get_softc(dev); + + arm_irq_memory_barrier(irq); + ti_aintc_irq_unmask(sc, irq); +} + +static void +ti_aintc_disable_intr(device_t dev, struct intr_irqsrc *isrc) +{ + u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq; + struct ti_aintc_softc *sc = device_get_softc(dev); + + ti_aintc_irq_mask(sc, irq); +} + +static int +ti_aintc_map_intr(device_t dev, struct intr_map_data *data, + struct intr_irqsrc **isrcp) +{ + struct ti_aintc_softc *sc; + + if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells != 1 || + data->fdt.cells[0] >= INTC_NIRQS) + return (EINVAL); + + sc = device_get_softc(dev); + *isrcp = &sc->aintc_isrcs[data->fdt.cells[0]].tai_isrc; + return (0); +} + +static void +ti_aintc_pre_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq; + struct ti_aintc_softc *sc = device_get_softc(dev); + + ti_aintc_irq_mask(sc, irq); + ti_aintc_irq_eoi(sc); +} + +static void +ti_aintc_post_ithread(device_t dev, struct intr_irqsrc *isrc) +{ + + ti_aintc_enable_intr(dev, isrc); +} + +static void +ti_aintc_post_filter(device_t dev, struct intr_irqsrc *isrc) +{ + + ti_aintc_irq_eoi(device_get_softc(dev)); +} + +static int +ti_aintc_pic_attach(struct ti_aintc_softc *sc) +{ + int error; + uint32_t irq; + const char *name; + intptr_t xref; + + name = device_get_nameunit(sc->sc_dev); + for (irq = 0; irq < INTC_NIRQS; irq++) { + sc->aintc_isrcs[irq].tai_irq = irq; + + error = intr_isrc_register(&sc->aintc_isrcs[irq].tai_isrc, + sc->sc_dev, 0, "%s,%u", name, irq); + if (error != 0) + return (error); + } + + xref = OF_xref_from_node(ofw_bus_get_node(sc->sc_dev)); + error = intr_pic_register(sc->sc_dev, xref); + if (error != 0) + return (error); + + return (intr_pic_claim_root(sc->sc_dev, xref, ti_aintc_intr, sc, 0)); +} + +#else +static void aintc_post_filter(void *arg) { arm_irq_memory_barrier(0); aintc_write_4(ti_aintc_sc, INTC_CONTROL, 1); /* EOI */ } +#endif static int ti_aintc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); device_set_desc(dev, "TI AINTC Interrupt Controller"); return (BUS_PROBE_DEFAULT); } static int ti_aintc_attach(device_t dev) { struct ti_aintc_softc *sc = device_get_softc(dev); uint32_t x; sc->sc_dev = dev; if (ti_aintc_sc) return (ENXIO); if (bus_alloc_resources(dev, ti_aintc_spec, sc->aintc_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->aintc_bst = rman_get_bustag(sc->aintc_res[0]); sc->aintc_bsh = rman_get_bushandle(sc->aintc_res[0]); ti_aintc_sc = sc; x = aintc_read_4(sc, INTC_REVISION); device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF); /* SoftReset */ aintc_write_4(sc, INTC_SYSCONFIG, 2); /* Wait for reset to complete */ while(!(aintc_read_4(sc, INTC_SYSSTATUS) & 1)); /*Set Priority Threshold */ aintc_write_4(sc, INTC_THRESHOLD, 0xFF); +#ifndef ARM_INTRNG arm_post_filter = aintc_post_filter; - +#else + if (ti_aintc_pic_attach(sc) != 0) { + device_printf(dev, "could not attach PIC\n"); + return (ENXIO); + } +#endif return (0); } static device_method_t ti_aintc_methods[] = { DEVMETHOD(device_probe, ti_aintc_probe), DEVMETHOD(device_attach, ti_aintc_attach), + +#ifdef ARM_INTRNG + DEVMETHOD(pic_disable_intr, ti_aintc_disable_intr), + DEVMETHOD(pic_enable_intr, ti_aintc_enable_intr), + DEVMETHOD(pic_map_intr, ti_aintc_map_intr), + DEVMETHOD(pic_post_filter, ti_aintc_post_filter), + DEVMETHOD(pic_post_ithread, ti_aintc_post_ithread), + DEVMETHOD(pic_pre_ithread, ti_aintc_pre_ithread), +#endif + { 0, 0 } }; static driver_t ti_aintc_driver = { "aintc", ti_aintc_methods, sizeof(struct ti_aintc_softc), }; static devclass_t ti_aintc_devclass; EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); SIMPLEBUS_PNP_INFO(compat_data); +#ifndef ARM_INTRNG int arm_get_next_irq(int last_irq) { struct ti_aintc_softc *sc = ti_aintc_sc; uint32_t active_irq; /* Get the next active interrupt */ active_irq = aintc_read_4(sc, INTC_SIR_IRQ); /* Check for spurious interrupt */ if ((active_irq & 0xffffff80)) { device_printf(sc->sc_dev, "Spurious interrupt detected (0x%08x)\n", active_irq); aintc_write_4(sc, INTC_SIR_IRQ, 0); return -1; } if (active_irq != last_irq) return active_irq; else return -1; } void arm_mask_irq(uintptr_t nb) { struct ti_aintc_softc *sc = ti_aintc_sc; aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F))); aintc_write_4(sc, INTC_CONTROL, 1); /* EOI */ } void arm_unmask_irq(uintptr_t nb) { struct ti_aintc_softc *sc = ti_aintc_sc; arm_irq_memory_barrier(nb); aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F))); } +#endif