Module Name:    src
Committed By:   jkunz
Date:           Sun Dec 16 19:45:52 UTC 2012

Modified Files:
        src/sys/arch/arm/imx: imx23_ssp.c
        src/sys/arch/evbarm/conf: IMX23_OLINUXINO

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


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/imx23_ssp.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/evbarm/conf/IMX23_OLINUXINO

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/imx/imx23_ssp.c
diff -u src/sys/arch/arm/imx/imx23_ssp.c:1.1 src/sys/arch/arm/imx/imx23_ssp.c:1.2
--- src/sys/arch/arm/imx/imx23_ssp.c:1.1	Tue Nov 20 19:06:14 2012
+++ src/sys/arch/arm/imx/imx23_ssp.c	Sun Dec 16 19:45:52 2012
@@ -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 int	issp_match(device_t, cfdata_t
 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_exec_command(sdmmc_chip
 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 @@ static struct sdmmc_chip_functions issp_
 	.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 @@ issp_match(device_t parent, cfdata_t mat
 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_attach(device_t parent, device_t se
 	}
 
 	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 @@ issp_attach(device_t parent, device_t se
 	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 @@ issp_host_ocr(sdmmc_chipset_handle_t sch
 static int
 issp_host_maxblklen(sdmmc_chipset_handle_t sch)
 {
-	/* XXX: This value was made up. */
 	return 512;
 }
 
@@ -242,10 +240,10 @@ issp_card_detect(sdmmc_chipset_handle_t 
 	/* 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 @@ issp_card_detect(sdmmc_chipset_handle_t 
 	 * 	#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 @@ issp_write_protect(sdmmc_chipset_handle_
 }
 
 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 @@ issp_bus_clock(sdmmc_chipset_handle_t sc
 	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 @@ issp_bus_clock(sdmmc_chipset_handle_t sc
 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 @@ issp_exec_command(sdmmc_chipset_handle_t
 {
 	struct issp_softc *sc = sch;
 	uint32_t reg;
+	uint32_t do_blkio;
+	uint32_t i;
+
+	do_blkio = 0;
 
-	/* Set excepted response type. */
-	SSP_WRITE(sc, HW_SSP_CTRL0_CLR,
+	/* 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);
+		SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_IGNORE_CRC);
 
 	/* Set command. */
-	SSP_WRITE(sc, HW_SSP_CMD0_CLR, HW_SSP_CMD0_CMD);
-	SSP_WRITE(sc, HW_SSP_CMD0_SET,
+	SSP_WR(sc, HW_SSP_CMD0_CLR, HW_SSP_CMD0_CMD);
+	SSP_WR(sc, HW_SSP_CMD0_SET,
 	    __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD));
 
 	/* Set command argument. */
-	SSP_WRITE(sc, HW_SSP_CMD1, cmd->c_arg);
+	SSP_WR(sc, HW_SSP_CMD1, cmd->c_arg);
+
+	/* Is data to be transferred? */
+	if (cmd->c_datalen > 0 && cmd->c_data != NULL) {
+		SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_DATA_XFER);
+		/* Transfer XFER_COUNT of 8-bit words. */
+		SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_XFER_COUNT);
+		SSP_WR(sc, HW_SSP_CTRL0_SET,
+		    __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT));
+
+		/* XXX: why 8CYC? Bit is never cleaned. */
+		SSP_WR(sc, HW_SSP_CMD0_SET, HW_SSP_CMD0_APPEND_8CYC);
+
+		if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
+			/* Read mode. */
+			do_blkio |= BLKIO_RD;
+			SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_READ);
+		} else {
+			/* Write mode. */
+			do_blkio |= BLKIO_WR;
+			SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_READ);
+		}
+	} else {
+		/* No data to be transferred. */
+		SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_DATA_XFER);
+	}
 
 	/* Run the command. */
-	SSP_WRITE(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_RUN);
+	SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_RUN);
 
-	/* Wait until SSP has processed the command. */
-	while (SSP_READ(sc, HW_SSP_STATUS) &
-	    (HW_SSP_STATUS_CMD_BUSY | HW_SSP_STATUS_BUSY))
-			;
-
-	/* Check if the command ran without errors. */
-	reg = SSP_READ(sc, HW_SSP_STATUS);
-	
-	if (reg & SSP_STATUS_ERR)
-		cmd->c_error = reg & SSP_STATUS_ERR;
+	if (ISSET(do_blkio, BLKIO_RD)) {
+		for (i = 0; i < cmd->c_datalen / 4; i++) {
+			/* Wait until data arrives to FIFO. */
+			while (SSP_RD(sc, HW_SSP_STATUS)
+			    & HW_SSP_STATUS_FIFO_EMPTY) {
+				/* Abort if error while waiting. */
+				if (SSP_RD(sc, HW_SSP_STATUS) & SSP_RUN_ERR) {
+					aprint_normal_dev(sc->sc_dev,
+					    "RD_ERR: %x\n",
+					    SSP_RD(sc, HW_SSP_STATUS));
+					cmd->c_error = 1;
+					goto pioerr;
+				}
+			}
+			*((uint32_t *)cmd->c_data+i) = SSP_RD(sc, HW_SSP_DATA);
+		}
+	} else if (ISSET(do_blkio, BLKIO_WR)) {
+		for (i = 0; i < (cmd->c_datalen / 4); i++) {
+			while (SSP_RD(sc, HW_SSP_STATUS)
+			    & HW_SSP_STATUS_FIFO_FULL) {
+				/* Abort if error while waiting. */
+				if (SSP_RD(sc, HW_SSP_STATUS) & SSP_RUN_ERR) {
+					aprint_normal_dev(sc->sc_dev,
+					    "WR_ERR: %x\n",
+					    SSP_RD(sc, HW_SSP_STATUS));
+					cmd->c_error = 1;
+					goto pioerr;
+				}
+			}
+			SSP_WR(sc, HW_SSP_DATA, *((uint32_t *)cmd->c_data+i));
+		}
+	}
+
+	/* Wait until SSP is done. */
+	while (SSP_RD(sc, HW_SSP_STATUS) & SSP_BUSY)
+                       ;
+
+	/* Check if the command ran successfully. */
+	reg = SSP_RD(sc, HW_SSP_STATUS);
+	if (reg & SSP_RUN_ERR)
+		cmd->c_error = reg & SSP_RUN_ERR;
 
 	/* Read response if such was requested. */
 	if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
-		cmd->c_resp[0] = SSP_READ(sc, HW_SSP_SDRESP0);
+		cmd->c_resp[0] = SSP_RD(sc, HW_SSP_SDRESP0);
 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
-		    cmd->c_resp[1] = SSP_READ(sc, HW_SSP_SDRESP1);
-		    cmd->c_resp[2] = SSP_READ(sc, HW_SSP_SDRESP2);
-		    cmd->c_resp[3] = SSP_READ(sc, HW_SSP_SDRESP3);
+			cmd->c_resp[1] = SSP_RD(sc, HW_SSP_SDRESP1);
+			cmd->c_resp[2] = SSP_RD(sc, HW_SSP_SDRESP2);
+			cmd->c_resp[3] = SSP_RD(sc, HW_SSP_SDRESP3);
+			/*
+			 * Remove CRC7 + LSB by rotating all bits right by 8 to
+			 * make sdmmc __bitfield() happy.
+			 */
+			cmd->c_resp[0] >>= 8; /* Remove CRC7 + LSB. */
+			cmd->c_resp[0] |= (0x000000FF & cmd->c_resp[1]) << 24;
+			cmd->c_resp[1] >>= 8;
+			cmd->c_resp[1] |= (0x000000FF & cmd->c_resp[2]) << 24;
+			cmd->c_resp[2] >>= 8;
+			cmd->c_resp[2] |= (0x000000FF & cmd->c_resp[3]) << 24;
+			cmd->c_resp[3] >>= 8;
 		}
 	}
-
-/*
-	apbdma_dmamem_alloc()
-	apbdma_do_dma()
-	wait_until_done()
-*/
+pioerr:
 	return;
 }
 
@@ -374,7 +467,7 @@ issp_card_enable_intr(sdmmc_chipset_hand
 	struct issp_softc *sc = sch;
 
 	aprint_normal_dev(sc->sc_dev,
-		"issp_card_enable_intr NOT IMPLEMENTED!\n");
+	    "issp_card_enable_intr NOT IMPLEMENTED!\n");
 
 	return;
 }
@@ -392,7 +485,7 @@ issp_card_intr_ack(sdmmc_chipset_handle_
 /*
  * Reset the SSP block.
  *
- * Inspired by i.MX233 RM "39.3.10 Correct Way to Soft Reset a Block"
+ * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
  */
 static void
 issp_reset(struct issp_softc *sc)
@@ -402,65 +495,77 @@ issp_reset(struct issp_softc *sc)
 	/* Prepare for soft-reset by making sure that SFTRST is not currently
 	 * asserted. Also clear CLKGATE so we can wait for its assertion below.
 	 */
-	SSP_WRITE(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
+	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
 
 	/* Wait at least a microsecond for SFTRST to deassert. */
 	loop = 0;
-	while ((SSP_READ(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
+	while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
 	    (loop < SSP_SOFT_RST_LOOP))
 		loop++;
 
 	/* Clear CLKGATE so we can wait for its assertion below. */
-	SSP_WRITE(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
+	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
 
 	/* Soft-reset the block. */
-	SSP_WRITE(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_SFTRST);
+	SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_SFTRST);
 
 	/* Wait until clock is in the gated state. */
-	while (!(SSP_READ(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE));
+	while (!(SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE));
 
 	/* Bring block out of reset. */
-	SSP_WRITE(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
+	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
 
 	loop = 0;
-	while ((SSP_READ(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
+	while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
 	    (loop < SSP_SOFT_RST_LOOP))
 		loop++;
 
-	SSP_WRITE(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
-	
+	SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
+
 	/* Wait until clock is in the NON-gated state. */
-	while (SSP_READ(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE);
+	while (SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE);
 
 	return;
 }
 
+
 /*
- * Initialize common options.
+ * DATA_TIMEOUT is calculated as:
+ * (1 / SSP_CLK) * (DATA_TIMEOUT * 4096)
+ */
+#define DATA_TIMEOUT 0x4240	/* 723ms */
+
+/*
+ * Initialize SSP controller to SD/MMC mode.
  */
 static void
 issp_init(struct issp_softc *sc)
 {
 	uint32_t reg;
 
-	/* Initialize SD/MMC controller. */
-	reg = SSP_READ(sc, HW_SSP_CTRL0);
+	/* Initial data bus width is 1-bit. */
+	reg = SSP_RD(sc, HW_SSP_CTRL0);
 	reg &= ~(HW_SSP_CTRL0_BUS_WIDTH);
-	reg |= __SHIFTIN(0x1, HW_SSP_CTRL0_BUS_WIDTH) | HW_SSP_CTRL0_ENABLE;
-	SSP_WRITE(sc, HW_SSP_CTRL0, reg);
+	reg |= __SHIFTIN(BUS_WIDTH_1_BIT, HW_SSP_CTRL0_BUS_WIDTH) |
+	    HW_SSP_CTRL0_WAIT_FOR_IRQ | HW_SSP_CTRL0_ENABLE;
+	SSP_WR(sc, HW_SSP_CTRL0, reg);
 
-	reg = SSP_READ(sc, HW_SSP_CTRL1);
+	/* Set data timeout. */
+	reg = SSP_RD(sc, HW_SSP_TIMING);
+	reg &= ~(HW_SSP_TIMING_TIMEOUT);
+	reg |= __SHIFTIN(DATA_TIMEOUT, HW_SSP_TIMING_TIMEOUT);
+
+	/* Set initial clock rate to minimum. */
+	issp_set_sck(sc, SSP_CLK_MIN * 1000);
+
+	SSP_WR(sc, HW_SSP_TIMING, reg);
+	/* Enable SD/MMC mode and use use 8-bits per word. */
+	reg = SSP_RD(sc, HW_SSP_CTRL1);
 	reg &= ~(HW_SSP_CTRL1_WORD_LENGTH | HW_SSP_CTRL1_SSP_MODE);
 	reg |= HW_SSP_CTRL1_POLARITY |
 	    __SHIFTIN(0x7, HW_SSP_CTRL1_WORD_LENGTH) |
 	    __SHIFTIN(0x3, HW_SSP_CTRL1_SSP_MODE);
-	SSP_WRITE(sc, HW_SSP_CTRL1, reg);
-
-	/* Set command timeout. */
-	reg = SSP_READ(sc, HW_SSP_TIMING);
-	reg &= ~(HW_SSP_TIMING_TIMEOUT);
-	reg |= __SHIFTIN(SSP_CMD_TIMEOUT, HW_SSP_TIMING_TIMEOUT);
-	SSP_WRITE(sc, HW_SSP_TIMING, reg);
+	SSP_WR(sc, HW_SSP_CTRL1, reg);
 
 	return;
 }
@@ -499,11 +604,11 @@ issp_set_sck(struct issp_softc *sc, uint
 		}
 	}
 out:
-	reg = SSP_READ(sc, HW_SSP_TIMING);
+	reg = SSP_RD(sc, HW_SSP_TIMING);
 	reg &= ~(HW_SSP_TIMING_CLOCK_DIVIDE | HW_SSP_TIMING_CLOCK_RATE);
 	reg |= __SHIFTIN(div, HW_SSP_TIMING_CLOCK_DIVIDE) |
 	    __SHIFTIN(rate, HW_SSP_TIMING_CLOCK_RATE);
-	SSP_WRITE(sc, HW_SSP_TIMING, reg);
+	SSP_WR(sc, HW_SSP_TIMING, reg);
 
-	return SSP_CLK / (d * (1 + r));
+	return SSP_CLK / (div * (1 + rate));
 }

Index: src/sys/arch/evbarm/conf/IMX23_OLINUXINO
diff -u src/sys/arch/evbarm/conf/IMX23_OLINUXINO:1.1 src/sys/arch/evbarm/conf/IMX23_OLINUXINO:1.2
--- src/sys/arch/evbarm/conf/IMX23_OLINUXINO:1.1	Tue Nov 20 19:08:45 2012
+++ src/sys/arch/evbarm/conf/IMX23_OLINUXINO	Sun Dec 16 19:45:52 2012
@@ -1,4 +1,4 @@
-# $Id: IMX23_OLINUXINO,v 1.1 2012/11/20 19:08:45 jkunz Exp $
+# $Id: IMX23_OLINUXINO,v 1.2 2012/12/16 19:45:52 jkunz Exp $
 #
 # IMX23_OLINUXINO -- Olimex i.MX23 OLinuXino kernel configuration file.
 #
@@ -7,7 +7,7 @@ include "arch/evbarm/conf/std.imx23_olin
 
 maxusers	8
 
-config	netbsd	root on ? type ?
+config netbsd root on ld0a type ?
 
 # The main bus device
 mainbus0	at root
@@ -25,9 +25,9 @@ apbh0		at mainbus? base 0x80000000 size 
 icoll0		at apbh? addr 0x80000000 size 0x2000 irq -1
 
 # Synchronous serial port for SD/MMC
-#ssp0		at apbh? addr 0x80010000 size 0x2000 irq 15
-#sdmmc*		at ssp?
-#ld*		at sdmmc?
+ssp0		at apbh? addr 0x80010000 size 0x2000 irq 15
+sdmmc*		at ssp?
+ld*			at sdmmc?
 
 # APBX bus
 apbx0		at mainbus? base 0x80040000 size 0x00040000
@@ -47,11 +47,7 @@ options		MEMSIZE=64
 options		DDB
 options		HZ=100
 
-options		MEMORY_DISK_HOOKS
-options		MEMORY_DISK_IS_ROOT
-options		MEMORY_DISK_ROOT_SIZE=12288 # 6 megs
-options		MEMORY_DISK_RBFLAGS=RB_SINGLE
-
-pseudo-device	md
-
 file-system	FFS
+file-system	EXT2FS
+file-system	MSDOSFS
+

Reply via email to