PERFORCE change 196124 for review
Jakub Wojciech Klama
jceel at FreeBSD.org
Thu Jul 14 00:13:30 UTC 2011
http://p4web.freebsd.org/@@196124?ac=10
Change 196124 by jceel at 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 at 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);
More information about the p4-projects
mailing list