From: Kees Jongenburger Date: Fri, 19 Oct 2012 13:44:10 +0000 (+0200) Subject: mmc:development X-Git-Tag: v3.2.1~36 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch08.html?a=commitdiff_plain;h=3de9b145672dd86c2664d306e7fec254adc6d9ef;p=minix.git mmc:development * let busy loops timeout. * Start using interrupt handlers. * Allocate the ramdisk only when used. Change-Id: Ie08d66eefef3c8cd3ee16c04f74a9a50cc12b021 --- diff --git a/drivers/mmc/mmcblk.c b/drivers/mmc/mmcblk.c index 4951b33b7..d2da50a3f 100644 --- a/drivers/mmc/mmcblk.c +++ b/drivers/mmc/mmcblk.c @@ -6,6 +6,8 @@ #include #include #include +#include + /* system headers */ #include /* disk IOCTL's */ @@ -24,25 +26,13 @@ /* used for logging */ static struct mmclog log = { .name = "mmc_block", - .log_level = LEVEL_DEBUG, + .log_level = LEVEL_INFO, .log_func = default_log }; /* holding the current host controller */ static struct mmc_host host; -/*@TODO REMOVE THIS */ -void -read_tsc_64(u64_t * t) -{ -} - -u32_t -tsc_64_to_micros(u64_t tsc) -{ - return 0; -} - #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS) #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) @@ -70,12 +60,18 @@ static void sef_local_startup(); static int block_system_event_cb(int type, sef_init_info_t * info); static void block_signal_handler_cb(int signo); +void +bdr_alarm(clock_t stamp) +{ + mmc_log_debug(&log, "alarm %d\n", stamp); + +} + static int apply_env(); +static void hw_intr(unsigned int irqs); -#if 0 /* set the global logging level */ static void set_log_level(int level); -#endif /* Entry points for the BLOCK driver. */ static struct blockdriver mmc_driver = { @@ -87,20 +83,28 @@ static struct blockdriver mmc_driver = { NULL, /* no need to clean up (yet) */ block_part, /* return partition information */ NULL, /* no geometry */ - NULL, /* no interrupt processing */ - NULL, /* no alarm processing */ + hw_intr, /* left over interrupts */ + bdr_alarm, /* no alarm processing */ NULL, /* no processing of other messages */ NULL /* no threading support */ }; +static void +hw_intr(unsigned int irqs) +{ + mmc_log_debug(&log, "Hardware inter left over\n"); + host.hw_intr(irqs); +} + static int apply_env() { + long v; /* apply the env setting passed to this driver parameters accepted - * log_level=[0-4] (NONE,WARNING,INFO,DEBUG,TRACE) instance=[0-3] + * log_level=[0-4] (NONE,WARN,INFO,DEBUG,TRACE) instance=[0-3] * instance/bus number to use for this driver Passing these arguments * is done when starting the driver using the service command in the - * following way service up /sbin/mmc -args "log_level=2 instance=1 + * following way service up /sbin/mmc -args "log_level=2 instance=1 * driver=dummy" -dev /dev/c2d0 */ char driver[16]; memset(driver, '\0', 16); @@ -115,10 +119,6 @@ apply_env() } else { mmc_log_warn(&log, "Unknown driver %s\n", driver); } -#if 0 - long v; - /* The following code(env_parse) uses strtol.c and needs __aeabi_idiv */ - /* @TODO: re-enable this function when __aeabi_idiv will be present */ /* Initialize the verbosity level. */ v = 0; if (env_parse("log_level", "d", 0, &v, LEVEL_NONE, @@ -133,7 +133,6 @@ apply_env() mmc_log_warn(&log, "Failed to set mmc instance to %d\n", v); return -1; /* NOT OK */ } -#endif return OK; } @@ -185,27 +184,27 @@ block_open(dev_t minor, int access) partition(&mmc_driver, 0 /* first card on bus */ , P_PRIMARY, 0 /* atapi device?? */ ); - mmc_log_debug(&log, "descr \toffset(bytes) size(bytes)\n", minor); + mmc_log_trace(&log, "descr \toffset(bytes) size(bytes)\n", minor); - mmc_log_debug(&log, "disk %d\t0x%016llx 0x%016llx\n", i, + mmc_log_trace(&log, "disk %d\t0x%016llx 0x%016llx\n", i, slot->card.part[0].dv_base, slot->card.part[0].dv_size); for (i = 1; i < 5; i++) { if (slot->card.part[i].dv_size == 0) continue; part_count++; - mmc_log_debug(&log, "part %d\t0x%016llx 0x%016llx\n", i, + mmc_log_trace(&log, "part %d\t0x%016llx 0x%016llx\n", i, slot->card.part[i].dv_base, slot->card.part[i].dv_size); for (j = 0; j < 4; j++) { if (slot->card.subpart[(i - 1) * 4 + j].dv_size == 0) continue; sub_part_count++; - mmc_log_debug(&log, + mmc_log_trace(&log, " sub %d/%d\t0x%016llx 0x%016llx\n", i, j, slot->card.subpart[(i - 1) * 4 + j].dv_base, slot->card.subpart[(i - 1) * 4 + j].dv_size); } } - mmc_log_info(&log, "Found %d partitions and %d sub partitions\n", + mmc_log_debug(&log, "Found %d partitions and %d sub partitions\n", part_count, sub_part_count); slot->card.open_ct++; assert(slot->card.open_ct == 1); @@ -312,7 +311,7 @@ block_transfer(dev_t minor, /* minor device number */ /* Unknown device */ return ENXIO; } - mmc_log_trace(&log, "I/O %d %s 0x%llx\n", minor, + mmc_log_trace(&log, "I/O on minor(%d) %s at 0x%016llx\n", minor, (do_write) ? "Write" : "Read", position); slot = get_slot(minor); @@ -636,20 +635,18 @@ get_slot(dev_t minor) } } -#if 0 static void set_log_level(int level) { if (level < 0 || level >= 4) { return; } - mmc_log_debug(&log, "Setting verbosity level to %d\n", level); + mmc_log_info(&log, "Setting verbosity level to %d\n", level); log.log_level = level; if (host.set_log_level) { host.set_log_level(level); } } -#endif int main(int argc, char **argv) @@ -657,7 +654,6 @@ main(int argc, char **argv) /* Set and apply the environment */ env_setargs(argc, argv); - sef_local_startup(); blockdriver_task(&mmc_driver); return EXIT_SUCCESS; diff --git a/drivers/mmc/mmchost.h b/drivers/mmc/mmchost.h index 37e44c4fa..bad9d0911 100644 --- a/drivers/mmc/mmchost.h +++ b/drivers/mmc/mmchost.h @@ -117,6 +117,9 @@ struct mmc_host /* Release the card */ int (*card_release) (struct sd_card * card); + /* Additional hardware interrupts */ + void (*hw_intr) (unsigned int irqs); + /* read count blocks into existing buf */ int (*read) (struct sd_card * card, uint32_t blknr, uint32_t count, unsigned char *buf); diff --git a/drivers/mmc/mmchost_dummy.c b/drivers/mmc/mmchost_dummy.c index 3d560abae..15a741284 100644 --- a/drivers/mmc/mmchost_dummy.c +++ b/drivers/mmc/mmchost_dummy.c @@ -1,11 +1,13 @@ /* kernel headers */ #include +#include /* usr headers */ #include #include #include #include +#include /* local headers */ #include "mmclog.h" @@ -17,14 +19,14 @@ */ static struct mmclog log = { .name = "mmc_host_memory", - .log_level = LEVEL_TRACE, + .log_level = LEVEL_INFO, .log_func = default_log }; /* This is currently a dummy driver using an in-memory structure */ -#define DUMMY_SIZE_IN_BLOCKS 0xFFFu +#define DUMMY_SIZE_IN_BLOCKS 0xFFFFFu #define DUMMY_BLOCK_SIZE 512 -static char dummy_data[DUMMY_BLOCK_SIZE * DUMMY_SIZE_IN_BLOCKS]; +static char *dummy_data = NULL; static struct sd_card * init_dummy_sdcard(struct sd_slot *slot) @@ -35,6 +37,13 @@ init_dummy_sdcard(struct sd_slot *slot) assert(slot != NULL); mmc_log_info(&log, "Using a dummy card \n"); + if (dummy_data == NULL) { + dummy_data = malloc(DUMMY_BLOCK_SIZE * DUMMY_SIZE_IN_BLOCKS); + if (dummy_data == NULL) { + panic + ("Failed to allocate data for dummy mmc driver\n"); + } + } card = &slot->card; memset(card, 0, sizeof(struct sd_card)); diff --git a/drivers/mmc/mmchost_mmchs.c b/drivers/mmc/mmchost_mmchs.c index cbf5a8384..1797febae 100644 --- a/drivers/mmc/mmchost_mmchs.c +++ b/drivers/mmc/mmchost_mmchs.c @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include /* usr headers */ #include @@ -12,6 +14,7 @@ #include #include #include +#include /* local headers */ #include "mmclog.h" @@ -25,6 +28,14 @@ /* omap /hardware related */ #include "omap_mmc.h" +#define USE_INTR + +#ifdef USE_INTR +static int hook_id = 1; +#define OMAP3_MMC1_IRQ 83 /* MMC/SD module 1 */ +#endif + +#define SANE_TIMEOUT 500000 /* 500 MS */ /* * Define a structure to be used for logging */ @@ -38,14 +49,14 @@ static struct mmclog log = { #define BIT(x)(0x1 << x) /* Write a uint32_t value to a memory address. */ -inline void +static inline void write32(uint32_t address, uint32_t value) { REG(address) = value; } /* Read an uint32_t from a memory address */ -inline uint32_t +static inline uint32_t read32(uint32_t address) { @@ -53,7 +64,7 @@ read32(uint32_t address) } /* Set a 32 bits value depending on a mask */ -inline void +static inline void set32(uint32_t address, uint32_t mask, uint32_t value) { uint32_t val; @@ -75,13 +86,11 @@ static uint32_t base_address; int mmchs_init(uint32_t instance) { - int counter; - uint32_t value; - counter = 0; + uint32_t value; value = 0; - struct minix_mem_range mr; + spin_t spin; mr.mr_base = MMCHS1_REG_BASE; mr.mr_limit = MMCHS1_REG_BASE + 0x400; @@ -106,11 +115,14 @@ mmchs_init(uint32_t instance) MMCHS_SD_SYSCONFIG_SOFTRESET); /* Read sysstatus to know when it's done */ + + spin_init(&spin, SANE_TIMEOUT); while (!(read32(base_address + MMCHS_SD_SYSSTATUS) & MMCHS_SD_SYSSTATUS_RESETDONE)) { - /* TODO:Add proper delay and escape route */ - - counter++; + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, "mmc init timeout\n"); + return 1; + } } /* Set SD default capabilities */ @@ -164,12 +176,14 @@ mmchs_init(uint32_t instance) set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP, MMCHS_SD_HCTL_SDBP_ON); - /* TODO: Add padconf stuff here as documented in the TRM */ - + // /* TODO: Add padconf/pinmux stuff here as documented in the TRM */ + spin_init(&spin, SANE_TIMEOUT); while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP) != MMCHS_SD_HCTL_SDBP_ON) { - /* TODO:Add proper delay and escape route */ - counter++; + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, "mmc init timeout SDBP not set\n"); + return 1; + } } /* Enable internal clock and clock to the card */ @@ -177,16 +191,23 @@ mmchs_init(uint32_t instance) MMCHS_SD_SYSCTL_ICE_EN); // @TODO Fix external clock enable , this one is very slow + // but we first need faster context switching + //set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD, + // (0x20 << 6)); set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD, - (0x3ff << 6)); + (0x5 << 6)); + set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN, MMCHS_SD_SYSCTL_CEN_EN); - counter = 0; + spin_init(&spin, SANE_TIMEOUT); while ((read32(base_address + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS) != MMCHS_SD_SYSCTL_ICS_STABLE) { - /* TODO:Add proper delay and escape route */ - counter++; + + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, "clock not stable\n"); + return 1; + } } /* @@ -216,7 +237,7 @@ mmchs_init(uint32_t instance) /* command 0 , type other commands not response etc) */ write32(base_address + MMCHS_SD_CMD, 0x00); - counter = 0; + spin_init(&spin, SANE_TIMEOUT); while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC) != MMCHS_SD_STAT_CC_RAISED) { if (read32(base_address + MMCHS_SD_STAT) & 0x8000) { @@ -225,7 +246,12 @@ mmchs_init(uint32_t instance) read32(base_address + MMCHS_SD_STAT)); return 1; } - counter++; + + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, + "Interrupt not raised during init\n"); + return 1; + } } /* clear the cc interrupt status */ @@ -238,41 +264,151 @@ mmchs_init(uint32_t instance) set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_INIT, MMCHS_SD_CON_INIT_NOINIT); + /* Set timeout */ + set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO, + MMCHS_SD_SYSCTL_DTO_2POW27); + /* Clean the MMCHS_SD_STAT register */ write32(base_address + MMCHS_SD_STAT, 0xffffffffu); +#ifdef USE_INTR + hook_id = 1; + if (sys_irqsetpolicy(OMAP3_MMC1_IRQ, 0, &hook_id) != OK) { + printf("mmc: couldn't set IRQ policy %d\n", OMAP3_MMC1_IRQ); + return 1; + } + /* enable signaling from MMC controller towards interrupt controller */ + write32(base_address + MMCHS_SD_ISE, 0xffffffffu); +#endif + return 0; } +static void +mmchs_hw_intr(unsigned int irqs) +{ + mmc_log_warn(&log, "Hardware interrupt left over\n"); + +#ifdef USE_INTR + if (sys_irqenable(&hook_id) != OK) + printf("couldn't re-enable interrupt \n"); +#endif + /* Leftover interrupt(s) received; ack it/them. */ +} + +/*===========================================================================* + * w_intr_wait * + *===========================================================================*/ +static int +intr_wait(int mask) +{ + long v; +#ifdef USE_INTR + if (sys_irqenable(&hook_id) != OK) + printf("Failed to enable irqenable irq\n"); +/* Wait for a task completion interrupt. */ + message m; + int ipc_status; + int ticks = SANE_TIMEOUT * sys_hz() / 1000000; + + if (ticks <= 0) ticks =1; + while (1) { + int rr; + sys_setalarm(ticks, 0); + if ((rr = driver_receive(ANY, &m, &ipc_status)) != OK) { + panic("driver_receive failed: %d", rr); + }; + if (is_ipc_notify(ipc_status)) { + switch (_ENDPOINT_P(m.m_source)) { + case CLOCK: + /* Timeout. */ + // w_timeout(); /* a.o. set w_status */ + mmc_log_warn(&log, "TIMEOUT\n"); + return 1; + break; + case HARDWARE: + v = read32(base_address + MMCHS_SD_STAT); + if (v & mask) { + sys_setalarm(0, 0); + return 0; + } else if (v & (1 << 15)){ + return 1; /* error */ + } else { + mmc_log_debug(&log, "unexpected HW interrupt 0x%08x mask 0X%08x\n", v, mask); + if (sys_irqenable(&hook_id) != OK) + printf + ("Failed to re-enable irqenable irq\n"); + continue; + // return 1; + } + default: + /* + * unhandled message. queue it and + * handle it in the blockdriver loop. + */ + blockdriver_mq_queue(&m, ipc_status); + } + } else { + mmc_log_debug(&log, "Other\n"); + /* + * unhandled message. queue it and handle it in the + * blockdriver loop. + */ + blockdriver_mq_queue(&m, ipc_status); + } + } + sys_setalarm(0, 0); /* cancel the alarm */ + +#else + spin_t spin; + spin_init(&spin, SANE_TIMEOUT); + /* Wait for completion */ + int counter =0; + while (1 == 1) { + counter ++; + v = read32(base_address + MMCHS_SD_STAT); + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, "Timeout waiting for interrupt (%d) value 0x%08x mask 0x%08x\n",counter, v,mask); + return 1; + } + if (v & mask) { + return 0; + } else if (v & 0xFF00) { + mmc_log_debug(&log, "unexpected HW interrupt (%d) 0x%08x mask 0x%08x\n", v, mask); + return 1; + } + } + return 1; /* unreached */ +#endif /* USE_INTR */ +} + +void +intr_assert(int mask) +{ + if (read32(base_address + MMCHS_SD_STAT) & 0x8000) { + mmc_log_debug(&log, "%s, error stat %08x\n", __FUNCTION__, + read32(base_address + MMCHS_SD_STAT)); + set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK, + 0xffffffffu); + } else { + write32(base_address + MMCHS_SD_STAT, mask); + } +} + int mmchs_send_cmd(uint32_t command, uint32_t arg) { - int count = 0; /* Read current interrupt status and fail it an interrupt is already * asserted */ - if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) { - mmc_log_warn(&log, "%s, interrupt already raised stat %08x\n", - __FUNCTION__, read32(base_address + MMCHS_SD_STAT)); - write32(base_address + MMCHS_SD_STAT, - MMCHS_SD_IE_CC_ENABLE_CLEAR); - // return 1; - } /* Set arguments */ write32(base_address + MMCHS_SD_ARG, arg); /* Set command */ set32(base_address + MMCHS_SD_CMD, MMCHS_SD_CMD_MASK, command); - /* Wait for completion */ - while ((read32(base_address + MMCHS_SD_STAT) & 0xffffu) == 0x0) { - count++; - } - - if (read32(base_address + MMCHS_SD_STAT) & 0x8000) { - mmc_log_warn(&log, "%s, error stat %08x\n", __FUNCTION__, - read32(base_address + MMCHS_SD_STAT)); - set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK, - 0xffffffffu); + if (intr_wait(MMCHS_SD_STAT_CC | MMCHS_SD_IE_TC_ENABLE_CLEAR)) { + intr_assert(MMCHS_SD_STAT_CC); + mmc_log_warn(&log, "Failure waiting for interrupt\n"); return 1; } @@ -281,16 +417,20 @@ mmchs_send_cmd(uint32_t command, uint32_t arg) /* * Command with busy response *CAN* also set the TC bit if they exit busy */ - while ((read32(base_address + MMCHS_SD_STAT) + if ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) { - count++; + mmc_log_warn(&log, "TC should be raised\n"); } write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR); - } - /* clear the cc status */ - write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR); + if (intr_wait(MMCHS_SD_STAT_CC | MMCHS_SD_IE_TC_ENABLE_CLEAR)) { + intr_assert(MMCHS_SD_STAT_CC); + mmc_log_warn(&log, "Failure waiting for clear\n"); + return 1; + } + } + intr_assert(MMCHS_SD_STAT_CC); return 0; } @@ -383,10 +523,11 @@ card_identification() int card_query_voltage_and_type(struct sd_card_regs *card) { - + spin_t spin; command.cmd = MMC_APP_CMD; command.resp_type = RESP_LEN_48; command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */ + if (mmc_send_cmd(&command)) { return 1; } @@ -405,6 +546,7 @@ card_query_voltage_and_type(struct sd_card_regs *card) return 1; } /* @todo wait for max 1 ms */ + spin_init(&spin, SANE_TIMEOUT); while (!(command.resp[0] & MMC_OCR_MEM_READY)) { command.cmd = MMC_APP_CMD; command.resp_type = RESP_LEN_48; @@ -432,6 +574,10 @@ card_query_voltage_and_type(struct sd_card_regs *card) if ((command.resp[0] & MMC_OCR_MEM_READY)) { break; } + if (spin_check(&spin) == FALSE) { + mmc_log_warn(&log, + "TIMEOUT waiting for the SD card\n"); + } } card->ocr = command.resp[3]; @@ -536,15 +682,18 @@ read_single_block(struct sd_card_regs *card, | MMCHS_SD_CMD_MSBS_SINGLE /* single block */ | MMCHS_SD_CMD_DDIR_READ /* read data from card */ , blknr)) { + mmc_log_warn(&log, "Error sending command\n"); return 1; } - while ((read32(base_address + MMCHS_SD_STAT) - & MMCHS_SD_IE_BRR_ENABLE_ENABLE) == 0) { - count++; + if (intr_wait(MMCHS_SD_IE_BRR_ENABLE_ENABLE)) { + intr_assert(MMCHS_SD_IE_BRR_ENABLE_ENABLE); + mmc_log_warn(&log, "Timeout waiting for interrupt\n"); + return 1; } if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN)) { + mmc_log_warn(&log, "Problem BRE should be true\n"); return 1; /* We are not allowed to read data from the * data buffer */ } @@ -558,11 +707,12 @@ read_single_block(struct sd_card_regs *card, } /* Wait for TC */ - while ((read32(base_address + - MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE) - == 0) { - count++; + if (intr_wait(MMCHS_SD_IE_TC_ENABLE_ENABLE)) { + intr_assert(MMCHS_SD_IE_TC_ENABLE_ENABLE); + mmc_log_warn(&log, "Timeout waiting for interrupt\n"); + return 1; } + write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR); /* clear and disable the bbr interrupt */ @@ -579,17 +729,21 @@ write_single_block(struct sd_card_regs *card, uint32_t count; uint32_t value; - count = 0; + if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) { + mmc_log_warn(&log, "%s, interrupt already raised stat %08x\n", + __FUNCTION__, read32(base_address + MMCHS_SD_STAT)); + write32(base_address + MMCHS_SD_STAT, + MMCHS_SD_IE_CC_ENABLE_CLEAR); + // return 1; + } set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE, MMCHS_SD_IE_BWR_ENABLE_ENABLE); + count = 0; + // set32(base_address + MMCHS_SD_IE, 0xfff , 0xfff); set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512); - /* Set timeout */ - set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_DTO, - MMCHS_SD_SYSCTL_DTO_2POW27); - /* write single block */ if (mmchs_send_cmd(MMCHS_SD_CMD_INDX_CMD(MMC_WRITE_BLOCK_SINGLE) | MMCHS_SD_CMD_DP_DATA /* Command with data transfer */ @@ -597,19 +751,32 @@ write_single_block(struct sd_card_regs *card, | MMCHS_SD_CMD_MSBS_SINGLE /* single block */ | MMCHS_SD_CMD_DDIR_WRITE /* write to the card */ , blknr)) { + mmc_log_warn(&log, "Write single block command failed\n"); + mmc_log_trace(&log, "STAT=(0x%08x)\n", + read32(base_address + MMCHS_SD_STAT)); return 1; } /* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */ - while ((read32(base_address + - MMCHS_SD_STAT) & MMCHS_SD_IE_BWR_ENABLE) == 0) { - count++; + if (intr_wait(MMCHS_SD_IE_BWR_ENABLE)) { + intr_assert(MMCHS_SD_IE_BWR_ENABLE); + mmc_log_warn(&log, "WFI failed\n"); + return 1; } + /* clear the interrupt directly */ + intr_assert(MMCHS_SD_IE_BWR_ENABLE); if (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) { + mmc_log_warn(&log, + "Error expected Buffer to be write enabled\n"); return 1; /* not ready to write data */ } + + for (count = 0; count < 512; count += 4) { + while (!(read32(base_address + MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)){ + mmc_log_trace(&log, "Error expected Buffer to be write enabled(%d)\n", count); + } *((char *) &value) = buf[count]; *((char *) &value + 1) = buf[count + 1]; *((char *) &value + 2) = buf[count + 2]; @@ -617,17 +784,14 @@ write_single_block(struct sd_card_regs *card, write32(base_address + MMCHS_SD_DATA, value); } + /* Wait for TC */ - while ((read32(base_address + - MMCHS_SD_STAT) & MMCHS_SD_IE_TC_ENABLE_ENABLE) - == 0) { - count++; + if (intr_wait(MMCHS_SD_IE_TC_ENABLE_CLEAR)) { + intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR); + mmc_log_warn(&log, "(Write) Timeout waiting for transfer complete\n"); + return 1; } - write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_TC_ENABLE_CLEAR); - write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_CC_ENABLE_CLEAR); /* finished. - */ - /* clear the bwr interrupt FIXME is this right when writing? */ - write32(base_address + MMCHS_SD_STAT, MMCHS_SD_IE_BWR_ENABLE_CLEAR); + intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR); set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_BWR_ENABLE, MMCHS_SD_IE_BWR_ENABLE_DISABLE); return 0; @@ -661,7 +825,7 @@ mmchs_host_set_instance(struct mmc_host *host, int instance) int mmchs_host_reset(struct mmc_host *host) { - mmchs_init(1); + // mmchs_init(1); return 0; } @@ -675,7 +839,7 @@ mmchs_card_detect(struct sd_slot *slot) struct sd_card * mmchs_card_initialize(struct sd_slot *slot) { - mmchs_init(1); + // mmchs_init(1); struct sd_card *card; card = &slot->card; @@ -785,6 +949,7 @@ host_initialize_host_structure_mmchs(struct mmc_host *host) host->card_detect = mmchs_card_detect; host->card_initialize = mmchs_card_initialize; host->card_release = mmchs_card_release; + host->hw_intr = mmchs_hw_intr; host->read = mmchs_host_read; host->write = mmchs_host_write; diff --git a/drivers/mmc/omap_mmc.h b/drivers/mmc/omap_mmc.h index 46011ebda..02dca94ea 100644 --- a/drivers/mmc/omap_mmc.h +++ b/drivers/mmc/omap_mmc.h @@ -23,6 +23,7 @@ #define MMCHS_SD_SYSCTL 0x22c /* SD System control (reset,clocks and timeout) */ #define MMCHS_SD_STAT 0x230 /* SD Interrupt status */ #define MMCHS_SD_IE 0x234 /* SD Interrupt Enable register */ +#define MMCHS_SD_ISE 0x238 /* SD Interrupt Signal Enable register */ #define MMCHS_SD_CAPA 0x240 /* Capabilities of the host controller */ #define MMCHS_SD_CUR_CAPA 0x248 /* Current capabilities of the host controller */ @@ -146,7 +147,7 @@ #define MMCHS_SD_SYSCTL_DTO (0xf << 16) /* Data timeout counter */ #define MMCHS_SD_SYSCTL_DTO_2POW13 (0x0 << 16) /* TCF x 2^13 */ #define MMCHS_SD_SYSCTL_DTO_2POW14 (0x1 << 16) /* TCF x 2^14 */ -#define MMCHS_SD_SYSCTL_DTO_2POW27 (0x3 << 16) /* TCF x 2^27 */ +#define MMCHS_SD_SYSCTL_DTO_2POW27 (0xe << 16) /* TCF x 2^27 */ #define MMCHS_SD_STAT_ERRI (0x01 << 15) /* Error interrupt */ #define MMCHS_SD_STAT_ERROR_MASK (0xff << 15 | 0x3 << 24 | 0x03 << 28) diff --git a/etc/system.conf b/etc/system.conf index 5bd104950..154e940ac 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -549,6 +549,9 @@ service mmc { system PRIVCTL # 4 + IRQCTL # 19 + ; + irq 83; # IRQ 83 allowed ; };