static int sdhi_intr(void __iomem *base) { unsigned long state = sd_ctrl_read32(base, CTL_STATUS); if (state & ALL_ERROR) { sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR); sd_ctrl_write32(base, CTL_IRQ_MASK, ALL_ERROR | sd_ctrl_read32(base, CTL_IRQ_MASK)); return -EINVAL; } if (state & TMIO_STAT_CMDRESPEND) { sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND); sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND | sd_ctrl_read32(base, CTL_IRQ_MASK)); return 0; } if (state & TMIO_STAT_RXRDY) { sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY); sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN | sd_ctrl_read32(base, CTL_IRQ_MASK)); return 0; } if (state & TMIO_STAT_DATAEND) { sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND); sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_DATAEND | sd_ctrl_read32(base, CTL_IRQ_MASK)); return 0; } return -EAGAIN; }
static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd) { int err, c = cmd->opcode; switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: c |= RESP_NONE; break; case MMC_RSP_R1: c |= RESP_R1; break; case MMC_RSP_R1B: c |= RESP_R1B; break; case MMC_RSP_R2: c |= RESP_R2; break; case MMC_RSP_R3: c |= RESP_R3; break; default: return -EINVAL; } /* No interrupts so this may not be cleared */ sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND); sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND | sd_ctrl_read32(base, CTL_IRQ_MASK)); sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg); sd_ctrl_write16(base, CTL_SD_CMD, c); sd_ctrl_write32(base, CTL_IRQ_MASK, ~(TMIO_STAT_CMDRESPEND | ALL_ERROR) & sd_ctrl_read32(base, CTL_IRQ_MASK)); err = sdhi_boot_wait_resp_end(base); if (err) return err; cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE); return 0; }
/* Set MMC clock / power. * Note: This controller uses a simple divider scheme therefore it cannot * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as * MMC wont run that fast, it has to be clocked at 12MHz which is the next * slowest setting. */ static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios) { if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY) return -EBUSY; if (ios->clock) sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ios->clock | CLK_MMC_ENABLE); /* Power sequence - OFF -> ON -> UP */ switch (ios->power_mode) { case MMC_POWER_OFF: /* power down SD bus */ sdhi_boot_mmc_clk_stop(base); break; case MMC_POWER_ON: /* power up SD bus */ break; case MMC_POWER_UP: /* start bus clock */ sdhi_boot_mmc_clk_start(base); break; } switch (ios->bus_width) { case MMC_BUS_WIDTH_1: sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0); break; case MMC_BUS_WIDTH_4: sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0); break; } /* Let things settle. delay taken from winCE driver */ udelay(140); return 0; }
static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity, unsigned long block, unsigned short *buf) { int err, i; /* CMD17 - Read */ { struct mmc_command cmd; cmd.opcode = MMC_READ_SINGLE_BLOCK | \ TRANSFER_READ | DATA_PRESENT; if (high_capacity) cmd.arg = block; else cmd.arg = block * TMIO_BBS; cmd.flags = MMC_RSP_R1; err = sdhi_boot_request(base, &cmd); if (err) return err; } sd_ctrl_write32(base, CTL_IRQ_MASK, ~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN) & sd_ctrl_read32(base, CTL_IRQ_MASK)); err = sdhi_boot_wait_resp_end(base); if (err) return err; sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS); for (i = 0; i < TMIO_BBS / sizeof(*buf); i++) *buf++ = sd_ctrl_read16(base, RESP_CMD12); err = sdhi_boot_wait_resp_end(base); if (err) return err; return 0; }
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i) { u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) | (i & TMIO_MASK_IRQ); sd_ctrl_write32(host, CTL_IRQ_MASK, mask); }