From owner-p4-projects@FreeBSD.ORG Thu Jul 14 00:13:30 2011 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 225841065670; Thu, 14 Jul 2011 00:13:30 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D6DF9106564A for ; Thu, 14 Jul 2011 00:13:29 +0000 (UTC) (envelope-from jceel@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id C3B438FC19 for ; Thu, 14 Jul 2011 00:13:29 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p6E0DTYU088916 for ; Thu, 14 Jul 2011 00:13:29 GMT (envelope-from jceel@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p6E0DT06088903 for perforce@freebsd.org; Thu, 14 Jul 2011 00:13:29 GMT (envelope-from jceel@freebsd.org) Date: Thu, 14 Jul 2011 00:13:29 GMT Message-Id: <201107140013.p6E0DT06088903@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to jceel@freebsd.org using -f From: Jakub Wojciech Klama To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 196124 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Jul 2011 00:13:30 -0000 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 #include +#include + #include #include #include @@ -53,10 +55,16 @@ #include #include +#include +#include + #include #include #include +#include +#include + 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);