From owner-freebsd-arm@FreeBSD.ORG Tue Oct 7 20:45:34 2014 Return-Path: Delivered-To: freebsd-arm@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C2DDDD7A for ; Tue, 7 Oct 2014 20:45:34 +0000 (UTC) Received: from smtprelay-b22.telenor.se (smtprelay-b22.telenor.se [195.54.99.213]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 82338D09 for ; Tue, 7 Oct 2014 20:45:32 +0000 (UTC) Received: from ipb5.telenor.se (ipb5.telenor.se [195.54.127.168]) by smtprelay-b22.telenor.se (Postfix) with ESMTP id 6EF7916807 for ; Tue, 7 Oct 2014 22:19:06 +0200 (CEST) X-SENDER-IP: [85.229.94.62] X-LISTENER: [smtp.bredband.net] X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnoGAM1JNFRV5V4+/2dsb2JhbABJFoMOU1gExDaILhkMh0uBEhcBAXqEBwMBAhcBDC4BaTwHBQweGQmIIQMVAQidcp0eDYcsjhKBRQMSCiwdhFcFix6EPoIaXYEvgU1lhAoyQYM+ESuDCIMshCwaglOEeIFag2U7LwEBgQSBRAEBAQ X-IPAS-Result: AnoGAM1JNFRV5V4+/2dsb2JhbABJFoMOU1gExDaILhkMh0uBEhcBAXqEBwMBAhcBDC4BaTwHBQweGQmIIQMVAQidcp0eDYcsjhKBRQMSCiwdhFcFix6EPoIaXYEvgU1lhAoyQYM+ESuDCIMshCwaglOEeIFag2U7LwEBgQSBRAEBAQ X-IronPort-AV: E=Sophos;i="5.04,672,1406584800"; d="scan'208";a="788520837" Received: from c-3e5ee555.06-11-73746f31.cust.bredbandsbolaget.se (HELO sigyn.alvermark.net) ([85.229.94.62]) by ipb5.telenor.se with ESMTP; 07 Oct 2014 22:19:04 +0200 Received: from localhost ([127.0.0.1] helo=webmail.alvermark.net) by sigyn.alvermark.net with esmtp (Exim 4.80.1 (FreeBSD)) (envelope-from ) id 1XbbDg-000BMa-Bm for freebsd-arm@freebsd.org; Tue, 07 Oct 2014 22:18:52 +0200 Received: from 85.229.95.175 (SquirrelMail authenticated user alvis) by webmail.alvermark.net with HTTP; Tue, 7 Oct 2014 22:18:52 +0200 (CEST) Message-ID: <18234.85.229.95.175.1412713132.squirrel@webmail.alvermark.net> Date: Tue, 7 Oct 2014 22:18:52 +0200 (CEST) Subject: Allwinner A13 support (patches attached) From: "Jakob Alvermark" To: freebsd-arm@freebsd.org User-Agent: SquirrelMail/1.5.1 MIME-Version: 1.0 Content-Type: multipart/mixed;boundary="----=_20141007221852_56350" References: In-Reply-To: X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "Porting FreeBSD to ARM processors." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Oct 2014 20:45:34 -0000 ------=_20141007221852_56350 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit Hello people! I have been sitting on this for too long now. (Thanks Arun Thomas for encouraging me to send this!) I have this Allwinner A13 board from Olimex, https://www.olimex.com/Products/OLinuXino/A13/A13-OLinuXino/open-source-hardware I have made it boot FreeBSD-current, and here are the patches. Hoping anyone (committers?) might be interrested in looking at this. It boots from the SD card, using this U-boot: https://github.com/linux-sunxi/u-boot-sunxi Adding CONFIG_CMD_ELF and CONFIG_API to allow ubldr to work. It can boot to multi user, with root on a USB stick. Wanting to get rid of the USB stick I added Alexander Fedorov's MMC-driver, http://lists.freebsd.org/pipermail/freebsd-arm/2013-June/005913.html but it fails: a10_mmc0: mem 0x1c0f000-0x1c0ffff irq 32 on simplebus0 MMC0 MODE_CLK: 0x04dd1e00 mmc0: on a10_mmc0 vm_fault(0xc066ff50, 3197000, 1, 0) -> 1 Fatal kernel mode data abort: 'Translation Fault (S)' trapframe: 0xc07cecd8 FSR=00000005, FAR=03197500, spsr=800001d3 r0 =c26bd400, r1 =03197500, r2 =00000400, r3 =c26bd409 r4 =00000000, r5 =00000008, r6 =c2674680, r7 =c2674b80 r8 =00000400, r9 =c26e2020, r10=c26bd800, r11=c07ced30 r12=c26bd408, ssp=c07ced28, slr=c0261810, pc =c0419ae0 [ thread pid 0 tid 100000 ] Stopped at strlcat+0x54: ldrb r4, [r1] I am not an experienced kernel hacker, so I don't know how to debug this. I also wanted to blink the onboard LED, so this is in the dts file: --- leds { compatible = "gpio-leds"; led1 { label = "led1"; gpios = <&gpio 201 1>; }; }; --- I do not get a /dev/led/led1 as I expected, manually toggling the LED with 'gpioctl -t 201' works fine... Thanks, Jakob ------=_20141007221852_56350 Content-Type: text/x-patch; name="a13.patch" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="a13.patch" Index: sys/arm/allwinner/a10_clk.c =================================================================== --- sys/arm/allwinner/a10_clk.c (revision 272713) +++ sys/arm/allwinner/a10_clk.c (working copy) @@ -148,6 +148,39 @@ } int +a10_clk_mmc_activate(void) +{ + struct a10_ccm_softc *sc = a10_ccm_sc; + uint32_t reg_value; + unsigned int pll5_clk; + unsigned int divider; + unsigned int n, k, p; + + if (sc == NULL) + return ENXIO; + + /* Gating AHB clock for SDMMC0 */ + reg_value = ccm_read_4(sc, CCM_AHB_GATING0); + reg_value |= CCM_AHB_GATING_SDMMC0; + ccm_write_4(sc, CCM_AHB_GATING0, reg_value); + + /* config mod clock */ + reg_value = ccm_read_4(sc, CCM_PLL5_CFG); + n = (reg_value >> 8) & 0x1f; + k = ((reg_value >> 4) & 3) + 1; + p = 1 << ((reg_value >> 16) & 3); + pll5_clk = 24000000 * n * k / p; + if (pll5_clk > 400000000) + divider = 4; + else + divider = 3; + ccm_write_4(sc, CCM_MMC0_SCLK_CFG, (1U << 31) | (2U << 24) | divider); + printf("MMC0 MODE_CLK: 0x%08x\n", pll5_clk / (divider + 1)); + + return 0; +} + +int a10_clk_usb_deactivate(void) { struct a10_ccm_softc *sc = a10_ccm_sc; Index: sys/arm/allwinner/a10_clk.h =================================================================== --- sys/arm/allwinner/a10_clk.h (revision 272713) +++ sys/arm/allwinner/a10_clk.h (working copy) @@ -103,6 +103,7 @@ #define CCM_AHB_GATING_USB0 (1 << 0) #define CCM_AHB_GATING_EHCI0 (1 << 1) #define CCM_AHB_GATING_EHCI1 (1 << 3) +#define CCM_AHB_GATING_SDMMC0 (1 << 8) #define CCM_AHB_GATING_EMAC (1 << 17) #define CCM_USB_PHY (1 << 8) @@ -112,6 +113,7 @@ int a10_clk_usb_activate(void); int a10_clk_usb_deactivate(void); +int a10_clk_mmc_activate(void); int a10_clk_emac_activate(void); #endif /* _A10_CLK_H_ */ Index: sys/arm/allwinner/a10_ehci.c =================================================================== --- sys/arm/allwinner/a10_ehci.c (revision 272713) +++ sys/arm/allwinner/a10_ehci.c (working copy) @@ -75,8 +75,8 @@ #define SW_AHB_INCRX_ALIGN (1 << 8) #define SW_AHB_INCR4 (1 << 9) #define SW_AHB_INCR8 (1 << 10) -#define GPIO_USB1_PWR 230 -#define GPIO_USB2_PWR 227 +#define GPIO_USB1_PWR 230 /* For Cubieboard */ +#define GPIO_USB2_PWR 227 /* For Cubieboard */ #define A10_READ_4(sc, reg) \ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg) @@ -110,7 +110,9 @@ { ehci_softc_t *sc = device_get_softc(self); bus_space_handle_t bsh; +#if 0 /* XXX For Cubieboard */ device_t sc_gpio_dev; +#endif int err; int rid; uint32_t reg_value = 0; @@ -163,6 +165,7 @@ sprintf(sc->sc_vendor, "Allwinner"); +#if 0 /* XXX For Cubieboard */ /* Get the GPIO device, we need this to give power to USB */ sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0); if (sc_gpio_dev == NULL) { @@ -169,6 +172,7 @@ device_printf(self, "Error: failed to get the GPIO device\n"); goto error; } +#endif err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); @@ -183,6 +187,7 @@ /* Enable clock for USB */ a10_clk_usb_activate(); +#if 0 /* XXX For Cubieboard */ /* Give power to USB */ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_OUTPUT); GPIO_PIN_SET(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_HIGH); @@ -190,6 +195,7 @@ /* Give power to USB */ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_OUTPUT); GPIO_PIN_SET(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_HIGH); +#endif /* Enable passby */ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE); Index: sys/arm/allwinner/a10_mmc.c =================================================================== --- sys/arm/allwinner/a10_mmc.c (revision 0) +++ sys/arm/allwinner/a10_mmc.c (working copy) @@ -0,0 +1,653 @@ +/*- + * Copyright (c) 2013 Alexander Fedorov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +__FBSDID("$FreeBSD: head/sys/arm/lpc/lpc_mmc.c 239278 2012-08-15 05:37:10Z gonzo $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +struct a10_mmc_softc { + device_t a10_dev; + struct mtx a10_mtx; + struct resource * a10_mem_res; + struct resource * a10_irq_res; + bus_space_tag_t a10_bst; + bus_space_handle_t a10_bsh; + void * a10_intrhand; + struct mmc_host a10_host; + struct mmc_request * a10_req; + int a10_bus_busy; + uint8_t wait; + uint32_t error; + enum{ + A10_MMC_ST_UNK = 0, + A10_MMC_ST_WAIT_CMD_DONE, + A10_MMC_ST_WAIT_DATA_DONE + }state; +}; + +static int a10_mmc_probe(device_t); +static int a10_mmc_attach(device_t); +static int a10_mmc_detach(device_t); +static void a10_mmc_intr(void *); + +static int a10_mmc_update_ios(device_t, device_t); +static int a10_mmc_request(device_t, device_t, struct mmc_request *); +static int a10_mmc_get_ro(device_t, device_t); +static int a10_mmc_acquire_host(device_t, device_t); +static int a10_mmc_release_host(device_t, device_t); + +#define a10_mmc_lock(_sc) \ + mtx_lock(&_sc->a10_mtx); +#define a10_mmc_unlock(_sc) \ + mtx_unlock(&_sc->a10_mtx); +#define a10_mmc_read_4(_sc, _reg) \ + bus_space_read_4(_sc->a10_bst, _sc->a10_bsh, _reg) +#define a10_mmc_write_4(_sc, _reg, _value) \ + bus_space_write_4(_sc->a10_bst, _sc->a10_bsh, _reg, _value) + +static int +a10_mmc_reset(struct a10_mmc_softc *sc) +{ + uint32_t rval = a10_mmc_read_4(sc, MMC_GCTRL) | MMC_SOFT_RESET_B | MMC_FIFO_RESET_B | MMC_DMA_RESET_B; + int time = 0xffff; + + a10_mmc_write_4(sc, MMC_GCTRL, rval); + while((a10_mmc_read_4(sc, MMC_GCTRL) & (MMC_SOFT_RESET_B | MMC_FIFO_RESET_B | MMC_DMA_RESET_B)) && time--); + if (time <= 0){ + device_printf(sc->a10_dev, "Reset failed\n"); + return -1; + } + return 0; +} + +static void +a10_mmc_int_enable(struct a10_mmc_softc *sc) +{ + a10_mmc_write_4(sc, MMC_GCTRL, a10_mmc_read_4(sc, MMC_GCTRL)|MMC_INT_ENABLE_B); +} + +static int +a10_mmc_update_clk(struct a10_mmc_softc *sc) +{ + unsigned int cmd; + unsigned timeout = 0xfffff; + + cmd = MMC_Start | MMC_UPCLKOnly | MMC_WaitPreOver; + a10_mmc_write_4(sc, MMC_CMDR, cmd); + while((a10_mmc_read_4(sc, MMC_CMDR) & MMC_Start) && timeout--); + if (!timeout) + return -1; + + return 0; +} + +static int +a10_mmc_config_clock(struct a10_mmc_softc *sc, unsigned div) +{ + unsigned rval = a10_mmc_read_4(sc, MMC_CLKCR); + + /* + * CLKCREG[7:0]: divider + * CLKCREG[16]: on/off + * CLKCREG[17]: power save + */ + + /* Disable Clock */ + rval &= ~MMC_CARD_CLK_ON; + a10_mmc_write_4(sc, MMC_CLKCR, rval); + if(a10_mmc_update_clk(sc)) + return -1; + + /* Change Divider Factor */ + rval &= ~(0xFF); + rval |= div; + a10_mmc_write_4(sc, MMC_CLKCR, rval); + if(a10_mmc_update_clk(sc)) + return -1; + + /* Enable Clock */ + rval |= MMC_CARD_CLK_ON; + a10_mmc_write_4(sc, MMC_CLKCR, rval); + if(a10_mmc_update_clk(sc)) + return -1; + + return 0; +} + +static int +a10_mmc_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-mmc")) + return (ENXIO); + + device_set_desc(dev, "Allwinner Integrated MMC/SD controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +a10_mmc_attach(device_t dev) +{ + struct a10_mmc_softc *sc = device_get_softc(dev); + device_t child; + int rid; + + sc->a10_dev = dev; + sc->a10_req = NULL; + + mtx_init(&sc->a10_mtx, device_get_nameunit(sc->a10_dev), "a10_mmc", MTX_DEF); + + rid = 0; + sc->a10_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (!sc->a10_mem_res) { + device_printf(dev, "cannot allocate memory window\n"); + return (ENXIO); + } + + sc->a10_bst = rman_get_bustag(sc->a10_mem_res); + sc->a10_bsh = rman_get_bushandle(sc->a10_mem_res); + + rid = 0; + sc->a10_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE | RF_SHAREABLE); + if (!sc->a10_irq_res) { + device_printf(dev, "cannot allocate interrupt\n"); + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->a10_mem_res); + return (ENXIO); + } + + if (bus_setup_intr(dev, sc->a10_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, a10_mmc_intr, sc, &sc->a10_intrhand)) + { + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->a10_mem_res); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->a10_irq_res); + device_printf(dev, "cannot setup interrupt handler\n"); + return (ENXIO); + } + + a10_clk_mmc_activate(); + + /* Reset controller */ + a10_mmc_reset(sc); + + /* config DMA/Interrupt Trigger threshold */ + // a10_mmc_write_4(sc, MMC_FTRGL, 0x70008); + + /* config timeout register */ + a10_mmc_write_4(sc, MMC_TMOUT, 0xffffffff); + + /* clear interrupt flags */ + a10_mmc_write_4(sc, MMC_RINTR, 0xffffffff); + + a10_mmc_write_4(sc, MMC_DBGC, 0xdeb); + a10_mmc_write_4(sc, MMC_FUNS, 0xceaa0000); + + sc->a10_host.f_min = 400000; + sc->a10_host.f_max = 52000000; + sc->a10_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340; + sc->a10_host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED; + sc->a10_host.mode = mode_sd; + + /* device_set_ivars(dev, &sc->a10_host); */ + + child = device_add_child(dev, "mmc", 0); + if (!child) { + device_printf(dev, "attaching MMC bus failed!\n"); + bus_teardown_intr(dev, sc->a10_irq_res, sc->a10_intrhand); + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->a10_mem_res); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->a10_irq_res); + return (ENXIO); + } + + device_set_ivars(dev, &sc->a10_host); + return (bus_generic_attach(dev)); + +} + +static int +a10_mmc_detach(device_t dev) +{ + return (EBUSY); +} + +static int +mmc_trans_data_by_cpu(struct a10_mmc_softc *sc, struct mmc_data *data) +{ + unsigned i; + unsigned byte_cnt = data->len; + unsigned *buff; + unsigned timeout = 0xfffff; + + if (data->flags & MMC_DATA_READ) { + buff = (unsigned int *)data->data; + for (i=0; i<(byte_cnt>>2); i++) { + while(--timeout && (a10_mmc_read_4(sc, MMC_STAS) & MMC_FIFOEmpty)); + if (timeout <= 0) + goto out; + buff[i] = a10_mmc_read_4(sc, MMC_FIFO); + timeout = 0xfffff; + } + } else { + buff = (unsigned int *)data->data; + for (i=0; i<(byte_cnt>>2); i++) { + while(--timeout && (a10_mmc_read_4(sc, MMC_STAS) & MMC_FIFOFull)); + if (timeout <= 0) + goto out; + a10_mmc_write_4(sc, MMC_FIFO, buff[i]); + timeout = 0xfffff; + } + } + +out: + if (timeout <= 0) + return -1; + + return 0; +} + +static void +a10_req_ok(struct a10_mmc_softc *sc) +{ + struct mmc_command *cmd = sc->a10_req->cmd; + uint32_t resp_status;; + + do{ + resp_status = a10_mmc_read_4(sc, MMC_STAS); + }while(resp_status & MMC_CardDataBusy); + + if (cmd->flags & MMC_RSP_136) { + cmd->resp[0] = a10_mmc_read_4(sc, MMC_RESP3); + cmd->resp[1] = a10_mmc_read_4(sc, MMC_RESP2); + cmd->resp[2] = a10_mmc_read_4(sc, MMC_RESP1); + cmd->resp[3] = a10_mmc_read_4(sc, MMC_RESP0); + } else { + cmd->resp[0] = a10_mmc_read_4(sc, MMC_RESP0); + } + + sc->a10_req->cmd->error = MMC_ERR_NONE; + sc->a10_req->done(sc->a10_req); + sc->a10_req = NULL; +} + +static void +a10_req_err(struct a10_mmc_softc *sc) +{ + struct mmc_command *cmd = sc->a10_req->cmd; + device_printf(sc->a10_dev, "req error\n"); + cmd->error = MMC_ERR_TIMEOUT; + sc->a10_req->done(sc->a10_req); + sc->a10_req = NULL; +} + +static void +a10_mmc_intr(void *arg) +{ + struct a10_mmc_softc *sc = (struct a10_mmc_softc *)arg; + uint32_t rint = a10_mmc_read_4(sc, MMC_RINTR); + uint32_t imask = a10_mmc_read_4(sc, MMC_IMASK); + + imask &= ~rint; + a10_mmc_write_4(sc, MMC_IMASK, imask); + a10_mmc_write_4(sc, MMC_RINTR, rint); + + if(sc->a10_req == NULL){ + device_printf(sc->a10_dev, "req == NULL, rint: 0x%08X\n", rint); + } + + struct mmc_command *cmd = sc->a10_req->cmd; + +// if (cmd->data) { +// if (cmd->data->flags & MMC_DATA_WRITE){ +// device_printf(sc->a10_dev, "rint: 0x%08X, imask: 0x%08X\n", rint, imask); +// } +// } + + if(rint & MMC_IntErrBit){ + device_printf(sc->a10_dev, "error rint: 0x%08X\n", rint); + a10_req_err(sc); + return; + } + + if(!cmd->data && (rint & MMC_CmdDone)){ + a10_req_ok(sc); + return; + } + + if(cmd->data && (rint & MMC_DataOver)){ + a10_req_ok(sc); + return; + } + + if(cmd->data->flags & MMC_DATA_READ){ + int ret = mmc_trans_data_by_cpu(sc, cmd->data); + if(ret){ + device_printf(sc->a10_dev, "data read error, rint: 0x%08X\n", rint); + a10_req_err(sc); + + } + } + + if(cmd->data->flags & MMC_DATA_WRITE){ + if(rint & MMC_TxDataReq){ + int ret = mmc_trans_data_by_cpu(sc, cmd->data); + if(ret){ + device_printf(sc->a10_dev, "data write error, rint: 0x%08X\n", rint); + a10_req_err(sc); + } + } + } +} + +static int +a10_mmc_request(device_t bus, device_t child, struct mmc_request *req) +{ + unsigned int cmdreg = 0x80000000; + struct a10_mmc_softc *sc = device_get_softc(bus); + struct mmc_command *cmd = req->cmd; + uint32_t imask = MMC_CmdDone | MMC_IntErrBit; + + a10_mmc_lock(sc); + if (sc->a10_req){ + a10_mmc_unlock(sc); + return (EBUSY); + } + + sc->a10_req = req; + + if (cmd->opcode == MMC_GO_IDLE_STATE) + cmdreg |= MMC_SendInitSeq; + if (cmd->flags & MMC_RSP_PRESENT) + cmdreg |= MMC_RspExp; + if (cmd->flags & MMC_RSP_136) + cmdreg |= MMC_LongRsp; + if (cmd->flags & MMC_RSP_CRC) + cmdreg |= MMC_CheckRspCRC; + + if (cmd->data) { + cmdreg |= MMC_DataExp | MMC_WaitPreOver; + imask |= MMC_DataOver; + if (cmd->data->flags & MMC_DATA_WRITE){ + cmdreg |= MMC_Write; + imask |= MMC_TxDataReq; + }else{ + imask |= MMC_RxDataReq; + } + +// if (data->blocks > 1) +// cmdreg |= MMC_SendAutoStop; + + a10_mmc_write_4(sc, MMC_BLKSZ, cmd->data->len); + a10_mmc_write_4(sc, MMC_BCNTR, cmd->data->len); + + /* Choose access by AHB */ + a10_mmc_write_4(sc, MMC_GCTRL, a10_mmc_read_4(sc, MMC_GCTRL)|0x80000000); + } + + if (cmd->flags & MMC_RSP_BUSY) { + imask |= MMC_DataTimeout; + } + + /* Enable interrupts and set IMASK */ + a10_mmc_write_4(sc, MMC_IMASK, imask); + a10_mmc_int_enable(sc); + + a10_mmc_write_4(sc, MMC_CARG, cmd->arg); + a10_mmc_write_4(sc, MMC_CMDR, cmdreg|cmd->opcode); + sc->state = A10_MMC_ST_WAIT_CMD_DONE; + + a10_mmc_unlock(sc); + return 0; +} + +static int +a10_mmc_read_ivar(device_t bus, device_t child, int which, + uintptr_t *result) +{ + struct a10_mmc_softc *sc = device_get_softc(bus); + + switch (which) { + default: + return (EINVAL); + case MMCBR_IVAR_BUS_MODE: + *(int *)result = sc->a10_host.ios.bus_mode; + break; + case MMCBR_IVAR_BUS_WIDTH: + *(int *)result = sc->a10_host.ios.bus_width; + break; + case MMCBR_IVAR_CHIP_SELECT: + *(int *)result = sc->a10_host.ios.chip_select; + break; + case MMCBR_IVAR_CLOCK: + *(int *)result = sc->a10_host.ios.clock; + break; + case MMCBR_IVAR_F_MIN: + *(int *)result = sc->a10_host.f_min; + break; + case MMCBR_IVAR_F_MAX: + *(int *)result = sc->a10_host.f_max; + break; + case MMCBR_IVAR_HOST_OCR: + *(int *)result = sc->a10_host.host_ocr; + break; + case MMCBR_IVAR_MODE: + *(int *)result = sc->a10_host.mode; + break; + case MMCBR_IVAR_OCR: + *(int *)result = sc->a10_host.ocr; + break; + case MMCBR_IVAR_POWER_MODE: + *(int *)result = sc->a10_host.ios.power_mode; + break; + case MMCBR_IVAR_VDD: + *(int *)result = sc->a10_host.ios.vdd; + break; + case MMCBR_IVAR_CAPS: + *(int *)result = sc->a10_host.caps; + break; + case MMCBR_IVAR_MAX_DATA: + *(int *)result = 1; + break; + } + + return (0); +} + +static int +a10_mmc_write_ivar(device_t bus, device_t child, int which, + uintptr_t value) +{ + struct a10_mmc_softc *sc = device_get_softc(bus); + + switch (which) { + default: + return (EINVAL); + case MMCBR_IVAR_BUS_MODE: + sc->a10_host.ios.bus_mode = value; + break; + case MMCBR_IVAR_BUS_WIDTH: + sc->a10_host.ios.bus_width = value; + break; + case MMCBR_IVAR_CHIP_SELECT: + sc->a10_host.ios.chip_select = value; + break; + case MMCBR_IVAR_CLOCK: + sc->a10_host.ios.clock = value; + break; + case MMCBR_IVAR_MODE: + sc->a10_host.mode = value; + break; + case MMCBR_IVAR_OCR: + sc->a10_host.ocr = value; + break; + case MMCBR_IVAR_POWER_MODE: + sc->a10_host.ios.power_mode = value; + break; + case MMCBR_IVAR_VDD: + sc->a10_host.ios.vdd = value; + break; + /* These are read-only */ + case MMCBR_IVAR_CAPS: + case MMCBR_IVAR_HOST_OCR: + case MMCBR_IVAR_F_MIN: + case MMCBR_IVAR_F_MAX: + case MMCBR_IVAR_MAX_DATA: + return (EINVAL); + } + return (0); +} + +static int +a10_mmc_update_ios(device_t bus, device_t child) +{ + struct a10_mmc_softc *sc = device_get_softc(bus); + struct mmc_ios *ios = &sc->a10_host.ios; + unsigned int clkdiv = 0; + + /* Change clock first */ + clkdiv = (0x04dd1e00 + (ios->clock>>1))/ios->clock/2; + if (ios->clock) { + if (a10_mmc_config_clock(sc, clkdiv)) { + return -1; + } + } + + /* Set the bus width */ + switch (ios->bus_width) { + case bus_width_1: + a10_mmc_write_4(sc, MMC_WIDTH, MMC_WIDTH1); + break; + case bus_width_4: + a10_mmc_write_4(sc, MMC_WIDTH, MMC_WIDTH4); + break; + case bus_width_8: + a10_mmc_write_4(sc, MMC_WIDTH, MMC_WIDTH8); + break; + } + + return (0); +} + +static int +a10_mmc_get_ro(device_t bus, device_t child) +{ + return (0); +} + +static int +a10_mmc_acquire_host(device_t bus, device_t child) +{ + struct a10_mmc_softc *sc = device_get_softc(bus); + int error = 0; + + a10_mmc_lock(sc); + while (sc->a10_bus_busy) + error = mtx_sleep(sc, &sc->a10_mtx, PZERO, "mmcah", 0); + + sc->a10_bus_busy++; + a10_mmc_unlock(sc); + return (error); +} + +static int +a10_mmc_release_host(device_t bus, device_t child) +{ + struct a10_mmc_softc *sc = device_get_softc(bus); + + a10_mmc_lock(sc); + sc->a10_bus_busy--; + wakeup(sc); + a10_mmc_unlock(sc); + return (0); +} + +static device_method_t a10_mmc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, a10_mmc_probe), + DEVMETHOD(device_attach, a10_mmc_attach), + DEVMETHOD(device_detach, a10_mmc_detach), + + /* Bus interface */ + DEVMETHOD(bus_read_ivar, a10_mmc_read_ivar), + DEVMETHOD(bus_write_ivar, a10_mmc_write_ivar), + /* DEVMETHOD(bus_print_child, bus_generic_print_child), */ + + /* MMC bridge interface */ + DEVMETHOD(mmcbr_update_ios, a10_mmc_update_ios), + DEVMETHOD(mmcbr_request, a10_mmc_request), + DEVMETHOD(mmcbr_get_ro, a10_mmc_get_ro), + DEVMETHOD(mmcbr_acquire_host, a10_mmc_acquire_host), + DEVMETHOD(mmcbr_release_host, a10_mmc_release_host), + + { 0, 0 } +}; + +static devclass_t a10_mmc_devclass; + +static driver_t a10_mmc_driver = { + .name = "a10_mmc", + .methods = a10_mmc_methods, + .size = sizeof(struct a10_mmc_softc), +}; + +DRIVER_MODULE(a10_mmc, simplebus, a10_mmc_driver, a10_mmc_devclass, 0, 0); + Index: sys/arm/allwinner/a10_mmc.h =================================================================== --- sys/arm/allwinner/a10_mmc.h (revision 0) +++ sys/arm/allwinner/a10_mmc.h (working copy) @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2013 Alexander Fedorov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _A10_MMC_H_ +#define _A10_MMC_H_ + +#define MMC_GCTRL 0x00 // SMC Global Control Register +#define MMC_CLKCR 0x04 // SMC Clock Control Register +#define MMC_TMOUT 0x08 // SMC Time Out Register +#define MMC_WIDTH 0x0C // SMC Bus Width Register +#define MMC_BLKSZ 0x10 // SMC Block Size Register +#define MMC_BCNTR 0x14 // SMC Byte Count Register +#define MMC_CMDR 0x18 // SMC Command Register +#define MMC_CARG 0x1C // SMC Argument Register +#define MMC_RESP0 0x20 // SMC Response Register 0 +#define MMC_RESP1 0x24 // SMC Response Register 1 +#define MMC_RESP2 0x28 // SMC Response Register 2 +#define MMC_RESP3 0x2C // SMC Response Register 3 +#define MMC_IMASK 0x30 // SMC Interrupt Mask Register +#define MMC_MISTA 0x34 // SMC Masked Interrupt Status Register +#define MMC_RINTR 0x38 // SMC Raw Interrupt Status Register +#define MMC_STAS 0x3C // SMC Status Register +#define MMC_FTRGL 0x40 // SMC FIFO Threshold Watermark Register +#define MMC_FUNS 0x44 // SMC Function Select Register +#define MMC_CBCR 0x48 // SMC CIU Byte Count Register +#define MMC_BBCR 0x4C // SMC BIU Byte Count Register +#define MMC_DBGC 0x50 // SMC Debug Enable Register +#define MMC_DMAC 0x80 // SMC IDMAC Control Register +#define MMC_DLBA 0x84 // SMC IDMAC Descriptor List Base Address Register +#define MMC_IDST 0x88 // SMC IDMAC Status Register +#define MMC_IDIE 0x8C // SMC IDMAC Interrupt Enable Register +#define MMC_CHDA 0x90 +#define MMC_CBDA 0x94 +#define MMC_FIFO 0x100 // SMC FIFO Access Address + +/* MMC_GCTRL */ +#define MMC_SOFT_RESET_B (1 << 0) +#define MMC_FIFO_RESET_B (1 << 1) +#define MMC_DMA_RESET_B (1 << 2) +#define MMC_INT_ENABLE_B (1 << 4) +#define MMC_DMA_ENABLE_B (1 << 5) +#define MMC_DEBOUNCE_ENABLE_B (1 << 8) +#define MMC_PosedgeLatchData (1 << 9) +#define MMC_NegedgeLatchData (0 << 9) +#define MMC_DDR_MODE (1 << 10) +#define MMC_ACCESS_BY_AHB (1 << 31) +#define MMC_ACCESS_BY_DMA (0 << 31) + +/* CLKCR */ +#define MMC_CARD_CLK_ON (1 << 16) +#define MMC_LOW_POWER_ON (1 << 17) + +/* MMC_WIDTH */ +#define MMC_WIDTH1 (0) +#define MMC_WIDTH4 (1) +#define MMC_WIDTH8 (2) + +/* MMC_CMDR */ +#define MMC_RspExp (1 << 6) //0x40 +#define MMC_LongRsp (1 << 7) //0x80 +#define MMC_CheckRspCRC (1 << 8) //0x100 +#define MMC_DataExp (1 << 9) //0x200 +#define MMC_Read (0 << 10) //0x000 +#define MMC_Write (1 << 10) //0x400 +#define MMC_Blockmod (0 << 11) //0x000 +#define MMC_Seqmod (1 << 11) //0x800 +#define MMC_SendAutoStop (1 << 12) //0x1000 +#define MMC_WaitPreOver (1 << 13) //0x2000 +#define MMC_StopAbortCMD (1 << 14) //0x4000 +#define MMC_SendInitSeq (1 << 15) //0x8000 +#define MMC_UPCLKOnly (1 << 21) //0x200000 +#define MMC_RdCEATADev (1 << 22) //0x400000 +#define MMC_CCSExp (1 << 23) //0x800000 +#define MMC_EnbBoot (1 << 24) //0x1000000 +#define MMC_AltBootOpt (1 << 25) //0x2000000 +#define MMC_MandBootOpt (0 << 25) //0x0000000 +#define MMC_BootACKExp (1 << 26) //0x4000000 +#define MMC_DisableBoot (1 << 27) //0x8000000 +#define MMC_VolSwitch (1 << 28) //0x10000000 +#define MMC_Start (1 << 31) //0x80000000 + +/* Struct for Intrrrupt Information */ +#define MMC_RespErr (1 << 1) //0x2 +#define MMC_CmdDone (1 << 2) //0x4 +#define MMC_DataOver (1 << 3) //0x8 +#define MMC_TxDataReq (1 << 4) //0x10 +#define MMC_RxDataReq (1 << 5) //0x20 +#define MMC_RespCRCErr (1 << 6) //0x40 +#define MMC_DataCRCErr (1 << 7) //0x80 +#define MMC_RespTimeout (1 << 8) //0x100 +#define MMC_ACKRcv (1 << 8) //0x100 +#define MMC_DataTimeout (1 << 9) //0x200 +#define MMC_BootStart (1 << 9) //0x200 +#define MMC_DataStarve (1 << 10) //0x400 +#define MMC_VolChgDone (1 << 10) //0x400 +#define MMC_FIFORunErr (1 << 11) //0x800 +#define MMC_HardWLocked (1 << 12) //0x1000 +#define MMC_StartBitErr (1 << 13) //0x2000 +#define MMC_AutoCMDDone (1 << 14) //0x4000 +#define MMC_EndBitErr (1 << 15) //0x8000 +#define MMC_SDIOInt (1 << 16) //0x10000 +#define MMC_CardInsert (1 << 30) //0x40000000 +#define MMC_CardRemove (1 << 31) //0x80000000 +#define MMC_IntErrBit (MMC_RespErr | MMC_RespCRCErr | MMC_DataCRCErr | MMC_RespTimeout | MMC_DataTimeout \ + | MMC_FIFORunErr | MMC_HardWLocked | MMC_StartBitErr | MMC_EndBitErr) //0xbfc2 +/* status */ +#define MMC_RXWLFlag (1 << 0) +#define MMC_TXWLFlag (1 << 1) +#define MMC_FIFOEmpty (1 << 2) +#define MMC_FIFOFull (1 << 3) +#define MMC_CardPresent (1 << 8) +#define MMC_CardDataBusy (1 << 9) +#define MMC_DataFSMBusy (1 << 10) +#define MMC_DMAReq (1 << 31) +#define MMC_FIFO_SIZE (16) +/* Function select */ +#define MMC_CEATAOn (0xceaaU<< 16) +#define MMC_SendIrqRsp (1 << 0) +#define MMC_SDIORdWait (1 << 1) +#define MMC_AbtRdData (1 << 2) +#define MMC_SendCCSD (1 << 8) +#define MMC_SendAutoStopCCSD (1 << 9) +#define MMC_CEATADevIntEnb (1 << 10) +/* IDMA controller bus mod bit field */ +#define MMC_IDMACSoftRST (1 << 0) +#define MMC_IDMACFixBurst (1 << 1) +#define MMC_IDMACIDMAOn (1 << 7) +#define MMC_IDMACRefetchDES (1 << 31) +/* IDMA status bit field */ +#define MMC_IDMACTransmitInt (1 << 0) +#define MMC_IDMACReceiveInt (1 << 1) +#define MMC_IDMACFatalBusErr (1 << 2) +#define MMC_IDMACDesInvalid (1 << 4) +#define MMC_IDMACCardErrSum (1 << 5) +#define MMC_IDMACNormalIntSum (1 << 8) +#define MMC_IDMACAbnormalIntSum (1 << 9) +#define MMC_IDMACHostAbtInTx (1 << 10) +#define MMC_IDMACHostAbtInRx (1 << 10) +#define MMC_IDMACIdle (0 << 13) +#define MMC_IDMACSuspend (1 << 13) +#define MMC_IDMACDESCRd (0x2U<< 13) +#define MMC_IDMACDESCCheck (0x3U<< 13) +#define MMC_IDMACRdReqWait (0x4U<< 13) +#define MMC_IDMACWrReqWait (0x5U<< 13) +#define MMC_IDMACRd (0x6U<< 13) +#define MMC_IDMACWr (0x7U<< 13) +#define MMC_IDMACDESCClose (0x8U<< 13) + +#define MMC_IDMA_OVER (MMC_IDMACTransmitInt|MMC_IDMACReceiveInt|MMC_IDMACNormalIntSum) +#define MMC_IDMA_ERR (MMC_IDMACFatalBusErr|MMC_IDMACDesInvalid|MMC_IDMACCardErrSum|MMC_IDMACAbnormalIntSum) + +#endif /* _A10_MMC_H_ */ + Index: sys/arm/allwinner/a13_gpio.c =================================================================== --- sys/arm/allwinner/a13_gpio.c (revision 0) +++ sys/arm/allwinner/a13_gpio.c (working copy) @@ -0,0 +1,521 @@ +/*- + * Copyright (c) 2013 Ganbold Tsagaankhuu + * Copyright (c) 2012 Oleksandr Tymoshenko + * Copyright (c) 2012 Luiz Otavio O Souza. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gpio_if.h" + +/* + * A13 have 7 banks of gpio, but PA is not used, meaning in reality there + * are only 6! + * 32 pins per bank, but not all to them usable: + * PB0 - PB4 + PB10 + PB15 - PB18 (10) + * PC0 - PC15 + PC19 (17) + * PD2 - PD7 + PD10 - PD27 (22) + * PE0 - PE11 (12) + * PF0 - PF5 (6) + * PG0 - PG4 + PG9 - PG12 (9) + */ + +#define A13_GPIO_PINS 224 +#define A13_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) + +#define A13_GPIO_NONE 0 +#define A13_GPIO_PULLUP 1 +#define A13_GPIO_PULLDOWN 2 + +#define A13_GPIO_INPUT 0 +#define A13_GPIO_OUTPUT 1 + +struct a13_gpio_softc { + device_t sc_dev; + struct mtx sc_mtx; + struct resource * sc_mem_res; + struct resource * sc_irq_res; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + void * sc_intrhand; + int sc_gpio_npins; + struct gpio_pin sc_gpio_pins[A13_GPIO_PINS]; +}; + +#define A13_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx) +#define A13_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx) +#define A13_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED) + +#define A13_GPIO_GP_CFG(_bank, _pin) 0x00 + ((_bank) * 0x24) + ((_pin)<<2) +#define A13_GPIO_GP_DAT(_bank) 0x10 + ((_bank) * 0x24) +#define A13_GPIO_GP_DRV(_bank, _pin) 0x14 + ((_bank) * 0x24) + ((_pin)<<2) +#define A13_GPIO_GP_PUL(_bank, _pin) 0x1c + ((_bank) * 0x24) + ((_pin)<<2) + +#define A13_GPIO_GP_INT_CFG0 0x200 +#define A13_GPIO_GP_INT_CFG1 0x204 +#define A13_GPIO_GP_INT_CFG2 0x208 +#define A13_GPIO_GP_INT_CFG3 0x20c + +#define A13_GPIO_GP_INT_CTL 0x210 +#define A13_GPIO_GP_INT_STA 0x214 +#define A13_GPIO_GP_INT_DEB 0x218 + +#define A13_GPIO_WRITE(_sc, _off, _val) \ + bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val) +#define A13_GPIO_READ(_sc, _off) \ + bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off) + +static uint32_t +a13_gpio_get_function(struct a13_gpio_softc *sc, uint32_t pin) +{ + uint32_t bank, func, offset; + + bank = pin / 32; + pin = pin - 32 * bank; + func = pin >> 3; + offset = ((pin & 0x07) << 2); + + A13_GPIO_LOCK(sc); + func = (A13_GPIO_READ(sc, A13_GPIO_GP_CFG(bank, func)) >> offset) & 7; + A13_GPIO_UNLOCK(sc); + + return (func); +} + +static uint32_t +a13_gpio_func_flag(uint32_t nfunc) +{ + + switch (nfunc) { + case A13_GPIO_INPUT: + return (GPIO_PIN_INPUT); + case A13_GPIO_OUTPUT: + return (GPIO_PIN_OUTPUT); + } + return (0); +} + +static void +a13_gpio_set_function(struct a13_gpio_softc *sc, uint32_t pin, uint32_t f) +{ + uint32_t bank, func, data, offset; + + /* Must be called with lock held. */ + A13_GPIO_LOCK_ASSERT(sc); + + bank = pin / 32; + pin = pin - 32 * bank; + func = pin >> 3; + offset = ((pin & 0x07) << 2); + + data = A13_GPIO_READ(sc, A13_GPIO_GP_CFG(bank, func)); + data &= ~(7 << offset); + data |= (f << offset); + A13_GPIO_WRITE(sc, A13_GPIO_GP_CFG(bank, func), data); +} + +static void +a13_gpio_set_pud(struct a13_gpio_softc *sc, uint32_t pin, uint32_t state) +{ + uint32_t bank, offset, pull, val; + + /* Must be called with lock held. */ + A13_GPIO_LOCK_ASSERT(sc); + + bank = pin / 32; + pin = pin - 32 * bank; + pull = pin >> 4; + offset = ((pin & 0x0f) << 1); + + val = A13_GPIO_READ(sc, A13_GPIO_GP_PUL(bank, pull)); + val &= ~(0x03 << offset); + val |= (state << offset); + A13_GPIO_WRITE(sc, A13_GPIO_GP_PUL(bank, pull), val); +} + +static void +a13_gpio_pin_configure(struct a13_gpio_softc *sc, struct gpio_pin *pin, + unsigned int flags) +{ + + A13_GPIO_LOCK(sc); + + /* + * Manage input/output. + */ + if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { + pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); + if (flags & GPIO_PIN_OUTPUT) { + pin->gp_flags |= GPIO_PIN_OUTPUT; + a13_gpio_set_function(sc, pin->gp_pin, + A13_GPIO_OUTPUT); + } else { + pin->gp_flags |= GPIO_PIN_INPUT; + a13_gpio_set_function(sc, pin->gp_pin, + A13_GPIO_INPUT); + } + } + + /* Manage Pull-up/pull-down. */ + pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN); + if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) { + if (flags & GPIO_PIN_PULLUP) { + pin->gp_flags |= GPIO_PIN_PULLUP; + a13_gpio_set_pud(sc, pin->gp_pin, A13_GPIO_PULLUP); + } else { + pin->gp_flags |= GPIO_PIN_PULLDOWN; + a13_gpio_set_pud(sc, pin->gp_pin, A13_GPIO_PULLDOWN); + } + } else + a13_gpio_set_pud(sc, pin->gp_pin, A13_GPIO_NONE); + + A13_GPIO_UNLOCK(sc); +} + +static int +a13_gpio_pin_max(device_t dev, int *maxpin) +{ + + *maxpin = A13_GPIO_PINS - 1; + return (0); +} + +static int +a13_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + A13_GPIO_LOCK(sc); + *caps = sc->sc_gpio_pins[i].gp_caps; + A13_GPIO_UNLOCK(sc); + + return (0); +} + +static int +a13_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + A13_GPIO_LOCK(sc); + *flags = sc->sc_gpio_pins[i].gp_flags; + A13_GPIO_UNLOCK(sc); + + return (0); +} + +static int +a13_gpio_pin_getname(device_t dev, uint32_t pin, char *name) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + A13_GPIO_LOCK(sc); + memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME); + A13_GPIO_UNLOCK(sc); + + return (0); +} + +static int +a13_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + /* Check for unwanted flags. */ + if ((flags & sc->sc_gpio_pins[i].gp_caps) != flags) + return (EINVAL); + + /* Can't mix input/output together. */ + if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == + (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) + return (EINVAL); + + /* Can't mix pull-up/pull-down together. */ + if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) == + (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) + return (EINVAL); + + a13_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags); + + return (0); +} + +static int +a13_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + uint32_t bank, offset, data; + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + bank = pin / 32; + pin = pin - 32 * bank; + offset = pin & 0x1f; + + A13_GPIO_LOCK(sc); + data = A13_GPIO_READ(sc, A13_GPIO_GP_DAT(bank)); + if (value) + data |= (1 << offset); + else + data &= ~(1 << offset); + A13_GPIO_WRITE(sc, A13_GPIO_GP_DAT(bank), data); + A13_GPIO_UNLOCK(sc); + + return (0); +} + +static int +a13_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + uint32_t bank, offset, reg_data; + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + bank = pin / 32; + pin = pin - 32 * bank; + offset = pin & 0x1f; + + A13_GPIO_LOCK(sc); + reg_data = A13_GPIO_READ(sc, A13_GPIO_GP_DAT(bank)); + A13_GPIO_UNLOCK(sc); + *val = (reg_data & (1 << offset)) ? 1 : 0; + + return (0); +} + +static int +a13_gpio_pin_toggle(device_t dev, uint32_t pin) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + uint32_t bank, data, offset; + int i; + + for (i = 0; i < sc->sc_gpio_npins; i++) { + if (sc->sc_gpio_pins[i].gp_pin == pin) + break; + } + + if (i >= sc->sc_gpio_npins) + return (EINVAL); + + bank = pin / 32; + pin = pin - 32 * bank; + offset = pin & 0x1f; + + A13_GPIO_LOCK(sc); + data = A13_GPIO_READ(sc, A13_GPIO_GP_DAT(bank)); + if (data & (1 << offset)) + data &= ~(1 << offset); + else + data |= (1 << offset); + A13_GPIO_WRITE(sc, A13_GPIO_GP_DAT(bank), data); + A13_GPIO_UNLOCK(sc); + + return (0); +} + +static int +a13_gpio_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "allwinner,sun5i-gpio")) + return (ENXIO); + + device_set_desc(dev, "Allwinner GPIO controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +a13_gpio_attach(device_t dev) +{ + struct a13_gpio_softc *sc = device_get_softc(dev); + uint32_t func; + int i, rid; + phandle_t gpio; + + sc->sc_dev = dev; + + mtx_init(&sc->sc_mtx, "a13 gpio", "gpio", MTX_DEF); + + rid = 0; + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (!sc->sc_mem_res) { + device_printf(dev, "cannot allocate memory window\n"); + return (ENXIO); + } + + sc->sc_bst = rman_get_bustag(sc->sc_mem_res); + sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); + + rid = 0; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (!sc->sc_irq_res) { + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); + device_printf(dev, "cannot allocate interrupt\n"); + return (ENXIO); + } + + /* Find our node. */ + gpio = ofw_bus_get_node(sc->sc_dev); + + if (!OF_hasprop(gpio, "gpio-controller")) + /* Node is not a GPIO controller. */ + goto fail; + + /* Initialize the software controlled pins. */ + for (i = 0; i < A13_GPIO_PINS; i++) { + snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, + "pin %d", i); + func = a13_gpio_get_function(sc, i); + sc->sc_gpio_pins[i].gp_pin = i; + sc->sc_gpio_pins[i].gp_caps = A13_GPIO_DEFAULT_CAPS; + sc->sc_gpio_pins[i].gp_flags = a13_gpio_func_flag(func); + } + sc->sc_gpio_npins = i; + + device_add_child(dev, "gpioc", device_get_unit(dev)); + device_add_child(dev, "gpiobus", device_get_unit(dev)); + return (bus_generic_attach(dev)); + +fail: + if (sc->sc_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); + if (sc->sc_mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); + return (ENXIO); +} + +static int +a13_gpio_detach(device_t dev) +{ + + return (EBUSY); +} + +static device_method_t a13_gpio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, a13_gpio_probe), + DEVMETHOD(device_attach, a13_gpio_attach), + DEVMETHOD(device_detach, a13_gpio_detach), + + /* GPIO protocol */ + DEVMETHOD(gpio_pin_max, a13_gpio_pin_max), + DEVMETHOD(gpio_pin_getname, a13_gpio_pin_getname), + DEVMETHOD(gpio_pin_getflags, a13_gpio_pin_getflags), + DEVMETHOD(gpio_pin_getcaps, a13_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_setflags, a13_gpio_pin_setflags), + DEVMETHOD(gpio_pin_get, a13_gpio_pin_get), + DEVMETHOD(gpio_pin_set, a13_gpio_pin_set), + DEVMETHOD(gpio_pin_toggle, a13_gpio_pin_toggle), + + DEVMETHOD_END +}; + +static devclass_t a13_gpio_devclass; + +static driver_t a13_gpio_driver = { + "gpio", + a13_gpio_methods, + sizeof(struct a13_gpio_softc), +}; + +DRIVER_MODULE(a13_gpio, simplebus, a13_gpio_driver, a13_gpio_devclass, 0, 0); Property changes on: sys/arm/allwinner/a13_gpio.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: sys/arm/allwinner/files.a13 =================================================================== --- sys/arm/allwinner/files.a13 (revision 0) +++ sys/arm/allwinner/files.a13 (working copy) @@ -0,0 +1,24 @@ +# $FreeBSD: head/sys/arm/allwinner/files.a10 262979 2014-03-10 18:10:09Z ian $ +kern/kern_clocksource.c standard + +arm/arm/bus_space_asm_generic.S standard +arm/arm/bus_space_generic.c standard +arm/arm/cpufunc_asm_armv5.S standard +arm/arm/cpufunc_asm_arm10.S standard +arm/arm/cpufunc_asm_arm11.S standard +arm/arm/cpufunc_asm_armv7.S standard + +arm/allwinner/a10_clk.c standard +arm/allwinner/a10_common.c standard +arm/allwinner/a13_gpio.c optional gpio +arm/allwinner/a10_ehci.c optional ehci +arm/allwinner/a10_mmc.c optional mmc +arm/allwinner/a10_machdep.c standard +arm/allwinner/a10_sramc.c standard +arm/allwinner/a10_wdog.c standard +arm/allwinner/a20/a20_cpu_cfg.c standard +arm/allwinner/aintc.c standard +arm/allwinner/timer.c standard +arm/arm/bus_space-v6.c standard +#arm/allwinner/console.c standard + Index: sys/arm/allwinner/std.a13 =================================================================== --- sys/arm/allwinner/std.a13 (revision 0) +++ sys/arm/allwinner/std.a13 (working copy) @@ -0,0 +1,19 @@ +# Allwinner A13 common options +#$FreeBSD: head/sys/arm/allwinner/std.a10 245450 2013-01-15 08:26:16Z ganbold $ + +cpu CPU_CORTEXA +machine arm armv6 +makeoption ARM_LITTLE_ENDIAN + +# Physical memory starts at 0x40200000. We assume images are loaded at +# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel' +# +# +options PHYSADDR=0x40000000 + +makeoptions KERNPHYSADDR=0x40200000 +options KERNPHYSADDR=0x40200000 +makeoptions KERNVIRTADDR=0xc0200000 +options KERNVIRTADDR=0xc0200000 + +files "../allwinner/files.a13" Index: sys/arm/conf/A13_OLINUXINO =================================================================== --- sys/arm/conf/A13_OLINUXINO (revision 0) +++ sys/arm/conf/A13_OLINUXINO (working copy) @@ -0,0 +1,134 @@ +# A13 -- Custom configuration for the A13 ARM Olinuxino +# platform, check out http://www.olimex.com +# +# For more information on this file, please read 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: head/sys/arm/conf/CUBIEBOARD 249083 2013-04-04 07:12:24Z mav $ + +ident A13_OLINUXINO + +include "../allwinner/std.a13" + +makeoptions MODULES_OVERRIDE="" +makeoptions WITHOUT_MODULES="ahc" + +options HZ=100 +options SCHED_4BSD # 4BSD scheduler +options INET # InterNETworking +options INET6 # IPv6 communications protocols +options GEOM_PART_BSD # BSD partition scheme +options GEOM_PART_MBR # MBR partition scheme +options TMPFS # Efficient memory filesystem +options FFS # Berkeley Fast Filesystem +options SOFTUPDATES # Enable FFS soft updates support +options UFS_ACL # Support for access control lists +options UFS_DIRHASH # Improve performance on big directories +options MSDOSFS # MSDOS Filesystem +options CD9660 # ISO 9660 Filesystem +options PROCFS # Process filesystem (requires PSEUDOFS) +options PSEUDOFS # Pseudo-filesystem framework +options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI +options KTRACE # ktrace(1) support +options SYSVSHM # SYSV-style shared memory +options SYSVMSG # SYSV-style message queues +options SYSVSEM # SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +options PREEMPTION +options FREEBSD_BOOT_LOADER +options VFP # vfp/neon + +# Debugging +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols +options BREAK_TO_DEBUGGER +#options VERBOSE_SYSINIT # Enable verbose sysinit messages +options KDB +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 + +options ARM_DEVICE_MULTIPASS + +# NFS support +#options NFSCL +#options NFSSERVER # Network Filesystem Server +#options NFSCLIENT # Network Filesystem Client + +# Uncomment this for NFS root +#options NFS_ROOT # NFS usable as /, requires NFSCLIENT +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=cpsw0 + +# MMC/SD/SDIO card slot support (currently broken) +#device mmc # mmc/sd bus +#device mmcsd # mmc/sd flash cards + +# Boot device is 2nd slice on MMC/SD card +options ROOTDEVNAME=\"ufs:/dev/da0s2\" + +# Console and misc +device uart +device uart_ns8250 +device pty +device snp +device md +device random # Entropy device + +# I2C support +#device iicbus +#device iic + +# GPIO +device gpio +device gpioled + +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device pass + +# USB support +options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. +device usb +options USB_DEBUG +#options USB_REQ_DEBUG +#options USB_VERBOSE +#device uhci +#device ohci +device ehci + +device umass + +# Ethernet +device loop +device ether +device mii +device bpf + +# USB ethernet support, requires miibus +device miibus + +# Flattened Device Tree +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=a13_olinuxino.dts + Index: sys/boot/fdt/dts/arm/a13_olinuxino.dts =================================================================== --- sys/boot/fdt/dts/arm/a13_olinuxino.dts (revision 0) +++ sys/boot/fdt/dts/arm/a13_olinuxino.dts (working copy) @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2012 Ganbold Tsagaankhuu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/dts-v1/; + +/include/ "sun5i-a13.dtsi" + +/ { + model = "Olimex Olinuxino A13"; + + memory { + device_type = "memory"; + reg = < 0x40000000 0x20000000 >; /* 512MB RAM */ + }; + + aliases { + soc = &SOC; + UART1 = &UART1; + }; + + SOC: a13 { + + usb1: usb@01c14000 { + status = "okay"; + }; + + UART1: serial@01c28400 { + status = "okay"; + }; + + mmc@01c0f000 { + compatible = "allwinner,sun4i-mmc"; + reg = <0x01c0f000 0x1000>; + interrupts = <32>; + interrupt-parent = <&AINTC>; + }; + + }; + + leds { + compatible = "gpio-leds"; + + led1 { + label = "led1"; + gpios = <&gpio 201 1>; + }; + }; + + chosen { + bootargs = "-v"; + stdin = "UART1"; + stdout = "UART1"; + }; +}; + Property changes on: sys/boot/fdt/dts/arm/a13_olinuxino.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: sys/boot/fdt/dts/arm/sun5i-a13.dtsi =================================================================== --- sys/boot/fdt/dts/arm/sun5i-a13.dtsi (revision 0) +++ sys/boot/fdt/dts/arm/sun5i-a13.dtsi (working copy) @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2014 Ganbold Tsagaankhuu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/ { + compatible = "allwinner,sun4i-a10"; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-parent = <&AINTC>; + + aliases { + soc = &SOC; + }; + + SOC: a13 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + bus-frequency = <0>; + + AINTC: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = < 0x01c20400 0x400 >; + }; + + sramc@01c00000 { + compatible = "allwinner,sun4i-sramc"; + #address-cells = <1>; + #size-cells = <1>; + reg = < 0x01c00000 0x1000 >; + }; + + ccm@01c20000 { + compatible = "allwinner,sun4i-ccm"; + #address-cells = <1>; + #size-cells = <1>; + reg = < 0x01c20000 0x400 >; + }; + + timer@01c20c00 { + compatible = "allwinner,sun4i-timer"; + reg = <0x01c20c00 0x90>; + interrupts = < 22 >; + interrupt-parent = <&AINTC>; + clock-frequency = < 24000000 >; + }; + + watchdog@01c20c90 { + compatible = "allwinner,sun4i-wdt"; + reg = <0x01c20c90 0x08>; + }; + + + gpio: gpio@01c20800 { + #gpio-cells = <3>; + compatible = "allwinner,sun5i-gpio"; + gpio-controller; + reg =< 0x01c20800 0x400 >; + interrupts = < 28 >; + interrupt-parent = <&AINTC>; + }; + + usb1: usb@01c14000 { + compatible = "allwinner,usb-ehci", "usb-ehci"; + reg = <0x01c14000 0x1000>; + interrupts = < 39 >; + interrupt-parent = <&AINTC>; + }; + + UART1: serial@01c28400 { + compatible = "ns16550"; + reg = <0x01c28400 0x400>; + reg-shift = <2>; + interrupts = <2>; + interrupt-parent = <&AINTC>; + current-speed = <115200>; + clock-frequency = < 24000000 >; + busy-detect = <1>; + broken-txfifo = <1>; + }; + + }; +}; + Property changes on: sys/boot/fdt/dts/arm/sun5i-a13.dtsi ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: sys/dev/mmc/mmc.c =================================================================== --- sys/dev/mmc/mmc.c (revision 272713) +++ sys/dev/mmc/mmc.c (working copy) @@ -1774,4 +1774,5 @@ DRIVER_MODULE(mmc, sdhci_ti, mmc_driver, mmc_devclass, NULL, NULL); DRIVER_MODULE(mmc, ti_mmchs, mmc_driver, mmc_devclass, NULL, NULL); DRIVER_MODULE(mmc, dwmmc, mmc_driver, mmc_devclass, NULL, NULL); +DRIVER_MODULE(mmc, a10_mmc, mmc_driver, mmc_devclass, NULL, NULL); ------=_20141007221852_56350--