Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Oct 2014 22:18:52 +0200 (CEST)
From:      "Jakob Alvermark" <jakob@alvermark.net>
To:        freebsd-arm@freebsd.org
Subject:   Allwinner A13 support (patches attached)
Message-ID:  <18234.85.229.95.175.1412713132.squirrel@webmail.alvermark.net>

next in thread | raw e-mail | index | archive | help
------=_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: <Allwinner Integrated MMC/SD controller> mem 0x1c0f000-0x1c0ffff
irq 32 on simplebus0
MMC0 MODE_CLK: 0x04dd1e00
mmc0: <MMC/SD bus> 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 <alexander.fedorov@rtlservice.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/arm/lpc/lpc_mmc.c 239278 2012-08-15 05:37:10Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+
+#include <arm/allwinner/a10_clk.h>
+#include <arm/allwinner/a10_mmc.h>
+
+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 <alexander.fedorov@rtlservice.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#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 <ganbold@gmail.com>
+ * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/resource.h>
+#include <machine/fdt.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#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 <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD$
+ */
+
+/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 <ganbold@freebsd.org>
+ * 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--





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?18234.85.229.95.175.1412713132.squirrel>