mmc/sd driver testing.
Alexander Fedorov
alexander.fedorov at rtlservice.com
Thu Apr 16 21:48:56 UTC 2015
Hello!
If it helps, I've updated my patch to CURRENT r281599.
These are the changes from the previous version:
- Style fixes, suggested by Ian.
- Speed improovment (reading from 2 MB/s to 5-6 MB/s, writing from 0.8
to 1.5 MB/s).
- Use bus_space_write_multi_4/bus_space_read_multi_4 for large blocks.
- Multiblock I/O support.
Some simple tests:
### Read test ####
# dd if=/dev/mmcsd0s2 of=/dev/null bs=4k count=4k
4096+0 records in
4096+0 records out
16777216 bytes transferred in 4.438201 secs (3780184 bytes/sec)
root@:~ # dd if=/dev/mmcsd0s2 of=/dev/null bs=8k count=4k
4096+0 records in
4096+0 records out
33554432 bytes transferred in 5.514032 secs (6085281 bytes/sec)
root@:~ # dd if=/dev/mmcsd0s2 of=/dev/null bs=16k count=4k
4096+0 records in
4096+0 records out
67108864 bytes transferred in 10.341467 secs (6489299 bytes/sec)
root@:~ # dd if=/dev/mmcsd0s2 of=/dev/null bs=32k count=4k
4096+0 records in
4096+0 records out
134217728 bytes transferred in 19.956929 secs (6725370 bytes/sec)
root@:~ #
### Write test ####
root@:~ # dd if=/dev/zero of=test bs=8k count=4k
4096+0 records in
4096+0 records out
33554432 bytes transferred in 21.556914 secs (1556551 bytes/sec)
root@:~ # dd if=/dev/zero of=test bs=32k count=1k
1024+0 records in
1024+0 records out
33554432 bytes transferred in 26.035960 secs (1288773 bytes/sec)
root@:~ # dd if=/dev/zero of=test bs=4k count=1k
1024+0 records in
1024+0 records out
4194304 bytes transferred in 4.173082 secs (1005085 bytes/sec)
root@:~ # rm test
root@:~ # dd if=/dev/zero of=test bs=16k count=1k
1024+0 records in
1024+0 records out
16777216 bytes transferred in 8.148621 secs (2058902 bytes/sec)
root@:~ #
### DMESG on PC-DUINO ###
sun4i#fatload mmc 0 0x40200000 kernel; go 0x40200100
reading kernel
5925139 bytes read
## Starting application at 0x40200100 ...
KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2015 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 11.0-CURRENT #98 r281599M: Thu Apr 16 23:56:20 MSK 2015
XeNoN at xenon.org:/usr/obj/arm.armv6/usr/home/XeNoN/mydoc/projects/head/sys/CUBIEBOARD
arm
FreeBSD clang version 3.6.0 (tags/RELEASE_360/final 230434) 20150225
WARNING: WITNESS option enabled, expect reduced performance.
CPU: Cortex A8-r3 rev 2 (Cortex-A core)
Supported features: ARM_ISA THUMB2 JAZELLE THUMBEE ARMv4 Security_Ext
WB disabled EABT branch prediction enabled
LoUU:2 LoC:3 LoUIS:1
Cache level 1:
32KB/64B 4-way data cache WT WB Read-Alloc
32KB/64B 4-way instruction cache Read-Alloc
Cache level 2:
256KB/64B 8-way unified cache WT WB Read-Alloc Write-Alloc
real memory = 1073741824 (1024 MB)
avail memory = 1038589952 (990 MB)
random: entropy device infrastructure driver
random: selecting highest priority adaptor <Dummy>
random: SOFT: yarrow init()
random: selecting highest priority adaptor <Yarrow>
ofwbus0: <Open Firmware Device Tree>
simplebus0: <Flattened device tree simple bus> on ofwbus0
aintc0: <A10 AINTC Interrupt Controller> mem 0x1c20400-0x1c207ff on simplebus0
a10_sramc0: <Allwinner sramc module> mem 0x1c00000-0x1c00fff on simplebus0
a10_ccm0: <Allwinner Clock Control Module> mem 0x1c20000-0x1c203ff on simplebus0
a10_timer0: <Allwinner A10/A20 timer> mem 0x1c20c00-0x1c20c8f irq 22
on simplebus0
Event timer "a10_timer Eventtimer" frequency 24000000 Hz quality 1000
Timecounter "a10_timer timer0" frequency 24000000 Hz quality 1000
a10wd0: <Allwinner A10 Watchdog> mem 0x1c20c90-0x1c20c97 on simplebus0
gpio0: <Allwinner GPIO controller> mem 0x1c20800-0x1c20bff irq 28 on simplebus0
gpiobus0: <GPIO bus> on gpio0
gpioc0: <GPIO controller> on gpio0
ehci0: <Allwinner Integrated USB 2.0 controller> mem
0x1c14000-0x1c14fff irq 39 on simplebus0
usbus0: EHCI version 1.0
usbus0 on ehci0
ehci1: <Allwinner Integrated USB 2.0 controller> mem
0x1c1c000-0x1c1cfff irq 40 on simplebus0
usbus1: EHCI version 1.0
usbus1 on ehci1
a10_mmc0: <A10 MMC/SD controller> mem 0x1c0f000-0x1c0ffff irq 32 on simplebus0
mmc0: <MMC/SD bus> on a10_mmc0
a10_mmc0: attach OK
uart0: <16750 or compatible> mem 0x1c28000-0x1c283ff irq 1 on simplebus0
uart0: console (115200,n,8,1)
emac0: <A10/A20 EMAC ethernet controller> mem 0x1c0b000-0x1c0bfff irq
55 on simplebus0
miibus0: <MII bus> on emac0
rlphy0: <IP101 10/100 PHY> PHY 1 on miibus0
rlphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
emac0: Ethernet address: 62:73:64:a3:05:c4
Timecounters tick every 10.000 msec
usbus0: 480Mbps High Speed USB v2.0
usbus1: 480Mbps High Speed USB v2.0
ugen1.1: <Allwinner> at usbus1
uhub0: <Allwinner EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus1
ugen0.1: <Allwinner> at usbus0
uhub1: <Allwinner EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
mmcsd0: 4GB <SDHC NCard 1.0 SN D701F44D MFG 10/2013 by 130 JT> at mmc0
50.0MHz/4bit/16-block
random: unblocking device.
WARNING: WITNESS option enabled, expect reduced performance.
Root mount waiting for: usbus1 usbus0
uhub1: 1 port with 1 removable, self powered
uhub0: 1 port with 1 removable, self powered
Trying to mount root from ufs:/dev/mmcsd0s2 []...
WARNING: / was not properly dismounted
warning: no time-of-day clock registered, system time will not be set accurately
Setting hostuuid: 381135a6-e476-11e4-a053-eb0bbb102e89.
Setting hostid: 0x199caa7a.
No suitable dump device was found.
Starting file system checks:
/dev/mmcsd0s2: FREE BLK COUNT(S) WRONG IN SUPERBLK (SALVAGED)
/dev/mmcsd0s2: SUMMARY INFORMATION BAD (SALVAGED)
/dev/mmcsd0s2: BLK(S) MISSING IN BIT MAPS (SALVAGED)
/dev/mmcsd0s2: 15693 files, 83449 used, 164210 free (34 frags, 20522
blocks, 0.0% fragmentation)
Mounting local file systems:.
/etc/rc: WARNING: $hostname is not set -- see rc.conf(5).
Feeding entropy:.
Starting Network: lo0 emac0.
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
inet 127.0.0.1 netmask 0xff000000
groups: lo
nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
emac0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=80008<VLAN_MTU,LINKSTATE>
ether 62:73:64:a3:05:c4
emac0: link state changed to DOWN
media: Ethernet autoselect (none)
status: no carrier
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Starting devd.
Starting Network: emac0.
emac0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=80008<VLAN_MTU,LINKSTATE>
ether 62:73:64:a3:05:c4
media: Ethernet autoselect (none)
status: no carrier
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
add net fe80::: gateway ::1
add net ff02::: gateway ::1
add net ::ffff:0.0.0.0: gateway ::1
add net ::0.0.0.0: gateway ::1
Creating and/or trimming log files.
Starting syslogd.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
Starting casperd.
Clearing /tmp (X related).
Updating motd:.
Mounting late file systems:.
Starting sendmail_submit.
Starting sendmail_msp_queue.
Starting cron.
Starting background file system checks in 60 seconds.
Thu Apr 16 21:05:55 UTC 2015
FreeBSD/arm (Amnesiac) (ttyu0)
login:
Patch:
Index: sys/arm/allwinner/a10_clk.c
===================================================================
--- sys/arm/allwinner/a10_clk.c (revision 281599)
+++ sys/arm/allwinner/a10_clk.c (working copy)
@@ -189,3 +189,40 @@
return (0);
}
+int
+a10_clk_mmc_activate(uint32_t *mod_clk)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value;
+ uint32_t pll5_clk;
+ uint32_t divider;
+ uint32_t 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,
+ CCM_MMC0_GATE_PASS | CCM_MMC0_CLK_SRC_PLL5 | divider);
+
+ *mod_clk = pll5_clk / (divider + 1);
+
+ return 0;
+}
+
Index: sys/arm/allwinner/a10_clk.h
===================================================================
--- sys/arm/allwinner/a10_clk.h (revision 281599)
+++ sys/arm/allwinner/a10_clk.h (working copy)
@@ -104,6 +104,7 @@
#define CCM_AHB_GATING_EHCI0 (1 << 1)
#define CCM_AHB_GATING_EHCI1 (1 << 3)
#define CCM_AHB_GATING_EMAC (1 << 17)
+#define CCM_AHB_GATING_SDMMC0 (1 << 8)
#define CCM_USB_PHY (1 << 8)
#define CCM_USB0_RESET (1 << 0)
@@ -110,8 +111,13 @@
#define CCM_USB1_RESET (1 << 1)
#define CCM_USB2_RESET (1 << 2)
+#define CCM_MMC0_CLK_SRC_PLL5 (2U << 24)
+#define CCM_MMC0_GATE_MASK (0 << 31)
+#define CCM_MMC0_GATE_PASS (1 << 31)
+
int a10_clk_usb_activate(void);
int a10_clk_usb_deactivate(void);
int a10_clk_emac_activate(void);
+int a10_clk_mmc_activate(uint32_t *mod_clk);
#endif /* _A10_CLK_H_ */
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,622 @@
+/*-
+ * Copyright (c) 2014 Alexander Fedorov <alexander.fedorov at 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$");
+
+#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/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 dev;
+ struct mmc_host host;
+ struct mmc_request * req;
+ struct mtx mtx;
+ struct resource * mem_res;
+ struct resource * irq_res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ void * intrhand;
+ uint32_t mod_clk;
+ int bus_busy;
+};
+
+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->mtx);
+#define a10_mmc_unlock(_sc) \
+ mtx_unlock(&_sc->mtx);
+#define RD4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WR4(_sc, _reg, _value) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _value)
+
+static int
+a10_mmc_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-mmc"))
+ return (ENXIO);
+
+ device_set_desc(dev, "A10 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;
+ uint32_t reg;
+ int rid;
+
+ sc->dev = dev;
+ sc->req = NULL;
+
+ mtx_init(&sc->mtx, "a10_mmc", "mmc", MTX_DEF);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->mem_res);
+ sc->bsh = rman_get_bushandle(sc->mem_res);
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, a10_mmc_intr, sc, &sc->intrhand))
+ {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+
+ if(a10_clk_mmc_activate(&sc->mod_clk)) {
+ return (ENXIO);
+ }
+
+ /* Reset controller */
+ reg = RD4(sc, A10_MMC_GCTRL) | \
+ A10_MMC_SOFT_RESET | A10_MMC_FIFO_RESET | A10_MMC_DMA_RESET;
+
+ WR4(sc, A10_MMC_GCTRL, reg);
+ while(RD4(sc, A10_MMC_GCTRL) & \
+ (A10_MMC_SOFT_RESET | A10_MMC_FIFO_RESET | A10_MMC_DMA_RESET));
+
+ /* config DMA/Interrupt Trigger threshold */
+ // WR4(sc, MMC_FTRGL, 0x70008);
+
+ /* Config timeout register */
+ WR4(sc, A10_MMC_TMOUT, 0xffffffff);
+
+ /* Clear interrupt flags */
+ WR4(sc, A10_MMC_RINTR, 0xffffffff);
+
+ WR4(sc, A10_MMC_DBGC, 0xdeb);
+ WR4(sc, A10_MMC_FUNS, 0xceaa0000);
+
+ sc->host.f_min = 400000;
+ sc->host.f_max = 50000000;
+ sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
+ sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED;
+ sc->host.mode = mode_sd;
+
+// device_set_ivars(dev, &sc->host);
+
+ child = device_add_child(dev, "mmc", 0);
+ if (!child) {
+ device_printf(dev, "attaching MMC bus failed!\n");
+ bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ return (ENXIO);
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+ device_printf(sc->dev, "attach OK\n");
+
+ return (0);
+}
+
+static int
+a10_mmc_detach(device_t dev)
+{
+ struct a10_mmc_softc *sc = device_get_softc(dev);
+ device_printf(sc->dev, "detach\n");
+ return (EBUSY);
+}
+
+static void
+a10_req_ok(struct a10_mmc_softc *sc)
+{
+ struct mmc_command *cmd = sc->req->cmd;
+ uint32_t resp_status;;
+
+ do{
+ resp_status = RD4(sc, A10_MMC_STAS);
+ }while(resp_status & A10_MMC_CARD_DATA_BUSY);
+
+ if (cmd->flags & MMC_RSP_136) {
+ cmd->resp[0] = RD4(sc, A10_MMC_RESP3);
+ cmd->resp[1] = RD4(sc, A10_MMC_RESP2);
+ cmd->resp[2] = RD4(sc, A10_MMC_RESP1);
+ cmd->resp[3] = RD4(sc, A10_MMC_RESP0);
+ } else {
+ cmd->resp[0] = RD4(sc, A10_MMC_RESP0);
+ }
+
+ sc->req->cmd->error = MMC_ERR_NONE;
+ sc->req->done(sc->req);
+ sc->req = NULL;
+}
+
+static void
+a10_req_err(struct a10_mmc_softc *sc)
+{
+ struct mmc_command *cmd = sc->req->cmd;
+// device_printf(sc->dev, "req error\n");
+ cmd->error = MMC_ERR_TIMEOUT;
+ sc->req->done(sc->req);
+ sc->req = NULL;
+}
+
+static void
+a10_mmc_intr(void *arg)
+{
+ struct a10_mmc_softc *sc = (struct a10_mmc_softc *)arg;
+ struct mmc_command *cmd = sc->req->cmd;
+ struct mmc_data *data = cmd->data;
+ uint32_t *buf = NULL;
+ uint32_t rint = RD4(sc, A10_MMC_RINTR);
+ uint32_t imask = RD4(sc, A10_MMC_IMASK);
+ int i = 0;
+
+ imask &= ~rint;
+ WR4(sc, A10_MMC_IMASK, imask);
+ WR4(sc, A10_MMC_RINTR, rint);
+
+ if (sc->req == NULL){
+ device_printf(sc->dev, "req == NULL, rint: 0x%08X\n", rint);
+ }
+
+ if (rint & A10_MMC_INT_ERR_BIT){
+ device_printf(sc->dev, "error rint: 0x%08X\n", rint);
+ a10_req_err(sc);
+ return;
+ }
+
+ if (!data && (rint & A10_MMC_CMD_DONE)){
+ a10_req_ok(sc);
+ return;
+ }
+
+ if (data && (rint & A10_MMC_DATA_OVER)){
+ a10_req_ok(sc);
+ return;
+ }
+
+ if (data != NULL) {
+ buf = (uint32_t*)data->data;
+
+ if (data->flags & MMC_DATA_READ){
+ if (data->len >= MMC_SECTOR_SIZE){
+ for (i = 0; i < (data->len >> 2) / A10_MMC_FIFO_SIZE; i++){
+ while (!(RD4(sc, A10_MMC_STAS) & A10_MMC_FIFO_FULL))
+ continue;
+
+ bus_space_read_multi_4(sc->bst, sc->bsh, A10_MMC_FIFO, \
+ buf, A10_MMC_FIFO_SIZE);
+ buf += A10_MMC_FIFO_SIZE;
+ }
+ }else{
+ for (i = 0; i < (data->len >> 2); i++) {
+ while (RD4(sc, A10_MMC_STAS) & A10_MMC_FIFO_EMPTY)
+ continue;
+
+ buf[i] = RD4(sc, A10_MMC_FIFO);
+ }
+ }
+ }
+
+ if ((data->flags & MMC_DATA_WRITE) && (rint & A10_MMC_TX_DATA_REQ)){
+ if (data->len >= MMC_SECTOR_SIZE){
+ for (i = 0; i < (data->len >> 2) / A10_MMC_FIFO_SIZE; i++){
+ while (!(RD4(sc, A10_MMC_STAS) & A10_MMC_FIFO_EMPTY))
+ continue;
+
+ bus_space_write_multi_4(sc->bst, sc->bsh,
A10_MMC_FIFO, buf, A10_MMC_FIFO_SIZE);
+ buf += A10_MMC_FIFO_SIZE;
+ }
+ }else{
+ for (i = 0; i < (data->len >> 2); i++) {
+ while(RD4(sc, A10_MMC_STAS) & A10_MMC_FIFO_FULL)
+ continue;
+
+ WR4(sc, A10_MMC_FIFO, buf[i]);
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+static int
+a10_mmc_request(device_t bus, device_t child, struct mmc_request *req)
+{
+ struct a10_mmc_softc *sc = device_get_softc(bus);
+ struct mmc_command *cmd = req->cmd;
+ uint32_t cmdreg = A10_MMC_START;
+ uint32_t imask = A10_MMC_CMD_DONE | A10_MMC_INT_ERR_BIT;
+
+// device_printf(sc->dev, "request\n");
+
+ a10_mmc_lock(sc);
+ if (sc->req){
+ a10_mmc_unlock(sc);
+ return (EBUSY);
+ }
+
+ sc->req = req;
+
+ if (cmd->opcode == MMC_GO_IDLE_STATE)
+ cmdreg |= A10_MMC_SEND_INIT_SEQ;
+ if (cmd->flags & MMC_RSP_PRESENT)
+ cmdreg |= A10_MMC_RESP_EXP;
+ if (cmd->flags & MMC_RSP_136)
+ cmdreg |= A10_MMC_LONG_RESP;
+ if (cmd->flags & MMC_RSP_CRC)
+ cmdreg |= A10_MMC_CHECK_RESP_CRC;
+
+ if (cmd->data) {
+
+ if ((cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK ||
+ cmd->opcode == MMC_READ_MULTIPLE_BLOCK))
+ cmdreg |= A10_MMC_SEND_AUTOSTOP;
+
+ cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER;
+ imask |= A10_MMC_DATA_OVER;
+ if (cmd->data->flags & MMC_DATA_WRITE){
+ cmdreg |= A10_MMC_WRITE;
+ imask |= A10_MMC_TX_DATA_REQ;
+ }else{
+ imask |= A10_MMC_RX_DATA_REQ;
+ }
+
+ uint32_t blksz = (cmd->data->len < MMC_SECTOR_SIZE) ? \
+ cmd->data->len : MMC_SECTOR_SIZE;
+
+ WR4(sc, A10_MMC_BLKSZ, blksz);
+ WR4(sc, A10_MMC_BCNTR, cmd->data->len);
+
+ /* Choose access by AHB */
+ WR4(sc, A10_MMC_GCTRL,
+ RD4(sc, A10_MMC_GCTRL)|A10_MMC_ACCESS_BY_AHB);
+ }
+
+ if (cmd->flags & MMC_RSP_BUSY) {
+ imask |= A10_MMC_DATA_TIMEOUT;
+ }
+
+ /* Enable interrupts and set IMASK */
+ WR4(sc, A10_MMC_IMASK, imask);
+ WR4(sc, A10_MMC_GCTRL,
+ RD4(sc, A10_MMC_GCTRL)|A10_MMC_INT_ENABLE);
+
+ WR4(sc, A10_MMC_CARG, cmd->arg);
+ WR4(sc, A10_MMC_CMDR, cmdreg|cmd->opcode);
+
+ 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);
+
+// device_printf(sc->dev, "read ivar\n");
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ *(int *)result = sc->host.ios.bus_mode;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ *(int *)result = sc->host.ios.bus_width;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ *(int *)result = sc->host.ios.chip_select;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ *(int *)result = sc->host.ios.clock;
+ break;
+ case MMCBR_IVAR_F_MIN:
+ *(int *)result = sc->host.f_min;
+ break;
+ case MMCBR_IVAR_F_MAX:
+ *(int *)result = sc->host.f_max;
+ break;
+ case MMCBR_IVAR_HOST_OCR:
+ *(int *)result = sc->host.host_ocr;
+ break;
+ case MMCBR_IVAR_MODE:
+ *(int *)result = sc->host.mode;
+ break;
+ case MMCBR_IVAR_OCR:
+ *(int *)result = sc->host.ocr;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ *(int *)result = sc->host.ios.power_mode;
+ break;
+ case MMCBR_IVAR_VDD:
+ *(int *)result = sc->host.ios.vdd;
+ break;
+ case MMCBR_IVAR_CAPS:
+ *(int *)result = sc->host.caps;
+ break;
+ case MMCBR_IVAR_MAX_DATA:
+ *(int *)result = 16;
+ 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);
+
+// device_printf(sc->dev, "write ivar\n");
+
+ switch (which) {
+ default:
+ return (EINVAL);
+ case MMCBR_IVAR_BUS_MODE:
+ sc->host.ios.bus_mode = value;
+ break;
+ case MMCBR_IVAR_BUS_WIDTH:
+ sc->host.ios.bus_width = value;
+ break;
+ case MMCBR_IVAR_CHIP_SELECT:
+ sc->host.ios.chip_select = value;
+ break;
+ case MMCBR_IVAR_CLOCK:
+ sc->host.ios.clock = value;
+ break;
+ case MMCBR_IVAR_MODE:
+ sc->host.mode = value;
+ break;
+ case MMCBR_IVAR_OCR:
+ sc->host.ocr = value;
+ break;
+ case MMCBR_IVAR_POWER_MODE:
+ sc->host.ios.power_mode = value;
+ break;
+ case MMCBR_IVAR_VDD:
+ sc->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->host.ios;
+ uint32_t clkdiv = 0;
+ uint32_t cmdreg = A10_MMC_START | A10_MMC_UPCLK_ONLY |
A10_MMC_WAIT_PREOVER;
+ uint32_t rval = RD4(sc, A10_MMC_CLKCR);
+
+// device_printf(sc->dev, "update ios\n");
+
+ /* Change clock first */
+ clkdiv = (sc->mod_clk + (ios->clock >> 1))/ios->clock/2;
+
+ if (ios->clock) {
+ /* Disable clock */
+ rval &= ~A10_MMC_CARD_CLK_ON;
+ WR4(sc, A10_MMC_CLKCR, rval);
+
+ WR4(sc, A10_MMC_CMDR, cmdreg);
+ while(RD4(sc, A10_MMC_CMDR) & A10_MMC_START);
+
+ /* Change divider */
+ rval &= ~(0xFF);
+ rval |= clkdiv;
+ WR4(sc, A10_MMC_CLKCR, rval);
+
+ WR4(sc, A10_MMC_CMDR, cmdreg);
+ while(RD4(sc, A10_MMC_CMDR) & A10_MMC_START);
+
+ /* Enable clock */
+ rval |= A10_MMC_CARD_CLK_ON;
+ WR4(sc, A10_MMC_CLKCR, rval);
+
+ WR4(sc, A10_MMC_CMDR, cmdreg);
+ while(RD4(sc, A10_MMC_CMDR) & A10_MMC_START);
+ }
+
+ /* Set the bus width */
+ switch (ios->bus_width) {
+ case bus_width_1:
+ WR4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH1);
+ break;
+ case bus_width_4:
+ WR4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH4);
+ break;
+ case bus_width_8:
+ WR4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH8);
+ break;
+ }
+
+ return (0);
+}
+
+static int
+a10_mmc_get_ro(device_t bus, device_t child)
+{
+// struct a10_mmc_softc *sc = device_get_softc(bus);
+// device_printf(sc->dev, "get ro\n");
+ 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;
+
+// device_printf(sc->dev, "aquire host\n");
+
+ a10_mmc_lock(sc);
+ while (sc->bus_busy)
+ error = mtx_sleep(sc, &sc->mtx, PZERO, "mmcah", 0);
+
+ sc->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);
+
+// device_printf(sc->dev, "release host\n");
+
+ a10_mmc_lock(sc);
+ sc->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 = {
+ "a10_mmc",
+ a10_mmc_methods,
+ sizeof(struct a10_mmc_softc),
+};
+
+DRIVER_MODULE(a10_mmc, simplebus, a10_mmc_driver, a10_mmc_devclass, 0, 0);
+
Property changes on: sys/arm/allwinner/a10_mmc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
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,181 @@
+/*-
+ * Copyright (c) 2013 Alexander Fedorov <alexander.fedorov at 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 A10_MMC_GCTRL 0x00 /* Global
Control Register */
+#define A10_MMC_CLKCR 0x04 /* Clock Control
Register */
+#define A10_MMC_TMOUT 0x08 /* Time Out Register */
+#define A10_MMC_WIDTH 0x0C /* Bus Width Register */
+#define A10_MMC_BLKSZ 0x10 /* Block Size Register */
+#define A10_MMC_BCNTR 0x14 /* Byte Count Register */
+#define A10_MMC_CMDR 0x18 /* Command Register */
+#define A10_MMC_CARG 0x1C /* Argument Register */
+#define A10_MMC_RESP0 0x20 /* Response Register 0 */
+#define A10_MMC_RESP1 0x24 /* Response Register 1 */
+#define A10_MMC_RESP2 0x28 /* Response Register 2 */
+#define A10_MMC_RESP3 0x2C /* Response Register 3 */
+#define A10_MMC_IMASK 0x30 /* Interrupt
Mask Register */
+#define A10_MMC_MISTA 0x34 /* Masked
Interrupt Status Register */
+#define A10_MMC_RINTR 0x38 /* Raw Interrupt
Status Register */
+#define A10_MMC_STAS 0x3C /* Status Register */
+#define A10_MMC_FTRGL 0x40 /* FIFO
Threshold Watermark Register */
+#define A10_MMC_FUNS 0x44 /* Function
Select Register */
+#define A10_MMC_CBCR 0x48 /* CIU Byte
Count Register */
+#define A10_MMC_BBCR 0x4C /* BIU Byte
Count Register */
+#define A10_MMC_DBGC 0x50 /* Debug Enable
Register */
+#define A10_MMC_DMAC 0x80 /* IDMAC Control
Register */
+#define A10_MMC_DLBA 0x84 /* IDMAC
Descriptor List Base Address Register */
+#define A10_MMC_IDST 0x88 /* IDMAC Status
Register */
+#define A10_MMC_IDIE 0x8C /* IDMAC
Interrupt Enable Register */
+#define A10_MMC_CHDA 0x90
+#define A10_MMC_CBDA 0x94
+#define A10_MMC_FIFO 0x100 /* FIFO Access Address */
+
+/* A10_MMC_GCTRL */
+#define A10_MMC_SOFT_RESET (1 << 0)
+#define A10_MMC_FIFO_RESET (1 << 1)
+#define A10_MMC_DMA_RESET (1 << 2)
+#define A10_MMC_INT_ENABLE (1 << 4)
+#define A10_MMC_DMA_ENABLE (1 << 5)
+#define A10_MMC_DEBOUNCE_ENABLE (1 << 8)
+#define A10_MMC_POSEDGE_LATCH_DATA (1 << 9)
+#define A10_MMC_NEGEDGE_LATCH_DATA (0 << 9)
+#define A10_MMC_DDR_MODE (1 << 10)
+#define A10_MMC_ACCESS_BY_AHB (1 << 31)
+#define A10_MMC_ACCESS_BY_DMA (0 << 31)
+
+/* A10_MMC_CLKCR */
+#define A10_MMC_CARD_CLK_ON (1 << 16)
+#define A10_MMC_LOW_POWER_ON (1 << 17)
+
+/* A10_MMC_WIDTH */
+#define A10_MMC_WIDTH1 (0)
+#define A10_MMC_WIDTH4 (1)
+#define A10_MMC_WIDTH8 (2)
+
+/* A10_MMC_CMDR */
+#define A10_MMC_RESP_EXP (1 << 6)
+#define A10_MMC_LONG_RESP (1 << 7)
+#define A10_MMC_CHECK_RESP_CRC (1 << 8)
+#define A10_MMC_DATA_EXP (1 << 9)
+#define A10_MMC_READ (0 << 10)
+#define A10_MMC_WRITE (1 << 10)
+#define A10_MMC_BLOCK_MODE (0 << 11)
+#define A10_MMC_SEQ_MODE (1 << 11)
+#define A10_MMC_SEND_AUTOSTOP (1 << 12)
+#define A10_MMC_WAIT_PREOVER (1 << 13)
+#define A10_MMC_STOP_ABORT_CMD (1 << 14)
+#define A10_MMC_SEND_INIT_SEQ (1 << 15)
+#define A10_MMC_UPCLK_ONLY (1 << 21)
+#define A10_MMC_RDCEATADEV (1 << 22)
+#define A10_MMC_CCS_EXP (1 << 23)
+#define A10_MMC_ENB_BOOT (1 << 24)
+#define A10_MMC_ALT_BOOT_OPT (1 << 25)
+#define A10_MMC_MAND_BOOT_OPT (0 << 25)
+#define A10_MMC_BOOT_ACK_EXP (1 << 26)
+#define A10_MMC_DISABLE_BOOT (1 << 27)
+#define A10_MMC_VOL_SWITCH (1 << 28)
+#define A10_MMC_START (1 << 31)
+
+/* A10_MMC_IMASK and A10_MMC_RINTR */
+#define A10_MMC_RESP_ERR (1 << 1)
+#define A10_MMC_CMD_DONE (1 << 2)
+#define A10_MMC_DATA_OVER (1 << 3)
+#define A10_MMC_TX_DATA_REQ (1 << 4)
+#define A10_MMC_RX_DATA_REQ (1 << 5)
+#define A10_MMC_RESP_CRC_ERR (1 << 6)
+#define A10_MMC_DATA_CRC_ERR (1 << 7)
+#define A10_MMC_RESP_TIMEOUT (1 << 8)
+#define A10_MMC_ACK_RECV (1 << 8)
+#define A10_MMC_DATA_TIMEOUT (1 << 9)
+#define A10_MMC_BOOT_START (1 << 9)
+#define A10_MMC_DATA_STARVE (1 << 10)
+#define A10_MMC_VOL_CHG_DONE (1 << 10)
+#define A10_MMC_FIFO_RUN_ERR (1 << 11)
+#define A10_MMC_HARDW_LOCKED (1 << 12)
+#define A10_MMC_START_BIT_ERR (1 << 13)
+#define A10_MMC_AUTOCMD_DONE (1 << 14)
+#define A10_MMC_END_BIT_ERR (1 << 15)
+#define A10_MMC_SDIO_INT (1 << 16)
+#define A10_MMC_CARD_INSERT (1 << 30)
+#define A10_MMC_CARD_REMOVE (1 << 31)
+#define A10_MMC_INT_ERR_BIT (A10_MMC_RESP_ERR |
A10_MMC_RESP_CRC_ERR | A10_MMC_DATA_CRC_ERR | A10_MMC_RESP_TIMEOUT |
A10_MMC_DATA_TIMEOUT \
+ | A10_MMC_FIFO_RUN_ERR |
A10_MMC_HARDW_LOCKED | A10_MMC_START_BIT_ERR | A10_MMC_END_BIT_ERR)
+/* A10_MMC_STAS */
+#define A10_MMC_RX_WLFLAG (1 << 0)
+#define A10_MMC_TX_WLFLAG (1 << 1)
+#define A10_MMC_FIFO_EMPTY (1 << 2)
+#define A10_MMC_FIFO_FULL (1 << 3)
+#define A10_MMC_CARD_PRESENT (1 << 8)
+#define A10_MMC_CARD_DATA_BUSY (1 << 9)
+#define A10_MMC_DATA_FSM_BUSY (1 << 10)
+#define A10_MMC_DMA_REQ (1 << 31)
+#define A10_MMC_FIFO_SIZE (16)
+
+/* A10_MMC_FUNS */
+#define A10_MMC_CE_ATA_ON (0XCEAAU<< 16)
+#define A10_MMC_SEND_IRQ_RESP (1 << 0)
+#define A10_MMC_SDIO_RD_WAIT (1 << 1)
+#define A10_MMC_ABT_RD_DATA (1 << 2)
+#define A10_MMC_SEND_CC_SD (1 << 8)
+#define A10_MMC_SEND_AUTOSTOP_CC_SD (1 << 9)
+#define A10_MMC_CE_ATA_DEV_INT_ENB (1 << 10)
+
+/* IDMA CONTROLLER BUS MOD BIT FIELD */
+#define A10_MMC_IDMAC_SOFT_RST (1 << 0)
+#define A10_MMC_IDMAC_FIX_BURST (1 << 1)
+#define A10_MMC_IDMAC_IDMA_ON (1 << 7)
+#define A10_MMC_IDMAC_REFETCH_DES (1 << 31)
+
+/* A10_MMC_IDST */
+#define A10_MMC_IDMAC_TRANSMIT_INT (1 << 0)
+#define A10_MMC_IDMAC_RECEIVE_INT (1 << 1)
+#define A10_MMC_IDMAC_FATAL_BUS_ERR (1 << 2)
+#define A10_MMC_IDMAC_DES_INVALID (1 << 4)
+#define A10_MMC_IDMAC_CARD_ERR_SUM (1 << 5)
+#define A10_MMC_IDMAC_NORMAL_INT_SUM (1 << 8)
+#define A10_MMC_IDMAC_ABNORMAL_INT_SUM (1 << 9)
+#define A10_MMC_IDMAC_HOST_ABT_INTX (1 << 10)
+#define A10_MMC_IDMAC_HOST_ABT_INRX (1 << 10)
+#define A10_MMC_IDMAC_IDLE (0 << 13)
+#define A10_MMC_IDMAC_SUSPEND (1 << 13)
+#define A10_MMC_IDMAC_DESC_RD (0X2U<< 13)
+#define A10_MMC_IDMAC_DESC_CHECK (0X3U<< 13)
+#define A10_MMC_IDMAC_RD_REQ_WAIT (0X4U<< 13)
+#define A10_MMC_IDMAC_WR_REQ_WAIT (0X5U<< 13)
+#define A10_MMC_IDMAC_RD (0X6U<< 13)
+#define A10_MMC_IDMAC_WR (0X7U<< 13)
+#define A10_MMC_IDMAC_DESC_CLOSE (0X8U<< 13)
+
+#define A10_MMC_IDMA_OVER
(A10_MMC_IDMAC_TRANSMIT_INT|A10_MMC_IDMAC_RECEIVE_INT|A10_MMC_IDMAC_NORMAL_INT_SUM)
+#define A10_MMC_IDMA_ERR
(A10_MMC_IDMAC_FATAL_BUS_ERR|A10_MMC_IDMAC_DES_INVALID|A10_MMC_IDMAC_CARD_ERR_SUM|A10_MMC_IDMAC_ABNORMAL_INT_SUM)
+
+#endif /* _A10_MMC_H_ */
+
+
Property changes on: sys/arm/allwinner/a10_mmc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: sys/arm/allwinner/files.a10
===================================================================
--- sys/arm/allwinner/files.a10 (revision 281599)
+++ sys/arm/allwinner/files.a10 (working copy)
@@ -8,6 +8,7 @@
arm/allwinner/a10_common.c standard
arm/allwinner/a10_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
Index: sys/arm/conf/CUBIEBOARD
===================================================================
--- sys/arm/conf/CUBIEBOARD (revision 281599)
+++ sys/arm/conf/CUBIEBOARD (working copy)
@@ -80,11 +80,11 @@
#options BOOTP_WIRED_TO=cpsw0
# Boot device is 2nd slice on MMC/SD card
-options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s2\"
# MMC/SD/SDIO Card slot support
-#device mmc # mmc/sd bus
-#device mmcsd # mmc/sd flash cards
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
# ATA controllers
#device ahci # AHCI-compatible SATA controllers
Index: sys/boot/fdt/dts/arm/cubieboard.dts
===================================================================
--- sys/boot/fdt/dts/arm/cubieboard.dts (revision 281599)
+++ sys/boot/fdt/dts/arm/cubieboard.dts (working copy)
@@ -60,6 +60,10 @@
emac at 01c0b000 {
status = "okay";
};
+
+ mmc0: mmc at 01c0f000 {
+ status = "okay";
+ };
};
chosen {
Index: sys/boot/fdt/dts/arm/sun4i-a10.dtsi
===================================================================
--- sys/boot/fdt/dts/arm/sun4i-a10.dtsi (revision 281599)
+++ sys/boot/fdt/dts/arm/sun4i-a10.dtsi (working copy)
@@ -103,6 +103,13 @@
interrupt-parent = <&AINTC>;
};
+ mmc0: mmc at 01c0f000 {
+ compatible = "allwinner,sun4i-mmc";
+ reg = <0x01c0f000 0x1000>;
+ interrupts = <32>;
+ interrupt-parent = <&AINTC>;
+ };
+
sata at 01c18000 {
compatible = "allwinner,sun4i-ahci";
reg = <0x01c18000 0x1000>;
Index: sys/dev/mmc/mmc.c
===================================================================
--- sys/dev/mmc/mmc.c (revision 281599)
+++ sys/dev/mmc/mmc.c (working copy)
@@ -1800,6 +1800,7 @@
DRIVER_MODULE(mmc, aml8726_mmc, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, aml8726_sdxc, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
+DRIVER_MODULE(mmc, a10_mmc, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci_bcm, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci_fdt, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL);
2015-04-14 13:55 GMT+03:00 Bas Vermin <bas at nimrev.com>:
> Thanks a lot!
>
> If you need some help testing patches during your GSoC, just let me know. I have quite a few Allwinner devices lying around.
>
>
>> 在 2015年4月13日,21:33,Pratik Singhal <ps06756 at gmail.com> 写道:
>>
>> Hello Bas,
>>
>> My GSOC mentor (Louiz) made some changes in the Alexander's patch. I added a function in the file a10_clk.c
>>
>> I'll send you the patch set which I used.
>>
>> Regards,
>> Pratik Singhal
>>
>> On Mon, Apr 13, 2015 at 11:40 PM, Bas Vermin <bas at nimrev.com> wrote:
>> Hi Pratik,
>>
>> Did you make any changes to Alexander’s patch? I remember testing it last year without much success.
>>
>> Have you considered porting the NetBSD Allwinner code to FreeBSD?
>>
>> Right now it has the best support for Allwinner devices. I started to port some of the NetBSD code a few months ago, but didn’t have enough spare time.
>>
>> Bas
>>
>> _______________________________________________
>> freebsd-arm at freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-arm
>> To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"
>>
>>
>>
>> --
>> Regards,
>> Pratik Singhal
>
> _______________________________________________
> freebsd-arm at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arm
> To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"
More information about the freebsd-arm
mailing list