/* on CB710 in HP nx9500: * src_freq_idx == 0 * indexes 1-7 work as written in the table * indexes 0,8-15 give no clock output
*/
pci_read_config_dword(pdev, 0x48, &src_freq_idx);
src_freq_idx = (src_freq_idx >> 16) & 0xF;
src_hz = cb710_src_freq_mhz[src_freq_idx] * 1000000;
for (divider_idx = 0; divider_idx < CB710_MAX_DIVIDER_IDX; ++divider_idx) { if (hz >= src_hz >> cb710_clock_divider_log2[divider_idx]) break;
}
staticvoid __cb710_mmc_enable_irq(struct cb710_slot *slot, unsignedshort enable, unsignedshort mask)
{ /* clear global IE
* - it gets set later if any interrupt sources are enabled */
mask |= CB710_MMC_IE_IRQ_ENABLE;
/* look like interrupt is fired whenever * WORD[0x0C] & WORD[0x10] != 0; * -> bit 15 port 0x0C seems to be global interrupt enable
*/
spin_lock_irqsave(&reader->irq_lock, flags); /* this is the only thing irq_lock protects */
__cb710_mmc_enable_irq(slot, enable, mask);
spin_unlock_irqrestore(&reader->irq_lock, flags);
}
status = cb710_read_port_16(slot, CB710_MMC_STATUS_PORT);
if (status & CB710_MMC_S0_FIFO_UNDERFLOW) { /* it is just a guess, so log it */
dev_dbg(cb710_slot_dev(slot), "CHECK : ignoring bit 6 in status %04X\n", status);
cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT,
CB710_MMC_S0_FIFO_UNDERFLOW);
status &= ~CB710_MMC_S0_FIFO_UNDERFLOW;
}
if (status & CB710_MMC_STATUS_ERROR_EVENTS) {
dev_dbg(cb710_slot_dev(slot), "CHECK : returning EIO on status %04X\n", status);
cb710_write_port_8(slot, CB710_MMC_STATUS0_PORT, status & 0xFF);
cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT,
CB710_MMC_S1_RESET); return -EIO;
}
/* 'what' is a bit in MMC_STATUS1 */ if ((status >> 8) & what) {
cb710_write_port_8(slot, CB710_MMC_STATUS1_PORT, what); return 1;
}
return 0;
}
staticint cb710_wait_for_event(struct cb710_slot *slot, u8 what)
{ int err = 0; unsigned limit = 2000000; /* FIXME: real timeout */
#ifdef CONFIG_CB710_DEBUG
u32 e, x;
e = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT); #endif
while (!(err = cb710_check_event(slot, what))) { if (!--limit) {
cb710_dump_regs(cb710_slot_to_chip(slot),
CB710_DUMP_REGS_MMC);
err = -ETIMEDOUT; break;
}
udelay(1);
}
#ifdef CONFIG_CB710_DEBUG
x = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
limit = 2000000 - limit; if (limit > 100)
dev_dbg(cb710_slot_dev(slot), "WAIT10: waited %d loops, what %d, entry val %08X, exit val %08X\n",
limit, what, e, x); #endif return err < 0 ? err : 0;
}
staticint cb710_wait_while_busy(struct cb710_slot *slot, uint8_t mask)
{ unsigned limit = 500000; /* FIXME: real timeout */ int err = 0;
#ifdef CONFIG_CB710_DEBUG
u32 e, x;
e = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT); #endif
while (cb710_read_port_8(slot, CB710_MMC_STATUS2_PORT) & mask) { if (!--limit) {
cb710_dump_regs(cb710_slot_to_chip(slot),
CB710_DUMP_REGS_MMC);
err = -ETIMEDOUT; break;
}
udelay(1);
}
#ifdef CONFIG_CB710_DEBUG
x = cb710_read_port_32(slot, CB710_MMC_STATUS_PORT);
limit = 500000 - limit; if (limit > 100)
dev_dbg(cb710_slot_dev(slot), "WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n",
limit, mask, e, x); #endif return err;
}
dev_vdbg(cb710_slot_dev(slot), "set up for %zu block%s of %zu bytes\n",
count, str_plural(count), blocksize);
}
staticvoid cb710_mmc_fifo_hack(struct cb710_slot *slot)
{ /* without this, received data is prepended with 8-bytes of zeroes */
u32 r1, r2; int ok = 0;
/* Windows driver returned 0 for commands for which no response * is expected. It happened that there were only two such commands * used: MMC_GO_IDLE_STATE and MMC_GO_INACTIVE_STATE so it might * as well be a bug in that driver. * * Original driver set bit 14 for MMC/SD application * commands. There's no difference 'on the wire' and * it apparently works without it anyway.
*/
switch (flags & MMC_CMD_MASK) { case MMC_CMD_AC: cb_flags = CB710_MMC_CMD_AC; break; case MMC_CMD_ADTC: cb_flags = CB710_MMC_CMD_ADTC; break; case MMC_CMD_BC: cb_flags = CB710_MMC_CMD_BC; break; case MMC_CMD_BCR: cb_flags = CB710_MMC_CMD_BCR; break;
}
if (flags & MMC_RSP_BUSY)
cb_flags |= CB710_MMC_RSP_BUSY;
if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
cb_flags |= CB710_MMC_DATA_READ;
if (flags & MMC_RSP_PRESENT) { /* Windows driver set 01 at bits 4,3 except for * MMC_SET_BLOCKLEN where it set 10. Maybe the * hardware can do something special about this * command? The original driver looks buggy/incomplete * anyway so we ignore this for now. * * I assume that 00 here means no response is expected.
*/
cb_flags |= CB710_MMC_RSP_PRESENT;
if (flags & MMC_RSP_136)
cb_flags |= CB710_MMC_RSP_136; if (!(flags & MMC_RSP_CRC))
cb_flags |= CB710_MMC_RSP_NO_CRC;
}
mmc->ops = &cb710_mmc_host;
mmc->f_max = val;
mmc->f_min = val >> cb710_clock_divider_log2[CB710_MAX_DIVIDER_IDX];
mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
mmc->caps = MMC_CAP_4_BIT_DATA; /* * In cb710_wait_for_event() we use a fixed timeout of ~2s, hence let's * inform the core about it. A future improvement should instead make * use of the cmd->busy_timeout.
*/
mmc->max_busy_timeout = CB710_MMC_REQ_TIMEOUT_MS;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.