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