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/c40bd899b25b
branches:  trunk
changeset: 826546:c40bd899b25b
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 59fbd86b126c -r c40bd899b25b 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 59fbd86b126c -r c40bd899b25b 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