Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Contribution from Petri Laakso: Initial support for...



details:   https://anonhg.NetBSD.org/src/rev/179f659a768a
branches:  trunk
changeset: 783356:179f659a768a
user:      jkunz <jkunz%NetBSD.org@localhost>
date:      Sun Dec 16 19:45:52 2012 +0000

description:
Contribution from Petri Laakso: Initial support for SD card controller.
iMX233-OLinuXino can now boot and run from its own SD card.

diffstat:

 sys/arch/arm/imx/imx23_ssp.c         |  333 +++++++++++++++++++++++-----------
 sys/arch/evbarm/conf/IMX23_OLINUXINO |   20 +-
 2 files changed, 227 insertions(+), 126 deletions(-)

diffs (truncated from 607 to 300 lines):

diff -r b30d3ee2e95e -r 179f659a768a sys/arch/arm/imx/imx23_ssp.c
--- a/sys/arch/arm/imx/imx23_ssp.c      Sun Dec 16 19:40:00 2012 +0000
+++ b/sys/arch/arm/imx/imx23_ssp.c      Sun Dec 16 19:45:52 2012 +0000
@@ -1,4 +1,4 @@
-/* $Id: imx23_ssp.c,v 1.1 2012/11/20 19:06:14 jkunz Exp $ */
+/* $Id: imx23_ssp.c,v 1.2 2012/12/16 19:45:52 jkunz Exp $ */
 
 /*
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -33,15 +33,10 @@
 #include <sys/types.h>
 #include <sys/bus.h>
 #include <sys/cdefs.h>
-#include <sys/cpu.h>
 #include <sys/device.h>
 #include <sys/errno.h>
 #include <sys/systm.h>
 
-#include <arm/pic/picvar.h>
-
-#include <arm/imx/imx23_apbdma.h>
-#include <arm/imx/imx23_icollreg.h>
 #include <arm/imx/imx23_sspreg.h>
 #include <arm/imx/imx23var.h>
 
@@ -50,7 +45,7 @@
 #include <dev/sdmmc/sdmmcvar.h>
 
 /*
- * SD/MMC host controller driver for i.MX233.
+ * SD/MMC host controller driver for i.MX23.
  */
 
 struct issp_softc {
@@ -65,7 +60,11 @@
 static void    issp_attach(device_t, device_t, void *);
 static int     issp_activate(device_t, enum devact);
 
-/* sdmmc chip function prototypes. */
+static void    issp_reset(struct issp_softc *);
+static void    issp_init(struct issp_softc *);
+static uint32_t        issp_set_sck(struct issp_softc *, uint32_t target);
+
+/* sdmmc(4) driver chip function prototypes. */
 static int     issp_host_reset(sdmmc_chipset_handle_t);
 static uint32_t        issp_host_ocr(sdmmc_chipset_handle_t);
 static int     issp_host_maxblklen(sdmmc_chipset_handle_t);
@@ -80,23 +79,6 @@
 static void    issp_card_enable_intr(sdmmc_chipset_handle_t, int);
 static void    issp_card_intr_ack(sdmmc_chipset_handle_t);
 
-/* Used from the above callbacks. */
-static void    issp_reset(struct issp_softc *);
-static void    issp_init(struct issp_softc *);
-static uint32_t        issp_set_sck(struct issp_softc *, uint32_t target);
-
-#define SSP_SOFT_RST_LOOP 455  /* At least 1 us ... */
-
-CFATTACH_DECL3_NEW(ssp,
-       sizeof(struct issp_softc),
-       issp_match,
-       issp_attach,
-       NULL,
-       issp_activate,
-       NULL,
-       NULL,
-       0);
-
 static struct sdmmc_chip_functions issp_functions = {
        .host_reset     = issp_host_reset,
        .host_ocr       = issp_host_ocr,
@@ -112,22 +94,45 @@
        .card_intr_ack  = issp_card_intr_ack
 };
 
-#define SSP_READ(sc, reg)                                              \
+CFATTACH_DECL3_NEW(ssp,
+       sizeof(struct issp_softc),
+       issp_match,
+       issp_attach,
+       NULL,
+       issp_activate,
+       NULL,
+       NULL,
+       0);
+
+#define SSP_SOFT_RST_LOOP 455  /* At least 1 us ... */
+
+#define SSP_RD(sc, reg)                                                        \
        bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
-#define SSP_WRITE(sc, reg, val)                                                \
+#define SSP_WR(sc, reg, val)                                           \
        bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
 
-#define SSP_CLK                        96000000 /* CLK_SSP from PLL is 96 MHz */
-#define SSP_CLK_MIN            2        /* 2 kHz */
-#define SSP_CLK_MAX            48000    /* 48 MHz */
-/* SSP_CMD_TIMEOUT is calculated as (1.0/SSP_SCK)*(SSP_CMD_TIMEOUT*4096) */
-#define SSP_CMD_TIMEOUT                0xffff  /* 2.8 seconds. */
-#define SSP_STATUS_ERR (HW_SSP_STATUS_RESP_CRC_ERR |                   \
+#define SSP_CLK                96000000        /* CLK_SSP from PLL is 96 MHz */
+#define SSP_CLK_MIN    400             /* 400 kHz */
+#define SSP_CLK_MAX    48000           /* 48 MHz */
+
+#define SSP_BUSY (HW_SSP_STATUS_CMD_BUSY |                             \
+                       HW_SSP_STATUS_DATA_BUSY |                       \
+                       HW_SSP_STATUS_BUSY)
+
+#define SSP_RUN_ERR (HW_SSP_STATUS_RESP_CRC_ERR |                      \
                        HW_SSP_STATUS_RESP_ERR |                        \
                        HW_SSP_STATUS_RESP_TIMEOUT |                    \
                        HW_SSP_STATUS_DATA_CRC_ERR |                    \
                        HW_SSP_STATUS_TIMEOUT)
 
+#define BLKIO_NONE 0
+#define BLKIO_RD 1
+#define BLKIO_WR 2
+
+#define BUS_WIDTH_1_BIT 0x0
+#define BUS_WIDTH_4_BIT 0x1
+#define BUS_WIDTH_8_BIT 0x2
+
 static int
 issp_match(device_t parent, cfdata_t match, void *aux)
 {
@@ -145,25 +150,18 @@
 static void
 issp_attach(device_t parent, device_t self, void *aux)
 {
-       static int issp_attached = 0;
        struct issp_softc *sc = device_private(self);
-       struct apb_softc *scp = device_private(parent);
+       struct apb_softc *sc_parent = device_private(parent);
        struct apb_attach_args *aa = aux;
        struct sdmmcbus_attach_args saa;
-       
-       
+       static int issp_attached = 0;
+
        if (issp_attached)
                return;
 
-//XXX:
-       if (scp == NULL)
-               printf("ISSP_ATTACH: scp == NULL\n");
-       if (scp->dmac == NULL)
-               printf("ISSP_ATTACH: scp->dmac == NULL\n");
-
        sc->sc_dev = self;
        sc->sc_iot = aa->aa_iot;
-       sc->dmac = scp->dmac;
+       sc->dmac = sc_parent->dmac;
 
        if (bus_space_map(sc->sc_iot,
            aa->aa_addr, aa->aa_size, 0, &(sc->sc_hdl))) {
@@ -172,9 +170,9 @@
        }
 
        issp_reset(sc);
-       issp_init(sc); 
+       issp_init(sc);
 
-       uint32_t issp_vers = SSP_READ(sc, HW_SSP_VERSION);
+       uint32_t issp_vers = SSP_RD(sc, HW_SSP_VERSION);
        aprint_normal(": SSP Block v%" __PRIuBIT ".%" __PRIuBIT "\n",
            __SHIFTOUT(issp_vers, HW_SSP_VERSION_MAJOR),
            __SHIFTOUT(issp_vers, HW_SSP_VERSION_MINOR));
@@ -186,7 +184,8 @@
        saa.saa_dmat    = aa->aa_dmat;
        saa.saa_clkmin  = SSP_CLK_MIN;
        saa.saa_clkmax  = SSP_CLK_MAX;
-       saa.saa_caps    = SMC_CAPS_4BIT_MODE | SMC_CAPS_DMA;
+       /* Add SMC_CAPS_DMA capability when DMA funtionality is implemented. */
+       saa.saa_caps    = SMC_CAPS_4BIT_MODE | SMC_CAPS_SINGLE_ONLY;
 
        sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL);
        if (sc->sc_sdmmc == NULL) {
@@ -228,7 +227,6 @@
 static int
 issp_host_maxblklen(sdmmc_chipset_handle_t sch)
 {
-       /* XXX: This value was made up. */
        return 512;
 }
 
@@ -242,10 +240,10 @@
        /* struct issp_softc *sc = sch;
         *
         * In the perfect world I'll just:
-        *      return SSP_READ(sc, HW_SSP_STATUS) & HW_SSP_STATUS_CARD_DETECT;
+        *      return SSP_RD(sc, HW_SSP_STATUS) & HW_SSP_STATUS_CARD_DETECT;
         * and call it a day.
         *
-        * But on i.MX233 OLinuXino MAXI, SSP1_DETECT is not used for the SD
+        * But on i.MX23 OLinuXino MAXI, SSP1_DETECT is not used for the SD
         * card detection but SSP1_DATA3 is, as Tsvetan put it:
         *
         * < Tsvetan> if you want to know if SD card is inserted watch
@@ -258,7 +256,7 @@
         *      #if BOARDTYPE == MAXI (Possibly MINI & MICRO)
         *              return GPIO_READ(PIN_125) & PIN_125
         *      #else
-        *              return SSP_READ(sc, STATUS) & CARD_DETECT;
+        *              return SSP_RD(sc, STATUS) & CARD_DETECT;
         *      #endif
         * Until GPIO functionality is not present I am just going to */
 
@@ -273,9 +271,9 @@
 }
 
 static int
-issp_bus_power(sdmmc_chipset_handle_t sch, uint32_t power)
+issp_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
 {
-       /* i.MX233 does not support setting bus power. */
+       /* i.MX23 SSP does not support setting bus power. */
        return 0;
 }
 
@@ -285,9 +283,13 @@
        struct issp_softc *sc = sch;
        uint32_t sck;
 
-       aprint_normal_dev(sc->sc_dev, "requested clock %d Hz", clock * 1000);
        sck = issp_set_sck(sc, clock * 1000);
-       aprint_normal(", got %d Hz\n", sck);
+
+       /* Notify user if we didn't get exact clock rate from SSP that was
+        * requested. */
+       if (sck != clock * 1000)
+               aprint_normal_dev(sc->sc_dev, "requested clock %dHz, "
+                   "but got %dHz\n", clock * 1000, sck);
 
        return 0;
 }
@@ -295,8 +297,29 @@
 static int
 issp_bus_width(sdmmc_chipset_handle_t sch, int width)
 {
-       /* Return error if other than 4-bit width is requested. */
-       return width - 4;
+       struct issp_softc *sc = sch;
+       uint32_t reg;
+
+       reg = SSP_RD(sc, HW_SSP_CTRL0);
+       reg &= ~(HW_SSP_CTRL0_BUS_WIDTH);
+
+       switch(width) {
+       case(1):
+               reg |= __SHIFTIN(BUS_WIDTH_1_BIT, HW_SSP_CTRL0_BUS_WIDTH);
+               break;
+       case(4):
+               reg |= __SHIFTIN(BUS_WIDTH_4_BIT, HW_SSP_CTRL0_BUS_WIDTH);
+               break;
+       case(8):
+               reg |= __SHIFTIN(BUS_WIDTH_8_BIT, HW_SSP_CTRL0_BUS_WIDTH);
+               break;
+       default:
+               return 1;
+       }
+
+       SSP_WR(sc, HW_SSP_CTRL0, reg);
+
+       return 0;
 }
 
 static int
@@ -311,60 +334,130 @@
 {
        struct issp_softc *sc = sch;
        uint32_t reg;
+       uint32_t do_blkio;
+       uint32_t i;
 
-       /* Set excepted response type. */
-       SSP_WRITE(sc, HW_SSP_CTRL0_CLR,
+       do_blkio = 0;
+
+       /* Wait until SSP done. (data I/O error + retry...) */
+       while (SSP_RD(sc, HW_SSP_STATUS) & SSP_BUSY)
+                       ;
+
+       /* Set expected response type. */
+       SSP_WR(sc, HW_SSP_CTRL0_CLR,
            HW_SSP_CTRL0_GET_RESP | HW_SSP_CTRL0_LONG_RESP);
 
        if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
-               SSP_WRITE(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_GET_RESP);
+               SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_GET_RESP);
                if (ISSET(cmd->c_flags, SCF_RSP_136))
-                       SSP_WRITE(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_LONG_RESP);
+                       SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_LONG_RESP);
        }
 
        /* If CMD does not need CRC validation, tell it to SSP. */
        if (ISSET(cmd->c_flags, SCF_RSP_CRC))
-               SSP_WRITE(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_IGNORE_CRC);
+               SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_IGNORE_CRC);
        else
-               SSP_WRITE(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_IGNORE_CRC);



Home | Main Index | Thread Index | Old Index