Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch A80 MMC support. Works for SD card slot on Cubie4, ...



details:   https://anonhg.NetBSD.org/src/rev/282612fde3c2
branches:  trunk
changeset: 334754:282612fde3c2
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Dec 05 14:36:44 2014 +0000

description:
A80 MMC support. Works for SD card slot on Cubie4, but not eMMC yet.

diffstat:

 sys/arch/arm/allwinner/awin_board.c |   32 ++++++-
 sys/arch/arm/allwinner/awin_io.c    |   20 +++-
 sys/arch/arm/allwinner/awin_mmc.c   |  155 +++++++++++++++++++++++++++++------
 sys/arch/arm/allwinner/awin_reg.h   |   77 ++++++++++++++++-
 sys/arch/arm/allwinner/awin_var.h   |    3 +-
 sys/arch/evbarm/conf/ALLWINNER_A80  |   12 +-
 6 files changed, 251 insertions(+), 48 deletions(-)

diffs (truncated from 566 to 300 lines):

diff -r f17aa29833d4 -r 282612fde3c2 sys/arch/arm/allwinner/awin_board.c
--- a/sys/arch/arm/allwinner/awin_board.c       Fri Dec 05 11:53:43 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_board.c       Fri Dec 05 14:36:44 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: awin_board.c,v 1.30 2014/12/05 01:13:11 jmcneill Exp $ */
+/*     $NetBSD: awin_board.c,v 1.31 2014/12/05 14:36:44 jmcneill Exp $ */
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_board.c,v 1.30 2014/12/05 01:13:11 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_board.c,v 1.31 2014/12/05 14:36:44 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -128,8 +128,8 @@
 #if defined(ALLWINNER_A80)
        const uint32_t c0cpux = bus_space_read_4(&awin_bs_tag, awin_core_bsh,
            AWIN_A80_CCU_OFFSET + AWIN_A80_CCU_PLL_C0CPUX_CTRL_REG);
-       const u_int p = (c0cpux & AWIN_A80_CCU_PLL_OUT_EXT_DIVP) ? 4 : 1;
-       const u_int n = __SHIFTOUT(c0cpux, AWIN_A80_CCU_PLL_FACTOR_N);
+       const u_int p = (c0cpux & AWIN_A80_CCU_PLL_CxCPUX_OUT_EXT_DIVP) ? 4 : 1;
+       const u_int n = __SHIFTOUT(c0cpux, AWIN_A80_CCU_PLL_CxCPUX_FACTOR_N);
 
        ci->ci_data.cpu_cc_freq = ((uint64_t)AWIN_REF_FREQ * n) / p;
 #else
@@ -333,6 +333,8 @@
        bus_space_tag_t bst = &awin_bs_tag;
        bus_space_handle_t bsh = awin_core_bsh;
 
+       KASSERT(awin_chip_id() != AWIN_CHIP_ID_A80);
+
        /*
         * SATA needs PLL6 to be a 100MHz clock.
         */
@@ -549,6 +551,7 @@
        unsigned int n, k, p;
 
        KASSERT(awin_chip_id() != AWIN_CHIP_ID_A31);
+       KASSERT(awin_chip_id() != AWIN_CHIP_ID_A80);
 
        const uint32_t cfg = bus_space_read_4(bst, bsh,
            AWIN_CCM_OFFSET + AWIN_PLL5_CFG_REG);
@@ -567,6 +570,8 @@
        bus_space_handle_t bsh = awin_core_bsh;
        unsigned int n, k, m;
 
+       KASSERT(awin_chip_id() != AWIN_CHIP_ID_A80);
+
        const uint32_t cfg = bus_space_read_4(bst, bsh,
            AWIN_CCM_OFFSET + AWIN_PLL6_CFG_REG);
 
@@ -582,3 +587,22 @@
 
        return (AWIN_REF_FREQ * n * k) / m;
 }
+
+uint32_t
+awin_periph0_get_rate(void)
+{
+       bus_space_tag_t bst = &awin_bs_tag;
+       bus_space_handle_t bsh = awin_core_bsh;
+       unsigned int n, idiv, odiv;
+
+       KASSERT(awin_chip_id() == AWIN_CHIP_ID_A80);
+
+       const uint32_t cfg = bus_space_read_4(bst, bsh,
+           AWIN_A80_CCU_OFFSET + AWIN_A80_CCU_PLL_PERIPH0_CTRL_REG);
+
+       n = __SHIFTOUT(cfg, AWIN_A80_CCU_PLL_PERIPH0_FACTOR_N);
+       idiv = __SHIFTOUT(cfg, AWIN_A80_CCU_PLL_PERIPH0_INPUT_DIV) + 1;
+       odiv = __SHIFTOUT(cfg, AWIN_A80_CCU_PLL_PERIPH0_OUTPUT_DIV) + 1;
+
+       return ((AWIN_REF_FREQ * n) / idiv) / odiv;
+}
diff -r f17aa29833d4 -r 282612fde3c2 sys/arch/arm/allwinner/awin_io.c
--- a/sys/arch/arm/allwinner/awin_io.c  Fri Dec 05 11:53:43 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_io.c  Fri Dec 05 14:36:44 2014 +0000
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_io.c,v 1.31 2014/12/05 11:53:43 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_io.c,v 1.32 2014/12/05 14:36:44 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -204,11 +204,23 @@
        sc->sc_dmat = &awin_dma_tag;
        sc->sc_coherent_dmat = &awin_coherent_dma_tag;
 
-       bus_space_subregion(sc->sc_bst, sc->sc_bsh, AWIN_CCM_OFFSET, 0x1000,
-           &sc->sc_ccm_bsh);
+       switch (awin_chip_id()) {
+       case AWIN_CHIP_ID_A80:
+               bus_space_subregion(sc->sc_bst, sc->sc_bsh,
+                   AWIN_A80_CCU_SCLK_OFFSET, 0x1000, &sc->sc_ccm_bsh);
+               break;
+       default:
+               bus_space_subregion(sc->sc_bst, sc->sc_bsh, AWIN_CCM_OFFSET,
+                   0x1000, &sc->sc_ccm_bsh);
+               break;
+       }
 
        aprint_naive("\n");
-       aprint_normal(": %s (0x%04x)\n", chip_name, chip_id);
+       aprint_normal(": %s", chip_name);
+       if ((chip_id & 0xff00) != 0xff00) {
+               aprint_normal(" (0x%04x)\n", chip_id);
+       }
+       aprint_normal("\n");
 
        const struct awin_locators * const eloc =
            awin_locators + __arraycount(awin_locators);
diff -r f17aa29833d4 -r 282612fde3c2 sys/arch/arm/allwinner/awin_mmc.c
--- a/sys/arch/arm/allwinner/awin_mmc.c Fri Dec 05 11:53:43 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_mmc.c Fri Dec 05 14:36:44 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_mmc.c,v 1.16 2014/12/04 03:03:44 jmcneill Exp $ */
+/* $NetBSD: awin_mmc.c,v 1.17 2014/12/05 14:36:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.16 2014/12/04 03:03:44 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.17 2014/12/05 14:36:44 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -46,7 +46,14 @@
 #include <arm/allwinner/awin_var.h>
 
 #define AWIN_MMC_NDESC         16
-#define AWIN_MMC_DMA_FTRGLEVEL 0x20070008
+#define AWIN_MMC_DMA_FTRGLEVEL_A20     0x20070008
+#define AWIN_MMC_DMA_FTRGLEVEL_A80     0x200f0010
+
+static const struct awin_gpio_pinset awin_mmc_pinsets_a80[4] = {
+       [0] = { 'F', AWIN_A80_PIO_PF_SDMMC0_FUNC, AWIN_A80_PIO_PF_SDMMC0_PINS },
+       [1] = { 'G', AWIN_A80_PIO_PG_SDMMC1_FUNC, AWIN_A80_PIO_PG_SDMMC1_PINS },
+       [2] = { 'C', AWIN_A80_PIO_PC_SDMMC2_FUNC, AWIN_A80_PIO_PC_SDMMC2_PINS },
+};
 
 static int     awin_mmc_match(device_t, cfdata_t, void *);
 static void    awin_mmc_attach(device_t, device_t, void *);
@@ -88,6 +95,7 @@
        bus_space_tag_t sc_bst;
        bus_space_handle_t sc_bsh;
        bus_space_handle_t sc_clk_bsh;
+       bus_space_handle_t sc_comm_bsh;
        bus_dma_tag_t sc_dmat;
 
        bool sc_use_dma;
@@ -99,10 +107,12 @@
 
        int sc_mmc_width;
        int sc_mmc_present;
+       int sc_mmc_port;
 
        device_t sc_sdmmc_dev;
 
        uint32_t sc_fifo_reg;
+       uint32_t sc_dma_ftrglevel;
 
        uint32_t sc_idma_xferlen;
        bus_dma_segment_t sc_idma_segs[1];
@@ -203,13 +213,12 @@
        sc->sc_dev = self;
        sc->sc_bst = aio->aio_core_bst;
        sc->sc_dmat = aio->aio_dmat;
+       sc->sc_mmc_port = loc->loc_port;
        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
        cv_init(&sc->sc_intr_cv, "awinmmcirq");
        cv_init(&sc->sc_idst_cv, "awinmmcdma");
        bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
            loc->loc_offset, loc->loc_size, &sc->sc_bsh);
-       bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
-           AWIN_SD0_CLK_REG + (loc->loc_port * 4), 0, &sc->sc_clk_bsh);
 
        sc->sc_use_dma = true;
        prop_dictionary_get_bool(cfg, "dma", &sc->sc_use_dma);
@@ -217,15 +226,47 @@
        aprint_naive("\n");
        aprint_normal(": SD3.0 (%s)\n", sc->sc_use_dma ? "DMA" : "PIO");
 
-       awin_pll6_enable();
+       if (awin_chip_id() == AWIN_CHIP_ID_A80) {
+
+               if (awin_mmc_pinsets_a80[loc->loc_port].pinset_group) {
+                       awin_gpio_pinset_acquire(
+                           &awin_mmc_pinsets_a80[loc->loc_port]);
+               }
+
+               bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
+                   AWIN_A80_CCU_SCLK_SDMMC0_CLK_REG + (loc->loc_port * 4), 4,
+                   &sc->sc_clk_bsh);
+               bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
+                   AWIN_A80_SDMMC_COMM_OFFSET + (loc->loc_port * 4), 4,
+                   &sc->sc_comm_bsh);
+               awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+                   AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_REG,
+                   AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_SD, 0);
+               awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+                   AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_REG,
+                   AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_SD, 0);
 
-       awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-           AWIN_AHB_GATING0_REG,
-           AWIN_AHB_GATING0_SDMMC0 << loc->loc_port, 0);
-       if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+               const uint32_t comm = bus_space_read_4(sc->sc_bst,
+                   sc->sc_comm_bsh, 0);
+               bus_space_write_4(sc->sc_bst, sc->sc_comm_bsh, 0,
+                   comm |
+                   AWIN_A80_SDMMC_COMM_SDC_RESET_SW |
+                   AWIN_A80_SDMMC_COMM_SDC_CLOCK_SW);
+               delay(1000);
+       } else {
+               bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
+                   AWIN_SD0_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_clk_bsh);
+
+               awin_pll6_enable();
+
                awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
-                   AWIN_A31_AHB_RESET0_REG,
-                   AWIN_A31_AHB_RESET0_SD0_RST << loc->loc_port, 0);
+                   AWIN_AHB_GATING0_REG,
+                   AWIN_AHB_GATING0_SDMMC0 << loc->loc_port, 0);
+               if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+                       awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
+                           AWIN_A31_AHB_RESET0_REG,
+                           AWIN_A31_AHB_RESET0_SD0_RST << loc->loc_port, 0);
+               }
        }
 
        if (prop_dictionary_get_cstring_nocopy(cfg, "detect-gpio", &pin_name)) {
@@ -253,10 +294,19 @@
                }
        }
 
-       if (awin_chip_id() == AWIN_CHIP_ID_A31) {
+       switch (awin_chip_id()) {
+       case AWIN_CHIP_ID_A80:
+               sc->sc_fifo_reg = AWIN_A31_MMC_FIFO;
+               sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A80;
+               break;
+       case AWIN_CHIP_ID_A31:
                sc->sc_fifo_reg = AWIN_A31_MMC_FIFO;
-       } else {
+               sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20;
+               break;
+       default:
                sc->sc_fifo_reg = AWIN_MMC_FIFO;
+               sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20;
+               break;
        }
 
        if (sc->sc_use_dma) {
@@ -293,7 +343,7 @@
        saa.saa_sct = &awin_mmc_chip_functions;
        saa.saa_sch = sc;
        saa.saa_clkmin = 400;
-       saa.saa_clkmax = 50000;
+       saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
        saa.saa_caps = SMC_CAPS_4BIT_MODE|
                       SMC_CAPS_8BIT_MODE|
                       SMC_CAPS_SD_HIGHSPEED|
@@ -394,13 +444,28 @@
 awin_mmc_host_reset(sdmmc_chipset_handle_t sch)
 {
        struct awin_mmc_softc *sc = sch;
+       int retry = 1000;
 
 #ifdef AWIN_MMC_DEBUG
        aprint_normal_dev(sc->sc_dev, "host reset\n");
 #endif
 
+       if (awin_chip_id() == AWIN_CHIP_ID_A80) {
+               if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) {
+                       MMC_WRITE(sc, AWIN_MMC_HWRST, 0);
+                       delay(10);
+                       MMC_WRITE(sc, AWIN_MMC_HWRST, 1);
+                       delay(300);
+               }
+       }
+
        MMC_WRITE(sc, AWIN_MMC_GCTRL,
            MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_RESET);
+       while (--retry > 0) {
+               if (!(MMC_READ(sc, AWIN_MMC_GCTRL) & AWIN_MMC_GCTRL_RESET))
+                       break;
+               delay(100);
+       }
 



Home | Main Index | Thread Index | Old Index