summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2016-08-20 19:41:15 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2016-08-20 19:41:15 +0000
commita03090c0f2121dd66ca984219394f1cd568de347 (patch)
treebbc63b28d2404d4bdeb2691b753497256b55b7a2 /sys
parent612a46d69f6570b5b12f011890bb9e8323a5fc08 (diff)
Various improvements to make this work better.
Restrict the block size to 512 bytes for now. While Linux and NetBSD seem to allow larger block sizes (4096 and 8192 bytes) I'm getting errors wth an older 2G Sandisk SD card that advertises support for 1024 byte blocks. Implement switching between the 400 KHz "discovery" clock and the 25 MHz "operational" clock. Enable the right clock based on the SD/MMC "unit" number. Don't advertise highspeed capabilities for now as I'm not sure how the adjust the clock timing in that case. Fix the way we calculate the number of blocks and the size of the total data transfer to matc what we do in sdhc(4).
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/armv7/sunxi/sximmc.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/arch/armv7/sunxi/sximmc.c b/sys/arch/armv7/sunxi/sximmc.c
index fde1d8362a2..38276a0b069 100644
--- a/sys/arch/armv7/sunxi/sximmc.c
+++ b/sys/arch/armv7/sunxi/sximmc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sximmc.c,v 1.1 2016/08/15 21:03:27 kettenis Exp $ */
+/* $OpenBSD: sximmc.c,v 1.2 2016/08/20 19:41:14 kettenis Exp $ */
/* $NetBSD: awin_mmc.c,v 1.23 2015/11/14 10:32:40 bouyer Exp $ */
/*-
@@ -40,6 +40,7 @@
#include <dev/sdmmc/sdmmcchip.h>
#include <dev/sdmmc/sdmmc_ioreg.h>
+#include <armv7/sunxi/sunxireg.h>
#include <armv7/sunxi/sxiccmuvar.h>
#include <dev/ofw/openfirm.h>
@@ -47,6 +48,8 @@
#include <dev/ofw/ofw_pinctrl.h>
#include <dev/ofw/fdt.h>
+//#define SXIMMC_DEBUG
+
#define SXIMMC_GCTRL 0x0000
#define SXIMMC_CLKCR 0x0004
#define SXIMMC_TIMEOUT 0x0008
@@ -234,6 +237,7 @@ struct sximmc_softc {
bus_space_handle_t sc_clk_bsh;
bus_dma_tag_t sc_dmat;
int sc_node;
+ int sc_unit;
int sc_use_dma;
@@ -344,6 +348,7 @@ sximmc_attach(struct device *parent, struct device *self, void *aux)
return;
sc->sc_node = faa->fa_node;
+ sc->sc_unit = (faa->fa_reg[0].addr - SDMMC0_ADDR) / SDMMCx_SIZE;
sc->sc_bst = faa->fa_iot;
sc->sc_dmat = faa->fa_dmat;
@@ -355,12 +360,12 @@ sximmc_attach(struct device *parent, struct device *self, void *aux)
sc->sc_use_dma = 1;
- printf("\n");
+ printf(": unit %d\n", sc->sc_unit);
pinctrl_byname(faa->fa_node, "default");
/* enable clock */
- sxiccmu_enablemodule(CCMU_SDMMC0);
+ sxiccmu_enablemodule(CCMU_SDMMC0 + sc->sc_unit);
delay(5000);
#if 0
@@ -447,7 +452,9 @@ sximmc_attach(struct device *parent, struct device *self, void *aux)
saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
#endif
+#if 0
saa.caps = SMC_CAPS_SD_HIGHSPEED | SMC_CAPS_MMC_HIGHSPEED;
+#endif
width = OF_getpropint(sc->sc_node, "bus-width", 1);
if (width >= 8)
@@ -524,6 +531,8 @@ sximmc_set_clock(struct sximmc_softc *sc, u_int freq)
delay(20000);
#endif
+ sxiccmu_set_sd_clock(CCMU_SDMMC0 + sc->sc_unit, freq * 1000);
+ delay(20000);
return 0;
}
@@ -653,7 +662,11 @@ sximmc_host_ocr(sdmmc_chipset_handle_t sch)
int
sximmc_host_maxblklen(sdmmc_chipset_handle_t sch)
{
+#if 0
return 8192;
+#else
+ return 512;
+#endif
}
int
@@ -922,23 +935,22 @@ sximmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
cmdval |= SXIMMC_CMD_CHECK_RSP_CRC;
if (cmd->c_datalen > 0) {
- unsigned int nblks;
+ uint16_t blksize;
+ uint16_t blkcount;
cmdval |= SXIMMC_CMD_DATA_EXP | SXIMMC_CMD_WAIT_PRE_OVER;
if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
cmdval |= SXIMMC_CMD_WRITE;
}
- nblks = cmd->c_datalen / cmd->c_blklen;
- if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
- ++nblks;
-
- if (nblks > 1) {
+ blksize = MIN(cmd->c_datalen, cmd->c_blklen);
+ blkcount = cmd->c_datalen / blksize;
+ if (blkcount > 1) {
cmdval |= SXIMMC_CMD_SEND_AUTO_STOP;
}
- MMC_WRITE(sc, SXIMMC_BLKSZ, cmd->c_blklen);
- MMC_WRITE(sc, SXIMMC_BYTECNT, nblks * cmd->c_blklen);
+ MMC_WRITE(sc, SXIMMC_BLKSZ, blksize);
+ MMC_WRITE(sc, SXIMMC_BYTECNT, blkcount * blksize);
}
sc->sc_intr_rint = 0;