#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
+#include <minix/log.h>
#include <minix/minlib.h>
/* system headers */
/* local headers */
#include "mmchost.h"
-#include "mmclog.h"
/* used for logging */
-static struct mmclog log = {
+static struct log log = {
.name = "mmc_block",
.log_level = LEVEL_INFO,
.log_func = default_log
void
bdr_alarm(clock_t stamp)
{
- mmc_log_debug(&log, "alarm %d\n", stamp);
-
+ log_debug(&log, "alarm %d\n", stamp);
}
static int apply_env();
static void
hw_intr(unsigned int irqs)
{
- mmc_log_debug(&log, "Hardware inter left over\n");
+ log_debug(&log, "Hardware inter left over\n");
host.hw_intr(irqs);
}
} else if (strncmp(driver, "dummy", strlen("dummy") + 1) == 0) {
host_initialize_host_structure_dummy(&host);
} else {
- mmc_log_warn(&log, "Unknown driver %s\n", driver);
+ log_warn(&log, "Unknown driver %s\n", driver);
}
/* Initialize the verbosity level. */
v = 0;
v = 0;
env_parse("instance", "d", 0, &v, 0, 3);
if (host.host_set_instance(&host, v)) {
- mmc_log_warn(&log, "Failed to set mmc instance to %d\n", v);
+ log_warn(&log, "Failed to set mmc instance to %d\n", v);
return -1; /* NOT OK */
}
return OK;
i = j = part_count = sub_part_count = 0;
if (!slot) {
- mmc_log_debug(&log,
- "Not handling open on non existing slot\n");
+ log_debug(&log, "Not handling open on non existing slot\n");
return EIO;
}
assert(slot->host != NULL);
if (!slot->host->card_detect(slot)) {
- mmc_log_debug(&log, "No card inserted in the SD slot\n");
+ log_debug(&log, "No card inserted in the SD slot\n");
return EIO;
}
if (slot->card.state == SD_MODE_DATA_TRANSFER_MODE) {
assert(slot->card.open_ct >= 0);
slot->card.open_ct++;
- mmc_log_trace(&log, "increased open count to %d\n",
+ log_trace(&log, "increased open count to %d\n",
slot->card.open_ct);
return OK;
}
/* We did not have an sd-card inserted so we are going to probe for it
*/
- mmc_log_debug(&log, "First open on (%d)\n", minor);
+ log_debug(&log, "First open on (%d)\n", minor);
if (!host.card_initialize(slot)) {
// * TODO: set card state to INVALID until removed? */
return EIO;
partition(&mmc_driver, 0 /* first card on bus */ , P_PRIMARY,
0 /* atapi device?? */ );
- mmc_log_trace(&log, "descr \toffset(bytes) size(bytes)\n", minor);
+ log_trace(&log, "descr \toffset(bytes) size(bytes)\n", minor);
- mmc_log_trace(&log, "disk %d\t0x%016llx 0x%016llx\n", i,
+ 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_trace(&log, "part %d\t0x%016llx 0x%016llx\n", i,
+ 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_trace(&log,
+ 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_debug(&log, "Found %d partitions and %d sub partitions\n",
+ 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);
slot = get_slot(minor);
if (!slot) {
- mmc_log_debug(&log,
- "Not handling open on non existing slot\n");
+ log_debug(&log, "Not handling open on non existing slot\n");
return EIO;
}
* return */
if (slot->card.open_ct > 1) {
slot->card.open_ct--;
- mmc_log_trace(&log, "decreased open count to %d\n",
+ log_trace(&log, "decreased open count to %d\n",
slot->card.open_ct);
return OK;
}
assert(slot->card.open_ct == 1);
- mmc_log_debug(&log,
- "freeing the block device as it is no longer used\n");
+ log_debug(&log, "freeing the block device as it is no longer used\n");
/* release the card as check the open_ct should be 0 */
slot->host->card_release(&slot->card);
/* Get the current "device" geometry */
dev = block_part(minor);
if (dev == NULL) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Transfer requested on unknown device minor(%d)\n", minor);
/* Unknown device */
return ENXIO;
}
- mmc_log_trace(&log, "I/O on minor(%d) %s at 0x%016llx\n", minor,
+ log_trace(&log, "I/O on minor(%d) %s at 0x%016llx\n", minor,
(do_write) ? "Write" : "Read", position);
slot = get_slot(minor);
assert(slot);
if (slot->card.blk_size == 0) {
- mmc_log_warn(&log, "Request on a card with block size of 0\n");
+ log_warn(&log, "Request on a card with block size of 0\n");
return EINVAL;
}
if (slot->card.blk_size > COPYBUFF_SIZE) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Card block size (%d) exceeds internal buffer size %d\n",
slot->card.blk_size, COPYBUFF_SIZE);
return EINVAL;
* parameters of transfers, in those cases we return EINVAL */
if (position % slot->card.blk_size != 0) {
/* Starting at a block boundary */
- mmc_log_warn(&log,
+ log_warn(&log,
"Requests must start at a block boundary"
"(start,block size)=(%016llx,%08x)\n", position,
slot->card.blk_size);
/* Are we trying to start reading past the end */
if (position >= dev->dv_size) {
- mmc_log_warn(&log, "start reading past drive size\n");
+ log_warn(&log, "start reading past drive size\n");
return 0;
};
assert(ciov != NULL);
if (ciov->iov_size % blk_size != 0) {
/* transfer a multiple of blk_size */
- mmc_log_warn(&log,
+ log_warn(&log,
"Requests must start at a block boundary "
"(start,block size)=(%016llx,%08x)\n", position,
slot->card.blk_size);
}
if (ciov->iov_size <= 0) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Invalid iov size for iov %d of %d size\n",
counter, nr_req, ciov->iov_size);
return EINVAL;
io_size = dev->dv_size - (position + bytes_written);
};
- mmc_log_trace(&log,
+ log_trace(&log,
"I/O %s request(%d/%d) iov(grant,size,iosize,"
"offset)=(%d,%d,%d,%d)\n",
(do_write) ? "write" : "read", counter + 1, nr_req,
i * blk_size, (vir_bytes) copybuff,
blk_size);
if (r != OK) {
- mmc_log_warn(&log,
+ log_warn(&log,
"I/O write error: %s iov(base,size)=(%d,%d)"
" at offset=%d\n",
strerror(_SIGN r), ciov->iov_addr,
r = copyto(endpt, ciov->iov_addr, i * blk_size,
(vir_bytes) copybuff, blk_size);
if (r != OK) {
- mmc_log_warn(&log,
+ log_warn(&log,
"I/O read error: %s iov(base,size)=(%d,%d)"
" at offset=%d\n",
strerror(_SIGN r), ciov->iov_addr,
{
/* IOCTL handling */
struct sd_slot *slot;
- mmc_log_trace(&log,
+ log_trace(&log,
"enter (minor,request,endpoint,grant)=(%d,%lu,%d)\n", minor,
request, endpt, grant);
slot = get_slot(minor);
if (!slot) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Doing ioctl on non existing block device(%d)\n", minor);
return EINVAL;
}
switch (request) {
case DIOCOPENCT:
// TODO: add a check for card validity */
- mmc_log_trace(&log, "returning open count %d\n",
+ log_trace(&log, "returning open count %d\n",
slot->card.open_ct);
/* return the current open count */
return sys_safecopyto(endpt, grant, 0,
dev = NULL;
slot = get_slot(minor);
if (!slot) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Device information requested for non existing partition "
"minor(%d)\n", minor);
return NULL;
}
if (!slot->host->card_detect(slot)) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Device information requested from empty slot(%d)\n",
minor);
return NULL;
if (minor < 5) {
/* we are talking about the first disk */
dev = &slot->card.part[minor];
- mmc_log_trace(&log,
+ log_trace(&log,
"returning partition(%d) (base,size)=(0x%016llx,0x%016llx)\n",
minor, dev->dv_base, dev->dv_size);
} else if (minor >= 128 && minor < 128 + 16) {
/* sub partitions of the first disk we don't care about the
* rest */
dev = &slot->card.subpart[minor - 128];
- mmc_log_trace(&log,
+ log_trace(&log,
"returning sub partition(%d) (base,size)=(0x%016llx,0x%016llx)\n",
minor - 128, dev->dv_base, dev->dv_size);
} else {
- mmc_log_warn(&log,
+ log_warn(&log,
"Device information requested for non existing "
"partition minor(%d)\n", minor);
}
static void
sef_local_startup()
{
- mmc_log_info(&log, "Initializing the MMC block device\n");
+ log_info(&log, "Initializing the MMC block device\n");
if (apply_env()) {
- mmc_log_warn(&log,
- "Failed while applying environment settings\n");
+ log_warn(&log, "Failed while applying environment settings\n");
exit(EXIT_FAILURE);
}
if (host.host_init(&host)) {
- mmc_log_warn(&log,
- "Failed to initialize the host controller\n");
+ log_warn(&log, "Failed to initialize the host controller\n");
exit(EXIT_FAILURE);
}
/*
* sef_local_startup */
switch (type) {
case SEF_INIT_FRESH:
- mmc_log_info(&log, "System event framework fresh start\n");
+ log_info(&log, "System event framework fresh start\n");
break;
case SEF_INIT_LU:
/* Restore the state. post update */
- mmc_log_info(&log, "System event framework live update\n");
+ log_info(&log, "System event framework live update\n");
break;
case SEF_INIT_RESTART:
- mmc_log_info(&log, "System event framework post restart\n");
+ log_info(&log, "System event framework post restart\n");
break;
}
blockdriver_announce(type);
{
struct sd_slot *slot;
- mmc_log_debug(&log, "System event framework signal handler sig(%d)\n",
+ log_debug(&log, "System event framework signal handler sig(%d)\n",
signo);
/* Only check for termination signal, ignore anything else. */
if (signo != SIGTERM)
slot = get_slot(0);
assert(slot);
if (slot->card.open_ct > 0) {
- mmc_log_debug(&log, "Not responding to SIGTERM (open count=%d)\n",
+ log_debug(&log, "Not responding to SIGTERM (open count=%d)\n",
slot->card.open_ct);
return;
}
- mmc_log_info(&log, "MMC driver exit");
+ log_info(&log, "MMC driver exit");
exit(0);
}
/* a minor from the first disk */
return &host.slot[0];
} else {
- mmc_log_trace(&log,
+ log_trace(&log,
"Device information requested for non existing partition "
"minor(%d)\n", minor);
return NULL;
if (level < 0 || level >= 4) {
return;
}
- mmc_log_info(&log, "Setting verbosity level to %d\n", level);
+ log_info(&log, "Setting verbosity level to %d\n", level);
log.log_level = level;
if (host.set_log_level) {
host.set_log_level(level);
#include <minix/com.h>
#include <minix/vm.h>
#include <minix/spin.h>
+#include <minix/log.h>
#include <minix/mmio.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
/* local headers */
-#include "mmclog.h"
#include "mmchost.h"
/* header imported from netbsd */
#endif
#endif
-#define SANE_TIMEOUT 500000 /* 500 MS */
+#define SANE_TIMEOUT 500000 /* 500 ms */
/*
* Define a structure to be used for logging
*/
-static struct mmclog log = {
+static struct log log = {
.name = "mmc_host_mmchs",
.log_level = LEVEL_INFO,
.log_func = default_log
while (!(read32(base_address + MMCHS_SD_SYSSTATUS)
& MMCHS_SD_SYSSTATUS_RESETDONE)) {
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log, "mmc init timeout\n");
+ log_warn(&log, "mmc init timeout\n");
return 1;
}
}
while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
!= MMCHS_SD_HCTL_SDBP_ON) {
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log, "mmc init timeout SDBP not set\n");
+ log_warn(&log, "mmc init timeout SDBP not set\n");
return 1;
}
}
spin_init(&spin, SANE_TIMEOUT);
while ((read32(base_address + MMCHS_SD_SYSCTL) & MMCHS_SD_SYSCTL_ICS)
!= MMCHS_SD_SYSCTL_ICS_STABLE) {
-
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log, "clock not stable\n");
+ log_warn(&log, "clock not stable\n");
return 1;
}
}
MMCHS_SD_IE_TC_ENABLE_ENABLE);
/* enable error interrupts */
- /* NOTE: We are currently skipping the BADA interrupt it does get
- * raised for unknown reasons */
- set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0x0fffffffu);
+ set32(base_address + MMCHS_SD_IE, MMCHS_SD_IE_ERROR_MASK, 0xffffffffu);
/* clear the error interrupts */
set32(base_address + MMCHS_SD_STAT, MMCHS_SD_STAT_ERROR_MASK,
while ((read32(base_address + MMCHS_SD_STAT) & MMCHS_SD_STAT_CC)
!= MMCHS_SD_STAT_CC_RAISED) {
if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
- mmc_log_warn(&log, "%s, error stat %x\n",
+ log_warn(&log, "%s, error stat %x\n",
__FUNCTION__,
read32(base_address + MMCHS_SD_STAT));
return 1;
}
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log,
- "Interrupt not raised during init\n");
+ log_warn(&log, "Interrupt not raised during init\n");
return 1;
}
}
return 0;
}
+void
+intr_deassert(int mask)
+{
+ if (read32(base_address + MMCHS_SD_STAT) & 0x8000) {
+ 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);
+ } else {
+ write32(base_address + MMCHS_SD_STAT, mask);
+ }
+}
+
+/* pointer to the data to transfer used in bwr and brr */
+unsigned char *io_data;
+int io_len;
+
+void
+handle_bwr()
+{
+ /* handle buffer write ready interrupts. These happen in a non
+ * predictable way (eg. we send a request but don't know if we are
+ * first doing to get a request completed before we are allowed to
+ * send the data to the harware or not */
+ uint32_t value;
+ uint32_t count;
+ assert(read32(base_address +
+ MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN);
+ assert(io_data != NULL);
+
+ for (count = 0; count < io_len; count += 4) {
+ while (!(read32(base_address +
+ MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BWE_EN)) {
+ log_warn(&log,
+ "Error expected Buffer to be write enabled(%d)\n",
+ count);
+ }
+ *((char *) &value) = io_data[count];
+ *((char *) &value + 1) = io_data[count + 1];
+ *((char *) &value + 2) = io_data[count + 2];
+ *((char *) &value + 3) = io_data[count + 3];
+ write32(base_address + MMCHS_SD_DATA, value);
+ }
+ intr_deassert(MMCHS_SD_IE_BWR_ENABLE);
+ /* expect buffer to be write enabled */
+ io_data = NULL;
+}
+
+void
+handle_brr()
+{
+ /* handle buffer read ready interrupts. genrally these happen afther
+ * the data is read from the sd card. */
+
+ uint32_t value;
+ uint32_t count;
+
+ /* Problem BRE should be true */
+ assert(read32(base_address +
+ MMCHS_SD_PSTATE) & MMCHS_SD_PSTATE_BRE_EN);
+
+ assert(io_data != NULL);
+
+ for (count = 0; count < io_len; count += 4) {
+ value = read32(base_address + MMCHS_SD_DATA);
+ io_data[count] = *((char *) &value);
+ io_data[count + 1] = *((char *) &value + 1);
+ io_data[count + 2] = *((char *) &value + 2);
+ io_data[count + 3] = *((char *) &value + 3);
+ }
+ /* clear bbr interrupt */
+ intr_deassert(MMCHS_SD_IE_BRR_ENABLE_ENABLE);
+ io_data = NULL;
+}
+
static void
mmchs_hw_intr(unsigned int irqs)
{
- mmc_log_warn(&log, "Hardware interrupt left over\n");
+ log_warn(&log, "Hardware interrupt left over (0x%08lx)\n",
+ read32(base_address + MMCHS_SD_STAT));
#ifdef USE_INTR
if (sys_irqenable(&hook_id) != OK)
switch (_ENDPOINT_P(m.m_source)) {
case CLOCK:
/* Timeout. */
- // w_timeout(); /* a.o. set w_status */
- mmc_log_warn(&log, "TIMEOUT\n");
+ 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,
+ while ((v =
+ read32(base_address +
+ MMCHS_SD_STAT)) != 0) {
+ if (v & MMCHS_SD_IE_BWR_ENABLE) {
+ handle_bwr();
+ continue;
+ }
+ if (v & MMCHS_SD_IE_BRR_ENABLE) {
+ handle_brr();
+ continue;
+ }
+
+ if (v & mask) {
+ /* this is the normal return
+ * path, the mask given
+ * matches the pending
+ * interrupt. canel the alarm
+ * and return */
+ sys_setalarm(0, 0);
+ return 0;
+ } else if (v & (1 << 15)) {
+ return 1; /* error */
+ }
+
+ log_warn(&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;
}
+ /* if we end up here re-enable interrupts for
+ * the next round */
+ if (sys_irqenable(&hook_id) != OK)
+ printf
+ ("Failed to re-enable irqenable irq\n");
+ break;
default:
/*
* unhandled message. queue it and
blockdriver_mq_queue(&m, ipc_status);
}
} else {
- mmc_log_debug(&log, "Other\n");
/*
* unhandled message. queue it and handle it in the
* blockdriver loop.
counter++;
v = read32(base_address + MMCHS_SD_STAT);
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log,
+ log_warn(&log,
"Timeout waiting for interrupt (%d) value 0x%08x mask 0x%08x\n",
counter, v, mask);
return 1;
}
+ if (v & MMCHS_SD_IE_BWR_ENABLE) {
+ handle_bwr();
+ continue;
+ }
+ if (v & MMCHS_SD_IE_BRR_ENABLE) {
+ handle_brr();
+ continue;
+ }
if (v & mask) {
return 0;
} else if (v & 0xFF00) {
- mmc_log_debug(&log,
+ log_debug(&log,
"unexpected HW interrupt (%d) 0x%08x mask 0x%08x\n",
v, mask);
return 1;
#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)
{
/* Read current interrupt status and fail it an interrupt is already
* asserted */
+ assert(read32(base_address + MMCHS_SD_STAT) == 0);
/* Set arguments */
write32(base_address + MMCHS_SD_ARG, arg);
/* Set command */
set32(base_address + MMCHS_SD_CMD, MMCHS_SD_CMD_MASK, command);
- 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");
+ if (intr_wait(MMCHS_SD_STAT_CC)) {
+ uint32_t v = read32(base_address + MMCHS_SD_STAT);
+ intr_deassert(MMCHS_SD_STAT_CC);
+ log_warn(&log, "Failure waiting for interrupt 0x%lx\n", v);
return 1;
}
+ intr_deassert(MMCHS_SD_STAT_CC);
if ((command & MMCHS_SD_CMD_RSP_TYPE) ==
MMCHS_SD_CMD_RSP_TYPE_48B_BUSY) {
*/
if ((read32(base_address + MMCHS_SD_STAT)
& MMCHS_SD_IE_TC_ENABLE_ENABLE) == 0) {
- mmc_log_warn(&log, "TC should be raised\n");
- }
- write32(base_address + MMCHS_SD_STAT,
- MMCHS_SD_IE_TC_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;
+ log_warn(&log, "TC should be raised\n");
}
+ intr_deassert(MMCHS_SD_STAT_TC);
}
- intr_assert(MMCHS_SD_STAT_CC);
return 0;
}
/* convert the command to a hsmmc command */
int ret;
uint32_t cmd, arg;
- uint32_t count;
- uint32_t value;
cmd = MMCHS_SD_CMD_INDX_CMD(c->cmd);
arg = c->args;
}
/* read single block */
- if (c->cmd == MMC_READ_BLOCK_SINGLE) {
+ if ((c->cmd == MMC_READ_BLOCK_SINGLE) || (c->cmd == SD_APP_SEND_SCR)) {
cmd |= MMCHS_SD_CMD_DP_DATA; /* Command with data transfer */
cmd |= MMCHS_SD_CMD_MSBS_SINGLE; /* single block */
cmd |= MMCHS_SD_CMD_DDIR_READ; /* read data from card */
-
}
/* write single block */
/* check we are in a sane state */
if ((read32(base_address + MMCHS_SD_STAT) & 0xffffu)) {
- mmc_log_warn(&log, "%s, interrupt already raised stat %08x\n",
+ 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);
MMCHS_SD_IE_BWR_ENABLE,
MMCHS_SD_IE_BWR_ENABLE_ENABLE);
}
+ io_data = c->data;
+ io_len = c->data_len;
+ assert(io_len <= 0xFFF); /* only 12 bits */
+ assert(io_data != NULL);
+ set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, io_len);
}
- set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
-
ret = mmchs_send_cmd(cmd, arg);
- /* copy response into cmd->resp */
- switch (c->resp_type) {
- case RESP_LEN_48_CHK_BUSY:
- case RESP_LEN_48:
- c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
- break;
- case RESP_LEN_136:
- c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
- c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
- c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
- c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
- break;
- case NO_RESPONSE:
- break;
- default:
- return 1;
- }
-
if (cmd & MMCHS_SD_CMD_DP_DATA) {
- count = 0;
assert(c->data_len);
if (cmd & MMCHS_SD_CMD_DDIR_READ) {
- 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 */
- }
-
- for (count = 0; count < c->data_len; count += 4) {
- value = read32(base_address + MMCHS_SD_DATA);
- c->data[count] = *((char *) &value);
- c->data[count + 1] = *((char *) &value + 1);
- c->data[count + 2] = *((char *) &value + 2);
- c->data[count + 3] = *((char *) &value + 3);
- }
-
/* Wait for TC */
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");
+ intr_deassert(MMCHS_SD_IE_TC_ENABLE_ENABLE);
+ log_warn(&log,
+ "(Read) 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 */
- write32(base_address + MMCHS_SD_STAT,
- MMCHS_SD_IE_BRR_ENABLE_CLEAR);
+ /* disable the bbr interrupt */
set32(base_address + MMCHS_SD_IE,
MMCHS_SD_IE_BRR_ENABLE,
MMCHS_SD_IE_BRR_ENABLE_DISABLE);
} else {
- /* Wait for the MMCHS_SD_IE_BWR_ENABLE interrupt */
- 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) = c->data[count];
- *((char *) &value + 1) = c->data[count + 1];
- *((char *) &value + 2) = c->data[count + 2];
- *((char *) &value + 3) = c->data[count + 3];
- write32(base_address + MMCHS_SD_DATA, value);
- }
-
/* Wait for TC */
- if (intr_wait(MMCHS_SD_IE_TC_ENABLE_CLEAR)) {
- intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
- mmc_log_warn(&log,
+ if (intr_wait(MMCHS_SD_IE_TC_ENABLE_ENABLE)) {
+ intr_deassert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
+ log_warn(&log,
"(Write) Timeout waiting for transfer complete\n");
return 1;
}
- intr_assert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
+ intr_deassert(MMCHS_SD_IE_TC_ENABLE_CLEAR);
+
set32(base_address + MMCHS_SD_IE,
MMCHS_SD_IE_BWR_ENABLE,
MMCHS_SD_IE_BWR_ENABLE_DISABLE);
}
}
+
+ /* copy response into cmd->resp */
+ switch (c->resp_type) {
+ case RESP_LEN_48_CHK_BUSY:
+ case RESP_LEN_48:
+ c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
+ break;
+ case RESP_LEN_136:
+ c->resp[0] = read32(base_address + MMCHS_SD_RSP10);
+ c->resp[1] = read32(base_address + MMCHS_SD_RSP32);
+ c->resp[2] = read32(base_address + MMCHS_SD_RSP54);
+ c->resp[3] = read32(base_address + MMCHS_SD_RSP76);
+ break;
+ case NO_RESPONSE:
+ break;
+ default:
+ return 1;
+ }
+
return ret;
}
if (mmc_send_cmd(&command)) {
/* We currently only support 2.0, and 1.0 won't respond to
* this request */
- mmc_log_warn(&log, "%s, non SDHC card inserted\n",
- __FUNCTION__);
+ log_warn(&log, "%s, non SDHC card inserted\n", __FUNCTION__);
return 1;
}
if (!(command.resp[0]
== (MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN))) {
- mmc_log_warn(&log, "%s, check pattern check failed %08x\n",
+ log_warn(&log, "%s, check pattern check failed %08x\n",
__FUNCTION__, command.resp[0]);
return 1;
}
{
struct mmc_command command;
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;
- }
command.cmd = SD_APP_OP_COND;
command.resp_type = RESP_LEN_48;
MMC_OCR_2_7V_2_8V;
command.args |= MMC_OCR_HCS; /* RCA=0000 */
- if (mmc_send_cmd(&command)) {
+ if (mmc_send_app_cmd(card, &command)) {
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;
- command.args = MMC_ARG_RCA(0x0); /* RCA=0000 */
- if (mmc_send_cmd(&command)) {
- return 1;
- }
/* Send ADMD41 */
/* 0x1 << 30 == send HCS (Host capacity support) and get OCR
| MMC_OCR_2_8V_2_9V | MMC_OCR_2_7V_2_8V;
command.args |= MMC_OCR_HCS; /* RCA=0000 */
- if (mmc_send_cmd(&command)) {
+ if (mmc_send_app_cmd(card, &command)) {
return 1;
}
break;
}
if (spin_check(&spin) == FALSE) {
- mmc_log_warn(&log,
- "TIMEOUT waiting for the SD card\n");
+ log_warn(&log, "TIMEOUT waiting for the SD card\n");
}
}
card->csd[3] = command.resp[3];
if (SD_CSD_CSDVER(card->csd) != SD_CSD_CSDVER_2_0) {
- mmc_log_warn(&log, "Version 2.0 of CSD register expected\n");
+ log_warn(&log, "Version 2.0 of CSD register expected\n");
return 1;
}
/* sanity check */
- // mmc_log_warn(&log,"size = %llu bytes\n", (long long
+ // log_warn(&log,"size = %llu bytes\n", (long long
// unsigned)SD_CSD_V2_CAPACITY( card->csd) * 512);
return 0;
}
}
return 0;
}
-
int
read_single_block(struct sd_card_regs *card,
uint32_t blknr, unsigned char *buf)
command.data_len = 512;
if (mmc_send_cmd(&command)) {
- mmc_log_warn(&log, "Error sending command\n");
+ log_warn(&log, "Error sending command\n");
return 1;
}
{
struct mmc_command command;
- set32(base_address + MMCHS_SD_BLK, MMCHS_SD_BLK_BLEN, 512);
-
command.cmd = MMC_WRITE_BLOCK_SINGLE;
command.args = blknr;
command.resp_type = RESP_LEN_48;
/* write single block */
if (mmc_send_cmd(&command)) {
- mmc_log_warn(&log, "Write single block command failed\n");
+ log_warn(&log, "Write single block command failed\n");
return 1;
}
int
mmchs_host_set_instance(struct mmc_host *host, int instance)
{
- mmc_log_info(&log, "Using instance number %d\n", instance);
+ log_info(&log, "Using instance number %d\n", instance);
if (instance != 0) {
return EIO;
}
card->slot = slot;
if (card_goto_idle_state()) {
- mmc_log_warn(&log, "Failed to go idle state\n");
+ log_warn(&log, "Failed to go idle state\n");
return NULL;
}
if (card_identification()) {
- mmc_log_warn(&log, "Failed to do card_identification\n");
+ log_warn(&log, "Failed to do card_identification\n");
return NULL;
}
if (card_query_voltage_and_type(&slot->card.regs)) {
- mmc_log_warn(&log,
- "Failed to do card_query_voltage_and_type\n");
+ log_warn(&log, "Failed to do card_query_voltage_and_type\n");
return NULL;
}
if (card_identify(&slot->card.regs)) {
- mmc_log_warn(&log, "Failed to identify card\n");
+ log_warn(&log, "Failed to identify card\n");
return NULL;
}
/* We have now initialized the hardware identified the card */
if (card_csd(&slot->card.regs)) {
- mmc_log_warn(&log,
- "failed to read csd (card specific data)\n");
+ log_warn(&log, "failed to read csd (card specific data)\n");
return NULL;
}
if (select_card(&slot->card.regs)) {
- mmc_log_warn(&log, "Failed to select card\n");
+ log_warn(&log, "Failed to select card\n");
return NULL;
}
if (SD_CSD_READ_BL_LEN(slot->card.regs.csd) != 0x09) {
/* for CSD version 2.0 the value is fixed to 0x09 and means a
* block size of 512 */
- mmc_log_warn(&log, "Block size expect to be 512\n");
+ log_warn(&log, "Block size expect to be 512\n");
return NULL;
}
card->open_ct--;
card->state = SD_MODE_UNINITIALIZED;
/* TODO:Set card state */
+
return OK;
}
+++ /dev/null
-#ifndef __MMCLOG_H__
-#define __MMCLOG_H__
-/*
- * Simple logging functions for the MMC layer
- */
-
-/*
- * LEVEL_NONE do not log anything.
- * LEVEL_WARN Information that needs to be known.
- * LEVEL_INFO Basic information like startup messages and occasional events.
- * LEVEL_DEBUG debug statements about things happening that are less expected.
- * LEVEL_TRACE Way to much information for anybody.
- */
-
-#define LEVEL_NONE 0
-#define LEVEL_WARN 1
-#define LEVEL_INFO 2
-#define LEVEL_DEBUG 3
-#define LEVEL_TRACE 4
-
-static const char *level_string[5] = {
- "none",
- "warn",
- "info",
- "debug",
- "trace"
-};
-
-/*
- * struct to be initialized by the user of the logging system.
- *
- * name: The name attribute is used in logging statements do differentiate
- * drivers
- *
- * log_level The level attribute describes the requested logging level. a level
- * of 1 will only print warnings while a level of 4 will print all the trace
- * information.
- *
- * log_func The logging function to use to log, mmclog.h provides default_log
- * to display information on the kernel output buffer. As a bonus if the
- * requested log level is debug or trace the method , file and line number will
- * be printed to the steam.
- */
-struct mmclog { const char *name; int log_level;
-
- /* the logging function itself */
- void (*log_func) (struct mmclog * driver,
- int level,
- const char *file,
- const char *function, int line, const char *fmt, ...);
-
-};
-
-#define __mmc_log(driver,log_level, fmt, args...) \
- ((driver)->log_func(driver,log_level, \
- __FILE__, __FUNCTION__, __LINE__,\
- fmt, ## args))
-
-/* Log a warning */
-#define mmc_log_warn(driver, fmt, args...) \
- __mmc_log(driver, LEVEL_WARN, fmt, ## args)
-
-/* Log an information message */
-#define mmc_log_info(driver, fmt, args...) \
- __mmc_log(driver, LEVEL_INFO, fmt, ## args)
-
-/* log debugging output */
-#define mmc_log_debug(driver, fmt, args...) \
- __mmc_log(driver, LEVEL_DEBUG, fmt, ## args)
-
-/* log trace output */
-#define mmc_log_trace(driver, fmt, args...) \
- __mmc_log(driver, LEVEL_TRACE, fmt, ## args)
-
-#endif /* __MMCLOG_H__ */
-
-static void
-default_log(struct mmclog *driver,
- int level,
- const char *file, const char *function, int line, const char *fmt, ...)
-{
- va_list args;
-
- if (level > driver->log_level) {
- return;
- }
- /* If the wanted level is debug also display line/method information */
- if (driver->log_level >= LEVEL_DEBUG) {
- fprintf(stderr, "%s(%s):%s+%d(%s):", driver->name,
- level_string[level], file, line, function);
- } else {
- fprintf(stderr, "%s(%s)", driver->name, level_string[level]);
- }
-
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
-}
-
-#ifdef hacks
-static void
-hexdump(unsigned char *d, unsigned int size)
-{
- int s;
- for (s = 0; s < size; s += 4) {
- fprintf(stdout, "0x%04x 0x%02X%02X%02X%02X %c%c%c%c\n", s,
- (unsigned int) d[s], (unsigned int) d[s + 1],
- (unsigned int) d[s + 2], (unsigned int) d[s + 3], d[s],
- d[s + 1], d[s + 2], d[s + 3]);
- }
-}
-#endif