Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sunxi Add support for sun50i new timing mode an...
details: https://anonhg.NetBSD.org/src/rev/37e044eff6ab
branches: trunk
changeset: 356245:37e044eff6ab
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Sep 11 22:00:05 2017 +0000
description:
Add support for sun50i new timing mode and calibration.
diffstat:
sys/arch/arm/sunxi/sunxi_mmc.c | 97 ++++++++++++++++++++++++++++++++---------
sys/arch/arm/sunxi/sunxi_mmc.h | 5 +-
2 files changed, 80 insertions(+), 22 deletions(-)
diffs (257 lines):
diff -r 66269967f0d4 -r 37e044eff6ab sys/arch/arm/sunxi/sunxi_mmc.c
--- a/sys/arch/arm/sunxi/sunxi_mmc.c Mon Sep 11 20:44:14 2017 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mmc.c Mon Sep 11 22:00:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_mmc.c,v 1.6 2017/09/07 01:07:04 jmcneill Exp $ */
+/* $NetBSD: sunxi_mmc.c,v 1.7 2017/09/11 22:00:05 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.6 2017/09/07 01:07:04 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.7 2017/09/11 22:00:05 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -67,8 +67,6 @@
};
#define SUNXI_MMC_NDESC 16
-#define SUNXI_MMC_DMA_XFERLEN 0x10000
-#define SUNXI_MMC_DMA_FTRGLEVEL 0x20070008
struct sunxi_mmc_softc;
@@ -110,6 +108,16 @@
.card_intr_ack = sunxi_mmc_card_intr_ack,
};
+struct sunxi_mmc_config {
+ u_int idma_xferlen;
+ u_int flags;
+#define SUNXI_MMC_FLAG_CALIB_REG 0x01
+#define SUNXI_MMC_FLAG_NEW_TIMINGS 0x02
+#define SUNXI_MMC_FLAG_MASK_DATA0 0x04
+ const struct sunxi_mmc_delay *delays;
+ uint32_t dma_ftrglevel;
+};
+
struct sunxi_mmc_softc {
device_t sc_dev;
bus_space_tag_t sc_bst;
@@ -127,9 +135,8 @@
device_t sc_sdmmc_dev;
- uint32_t sc_dma_ftrglevel;
+ struct sunxi_mmc_config *sc_config;
- uint32_t sc_idma_xferlen;
bus_dma_segment_t sc_idma_segs[1];
int sc_idma_nsegs;
bus_size_t sc_idma_size;
@@ -164,11 +171,34 @@
#define MMC_READ(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
-static const char * const compatible[] = {
- "allwinner,sun5i-a13-mmc",
- "allwinner,sun7i-a20-mmc",
- "allwinner,sun50i-a64-mmc",
- NULL
+static const struct sunxi_mmc_config sun5i_a13_mmc_config = {
+ .idma_xferlen = 0x10000,
+ .dma_ftrglevel = 0x20070008,
+ .delays = NULL,
+ .flags = 0,
+};
+
+static const struct sunxi_mmc_config sun7i_a20_mmc_config = {
+ .idma_xferlen = 0x10000,
+ .dma_ftrglevel = 0x20070008,
+ .delays = sunxi_mmc_delays,
+ .flags = 0,
+};
+
+static const struct sunxi_mmc_config sun50i_a64_mmc_config = {
+ .idma_xferlen = 0x10000,
+ .dma_ftrglevel = 0x20070008,
+ .delays = NULL,
+ .flags = SUNXI_MMC_FLAG_CALIB_REG |
+ SUNXI_MMC_FLAG_NEW_TIMINGS |
+ SUNXI_MMC_FLAG_MASK_DATA0,
+};
+
+static const struct of_compat_data compat_data[] = {
+ { "allwinner,sun5i-a13-mmc", (uintptr_t)&sun5i_a13_mmc_config },
+ { "allwinner,sun7i-a20-mmc", (uintptr_t)&sun7i_a20_mmc_config },
+ { "allwinner,sun50i-a64-mmc", (uintptr_t)&sun50i_a64_mmc_config },
+ { NULL }
};
static int
@@ -176,7 +206,7 @@
{
struct fdt_attach_args * const faa = aux;
- return of_match_compatible(faa->faa_phandle, compatible);
+ return of_match_compat_data(faa->faa_phandle, compat_data);
}
static void
@@ -228,6 +258,7 @@
sc->sc_dev = self;
sc->sc_phandle = phandle;
+ sc->sc_config = (void *)of_search_compatible(phandle, compat_data)->data;
sc->sc_bst = faa->faa_bst;
sc->sc_dmat = faa->faa_dmat;
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
@@ -250,8 +281,6 @@
sc->sc_gpio_cd_inverted = of_hasprop(phandle, "cd-inverted") ? 0 : 1;
sc->sc_gpio_wp_inverted = of_hasprop(phandle, "wp-inverted") ? 0 : 1;
- sc->sc_dma_ftrglevel = SUNXI_MMC_DMA_FTRGLEVEL;
-
if (sunxi_mmc_idma_setup(sc) != 0) {
aprint_error_dev(self, "failed to setup DMA\n");
return;
@@ -279,8 +308,6 @@
{
int error;
- sc->sc_idma_xferlen = SUNXI_MMC_DMA_XFERLEN;
-
sc->sc_idma_ndesc = SUNXI_MMC_NDESC;
sc->sc_idma_size = sizeof(struct sunxi_mmc_idma_descriptor) *
sc->sc_idma_ndesc;
@@ -334,12 +361,15 @@
} else
return EINVAL;
- delays = &sunxi_mmc_delays[timing];
-
error = clk_set_rate(sc->sc_clk_mmc, (freq * 1000) << ddr);
if (error != 0)
return error;
+ if (sc->sc_config->delays == NULL)
+ return 0;
+
+ delays = &sc->sc_config->delays[timing];
+
if (sc->sc_clk_sample) {
error = clk_set_rate(sc->sc_clk_sample, delays->sample_phase);
if (error != 0)
@@ -601,14 +631,22 @@
sunxi_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, bool ddr)
{
struct sunxi_mmc_softc *sc = sch;
- uint32_t clkcr, gctrl;
+ uint32_t clkcr, gctrl, ntsr;
+ const u_int flags = sc->sc_config->flags;
clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR);
if (clkcr & SUNXI_MMC_CLKCR_CARDCLKON) {
clkcr &= ~SUNXI_MMC_CLKCR_CARDCLKON;
+ if (flags & SUNXI_MMC_CLKCR_MASK_DATA0)
+ clkcr |= SUNXI_MMC_CLKCR_MASK_DATA0;
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
if (sunxi_mmc_update_clock(sc) != 0)
return 1;
+ if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) {
+ clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR);
+ clkcr &= ~SUNXI_MMC_CLKCR_MASK_DATA0;
+ MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
+ }
}
if (freq) {
@@ -616,6 +654,16 @@
clkcr &= ~SUNXI_MMC_CLKCR_DIV;
clkcr |= __SHIFTIN(ddr, SUNXI_MMC_CLKCR_DIV);
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
+
+ if (flags & SUNXI_MMC_FLAG_NEW_TIMINGS) {
+ ntsr = MMC_READ(sc, SUNXI_MMC_NTSR);
+ ntsr |= SUNXI_MMC_NTSR_MODE_SELECT;
+ MMC_WRITE(sc, SUNXI_MMC_NTSR, ntsr);
+ }
+
+ if (flags & SUNXI_MMC_FLAG_CALIB_REG)
+ MMC_WRITE(sc, SUNXI_MMC_SAMP_DL, SUNXI_MMC_SAMP_DL_SW_EN);
+
if (sunxi_mmc_update_clock(sc) != 0)
return 1;
@@ -630,9 +678,16 @@
return 1;
clkcr |= SUNXI_MMC_CLKCR_CARDCLKON;
+ if (flags & SUNXI_MMC_CLKCR_MASK_DATA0)
+ clkcr |= SUNXI_MMC_CLKCR_MASK_DATA0;
MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
if (sunxi_mmc_update_clock(sc) != 0)
return 1;
+ if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) {
+ clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR);
+ clkcr &= ~SUNXI_MMC_CLKCR_MASK_DATA0;
+ MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr);
+ }
}
return 0;
@@ -718,7 +773,7 @@
while (resid > 0) {
if (desc == sc->sc_idma_ndesc)
break;
- len = min(sc->sc_idma_xferlen, resid);
+ len = min(sc->sc_config->idma_xferlen, resid);
dma[desc].dma_buf_size = htole32(len);
dma[desc].dma_buf_addr = htole32(paddr + off);
dma[desc].dma_config = htole32(SUNXI_MMC_IDMA_CONFIG_CH |
@@ -772,7 +827,7 @@
val |= SUNXI_MMC_IDST_TRANSMIT_INT;
MMC_WRITE(sc, SUNXI_MMC_IDIE, val);
MMC_WRITE(sc, SUNXI_MMC_DLBA, desc_paddr);
- MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
+ MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_config->dma_ftrglevel);
return 0;
}
diff -r 66269967f0d4 -r 37e044eff6ab sys/arch/arm/sunxi/sunxi_mmc.h
--- a/sys/arch/arm/sunxi/sunxi_mmc.h Mon Sep 11 20:44:14 2017 +0000
+++ b/sys/arch/arm/sunxi/sunxi_mmc.h Mon Sep 11 22:00:05 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_mmc.h,v 1.2 2017/07/17 23:31:05 jmcneill Exp $ */
+/* $NetBSD: sunxi_mmc.h,v 1.3 2017/09/11 22:00:05 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -59,6 +59,7 @@
#define SUNXI_MMC_IDIE 0x008C
#define SUNXI_MMC_CHDA 0x0090
#define SUNXI_MMC_CBDA 0x0094
+#define SUNXI_MMC_SAMP_DL 0x0144
#define SUNXI_MMC_GCTRL_ACCESS_BY_AHB __BIT(31)
#define SUNXI_MMC_GCTRL_WAIT_MEM_ACCESS_DONE __BIT(30)
@@ -72,6 +73,7 @@
#define SUNXI_MMC_GCTRL_RESET \
(SUNXI_MMC_GCTRL_SOFTRESET | SUNXI_MMC_GCTRL_FIFORESET | \
SUNXI_MMC_GCTRL_DMARESET)
+#define SUNXI_MMC_CLKCR_MASK_DATA0 __BIT(31)
#define SUNXI_MMC_CLKCR_LOWPOWERON __BIT(17)
#define SUNXI_MMC_CLKCR_CARDCLKON __BIT(16)
#define SUNXI_MMC_CLKCR_DIV __BITS(7,0)
@@ -165,6 +167,7 @@
#define SUNXI_MMC_IDMA_CONFIG_ER __BIT(5)
#define SUNXI_MMC_IDMA_CONFIG_CES __BIT(30)
#define SUNXI_MMC_IDMA_CONFIG_OWN __BIT(31)
+#define SUNXI_MMC_SAMP_DL_SW_EN __BIT(7)
struct sunxi_mmc_idma_descriptor {
uint32_t dma_config;
Home |
Main Index |
Thread Index |
Old Index