Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Jul 2011 00:13:29 GMT
From:      Jakub Wojciech Klama <jceel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 196124 for review
Message-ID:  <201107140013.p6E0DT06088903@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@196124?ac=10

Change 196124 by jceel@jceel_cyclone on 2011/07/14 00:12:59

	MMC/SD driver. Detects card, but data transfer is broken.

Affected files ...

.. //depot/projects/soc2011/jceel_lpc/sys/arm/conf/EA3250#5 edit
.. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/files.lpc#4 edit
.. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpc_mmc.c#2 edit
.. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpcreg.h#3 edit
.. //depot/projects/soc2011/jceel_lpc/sys/boot/fdt/dts/ea3250.dts#5 edit
.. //depot/projects/soc2011/jceel_lpc/sys/dev/mmc/mmc.c#2 edit

Differences ...

==== //depot/projects/soc2011/jceel_lpc/sys/arm/conf/EA3250#5 (text+ko) ====

@@ -18,13 +18,13 @@
 options 	FFS			#Berkeley Fast Filesystem
 options 	NFSCL			#Network Filesystem Client
 options 	NFSLOCKD		#Network Lock Manager
-options 	NFS_ROOT		#NFS usable as /, requires NFSCLIENT
-options 	BOOTP
-options 	BOOTP_NFSROOT
-options 	BOOTP_NFSV3
-options 	BOOTP_WIRED_TO=lpe0
+#options 	NFS_ROOT		#NFS usable as /, requires NFSCLIENT
+#options 	BOOTP
+#options 	BOOTP_NFSROOT
+#options 	BOOTP_NFSV3
+#options 	BOOTP_WIRED_TO=lpe0
 
-#options 	ROOTDEVNAME=\"ufs:/dev/da0a\"
+options 	ROOTDEVNAME=\"ufs:/dev/da0a\"
 
 #options		MD_ROOT			# MD is a potential root device
 #options		MD_ROOT_SIZE=8192	# 8MB ram disk
@@ -82,6 +82,10 @@
 device		pass
 device		da
 
+device		mmc
+device		mmcsd
+device		lpcmmc
+
 # Flattened Device Tree
 options 	FDT
 options 	FDT_DTB_STATIC

==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/files.lpc#4 (text+ko) ====

@@ -11,5 +11,6 @@
 arm/lpc/lpc_rtc.c			standard
 arm/lpc/if_lpe.c			optional	lpe
 arm/lpc/lpc_ohci.c			optional	ohci
+arm/lpc/lpc_mmc.c			optional	lpcmmc
 dev/uart/uart_dev_ns8250.c		optional	uart
 kern/kern_clocksource.c			standard

==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpc_mmc.c#2 (text+ko) ====

@@ -46,6 +46,8 @@
 #include <sys/timetc.h>
 #include <sys/watchdog.h>
 
+#include <sys/kdb.h>
+
 #include <machine/bus.h>
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
@@ -53,10 +55,16 @@
 #include <machine/frame.h>
 #include <machine/intr.h>
 
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
 #include <dev/mmc/bridge.h>
 #include <dev/mmc/mmcreg.h>
 #include <dev/mmc/mmcbrvar.h>
 
+#include <arm/lpc/lpcreg.h>
+#include <arm/lpc/lpcvar.h>
+
 struct lpc_mmc_softc {
 	device_t		lm_dev;
 	struct mtx		lm_mtx;
@@ -68,15 +76,48 @@
 	struct mmc_host		lm_host;
 	struct mmc_request *	lm_req;
 	struct mmc_data *	lm_data;
+	uint32_t		lm_flags;
+#define	LPC_SD_FLAGS_IGNORECRC		(1 << 0)
+	int			lm_xfer_direction;
+#define	DIRECTION_READ		0
+#define	DIRECTION_WRITE		1
+	int			lm_xfer_done;
+	int			lm_bus_busy;
 };
 
+#define	LPC_SD_BLOCKSIZE	512
+
 static int lpc_mmc_probe(device_t);
 static int lpc_mmc_attach(device_t);
 static int lpc_mmc_detach(device_t);
+static void lpc_mmc_intr(void *);
 
+static void lpc_mmc_cmd(struct lpc_mmc_softc *, struct mmc_command *);
+static void lpc_mmc_setup_xfer(struct lpc_mmc_softc *, struct mmc_data *);
+static void lpc_mmc_fifo_read(struct lpc_mmc_softc *);
+static void lpc_mmc_fifo_write(struct lpc_mmc_softc *);
+
+static int lpc_mmc_update_ios(device_t, device_t);
+static int lpc_mmc_request(device_t, device_t, struct mmc_request *);
+static int lpc_mmc_get_ro(device_t, device_t);
+static int lpc_mmc_acquire_host(device_t, device_t);
+static int lpc_mmc_release_host(device_t, device_t);
+
+#define	lpc_mmc_lock(_sc)						\
+    mtx_lock(&_sc->lm_mtx);
+#define	lpc_mmc_unlock(_sc)						\
+    mtx_unlock(&_sc->lm_mtx);
+#define	lpc_mmc_read_4(_sc, _reg)					\
+    bus_space_read_4(_sc->lm_bst, _sc->lm_bsh, _reg)
+#define	lpc_mmc_write_4(_sc, _reg, _value)				\
+    bus_space_write_4(_sc->lm_bst, _sc->lm_bsh, _reg, _value)
+
 static int
 lpc_mmc_probe(device_t dev)
 {
+	if (!ofw_bus_is_compatible(dev, "lpc,mmc"))
+		return (ENXIO);
+
 	device_set_desc(dev, "LPC32x0 MMC/SD controller");
 	return (BUS_PROBE_DEFAULT);
 }
@@ -85,8 +126,14 @@
 lpc_mmc_attach(device_t dev)
 {
 	struct lpc_mmc_softc *sc = device_get_softc(dev);
+	device_t child;
 	int rid;
 
+	sc->lm_dev = dev;
+	sc->lm_req = NULL;
+
+	mtx_init(&sc->lm_mtx, "lpcmmc", "mmc", MTX_DEF);
+
 	rid = 0;
 	sc->lm_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 	    RF_ACTIVE);
@@ -98,6 +145,8 @@
 	sc->lm_bst = rman_get_bustag(sc->lm_mem_res);
 	sc->lm_bsh = rman_get_bushandle(sc->lm_mem_res);
 
+	device_printf(dev, "virtual register space: 0x%08lx\n", sc->lm_bsh);
+
 	rid = 0;
 	sc->lm_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 	    RF_ACTIVE);
@@ -116,7 +165,16 @@
 		return (ENXIO);
 	}
 
-	device_set_ivars(dev, &sc->dm_host);
+	sc->lm_host.f_min = 312500;
+	sc->lm_host.f_max = 25000000;
+	sc->lm_host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
+	sc->lm_host.caps = MMC_CAP_4_BIT_DATA;
+
+	lpc_pwr_write(dev, LPC_CLKPWR_MS_CTRL,
+	    LPC_CLKPWR_MS_CTRL_CLOCK_EN | LPC_CLKPWR_MS_CTRL_SD_CLOCK | 1);
+	lpc_mmc_write_4(sc, LPC_SD_POWER, LPC_SD_POWER_CTRL_ON);
+
+	device_set_ivars(dev, &sc->lm_host);
 
 	child = device_add_child(dev, "mmc", -1);
 	if (!child) {
@@ -130,6 +188,14 @@
 	bus_generic_probe(dev);
 	bus_generic_attach(dev);
 
+	device_printf(dev, "attached\n");
+
+	return (0);
+}
+
+static int
+lpc_mmc_detach(device_t dev)
+{
 	return (0);
 }
 
@@ -137,23 +203,51 @@
 lpc_mmc_intr(void *arg)
 {
 	struct lpc_mmc_softc *sc = (struct lpc_mmc_softc *)arg;
+	struct mmc_command *cmd;
+	uint32_t status;
 
-	if (status & LPC_SD_STATUS_CMDCRCFAIL) {
+	status = lpc_mmc_read_4(sc, LPC_SD_STATUS);
+
+	device_printf(sc->lm_dev, "interrupt: 0x%08x\n", status);
+
+	if (status & LPC_SD_STATUS_TXACTIVE) {
+		device_printf(sc->lm_dev, "TX active\n");
+		lpc_mmc_fifo_write(sc);
+	}
 
+	if (status & LPC_SD_STATUS_RXACTIVE) {
+		device_printf(sc->lm_dev, "RX active\n");
+		lpc_mmc_fifo_read(sc);
 	}
 
+	if (status & LPC_SD_STATUS_CMDCRCFAIL) {
+		device_printf(sc->lm_dev, "command CRC error\n");
+		cmd = sc->lm_req->cmd;
+		cmd->error = MMC_ERR_NONE;
+		cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+		sc->lm_req->done(sc->lm_req);
+		sc->lm_req = NULL;
+		lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDCRCFAIL);	
+	}
+#if 0
 	if (status & LPC_SD_STATUS_DATACRCFAIL) {
 
 	}
-
-	if (status & LPC_SD_STATUS_CMDTIMEOUT) {
-
+#endif
+	if (status & LPC_SD_STATUS_CMDACTIVE)
+	{
+		device_printf(sc->lm_dev, "command active\n");
+		cmd = sc->lm_req->cmd;
+		cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+		sc->lm_req->done(sc->lm_req);
+		sc->lm_req = NULL;
 	}
-
+	
 	if (status & LPC_SD_STATUS_DATATIMEOUT) {
-
+		device_printf(sc->lm_dev, "data timeout\n");
+		lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_DATATIMEOUT);
 	}
-
+#if 0
 	if (status & LPC_SD_STATUS_TXUNDERRUN) {
 
 	}
@@ -161,15 +255,36 @@
 	if (status & LPC_SD_STATUS_RXOVERRUN) {
 
 	}
-
+#endif
 	if (status & LPC_SD_STATUS_CMDRESPEND) {
+		device_printf(sc->lm_dev, "command response\n");
+		device_printf(sc->lm_dev, "req: %p\n", sc->lm_req);
+		device_printf(sc->lm_dev, "cmd: %p\n", sc->lm_req->cmd);
+		cmd = sc->lm_req->cmd;
+		if (cmd->flags & MMC_RSP_136) {
+			cmd->resp[3] = lpc_mmc_read_4(sc, LPC_SD_RESP3);
+			cmd->resp[2] = lpc_mmc_read_4(sc, LPC_SD_RESP2);
+			cmd->resp[1] = lpc_mmc_read_4(sc, LPC_SD_RESP1);
+		}
 
+		cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+		cmd->error = MMC_ERR_NONE;
+		
+		sc->lm_req->done(sc->lm_req);
+		sc->lm_req = NULL;
+		lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDRESPEND);
+		device_printf(sc->lm_dev, "command response done\n");
 	}
 
 	if (status & LPC_SD_STATUS_CMDSENT) {
-
+		device_printf(sc->lm_dev, "command sent\n");
+		cmd = sc->lm_req->cmd;
+		cmd->error = MMC_ERR_NONE;
+		sc->lm_req->done(sc->lm_req);
+		sc->lm_req = NULL;
+		lpc_mmc_write_4(sc, LPC_SD_CLEAR, LPC_SD_STATUS_CMDSENT);
 	}
-
+#if 0
 	if (status & LPC_SD_STATUS_DATAEND) {
 
 	}
@@ -183,41 +298,87 @@
 	}
 
 	if (status & LPC_SD_STATUS_CMDACTIVE) {
+		if (sc->lm_req == NULL)
+			return;
+
+		cmd = sc->lm_req->cmd;
+		printf("sc=%p req=%p\n", sc, sc->lm_req);
+		printf("cmd=%p\n", cmd);
 
+		cmd->resp[0] = lpc_mmc_read_4(sc, LPC_SD_RESP0);
+		cmd->error = MMC_ERR_NONE;
+		sc->lm_req->done(sc->lm_req);
+		sc->lm_req = NULL;
+		lpc_mmc_write_4(sc, LPC_SD_MASK0, (0xffffffff & ~LPC_SD_STATUS_CMDACTIVE));
 	}
+#endif
+
+	lpc_mmc_write_4(sc, LPC_SD_CLEAR, 0xfff);
+	lpc_mmc_write_4(sc, LPC_SD_MASK0, 0);
+	device_printf(sc->lm_dev, "isr done\n");
+}
+
+static int
+lpc_mmc_request(device_t bus, device_t child, struct mmc_request *req)
+{
+	struct lpc_mmc_softc *sc = device_get_softc(bus);
 
-	if (status & LPC_SD_STATUS_TXACTIVE) {
+	device_printf(bus, "lpc_mmc_request: %p\n", req);
 
-	}
+	lpc_mmc_lock(sc);
+	if (sc->lm_req)
+		return (EBUSY);
 
-	if (status & LPC_SD_STATUS_RXACTIVE) {
+	sc->lm_req = req;
+	//sc->lm_state = STARTED_CMD;
 
-	}
+	if (req->cmd->data)
+		lpc_mmc_setup_xfer(sc, req->cmd->data);
 
+	lpc_mmc_cmd(sc, req->cmd);
+	lpc_mmc_unlock(sc);
 
+	return (0);
 }
 
 static void
 lpc_mmc_cmd(struct lpc_mmc_softc *sc, struct mmc_command *cmd)
 {
-	struct mmc_data *data = cmd->data;
-	uint32_t cmd = 0;
+	//struct mmc_data *data = cmd->data;
+	uint32_t cmdreg = 0;
+
+	device_printf(sc->lm_dev, "cmd: %d arg: 0x%08x\n", cmd->opcode, cmd->arg);
 
-	if (MMC_RSP(cmd->flags) != 0)
-		cmd |= LPC_SD_COMMAND_RESPONSE;
+	if (cmd->flags & MMC_RSP_PRESENT)
+		cmdreg |= LPC_SD_COMMAND_RESPONSE;
 
 	if (MMC_RSP(cmd->flags) == MMC_RSP_R2)
-		cmd |= LPC_SD_COMMAND_LONGRSP;
+		cmdreg |= LPC_SD_COMMAND_LONGRSP;
+
+	if (MMC_RSP(cmd->flags) == MMC_RSP_R3)
+		sc->lm_flags |= LPC_SD_FLAGS_IGNORECRC;
+
+	cmdreg |= LPC_SD_COMMAND_ENABLE;
+	cmdreg |= (cmd->opcode & LPC_SD_COMMAND_CMDINDEXMASK);
 
+	lpc_mmc_write_4(sc, LPC_SD_MASK0, 0xffffffff);
+	lpc_mmc_write_4(sc, LPC_SD_MASK1, 0xffffffff);
 	lpc_mmc_write_4(sc, LPC_SD_ARGUMENT, cmd->arg);
-	lpc_mmc_write_4(sc, LPC_SD_COMMAND, cmd);
+	lpc_mmc_write_4(sc, LPC_SD_COMMAND, cmdreg);
+
+	device_printf(sc->lm_dev, "cmdarg: 0x%08x, cmdreg: 0x%08x\n", cmd->arg, cmdreg);
 }
 
 static void
-lpc_mmc_setup_xfer(struct lpc_mmc_softc *sc, struct mmc_data *data
+lpc_mmc_setup_xfer(struct lpc_mmc_softc *sc, struct mmc_data *data)
 {
 	uint32_t datactrl = 0;
 
+	sc->lm_data = data;
+	sc->lm_xfer_done = 0;
+
+	device_printf(sc->lm_dev, "setup_xfer data: %p\n", data);
+
 	if (data->flags & MMC_DATA_READ)
 		sc->lm_xfer_direction = DIRECTION_READ;
 
@@ -227,6 +388,62 @@
 	datactrl |= (sc->lm_xfer_direction 
 	    ? LPC_SD_DATACTRL_WRITE 
 	    : LPC_SD_DATACTRL_READ);
+
+	datactrl |= LPC_SD_DATACTRL_ENABLE;
+
+	if (data->len > LPC_SD_BLOCKSIZE)
+		datactrl |= 0x90;
+
+	device_printf(sc->lm_dev, "setup_xfer: datactrl=0x%08x\n", datactrl);
+
+	lpc_mmc_write_4(sc, LPC_SD_DATATIMER, 0x100000);
+	lpc_mmc_write_4(sc, LPC_SD_DATALENGTH, data->len);
+	lpc_mmc_write_4(sc, LPC_SD_DATACTRL, datactrl);
+
+	if (sc->lm_xfer_direction == DIRECTION_WRITE)
+		lpc_mmc_fifo_write(sc);
+}
+
+static void
+lpc_mmc_fifo_read(struct lpc_mmc_softc *sc)
+{
+	do {
+		uint32_t *data = sc->lm_data->data;
+		int i;
+		int todo = sc->lm_data->len > 16 ? 16 : (sc->lm_data->len / 4) - sc->lm_xfer_done; 
+		device_printf(sc->lm_dev, "reading from fifo %d words [%d of %d words done]\n",
+		    todo, sc->lm_xfer_done, (sc->lm_data->len / 4));
+	
+		for (i = 0; i < 16; i++) {
+			data[sc->lm_xfer_done] = 
+			    lpc_mmc_read_4(sc, LPC_SD_FIFO);
+			sc->lm_xfer_done++;
+		}
+
+		/*
+		bus_space_read_region_4(sc->lm_bst, sc->lm_bsh,
+		    LPC_SD_FIFO,
+		    &data[sc->lm_xfer_done],
+		    todo);
+		*/
+
+		//sc->lm_xfer_done += 16;
+		device_printf(sc->lm_dev, "currently done %d\n", sc->lm_xfer_done);
+		kdb_enter("data read", "data read");
+	} while (lpc_mmc_read_4(sc, LPC_SD_STATUS) & LPC_SD_STATUS_RXDATAAVLBL);
+
+	device_printf(sc->lm_dev, "partial read done\n");
+}
+
+static void
+lpc_mmc_fifo_write(struct lpc_mmc_softc *sc)
+{
+	do {
+		lpc_mmc_write_4(sc, LPC_SD_FIFO,
+		    ((uint32_t *)sc->lm_data->data)[sc->lm_xfer_done]);
+
+		sc->lm_xfer_done++;
+	} while (lpc_mmc_read_4(sc, LPC_SD_STATUS) & LPC_SD_STATUS_TXDATAAVLBL);
 }
 
 static int
@@ -283,25 +500,6 @@
 }
 
 static int
-lpc_mmc_request(device_t bus, device_t child, struct mmc_request *req)
-{
-	struct lpc_mmc_softc *sc = device_get_softc(bus);
-
-	lpc_mmc_lock(sc);
-	if (sc->lm_req)
-		return (EBUSY);
-
-	sc->lm_req = req;
-	sc->lm_state = STARTED_CMD;
-
-	if (req->cmd->data)
-		lpc_mmc_setup_xfer(sc, req->cmd->data);
-
-	lpc_mmc_cmd(sc, req->cmd);
-	lpc_mmc_unlosck(sc);
-}
-
-static int
 lpc_mmc_write_ivar(device_t bus, device_t child, int which,
     uintptr_t value)
 {
@@ -345,6 +543,63 @@
 	return (0);
 }
 
+static int
+lpc_mmc_update_ios(device_t bus, device_t child)
+{
+	struct lpc_mmc_softc *sc = device_get_softc(bus);
+	struct mmc_ios *ios = &sc->lm_host.ios;
+	uint32_t clkdiv = 0;
+
+	if (ios->bus_width == bus_width_4)
+		clkdiv |= LPC_SD_CLOCK_WIDEBUS;
+
+	/* Calculate clock divider */
+	clkdiv = (LPC_SD_CLK / (2 * ios->clock)) - 1;
+
+	/* Clock rate should not exceed rate requested in ios */
+	if ((LPC_SD_CLK / (2 * (clkdiv + 1))) > ios->clock)
+		clkdiv++;
+
+	device_printf(bus, "clock: %dHz, clkdiv: %d\n", ios->clock, clkdiv);
+
+	lpc_mmc_write_4(sc, LPC_SD_CLOCK, clkdiv | LPC_SD_CLOCK_ENABLE);
+	return (0);
+}
+
+static int
+lpc_mmc_get_ro(device_t bus, device_t child)
+{
+
+	return (0);
+}
+
+static int
+lpc_mmc_acquire_host(device_t bus, device_t child)
+{
+	struct lpc_mmc_softc *sc = device_get_softc(bus);
+	int error = 0;
+
+	lpc_mmc_lock(sc);
+	while (sc->lm_bus_busy)
+		error = mtx_sleep(sc, &sc->lm_mtx, PZERO, "mmcah", 0);
+
+	sc->lm_bus_busy++;
+	lpc_mmc_unlock(sc);
+	return (error);
+}
+
+static int
+lpc_mmc_release_host(device_t bus, device_t child)
+{
+	struct lpc_mmc_softc *sc = device_get_softc(bus);
+
+	lpc_mmc_lock(sc);
+	sc->lm_bus_busy--;
+	wakeup(sc);
+	lpc_mmc_unlock(sc);
+	return (0);
+}
+
 static device_method_t lpc_mmc_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		lpc_mmc_probe),

==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpcreg.h#3 (text+ko) ====

@@ -133,6 +133,13 @@
 #define	LPC_CLKPWR_USB_CTRL_PLL_LOCK	(1 << 0)
 #define	LPC_CLKPWR_USBDIV_CTRL		0x1c
 #define	LPC_CLKPWR_MS_CTRL		0x80
+#define	LPC_CLKPWR_MS_CTRL_DISABLE_SD	(1 << 10)
+#define	LPC_CLKPWR_MS_CTRL_CLOCK_EN	(1 << 9)
+#define	LPC_CLKPWR_MS_CTRL_MSSDIO23_PAD	(1 << 8)
+#define	LPC_CLKPWR_MS_CTRL_MSSDIO1_PAD	(1 << 7)
+#define	LPC_CLKPWR_MS_CTRL_MSSDIO0_PAD	(1 << 6)
+#define	LPC_CLKPWR_MS_CTRL_SD_CLOCK	(1 << 5)
+#define	LPC_CLKPWR_MS_CTRL_CLKDIV_MASK	0xf
 #define	LPC_CLKPWR_DMACLK_CTRL		0xe8
 #define	LPC_CLKPWR_FLASHCLK_CTRL	0xc8
 #define	LPC_CLKPWR_MACCLK_CTRL		0x90
@@ -183,32 +190,42 @@
 /*
  * MMC/SD controller. (from UM10326: LPC32x0 User manual, page 436)
  */
-#define	LPC_SD_POWER			0x8000
-#define	LPC_SD_CLOCK			0x8004
-#define	LPC_SD_ARGUMENT			0x8008
-#define	LPC_SD_COMMAND			0x800c
+#define	LPC_SD_CLK			(13 * 1000 * 1000)	// 13Mhz
+#define	LPC_SD_POWER			0x00
+#define	LPC_SD_POWER_OPENDRAIN		(1 << 6)
+#define	LPC_SD_POWER_CTRL_OFF		0x00
+#define	LPC_SD_POWER_CTRL_ON		0x03
+#define	LPC_SD_CLOCK			0x04
+#define	LPC_SD_CLOCK_WIDEBUS		(1 << 11)
+#define	LPC_SD_CLOCK_BYPASS		(1 << 10)
+#define	LPC_SD_CLOCK_PWRSAVE		(1 << 9)
+#define	LPC_SD_CLOCK_ENABLE		(1 << 8)
+#define	LPC_SD_CLOCK_CLKDIVMASK		0xff
+#define	LPC_SD_ARGUMENT			0x08
+#define	LPC_SD_COMMAND			0x0c
 #define	LPC_SD_COMMAND_ENABLE		(1 << 10)
 #define	LPC_SD_COMMAND_PENDING		(1 << 9)
 #define	LPC_SD_COMMAND_INTERRUPT	(1 << 8)
 #define	LPC_SD_COMMAND_LONGRSP		(1 << 7)
 #define	LPC_SD_COMMAND_RESPONSE		(1 << 6)
-#define	LPC_SD_COMMAND_CMDINDEXMASK	0x1f
-#define	LPC_SD_RESPCMD			0x8010
-#define	LPC_SD_RESP0			0x8014
-#define	LPC_SD_RESP1			0x8018
-#define	LPC_SD_RESP2			0x801c
-#define	LPC_SD_RESP3			0x8020
-#define	LPC_SD_DATATIMER		0x8024
-#define	LPC_SD_DATALENGTH		0x8028
-#define	LPC_SD_DATACTRL			0x802c
+#define	LPC_SD_COMMAND_CMDINDEXMASK	0x3f
+#define	LPC_SD_RESPCMD			0x10
+#define	LPC_SD_RESP0			0x14
+#define	LPC_SD_RESP1			0x18
+#define	LPC_SD_RESP2			0x1c
+#define	LPC_SD_RESP3			0x20
+#define	LPC_SD_DATATIMER		0x24
+#define	LPC_SD_DATALENGTH		0x28
+#define	LPC_SD_DATACTRL			0x2c
 #define	LPC_SD_DATACTRL_BLOCKSIZESHIFT	4
 #define	LPC_SD_DATACTRL_BLOCKSIZEMASK	0xf
 #define	LPC_SD_DATACTRL_DMAENABLE	(1 << 3)
 #define	LPC_SD_DATACTRL_MODE		(1 << 2)
-#define	LPC_SD_DATACTRL_DIRECTION	(1 << 1)
+#define	LPC_SD_DATACTRL_WRITE		(0 << 1)
+#define	LPC_SD_DATACTRL_READ		(1 << 1)
 #define	LPC_SD_DATACTRL_ENABLE		(1 << 0)
-#define	LPC_SD_DATACNT			0x8030
-#define	LPC_SD_STATUS			0x8034
+#define	LPC_SD_DATACNT			0x30
+#define	LPC_SD_STATUS			0x34
 #define	LPC_SD_STATUS_RXDATAAVLBL	(1 << 21)
 #define	LPC_SD_STATUS_TXDATAAVLBL	(1 << 20)
 #define	LPC_SD_STATUS_RXFIFOEMPTY	(1 << 19)
@@ -219,11 +236,23 @@
 #define	LPC_SD_STATUS_TXFIFOHALFEMPTY	(1 << 14)
 #define	LPC_SD_STATUS_RXACTIVE		(1 << 13)
 #define	LPC_SD_STATUS_TXACTIVE		(1 << 12)
-#define	LPC_SD_CLEAR			0x8038
-#define	LPC_SD_MASK0			0x803c
-#define	LPC_SD_MASK1			0x8040
-#define	LPC_SD_FIFOCNT			0x8048
-#define	LPC_SD_FIFO			0x8080
+#define	LPC_SD_STATUS_CMDACTIVE		(1 << 11)
+#define	LPC_SD_STATUS_DATABLOCKEND	(1 << 10)
+#define	LPC_SD_STATUS_STARTBITERR	(1 << 9)
+#define	LPC_SD_STATUS_DATAEND		(1 << 8)
+#define	LPC_SD_STATUS_CMDSENT		(1 << 7)
+#define	LPC_SD_STATUS_CMDRESPEND	(1 << 6)
+#define	LPC_SD_STATUS_RXOVERRUN		(1 << 5)
+#define	LPC_SD_STATUS_TXUNDERRUN	(1 << 4)
+#define	LPC_SD_STATUS_DATATIMEOUT	(1 << 3)
+#define	LPC_SD_STATUS_CMDTIMEOUT	(1 << 2)
+#define	LPC_SD_STATUS_DATACRCFAIL	(1 << 1)
+#define	LPC_SD_STATUS_CMDCRCFAIL	(1 << 0)
+#define	LPC_SD_CLEAR			0x38
+#define	LPC_SD_MASK0			0x03c
+#define	LPC_SD_MASK1			0x40
+#define	LPC_SD_FIFOCNT			0x48
+#define	LPC_SD_FIFO			0x80
 
 /*
  * USB OTG controller (from UM10326: LPC32x0 User manual, page 410)

==== //depot/projects/soc2011/jceel_lpc/sys/boot/fdt/dts/ea3250.dts#5 (text+ko) ====

@@ -205,6 +205,13 @@
 		#size-cells = <1>;
 		compatible = "simple-bus";
 		ranges = <0x0 0x20000000 0x10000000>;
+
+		lpcmmc@98000 {
+			compatible = "lpc,mmc";
+			reg = <0x98000 0x4000>;
+			interrupts = <15>;
+			interrupt-parent = <&PIC>;
+		};
 	};
 
 	chosen {

==== //depot/projects/soc2011/jceel_lpc/sys/dev/mmc/mmc.c#2 (text+ko) ====

@@ -107,7 +107,7 @@
 
 SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
 
-static int mmc_debug;
+static int mmc_debug = 3;
 SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level");
 
 /* bus entry points */
@@ -1540,3 +1540,4 @@
 
 DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
 DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
+DRIVER_MODULE(mmc, lpcmmc, mmc_driver, mmc_devclass, NULL, NULL);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107140013.p6E0DT06088903>