From 5d4c5b9406660e986c308e9429d386203c44541f Mon Sep 17 00:00:00 2001 From: Patrick Wildt Date: Fri, 6 Feb 2015 00:31:10 +0100 Subject: [PATCH] arm: support for the raspberry Pi 2 * Interrupt controller * Mailbox read/write * GPIO * SDHC * Watchdog * Simple bootloader code * USB (work in progress) Some stuff taken from NetBSD. --- sys/arch/armv7/Makefile | 2 +- sys/arch/armv7/broadcom/bcm2835_dwctwo.c | 151 ++++++ sys/arch/armv7/broadcom/bcm2835_gpio.c | 240 +++++++++ sys/arch/armv7/broadcom/bcm2835_mbox.c | 283 +++++++++++ sys/arch/armv7/broadcom/bcm2835_mbox.h | 60 +++ sys/arch/armv7/broadcom/bcm2835_mbox_subr.c | 99 ++++ sys/arch/armv7/broadcom/bcm2835_mboxreg.h | 75 +++ sys/arch/armv7/broadcom/bcm2835_pm.c | 157 ++++++ sys/arch/armv7/broadcom/bcm2835_sdhc.c | 136 +++++ sys/arch/armv7/broadcom/bcm2836_intr.c | 529 ++++++++++++++++++++ sys/arch/armv7/broadcom/files.broadcom | 27 + sys/arch/armv7/conf/Makefile.armv7 | 2 + sys/arch/armv7/conf/files.armv7 | 1 + sys/arch/armv7/conf/generic | 1 + sys/arch/armv7/conf/generic.broadcom | 11 + sys/arch/armv7/fdt/fdt_machdep.c | 3 + sys/arch/armv7/stand/Makefile | 3 + sys/arch/armv7/stand/rpiboot/Makefile | 13 + sys/arch/armv7/stand/rpiboot/rpi.S | 34 ++ 19 files changed, 1826 insertions(+), 1 deletion(-) create mode 100644 sys/arch/armv7/broadcom/bcm2835_dwctwo.c create mode 100644 sys/arch/armv7/broadcom/bcm2835_gpio.c create mode 100644 sys/arch/armv7/broadcom/bcm2835_mbox.c create mode 100644 sys/arch/armv7/broadcom/bcm2835_mbox.h create mode 100644 sys/arch/armv7/broadcom/bcm2835_mbox_subr.c create mode 100644 sys/arch/armv7/broadcom/bcm2835_mboxreg.h create mode 100644 sys/arch/armv7/broadcom/bcm2835_pm.c create mode 100644 sys/arch/armv7/broadcom/bcm2835_sdhc.c create mode 100644 sys/arch/armv7/broadcom/bcm2836_intr.c create mode 100644 sys/arch/armv7/broadcom/files.broadcom create mode 100644 sys/arch/armv7/conf/generic.broadcom create mode 100644 sys/arch/armv7/stand/Makefile create mode 100644 sys/arch/armv7/stand/rpiboot/Makefile create mode 100644 sys/arch/armv7/stand/rpiboot/rpi.S diff --git a/sys/arch/armv7/Makefile b/sys/arch/armv7/Makefile index 0fe8df16c87..daca15d0be3 100644 --- a/sys/arch/armv7/Makefile +++ b/sys/arch/armv7/Makefile @@ -11,7 +11,7 @@ TAGS= ${.CURDIR}/tags NOPROG= NOMAN= NOOBJ= -SUBDIR= +SUBDIR= stand # config the fattest kernel we can find into a temporary dir # to create a Makefile. Then use make to pull some variables diff --git a/sys/arch/armv7/broadcom/bcm2835_dwctwo.c b/sys/arch/armv7/broadcom/bcm2835_dwctwo.c new file mode 100644 index 00000000000..85eb7ea7563 --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_dwctwo.c @@ -0,0 +1,151 @@ +/* $OpenBSD: octdwctwo.c,v 1.4 2015/02/14 06:46:03 uebayasi Exp $ */ + +/* + * Copyright (c) 2015 Masao Uebayashi + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +struct bcm_dwctwo_softc { + struct dwc2_softc sc_dwc2; + struct arm32_bus_dma_tag sc_dmat; + struct arm32_dma_range sc_dmarange[1]; + + void *sc_ih; +}; + +int bcm_dwctwo_match(struct device *, void *, void *); +void bcm_dwctwo_attach(struct device *, struct device *, + void *); +void bcm_dwctwo_deferred(void *); + +const struct cfattach bcmdwctwo_ca = { + sizeof(struct bcm_dwctwo_softc), bcm_dwctwo_match, bcm_dwctwo_attach, +}; + +struct cfdriver dwctwo_cd = { + NULL, "dwctwo", DV_DULL +}; + +static struct dwc2_core_params bcm_dwctwo_params = { + .otg_cap = 0, /* HNP/SRP capable */ + .otg_ver = 0, /* 1.3 */ + .dma_enable = 1, + .dma_desc_enable = 0, + .speed = 0, /* High Speed */ + .enable_dynamic_fifo = 1, + .en_multiple_tx_fifo = 1, + .host_rx_fifo_size = 774, /* 774 DWORDs */ + .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */ + .host_perio_tx_fifo_size = 512, /* 512 DWORDs */ + .max_transfer_size = 65535, + .max_packet_count = 511, + .host_channels = 8, + .phy_type = 1, /* UTMI */ + .phy_utmi_width = 8, /* 8 bits */ + .phy_ulpi_ddr = 0, /* Single */ + .phy_ulpi_ext_vbus = 0, + .i2c_enable = 0, + .ulpi_fs_ls = 0, + .host_support_fs_ls_low_power = 0, + .host_ls_low_power_phy_clk = 0, /* 48 MHz */ + .ts_dline = 0, + .reload_ctl = 0, + .ahbcfg = 0x10, + .uframe_sched = 1, +}; + +int +bcm_dwctwo_match(struct device *parent, void *match, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-usb", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-usb", aa->aa_node)) + return (1); + + return 0; +} + +void +bcm_dwctwo_attach(struct device *parent, struct device *self, void *aux) +{ + struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self; + struct armv7_attach_args *aa = aux; + struct fdt_memory mem; + extern int physmem; + int rc; + + printf("\n"); + + memcpy(&sc->sc_dmat, aa->aa_dmat, sizeof(sc->sc_dmat)); + sc->sc_dmarange[0].dr_sysbase = 0; + sc->sc_dmarange[0].dr_busbase = 0xC0000000; + sc->sc_dmarange[0].dr_len = physmem * PAGE_SIZE; + sc->sc_dmat._ranges = sc->sc_dmarange; + sc->sc_dmat._nranges = 1; + + sc->sc_dwc2.sc_iot = aa->aa_iot; + sc->sc_dwc2.sc_bus.pipe_size = sizeof(struct usbd_pipe); + sc->sc_dwc2.sc_bus.dmatag = &sc->sc_dmat; + sc->sc_dwc2.sc_params = &bcm_dwctwo_params; + + rc = fdt_get_memory_address(aa->aa_node, 0, &mem); + KASSERT(rc == 0); + + rc = bus_space_map(aa->aa_iot, mem.addr, mem.size, + 0, &sc->sc_dwc2.sc_ioh); + KASSERT(rc == 0); + + sc->sc_ih = arm_intr_establish_fdt(aa->aa_node, IPL_SCHED, dwc2_intr, + (void *)&sc->sc_dwc2, sc->sc_dwc2.sc_bus.bdev.dv_xname); + KASSERT(sc->sc_ih != NULL); + + kthread_create_deferred(bcm_dwctwo_deferred, sc); +} + +void +bcm_dwctwo_deferred(void *self) +{ + struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self; + int rc; + + rc = dwc2_init(&sc->sc_dwc2); + if (rc != 0) + return; + + sc->sc_dwc2.sc_child = config_found(&sc->sc_dwc2.sc_bus.bdev, + &sc->sc_dwc2.sc_bus, usbctlprint); +} diff --git a/sys/arch/armv7/broadcom/bcm2835_gpio.c b/sys/arch/armv7/broadcom/bcm2835_gpio.c new file mode 100644 index 00000000000..43dd99f646d --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_gpio.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpio.h" + +#define GPIOFSEL(x) (0x00 + (x) * 4) +#define GPIOSET(x) (0x1c + (x) * 4) +#define GPIOCLR(x) (0x28 + (x) * 4) +#define GPIOLEV(x) (0x34 + (x) * 4) +#define GPIOEDS(x) (0x40 + (x) * 4) +#define GPIOREN(x) (0x4c + (x) * 4) +#define GPIOFEN(x) (0x58 + (x) * 4) +#define GPIOHEN(x) (0x64 + (x) * 4) +#define GPIOLEN(x) (0x70 + (x) * 4) +#define GPIOAREN(x) (0x7c + (x) * 4) +#define GPIOAFREN(x) (0x88 + (x) * 4) +#define GPIOUD(x) (0x94 + (x) * 4) +#define GPIOUDCLK(x) (0x98 + (x) * 4) + +#define GPIO_FSEL_INPUT 0 +#define GPIO_FSEL_OUTPUT 1 +#define GPIO_FSEL_ALT5 2 +#define GPIO_FSEL_ALT4 3 +#define GPIO_FSEL_ALT0 4 +#define GPIO_FSEL_ALT1 5 +#define GPIO_FSEL_ALT2 6 +#define GPIO_FSEL_ALT3 7 + +#define GPIO_NPINS 54 +#define GPIO_NBANKS 2 + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) +#define HSET4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) +#define HCLR4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) + +struct bcmgpio_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + struct gpio_chipset_tag sc_gpio_gc; + gpio_pin_t sc_gpio_pins[GPIO_NPINS]; +}; + +int bcmgpio_match(struct device *, void *, void *); +void bcmgpio_attach(struct device *, struct device *, void *); +int bcmgpio_pin_read(void *, int); +void bcmgpio_pin_write(void *, int, int); +void bcmgpio_pin_ctl(void *, int, int); +int bcmgpio_func_read(struct bcmgpio_softc *, int); +void bcmgpio_func_set(struct bcmgpio_softc *, int, int); + +struct cfattach bcmgpio_ca = { + sizeof (struct bcmgpio_softc), bcmgpio_match, bcmgpio_attach +}; + +struct cfdriver bcmgpio_cd = { + NULL, "bcmgpio", DV_DULL +}; + +int +bcmgpio_match(struct device *parent, void *cfdata, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-gpio", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-gpio", aa->aa_node)) + return (1); + + return 0; +} + +void +bcmgpio_attach(struct device *parent, struct device *self, void *args) +{ + struct bcmgpio_softc *sc = (struct bcmgpio_softc *)self; + struct armv7_attach_args *aa = args; + struct gpiobus_attach_args gba; + struct fdt_memory mem; + int i; + + sc->sc_iot = aa->aa_iot; + if (fdt_get_memory_address(aa->aa_node, 0, &mem)) + panic("%s: could not extract memory data from FDT", + __func__); + + if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + printf("\n"); + + for (i = 0; i < GPIO_NPINS; i++) { + sc->sc_gpio_pins[i].pin_num = i; + + int func = bcmgpio_func_read(sc, i); + if (func == GPIO_FSEL_INPUT || func == GPIO_FSEL_OUTPUT) { + sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | + GPIO_PIN_OUTPUT | + GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN; + sc->sc_gpio_pins[i].pin_state = + bcmgpio_pin_read(sc, i); + } else { + sc->sc_gpio_pins[i].pin_caps = 0; + sc->sc_gpio_pins[i].pin_state = 0; + } + } + + sc->sc_gpio_gc.gp_cookie = sc; + sc->sc_gpio_gc.gp_pin_read = bcmgpio_pin_read; + sc->sc_gpio_gc.gp_pin_write = bcmgpio_pin_write; + sc->sc_gpio_gc.gp_pin_ctl = bcmgpio_pin_ctl; + + gba.gba_name = "gpio"; + gba.gba_gc = &sc->sc_gpio_gc; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = GPIO_NPINS; + + config_found(&sc->sc_dev, &gba, gpiobus_print); +} + +int +bcmgpio_pin_read(void *arg, int pin) +{ + struct bcmgpio_softc *sc = arg; + int bank = pin / 32; + int off = pin % 32; + int reg; + + if (pin >= GPIO_NPINS) + return 0; + + reg = HREAD4(sc, GPIOLEV(bank)); + + return !!(reg & (1U << off)); +} + +void +bcmgpio_pin_write(void *arg, int pin, int val) +{ + struct bcmgpio_softc *sc = arg; + int bank = pin / 32; + int off = pin % 32; + + if (pin >= GPIO_NPINS) + return; + + if (val) + HWRITE4(sc, GPIOSET(bank), 1U << off); + else + HWRITE4(sc, GPIOCLR(bank), 1U << off); + + return; +} + +void +bcmgpio_pin_ctl(void *arg, int pin, int flags) +{ + struct bcmgpio_softc *sc = arg; + int bank = pin / 32; + int off = pin % 32; + + if (pin >= GPIO_NPINS) + return; + + if (flags & GPIO_PIN_INPUT) + bcmgpio_func_set(sc, pin, GPIO_FSEL_INPUT); + else if (flags & GPIO_PIN_OUTPUT) + bcmgpio_func_set(sc, pin, GPIO_FSEL_OUTPUT); + + if (flags & GPIO_PIN_PULLUP) + HWRITE4(sc, GPIOUD(0), 2); + else if (flags & GPIO_PIN_PULLDOWN) + HWRITE4(sc, GPIOUD(0), 1); + else + HWRITE4(sc, GPIOUD(0), 0); + + delay(5); + HWRITE4(sc, GPIOUDCLK(bank), 1 << off); + delay(5); + HWRITE4(sc, GPIOUD(0), 0); + HWRITE4(sc, GPIOUDCLK(bank), 0 << off); + + return; +} + +int +bcmgpio_func_read(struct bcmgpio_softc *sc, int pin) +{ + int bank = pin / 10; + int shift = (pin % 10) * 3; + uint32_t reg; + + reg = HREAD4(sc, GPIOFSEL(bank)); + + return ((reg >> shift) & 0x7); +} + + +void +bcmgpio_func_set(struct bcmgpio_softc *sc, int pin, int func) +{ + int bank = pin / 10; + int shift = (pin % 10) * 3; + uint32_t reg; + + reg = HREAD4(sc, GPIOFSEL(bank)); + reg &= ~(0x7 << shift); + reg |= func << shift; + HWRITE4(sc, GPIOFSEL(bank), reg); +} diff --git a/sys/arch/armv7/broadcom/bcm2835_mbox.c b/sys/arch/armv7/broadcom/bcm2835_mbox.c new file mode 100644 index 00000000000..998e378650d --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_mbox.c @@ -0,0 +1,283 @@ +/* $NetBSD: bcm2835_mbox.c,v 1.9 2014/10/15 06:57:27 skrll Exp $ */ + +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +//#include + +struct bcm2835mbox_softc { + struct device sc_dev; + struct device sc_platdev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_dma_tag_t sc_dmat; + void *sc_intrh; + + struct mutex sc_lock; + //struct mutex sc_intr_lock; + uint32_t sc_chan[BCM2835_MBOX_NUMCHANNELS]; + uint32_t sc_mbox[BCM2835_MBOX_NUMCHANNELS]; +}; + +static struct bcm2835mbox_softc *bcm2835mbox_sc; + +static int bcmmbox_match(struct device *, void *, void *); +static void bcmmbox_attach(struct device *, struct device *, void *); +static int bcmmbox_intr1(struct bcm2835mbox_softc *, int); +static int bcmmbox_intr(void *); + +const struct cfattach bcmmbox_ca = { + sizeof(struct bcm2835mbox_softc), bcmmbox_match, bcmmbox_attach, +}; + +struct cfdriver bcmmbox_cd = { + NULL, "bcmmbox", DV_DULL +}; + +/* ARGSUSED */ +static int +bcmmbox_match(struct device *parent, void *match, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-mbox", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-mbox", aa->aa_node)) + return (1); + + return 0; +} + +static void +bcmmbox_attach(struct device *parent, struct device *self, void *aux) +{ + struct bcm2835mbox_softc *sc = (struct bcm2835mbox_softc *)self; + struct armv7_attach_args *aa = aux; + //struct bcmmbox_attach_args baa; + struct fdt_memory mem; + + sc->sc_iot = aa->aa_iot; + sc->sc_dmat = aa->aa_dmat; + mtx_init(&sc->sc_lock, IPL_NONE); + //mtx_init(&sc->sc_intr_lock, IPL_VM); + + if (fdt_get_memory_address(aa->aa_node, 0, &mem)) { + printf(": could not extract memory data from FDT"); + return; + } + + if (bus_space_map(aa->aa_iot, mem.addr, mem.size, 0, + &sc->sc_ioh)) { + printf(": unable to map device\n"); + return; + } + + sc->sc_intrh = arm_intr_establish_fdt(aa->aa_node, IPL_VM, + bcmmbox_intr, sc, sc->sc_dev.dv_xname); + if (sc->sc_intrh == NULL) { + printf(": unable to establish interrupt\n"); + return; + } + + printf(": VC mailbox\n"); + + /* enable mbox interrupt */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_MBOX_CFG, + BCM2835_MBOX_CFG_DATAIRQEN); + + if (bcm2835mbox_sc == NULL) + bcm2835mbox_sc = sc; + + //baa.baa_dmat = aa->aa_dmat; + //sc->sc_platdev = config_found_ia(self, "bcmmboxbus", &baa, NULL); + + /* Enable power for SD, UART and USB. */ + /* FIXME: not here? */ + bcmmbox_write(0, ( /* CHANPM */ + (1 << 0) | /* SDCARD */ + (1 << 1) | /* UART0 */ + (1 << 3) | /* USB */ + 0) << 4); +} + +static int +bcmmbox_intr1(struct bcm2835mbox_softc *sc, int cv) +{ + uint32_t mbox, chan, data; + int ret = 0; + + //KASSERT(mtx_owned(&sc->sc_intr_lock)); + + bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, BCM2835_MBOX_SIZE, + BUS_SPACE_BARRIER_READ); + + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, + BCM2835_MBOX0_STATUS) & BCM2835_MBOX_STATUS_EMPTY) == 0) { + + mbox = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + BCM2835_MBOX0_READ); + + chan = BCM2835_MBOX_CHAN(mbox); + data = BCM2835_MBOX_DATA(mbox); + ret = 1; + + if (BCM2835_MBOX_CHAN(sc->sc_mbox[chan]) != 0) { + printf("bcmmbox_intr: chan %d overflow\n", chan); + continue; + } + + sc->sc_mbox[chan] = data | BCM2835_MBOX_CHANMASK; + + if (cv) + wakeup(&sc->sc_chan[chan]); + } + + return ret; +} + +static int +bcmmbox_intr(void *cookie) +{ + struct bcm2835mbox_softc *sc = cookie; + int ret; + + //mtx_enter(&sc->sc_intr_lock); + + ret = bcmmbox_intr1(sc, 1); + + //mtx_leave(&sc->sc_intr_lock); + + return ret; +} + +void +bcmmbox_read(uint8_t chan, uint32_t *data) +{ + struct bcm2835mbox_softc *sc = bcm2835mbox_sc; + + KASSERT(sc != NULL); + + mtx_enter(&sc->sc_lock); + + //mtx_enter(&sc->sc_intr_lock); + while (BCM2835_MBOX_CHAN(sc->sc_mbox[chan]) == 0) { + if (cold) + bcmmbox_intr1(sc, 0); + else + tsleep(&sc->sc_chan[chan], PWAIT, "bcmmbox", 10*hz); + } + *data = BCM2835_MBOX_DATA(sc->sc_mbox[chan]); + sc->sc_mbox[chan] = 0; + //mtx_leave(&sc->sc_intr_lock); + + mtx_leave(&sc->sc_lock); +} + +void +bcmmbox_write(uint8_t chan, uint32_t data) +{ + struct bcm2835mbox_softc *sc = bcm2835mbox_sc; + + KASSERT(sc != NULL); + KASSERT(BCM2835_MBOX_CHAN(chan) == chan); + KASSERT(BCM2835_MBOX_CHAN(data) == 0); + + mtx_enter(&sc->sc_lock); + + bcm2835_mbox_write(sc->sc_iot, sc->sc_ioh, chan, data); + + mtx_leave(&sc->sc_lock); +} + +int +bcmmbox_request(uint8_t chan, void *buf, size_t buflen, uint32_t *pres) +{ + struct bcm2835mbox_softc *sc = bcm2835mbox_sc; + caddr_t dma_buf; + bus_dmamap_t map; + bus_dma_segment_t segs[1]; + int nsegs; + int error; + + KASSERT(sc != NULL); + + error = bus_dmamem_alloc(sc->sc_dmat, buflen, 16, 0, segs, 1, + &nsegs, BUS_DMA_WAITOK); + if (error) + return error; + error = bus_dmamem_map(sc->sc_dmat, segs, nsegs, buflen, &dma_buf, + BUS_DMA_WAITOK); + if (error) + goto map_failed; + error = bus_dmamap_create(sc->sc_dmat, buflen, 1, buflen, 0, + BUS_DMA_WAITOK, &map); + if (error) + goto create_failed; + error = bus_dmamap_load(sc->sc_dmat, map, dma_buf, buflen, NULL, + BUS_DMA_WAITOK); + if (error) + goto load_failed; + + memcpy(dma_buf, buf, buflen); + + bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, + BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + bcmmbox_write(chan, map->dm_segs[0].ds_addr); + bcmmbox_read(chan, pres); + bus_dmamap_sync(sc->sc_dmat, map, 0, buflen, + BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD); + + memcpy(buf, dma_buf, buflen); + + bus_dmamap_unload(sc->sc_dmat, map); +load_failed: + bus_dmamap_destroy(sc->sc_dmat, map); +create_failed: + bus_dmamem_unmap(sc->sc_dmat, dma_buf, buflen); +map_failed: + bus_dmamem_free(sc->sc_dmat, segs, nsegs); + + return error; +} diff --git a/sys/arch/armv7/broadcom/bcm2835_mbox.h b/sys/arch/armv7/broadcom/bcm2835_mbox.h new file mode 100644 index 00000000000..20867ca974b --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_mbox.h @@ -0,0 +1,60 @@ +/* $NetBSD: bcm2835_mbox.h,v 1.5 2014/10/07 08:30:05 skrll Exp $ */ + +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _BCM2835_MBOX_H_ +#define _BCM2835_MBOX_H_ + +#include + +#define BCM2835_MBOX_NUMCHANNELS 16 +#define BCM2835_MBOX_CHANMASK 0xf + +#define BCM2835_MBOX_CHAN(chan) ((chan) & BCM2835_MBOX_CHANMASK) +#define BCM2835_MBOX_DATA(data) ((data) & ~BCM2835_MBOX_CHANMASK) + +#define BCM2835_MBOX_MSG(chan, data) \ + (BCM2835_MBOX_CHAN(chan) | BCM2835_MBOX_DATA(data)) + +void bcm2835_mbox_read(bus_space_tag_t, bus_space_handle_t, uint8_t, + uint32_t *); +void bcm2835_mbox_write(bus_space_tag_t, bus_space_handle_t, uint8_t, + uint32_t); + +void bcmmbox_read(uint8_t, uint32_t *); +void bcmmbox_write(uint8_t, uint32_t); + +int bcmmbox_request(uint8_t, void *, size_t, uint32_t *); + +struct bcmmbox_attach_args { + bus_dma_tag_t baa_dmat; +}; + +#endif /* _BCM2835_MBOX_H_ */ diff --git a/sys/arch/armv7/broadcom/bcm2835_mbox_subr.c b/sys/arch/armv7/broadcom/bcm2835_mbox_subr.c new file mode 100644 index 00000000000..46f4688f86c --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_mbox_subr.c @@ -0,0 +1,99 @@ +/* $NetBSD: bcm2835_mbox_subr.c,v 1.4 2014/10/07 08:30:05 skrll Exp $ */ + +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 + +#include +#include +#include +#include + +#include + +#include +#include +//#include + +void +bcm2835_mbox_read(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t chan, + uint32_t *data) +{ + uint32_t mbox; + + KASSERT((chan & 0xf) == chan); + + for (;;) { + uint8_t rchan; + uint32_t rdata; + + bus_space_barrier(iot, ioh, 0, BCM2835_MBOX_SIZE, + BUS_SPACE_BARRIER_READ); + + if ((bus_space_read_4(iot, ioh, + BCM2835_MBOX0_STATUS) & BCM2835_MBOX_STATUS_EMPTY) != 0) + continue; + + mbox = bus_space_read_4(iot, ioh, BCM2835_MBOX0_READ); + + rchan = BCM2835_MBOX_CHAN(mbox); + rdata = BCM2835_MBOX_DATA(mbox); + + if (rchan == chan) { + *data = rdata; + return; + } + } +} + +void +bcm2835_mbox_write(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t chan, + uint32_t data) +{ + uint32_t rdata; + + KASSERT((chan & 0xf) == chan); + KASSERT((data & 0xf) == 0); + for (;;) { + + bus_space_barrier(iot, ioh, 0, BCM2835_MBOX_SIZE, + BUS_SPACE_BARRIER_READ); + + if ((rdata = bus_space_read_4(iot, ioh, + BCM2835_MBOX0_STATUS) & BCM2835_MBOX_STATUS_FULL) == 0) + break; + } + + bus_space_write_4(iot, ioh, BCM2835_MBOX1_WRITE, + BCM2835_MBOX_MSG(chan, data)); + + bus_space_barrier(iot, ioh, 0, BCM2835_MBOX_SIZE, + BUS_SPACE_BARRIER_WRITE); +} diff --git a/sys/arch/armv7/broadcom/bcm2835_mboxreg.h b/sys/arch/armv7/broadcom/bcm2835_mboxreg.h new file mode 100644 index 00000000000..7b683c7d828 --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_mboxreg.h @@ -0,0 +1,75 @@ +/* $NetBSD: bcm2835_mboxreg.h,v 1.1 2012/08/20 07:45:24 skrll Exp $ */ + +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _BCM2835_MBOXREG_H_ +#define _BCM2835_MBOXREG_H_ + +/* mailbox 0 (from VC) and mailbox 1 (to VC) */ +#define BCM2835_MBOX_SIZE 0x80 + +#define BCM2835_MBOX_READ 0x00 +#define BCM2835_MBOX_WRITE 0x00 +#define BCM2835_MBOX_POLL 0x10 /* read without popping the fifo */ +#define BCM2835_MBOX_ID 0x14 /* sender ID (bottom two bits) */ +#define BCM2835_MBOX_STATUS 0x18 /* status */ +#define BCM2835_MBOX_STATUS_FULL 0x80000000 +#define BCM2835_MBOX_STATUS_EMPTY 0x40000000 +#define BCM2835_MBOX_STATUS_LEVEL 0x400000FF +#define BCM2835_MBOX_CFG 0x1C /* configuration */ +#define BCM2835_MBOX_CFG_DATAIRQEN 0x00000001 +#define BCM2835_MBOX_CFG_SPACEIRQEN 0x00000002 +#define BCM2835_MBOX_CFG_EMPTYOPIRQEN 0x00000004 +#define BCM2835_MBOX_CFG_MAILCLEAR 0x00000008 +#define BCM2835_MBOX_CFG_DATAPENDING 0x00000010 +#define BCM2835_MBOX_CFG_SPACEPENDING 0x00000020 +#define BCM2835_MBOX_CFG_EMPTYOPPENDING 0x00000040 +#define BCM2835_MBOX_CFG_ENOOWN 0x00000100 +#define BCM2835_MBOX_CFG_EOVERFLOW 0x00000200 +#define BCM2835_MBOX_CFG_EUNDERFLOW 0x00000400 + +#define BCM2835_MBOX0_BASE 0x00 +#define BCM2835_MBOX1_BASE 0x20 + +#define BCM2835_MBOX0_READ (BCM2835_MBOX0_BASE + BCM2835_MBOX_READ) +#define BCM2835_MBOX0_WRITE (BCM2835_MBOX0_BASE + BCM2835_MBOX_WRITE) +#define BCM2835_MBOX0_POLL (BCM2835_MBOX0_BASE + BCM2835_MBOX_POLL) +#define BCM2835_MBOX0_ID (BCM2835_MBOX0_BASE + BCM2835_MBOX_ID) +#define BCM2835_MBOX0_STATUS (BCM2835_MBOX0_BASE + BCM2835_MBOX_STATUS) +#define BCM2835_MBOX0_CFG (BCM2835_MBOX0_BASE + BCM2835_MBOX_READ) + +#define BCM2835_MBOX1_READ (BCM2835_MBOX1_BASE + BCM2835_MBOX_READ) +#define BCM2835_MBOX1_WRITE (BCM2835_MBOX1_BASE + BCM2835_MBOX_WRITE) +#define BCM2835_MBOX1_POLL (BCM2835_MBOX1_BASE + BCM2835_MBOX_POLL) +#define BCM2835_MBOX1_ID (BCM2835_MBOX1_BASE + BCM2835_MBOX_ID) +#define BCM2835_MBOX1_STATUS (BCM2835_MBOX1_BASE + BCM2835_MBOX_STATUS) +#define BCM2835_MBOX1_CFG (BCM2835_MBOX1_BASE + BCM2835_MBOX_READ) + +#endif /* _BCM2835_MBOXREG_H_ */ diff --git a/sys/arch/armv7/broadcom/bcm2835_pm.c b/sys/arch/armv7/broadcom/bcm2835_pm.c new file mode 100644 index 00000000000..f49396338b9 --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_pm.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* registers */ +#define PM_RSTC 0x1c +#define PM_RSTS 0x20 +#define PM_WDOG 0x24 + +/* bits and bytes */ +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC_CONFIGMASK 0x00000030 +#define PM_RSTC_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 +#define PM_WDOG_TIMEMASK 0x000fffff + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) +#define HSET4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) +#define HCLR4(sc, reg, bits) \ + HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) + +struct bcmpm_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +struct bcmpm_softc *bcmpm_sc; + +int bcmpm_match(struct device *, void *, void *); +void bcmpm_attach(struct device *, struct device *, void *); +int bcmpm_activate(struct device *, int); +int bcmpm_wdog_cb(void *, int); +void bcmpm_wdog_reset(void); + +struct cfattach bcmpm_ca = { + sizeof (struct bcmpm_softc), bcmpm_match, bcmpm_attach, NULL, + bcmpm_activate +}; + +struct cfdriver bcmpm_cd = { + NULL, "bcmpm", DV_DULL +}; + +int +bcmpm_match(struct device *parent, void *cfdata, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-pm", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-pm", aa->aa_node)) + return (1); + + return 0; +} + +void +bcmpm_attach(struct device *parent, struct device *self, void *args) +{ + struct bcmpm_softc *sc = (struct bcmpm_softc *)self; + struct armv7_attach_args *aa = args; + struct fdt_memory mem; + + sc->sc_iot = aa->aa_iot; + if (fdt_get_memory_address(aa->aa_node, 0, &mem)) + panic("%s: could not extract memory data from FDT", + __func__); + + if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + printf("\n"); + + bcmpm_sc = sc; + + extern void (*fdt_platform_watchdog_reset_fn)(void); + fdt_platform_watchdog_reset_fn = bcmpm_wdog_reset; + + wdog_register(bcmpm_wdog_cb, sc); +} + +int +bcmpm_activate(struct device *self, int act) +{ + switch (act) { + case DVACT_POWERDOWN: + wdog_shutdown(self); + break; + } + + return 0; +} + +void +bcmpm_wdog_set(struct bcmpm_softc *sc, uint32_t period) +{ + uint32_t rstc, wdog; + + if (period == 0) { + HWRITE4(sc, PM_RSTC, PM_RSTC_RESET | PM_PASSWORD); + return; + } + + rstc = HREAD4(sc, PM_RSTC) & PM_RSTC_CONFIGMASK; + rstc |= PM_RSTC_FULL_RESET; + rstc |= PM_PASSWORD; + + wdog = period & PM_WDOG_TIMEMASK; + wdog |= PM_PASSWORD; + + HWRITE4(sc, PM_RSTC, wdog); + HWRITE4(sc, PM_RSTC, rstc); +} + +int +bcmpm_wdog_cb(void *self, int period) +{ + struct bcmpm_softc *sc = self; + + bcmpm_wdog_set(sc, period << 16); + + return period; +} + +void +bcmpm_wdog_reset(void) +{ + struct bcmpm_softc *sc = bcmpm_sc; + bcmpm_wdog_set(sc, 10); + delay(100000); +} diff --git a/sys/arch/armv7/broadcom/bcm2835_sdhc.c b/sys/arch/armv7/broadcom/bcm2835_sdhc.c new file mode 100644 index 00000000000..11fafa99ccb --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2835_sdhc.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct bcm_sdhc_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + void *sc_ih; +}; + +int bcm_sdhc_match(struct device *, void *, void *); +void bcm_sdhc_attach(struct device *, struct device *, void *); + +struct cfattach bcmsdhc_ca = { + sizeof (struct bcm_sdhc_softc), bcm_sdhc_match, bcm_sdhc_attach +}; + +struct cfdriver bcmsdhc_cd = { + NULL, "bcmsdhc", DV_DULL +}; + +int +bcm_sdhc_match(struct device *parent, void *cfdata, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-sdhci", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-sdhci", aa->aa_node)) + return (1); + + return 0; +} + +void +bcm_sdhc_attach(struct device *parent, struct device *self, void *args) +{ + struct bcm_sdhc_softc *sc = (struct bcm_sdhc_softc *)self; + struct armv7_attach_args *aa = args; + struct sdhc_softc *ssc; + struct fdt_memory mem; + + sc->sc_iot = aa->aa_iot; + if (fdt_get_memory_address(aa->aa_node, 0, &mem)) + panic("%s: could not extract memory data from FDT", + __func__); + + if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + printf("\n"); + + if ((ssc = (struct sdhc_softc *)config_found(self, NULL, NULL)) == NULL) + goto mem; + + ssc->sc_flags = 0; + ssc->sc_flags |= SDHC_F_32BIT_ACCESS; + ssc->sc_flags |= SDHC_F_HOSTCAPS; + ssc->sc_caps = SDHC_VOLTAGE_SUPP_3_3V | SDHC_HIGH_SPEED_SUPP | + (SDHC_MAX_BLK_LEN_1024 << SDHC_MAX_BLK_LEN_SHIFT); + ssc->sc_clkbase = 50000; /* Default to 50MHz */ + + /* TODO: Fetch frequency from FDT. */ + + /* Allocate an array big enough to hold all the possible hosts */ + ssc->sc_host = mallocarray(1, sizeof(struct sdhc_host *), + M_DEVBUF, M_WAITOK); + + sc->sc_ih = arm_intr_establish_fdt(aa->aa_node, IPL_SDMMC, sdhc_intr, + ssc, ssc->sc_dev.dv_xname); + if (sc->sc_ih == NULL) { + printf("%s: unable to establish interrupt\n", + ssc->sc_dev.dv_xname); + goto mem; + } + + if (sdhc_host_found(ssc, sc->sc_iot, sc->sc_ioh, mem.size) != 0) { + /* XXX: sc->sc_host leak */ + printf("%s: can't initialize host\n", ssc->sc_dev.dv_xname); + goto intr; + } + + return; + +intr: + arm_intr_disestablish(sc->sc_ih); + sc->sc_ih = NULL; +mem: + bus_space_unmap(sc->sc_iot, sc->sc_ioh, mem.size); +} + +int sdhc_bcm_match(struct device *, void *, void *); +void sdhc_bcm_attach(struct device *, struct device *, void *); + +struct cfattach sdhc_bcm_ca = { + sizeof (struct sdhc_softc), sdhc_bcm_match, sdhc_bcm_attach +}; + +int +sdhc_bcm_match(struct device *parent, void *v, void *aux) +{ + return 1; +} + +void +sdhc_bcm_attach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); +} diff --git a/sys/arch/armv7/broadcom/bcm2836_intr.c b/sys/arch/armv7/broadcom/bcm2836_intr.c new file mode 100644 index 00000000000..b943c9cec82 --- /dev/null +++ b/sys/arch/armv7/broadcom/bcm2836_intr.c @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2007,2009 Dale Rahn + * Copyright (c) 2015 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* registers */ +#define INTC_PENDING_BANK0 0x00 +#define INTC_PENDING_BANK1 0x04 +#define INTC_PENDING_BANK2 0x08 +#define INTC_FIQ_CONTROL 0x0C +#define INTC_ENABLE_BANK1 0x10 +#define INTC_ENABLE_BANK2 0x14 +#define INTC_ENABLE_BANK0 0x18 +#define INTC_DISABLE_BANK1 0x1C +#define INTC_DISABLE_BANK2 0x20 +#define INTC_DISABLE_BANK0 0x24 + +/* arm local */ +#define ARM_LOCAL_CONTROL 0x00 +#define ARM_LOCAL_PRESCALER 0x08 +#define PRESCALER_19_2 0x80000000 /* 19.2 MHz */ +#define ARM_LOCAL_INT_TIMER(n) (0x40 + (n) * 4) +#define ARM_LOCAL_INT_MAILBOX(n) (0x50 + (n) * 4) +#define ARM_LOCAL_INT_PENDING(n) (0x60 + (n) * 4) +#define ARM_LOCAL_INT_PENDING_MASK 0x0f + +#define BANK0_START 64 +#define BANK0_END (BANK0_START + 32 - 1) +#define BANK1_START 0 +#define BANK1_END (BANK1_START + 32 - 1) +#define BANK2_START 32 +#define BANK2_END (BANK2_START + 32 - 1) +#define LOCAL_START 96 +#define LOCAL_END (LOCAL_START + 32 - 1) + +#define IS_IRQ_BANK0(n) (((n) >= BANK0_START) && ((n) <= BANK0_END)) +#define IS_IRQ_BANK1(n) (((n) >= BANK1_START) && ((n) <= BANK1_END)) +#define IS_IRQ_BANK2(n) (((n) >= BANK2_START) && ((n) <= BANK2_END)) +#define IS_IRQ_LOCAL(n) (((n) >= LOCAL_START) && ((n) <= LOCAL_END)) +#define IRQ_BANK0(n) ((n) - BANK0_START) +#define IRQ_BANK1(n) ((n) - BANK1_START) +#define IRQ_BANK2(n) ((n) - BANK2_START) +#define IRQ_LOCAL(n) ((n) - LOCAL_START) + +#define INTC_NIRQ 128 +#define INTC_NBANK 4 + +#define INTC_IRQ_TO_REG(i) (((i) >> 5) & 0x3) +#define INTC_IRQ_TO_REGi(i) ((i) & 0x1f) + +struct bcm_intc_softc { + struct device sc_dev; + struct intrsource sc_bcm_intc_handler[INTC_NIRQ]; + uint32_t sc_bcm_intc_imask[INTC_NBANK][NIPL]; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_space_handle_t sc_lioh; + int sc_ncells; +}; +struct bcm_intc_softc *bcm_intc; + +int bcm_intc_match(struct device *, void *, void *); +void bcm_intc_attach(struct device *, struct device *, void *); +void bcm_intc_splx(int new); +int bcm_intc_spllower(int new); +int bcm_intc_splraise(int new); +void bcm_intc_setipl(int new); +void bcm_intc_calc_mask(void); +void *bcm_intc_intr_establish(int, int, int (*)(void *), + void *, char *); +void *bcm_intc_intr_establish_fdt_idx(void *, int, int, int (*)(void *), + void *, char *); +void bcm_intc_intr_disestablish(void *); +const char *bcm_intc_intr_string(void *); +void bcm_intc_irq_handler(void *); + +struct cfattach bcmintc_ca = { + sizeof (struct bcm_intc_softc), bcm_intc_match, bcm_intc_attach +}; + +struct cfdriver bcmintc_cd = { + NULL, "bcmintc", DV_DULL +}; + +int +bcm_intc_match(struct device *parent, void *cfdata, void *aux) +{ + struct armv7_attach_args *aa = aux; + + if (fdt_node_compatible("brcm,bcm2835-armctrl-ic", aa->aa_node) || + fdt_node_compatible("broadcom,bcm2835-armctrl-ic", aa->aa_node)) + return (1); + + return 0; +} + +void +bcm_intc_attach(struct device *parent, struct device *self, void *args) +{ + struct bcm_intc_softc *sc = (struct bcm_intc_softc *)self; + struct armv7_attach_args *aa = args; + struct fdt_memory mem; + int i; + + bcm_intc = sc; + + sc->sc_iot = aa->aa_iot; + if (fdt_get_memory_address(aa->aa_node, 0, &mem)) + panic("%s: could not extract memory data from FDT", + __func__); + + if (fdt_node_property_int(aa->aa_node, "#interrupt-cells", + &sc->sc_ncells) != 1) + panic("%s: no #interrupt-cells property", sc->sc_dev.dv_xname); + + if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh)) + panic("%s: bus_space_map failed!", __func__); + + /* + * ARM Local area, because fuck you. + * + * The original rPi with the BCM2835 does implement the same IC + * but with a different IRQ basis. On the BCM2836 there's an + * additional area to enable Timer/Mailbox interrupts, which + * is not yet exposed in the given DT. + */ + if (bus_space_map(sc->sc_iot, 0x40000000, 0x1000, 0, &sc->sc_lioh)) + panic("%s: bus_space_map failed!", __func__); + + printf("\n"); + + /* mask all interrupts */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK0, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK1, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK2, + 0xffffffff); + + /* ARM local specific */ + bus_space_write_4(sc->sc_iot, sc->sc_lioh, ARM_LOCAL_CONTROL, 0); + bus_space_write_4(sc->sc_iot, sc->sc_lioh, ARM_LOCAL_PRESCALER, + PRESCALER_19_2); + for (int i = 0; i < 4; i++) + bus_space_write_4(sc->sc_iot, sc->sc_lioh, + ARM_LOCAL_INT_TIMER(i), 0); + for (int i = 0; i < 4; i++) + bus_space_write_4(sc->sc_iot, sc->sc_lioh, + ARM_LOCAL_INT_MAILBOX(i), 1); + + for (i = 0; i < INTC_NIRQ; i++) { + TAILQ_INIT(&sc->sc_bcm_intc_handler[i].is_list); + } + + bcm_intc_calc_mask(); + + /* insert self as interrupt handler */ + arm_set_intr_handler(bcm_intc_splraise, bcm_intc_spllower, bcm_intc_splx, + bcm_intc_setipl, + bcm_intc_intr_establish, bcm_intc_intr_disestablish, bcm_intc_intr_string, + bcm_intc_irq_handler); + + arm_set_intr_handler_fdt(aa->aa_node, bcm_intc_intr_establish_fdt_idx); + + bcm_intc_setipl(IPL_HIGH); /* XXX ??? */ + intr_enable(); +} + +void +bcm_intc_intr_enable(int irq, int ipl) +{ + struct bcm_intc_softc *sc = bcm_intc; + + if (IS_IRQ_BANK0(irq)) + sc->sc_bcm_intc_imask[0][ipl] |= (1 << IRQ_BANK0(irq)); + else if (IS_IRQ_BANK1(irq)) + sc->sc_bcm_intc_imask[1][ipl] |= (1 << IRQ_BANK1(irq)); + else if (IS_IRQ_BANK2(irq)) + sc->sc_bcm_intc_imask[2][ipl] |= (1 << IRQ_BANK2(irq)); + else if (IS_IRQ_LOCAL(irq)) + sc->sc_bcm_intc_imask[3][ipl] |= (1 << IRQ_LOCAL(irq)); + else + printf("%s: invalid irq number: %d\n", __func__, irq); +} + +void +bcm_intc_intr_disable(int irq, int ipl) +{ + struct bcm_intc_softc *sc = bcm_intc; + + if (IS_IRQ_BANK0(irq)) + sc->sc_bcm_intc_imask[0][ipl] &= ~(1 << IRQ_BANK0(irq)); + else if (IS_IRQ_BANK1(irq)) + sc->sc_bcm_intc_imask[1][ipl] &= ~(1 << IRQ_BANK1(irq)); + else if (IS_IRQ_BANK2(irq)) + sc->sc_bcm_intc_imask[2][ipl] &= ~(1 << IRQ_BANK2(irq)); + else if (IS_IRQ_LOCAL(irq)) + sc->sc_bcm_intc_imask[3][ipl] &= ~(1 << IRQ_LOCAL(irq)); + else + printf("%s: invalid irq number: %d\n", __func__, irq); +} + +void +bcm_intc_calc_mask(void) +{ + struct cpu_info *ci = curcpu(); + struct bcm_intc_softc *sc = bcm_intc; + int irq; + struct intrhand *ih; + int i; + + for (irq = 0; irq < INTC_NIRQ; irq++) { + int max = IPL_NONE; + int min = IPL_HIGH; + TAILQ_FOREACH(ih, &sc->sc_bcm_intc_handler[irq].is_list, + ih_list) { + if (ih->ih_ipl > max) + max = ih->ih_ipl; + + if (ih->ih_ipl < min) + min = ih->ih_ipl; + } + + sc->sc_bcm_intc_handler[irq].is_irq = max; + + if (max == IPL_NONE) + min = IPL_NONE; + +#ifdef DEBUG_INTC + if (min != IPL_NONE) { + printf("irq %d to block at %d %d reg %d bit %d\n", + irq, max, min, INTC_IRQ_TO_REG(irq), + INTC_IRQ_TO_REGi(irq)); + } +#endif + /* Enable interrupts at lower levels, clear -> enable */ + for (i = 0; i < min; i++) + bcm_intc_intr_enable(irq, i); + for (; i <= IPL_HIGH; i++) + bcm_intc_intr_disable(irq, i); + } + arm_init_smask(); + bcm_intc_setipl(ci->ci_cpl); +} + +void +bcm_intc_splx(int new) +{ + struct cpu_info *ci = curcpu(); + bcm_intc_setipl(new); + + if (ci->ci_ipending & arm_smask[ci->ci_cpl]) + arm_do_pending_intr(ci->ci_cpl); +} + +int +bcm_intc_spllower(int new) +{ + struct cpu_info *ci = curcpu(); + int old = ci->ci_cpl; + bcm_intc_splx(new); + return (old); +} + +int +bcm_intc_splraise(int new) +{ + struct cpu_info *ci = curcpu(); + int old; + old = ci->ci_cpl; + + /* + * setipl must always be called because there is a race window + * where the variable is updated before the mask is set + * an interrupt occurs in that window without the mask always + * being set, the hardware might not get updated on the next + * splraise completely messing up spl protection. + */ + if (old > new) + new = old; + + bcm_intc_setipl(new); + + return (old); +} + +void +bcm_intc_setipl(int new) +{ + struct cpu_info *ci = curcpu(); + struct bcm_intc_softc *sc = bcm_intc; + int psw; + + psw = intr_disable(); + ci->ci_cpl = new; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK0, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK1, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_DISABLE_BANK2, + 0xffffffff); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_ENABLE_BANK0, + sc->sc_bcm_intc_imask[0][new]); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_ENABLE_BANK1, + sc->sc_bcm_intc_imask[1][new]); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, INTC_ENABLE_BANK2, + sc->sc_bcm_intc_imask[2][new]); + /* XXX: SMP */ + for (int i = 0; i < 4; i++) + bus_space_write_4(sc->sc_iot, sc->sc_lioh, + ARM_LOCAL_INT_TIMER(i), sc->sc_bcm_intc_imask[3][new]); + intr_restore(psw); +} + +int +bcm_intc_get_next_irq(int last_irq) +{ + struct bcm_intc_softc *sc = bcm_intc; + uint32_t pending; + int32_t irq = last_irq + 1; + + /* Sanity check */ + if (irq < 0) + irq = 0; + + /* We need to keep this order. */ + /* TODO: should we mask last_irq? */ + if (IS_IRQ_BANK1(irq)) { + pending = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + INTC_PENDING_BANK1); + if (pending == 0) { + irq = BANK2_START; /* skip to next bank */ + } else do { + if (pending & (1 << IRQ_BANK1(irq))) + return irq; + irq++; + } while (IS_IRQ_BANK1(irq)); + } + if (IS_IRQ_BANK2(irq)) { + pending = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + INTC_PENDING_BANK2); + if (pending == 0) { + irq = BANK0_START; /* skip to next bank */ + } else do { + if (pending & (1 << IRQ_BANK2(irq))) + return irq; + irq++; + } while (IS_IRQ_BANK2(irq)); + } + if (IS_IRQ_BANK0(irq)) { + pending = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + INTC_PENDING_BANK0); + if (pending == 0) { + irq = LOCAL_START; /* skip to next bank */ + } else do { + if (pending & (1 << IRQ_BANK0(irq))) + return irq; + irq++; + } while (IS_IRQ_BANK0(irq)); + } + if (IS_IRQ_LOCAL(irq)) { + /* XXX: SMP */ + pending = bus_space_read_4(sc->sc_iot, sc->sc_lioh, + ARM_LOCAL_INT_PENDING(0)); + pending &= ARM_LOCAL_INT_PENDING_MASK; + if (pending != 0) do { + if (pending & (1 << IRQ_LOCAL(irq))) + return irq; + irq++; + } while (IS_IRQ_LOCAL(irq)); + } + return (-1); +} + +static void +bcm_intc_call_handler(int irq, void *frame) +{ + struct bcm_intc_softc *sc = bcm_intc; + struct intrhand *ih; + int pri, s; + void *arg; + +//#define DEBUG_INTC +#ifdef DEBUG_INTC + if (irq != 99) + printf("irq %d fired\n", irq); + else { + static int cnt = 0; + if ((cnt++ % 100) == 0) { + printf("irq %d fired * _100\n", irq); + Debugger(); + } + } +#endif + + pri = sc->sc_bcm_intc_handler[irq].is_irq; + s = bcm_intc_splraise(pri); + TAILQ_FOREACH(ih, &sc->sc_bcm_intc_handler[irq].is_list, ih_list) { + if (ih->ih_arg != 0) + arg = ih->ih_arg; + else + arg = frame; + + if (ih->ih_fun(arg)) + ih->ih_count.ec_count++; + + } + + bcm_intc_splx(s); +} + +void +bcm_intc_irq_handler(void *frame) +{ + int irq = -1; + + while ((irq = bcm_intc_get_next_irq(irq)) != -1) + bcm_intc_call_handler(irq, frame); +} + +void * +bcm_intc_intr_establish_fdt_idx(void *node, int idx, int level, + int (*func)(void *), void *arg, char *name) +{ + struct bcm_intc_softc *sc = bcm_intc; + int nints = sc->sc_ncells * (idx + 1); + int ints[nints]; + int irq; + + if (fdt_node_property_ints(node, "interrupts", ints, nints) != nints) + panic("%s: no interrupts property", sc->sc_dev.dv_xname); + + irq = ints[idx * 2 + 1]; + if (ints[idx * 2] == 0) + irq += BANK0_START; + else if (ints[idx * 2] == 1) + irq += BANK1_START; + else if (ints[idx * 2] == 2) + irq += BANK2_START; + else if (ints[idx * 2] == 3) + irq += LOCAL_START; + else + panic("%s: bogus interrupt type", sc->sc_dev.dv_xname); + + return bcm_intc_intr_establish(irq, level, func, arg, name); +} + +void * +bcm_intc_intr_establish(int irqno, int level, int (*func)(void *), + void *arg, char *name) +{ + struct bcm_intc_softc *sc = bcm_intc; + struct intrhand *ih; + int psw; + + if (irqno < 0 || irqno >= INTC_NIRQ) + panic("bcm_intc_intr_establish: bogus irqnumber %d: %s", + irqno, name); + psw = intr_disable(); + + /* no point in sleeping unless someone can free memory. */ + ih = (struct intrhand *)malloc (sizeof *ih, M_DEVBUF, + cold ? M_NOWAIT : M_WAITOK); + if (ih == NULL) + panic("intr_establish: can't malloc handler info"); + ih->ih_fun = func; + ih->ih_arg = arg; + ih->ih_ipl = level; + ih->ih_irq = irqno; + ih->ih_name = name; + + TAILQ_INSERT_TAIL(&sc->sc_bcm_intc_handler[irqno].is_list, ih, ih_list); + + if (name != NULL) + evcount_attach(&ih->ih_count, name, &ih->ih_irq); + +#ifdef DEBUG_INTC + printf("%s irq %d level %d [%s]\n", __func__, irqno, level, + name); +#endif + bcm_intc_calc_mask(); + + intr_restore(psw); + return (ih); +} + +void +bcm_intc_intr_disestablish(void *cookie) +{ + struct bcm_intc_softc *sc = bcm_intc; + struct intrhand *ih = cookie; + int irqno = ih->ih_irq; + int psw; + psw = intr_disable(); + TAILQ_REMOVE(&sc->sc_bcm_intc_handler[irqno].is_list, ih, ih_list); + if (ih->ih_name != NULL) + evcount_detach(&ih->ih_count); + free(ih, M_DEVBUF, 0); + intr_restore(psw); +} + +const char * +bcm_intc_intr_string(void *cookie) +{ + return "huh?"; +} diff --git a/sys/arch/armv7/broadcom/files.broadcom b/sys/arch/armv7/broadcom/files.broadcom new file mode 100644 index 00000000000..97ee7d83cc5 --- /dev/null +++ b/sys/arch/armv7/broadcom/files.broadcom @@ -0,0 +1,27 @@ +# Broadcom + +device bcmintc +attach bcmintc at fdt +file arch/armv7/broadcom/bcm2836_intr.c bcmintc + +device bcmpm +attach bcmpm at fdt +file arch/armv7/broadcom/bcm2835_pm.c bcmpm + +device bcmmbox +attach bcmmbox at fdt +file arch/armv7/broadcom/bcm2835_mbox.c bcmmbox +file arch/armv7/broadcom/bcm2835_mbox_subr.c bcmmbox + +device bcmgpio {}: gpiobus +attach bcmgpio at fdt +file arch/armv7/broadcom/bcm2835_gpio.c bcmgpio + +device bcmsdhc {} +attach bcmsdhc at fdt +attach sdhc at bcmsdhc with sdhc_bcm +file arch/armv7/broadcom/bcm2835_sdhc.c bcmsdhc + +#include "dev/usb/dwc2/files.dwc2" +#attach dwctwo at fdt with bcmdwctwo +#file arch/armv7/broadcom/bcm2835_dwctwo.c bcmdwctwo needs-flag diff --git a/sys/arch/armv7/conf/Makefile.armv7 b/sys/arch/armv7/conf/Makefile.armv7 index 7ec36c8421b..5145e46e6b2 100644 --- a/sys/arch/armv7/conf/Makefile.armv7 +++ b/sys/arch/armv7/conf/Makefile.armv7 @@ -183,5 +183,7 @@ bsd.OMAP.umg: bsd mkuboot -a arm -o linux -e 0x80300000 -l 0x80300000 bsd bsd.OMAP.umg bsd.SUNXI.umg: bsd mkuboot -a arm -o linux -e 0x40300000 -l 0x40300000 bsd bsd.SUNXI.umg +bsd.RAW.umg: bsd + mkuboot -r bsd bsd.RAW.umg %RULES diff --git a/sys/arch/armv7/conf/files.armv7 b/sys/arch/armv7/conf/files.armv7 index 7a996745545..baa8d4a59dc 100644 --- a/sys/arch/armv7/conf/files.armv7 +++ b/sys/arch/armv7/conf/files.armv7 @@ -58,6 +58,7 @@ include "dev/onewire/files.onewire" # SoC includes include "arch/armv7/fdt/files.fdt" +include "arch/armv7/broadcom/files.broadcom" include "arch/armv7/exynos/files.exynos" include "arch/armv7/imx/files.imx" include "arch/armv7/omap/files.omap" diff --git a/sys/arch/armv7/conf/generic b/sys/arch/armv7/conf/generic index c6bab9f054c..111f2215b81 100644 --- a/sys/arch/armv7/conf/generic +++ b/sys/arch/armv7/conf/generic @@ -59,6 +59,7 @@ ampscu* at cortex? # SoCs include "../../../arch/armv7/conf/generic.fdt" +include "../../../arch/armv7/conf/generic.broadcom" include "../../../arch/armv7/conf/generic.exynos" include "../../../arch/armv7/conf/generic.imx" include "../../../arch/armv7/conf/generic.omap" diff --git a/sys/arch/armv7/conf/generic.broadcom b/sys/arch/armv7/conf/generic.broadcom new file mode 100644 index 00000000000..2ff4c3832de --- /dev/null +++ b/sys/arch/armv7/conf/generic.broadcom @@ -0,0 +1,11 @@ +# Broadcom SoC +bcmintc* at fdt? +bcmpm* at fdt? +bcmmbox* at fdt? +bcmgpio* at fdt? +gpio* at bcmgpio? +bcmsdhc* at fdt? +sdhc* at bcmsdhc? +sdmmc* at sdhc? +#dwctwo0 at fdt? +#usb* at dwctwo? diff --git a/sys/arch/armv7/fdt/fdt_machdep.c b/sys/arch/armv7/fdt/fdt_machdep.c index d802a37f971..b82dc800679 100644 --- a/sys/arch/armv7/fdt/fdt_machdep.c +++ b/sys/arch/armv7/fdt/fdt_machdep.c @@ -83,9 +83,12 @@ fdt_platform_init_cons(void) comdefaultrate = comcnspeed; } +void (*fdt_platform_watchdog_reset_fn)(void); static void fdt_platform_watchdog_reset(void) { + if (fdt_platform_watchdog_reset_fn != NULL) + fdt_platform_watchdog_reset_fn(); } static void diff --git a/sys/arch/armv7/stand/Makefile b/sys/arch/armv7/stand/Makefile new file mode 100644 index 00000000000..f33c303b8d6 --- /dev/null +++ b/sys/arch/armv7/stand/Makefile @@ -0,0 +1,3 @@ +SUBDIR+=rpiboot + +.include diff --git a/sys/arch/armv7/stand/rpiboot/Makefile b/sys/arch/armv7/stand/rpiboot/Makefile new file mode 100644 index 00000000000..7a406ffa2fb --- /dev/null +++ b/sys/arch/armv7/stand/rpiboot/Makefile @@ -0,0 +1,13 @@ +.if ${MACHINE} == "armv7" +PROG= rpiboot +SRCS= rpi.S + +${PROG}: ${OBJS} + ${OBJCOPY} ${OBJS} -O binary ${PROG} +.else +NOPROG= +.endif + +NOMAN= + +.include diff --git a/sys/arch/armv7/stand/rpiboot/rpi.S b/sys/arch/armv7/stand/rpiboot/rpi.S new file mode 100644 index 00000000000..f5f72907c79 --- /dev/null +++ b/sys/arch/armv7/stand/rpiboot/rpi.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Patrick Wildt + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + + .text + + .global _C_LABEL(rpi_entry) +_C_LABEL(rpi_entry): + b jump + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 +jump: + ldr pc, [pc] + mov r0, r0 + .word 0x00300000