Loading drivers/mmc/host/mmci.c +20 −78 Original line number Original line Diff line number Diff line Loading @@ -46,10 +46,6 @@ static unsigned int fmax = 515633; * is asserted (likewise for RX) * is asserted (likewise for RX) * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY * is asserted (likewise for RX) * is asserted (likewise for RX) * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware * and will not work at all. * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when * using DMA. * @sdio: variant supports SDIO * @sdio: variant supports SDIO * @st_clkdiv: true if using a ST-specific clock divider algorithm * @st_clkdiv: true if using a ST-specific clock divider algorithm */ */ Loading @@ -59,8 +55,6 @@ struct variant_data { unsigned int datalength_bits; unsigned int datalength_bits; unsigned int fifosize; unsigned int fifosize; unsigned int fifohalfsize; unsigned int fifohalfsize; bool broken_blockend; bool broken_blockend_dma; bool sdio; bool sdio; bool st_clkdiv; bool st_clkdiv; }; }; Loading @@ -76,7 +70,6 @@ static struct variant_data variant_u300 = { .fifohalfsize = 8 * 4, .fifohalfsize = 8 * 4, .clkreg_enable = 1 << 13, /* HWFCEN */ .clkreg_enable = 1 << 13, /* HWFCEN */ .datalength_bits = 16, .datalength_bits = 16, .broken_blockend_dma = true, .sdio = true, .sdio = true, }; }; Loading @@ -86,7 +79,6 @@ static struct variant_data variant_ux500 = { .clkreg = MCI_CLK_ENABLE, .clkreg = MCI_CLK_ENABLE, .clkreg_enable = 1 << 14, /* HWFCEN */ .clkreg_enable = 1 << 14, /* HWFCEN */ .datalength_bits = 24, .datalength_bits = 24, .broken_blockend = true, .sdio = true, .sdio = true, .st_clkdiv = true, .st_clkdiv = true, }; }; Loading Loading @@ -210,8 +202,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) host->data = data; host->data = data; host->size = data->blksz * data->blocks; host->size = data->blksz * data->blocks; host->data_xfered = 0; host->data_xfered = 0; host->blockend = false; host->dataend = false; mmci_init_sg(host, data); mmci_init_sg(host, data); Loading Loading @@ -288,21 +278,26 @@ static void mmci_data_irq(struct mmci_host *host, struct mmc_data *data, mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) unsigned int status) { { struct variant_data *variant = host->variant; /* First check for errors */ /* First check for errors */ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { u32 remain, success; /* Calculate how far we are into the transfer */ remain = readl(host->base + MMCIDATACNT) << 2; success = data->blksz * data->blocks - remain; dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); if (status & MCI_DATACRCFAIL) if (status & MCI_DATACRCFAIL) { /* Last block was not successful */ host->data_xfered = ((success / data->blksz) - 1 * data->blksz); data->error = -EILSEQ; data->error = -EILSEQ; else if (status & MCI_DATATIMEOUT) } else if (status & MCI_DATATIMEOUT) { host->data_xfered = success; data->error = -ETIMEDOUT; data->error = -ETIMEDOUT; else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) } else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) { host->data_xfered = success; data->error = -EIO; data->error = -EIO; } /* Force-complete the transaction */ host->blockend = true; host->dataend = true; /* /* * We hit an error condition. Ensure that any data * We hit an error condition. Ensure that any data Loading @@ -321,61 +316,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, } } } } /* if (status & MCI_DATABLOCKEND) * On ARM variants in PIO mode, MCI_DATABLOCKEND dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); * is always sent first, and we increase the * transfered number of bytes for that IRQ. Then * MCI_DATAEND follows and we conclude the transaction. * * On the Ux500 single-IRQ variant MCI_DATABLOCKEND * doesn't seem to immediately clear from the status, * so we can't use it keep count when only one irq is * used because the irq will hit for other reasons, and * then the flag is still up. So we use the MCI_DATAEND * IRQ at the end of the entire transfer because * MCI_DATABLOCKEND is broken. * * In the U300, the IRQs can arrive out-of-order, * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND, * so for this case we use the flags "blockend" and * "dataend" to make sure both IRQs have arrived before * concluding the transaction. (This does not apply * to the Ux500 which doesn't fire MCI_DATABLOCKEND * at all.) In DMA mode it suffers from the same problem * as the Ux500. */ if (status & MCI_DATABLOCKEND) { /* * Just being a little over-cautious, we do not * use this progressive update if the hardware blockend * flag is unreliable: since it can stay high between * IRQs it will corrupt the transfer counter. */ if (!variant->broken_blockend) host->data_xfered += data->blksz; host->blockend = true; } if (status & MCI_DATAEND) host->dataend = true; /* if (status & MCI_DATAEND) { * On variants with broken blockend we shall only wait for dataend, * on others we must sync with the blockend signal since they can * appear out-of-order. */ if (host->dataend && (host->blockend || variant->broken_blockend)) { mmci_stop_data(host); mmci_stop_data(host); /* Reset these flags */ if (!data->error) host->blockend = false; /* The error clause is handled above, success! */ host->dataend = false; /* * Variants with broken blockend flags need to handle the * end of the entire transfer here. */ if (variant->broken_blockend && !data->error) host->data_xfered += data->blksz * data->blocks; host->data_xfered += data->blksz * data->blocks; if (!data->stop) { if (!data->stop) { Loading Loading @@ -770,7 +718,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) struct variant_data *variant = id->data; struct variant_data *variant = id->data; struct mmci_host *host; struct mmci_host *host; struct mmc_host *mmc; struct mmc_host *mmc; unsigned int mask; int ret; int ret; /* must have platform data */ /* must have platform data */ Loading Loading @@ -951,12 +898,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto irq0_free; goto irq0_free; } } mask = MCI_IRQENABLE; writel(MCI_IRQENABLE, host->base + MMCIMASK0); /* Don't use the datablockend flag if it's broken */ if (variant->broken_blockend) mask &= ~MCI_DATABLOCKEND; writel(mask, host->base + MMCIMASK0); amba_set_drvdata(dev, mmc); amba_set_drvdata(dev, mmc); Loading drivers/mmc/host/mmci.h +1 −4 Original line number Original line Diff line number Diff line Loading @@ -137,7 +137,7 @@ #define MCI_IRQENABLE \ #define MCI_IRQENABLE \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) MCI_CMDRESPENDMASK|MCI_CMDSENTMASK) /* These interrupts are directed to IRQ1 when two IRQ lines are available */ /* These interrupts are directed to IRQ1 when two IRQ lines are available */ #define MCI_IRQ1MASK \ #define MCI_IRQ1MASK \ Loading Loading @@ -177,9 +177,6 @@ struct mmci_host { struct timer_list timer; struct timer_list timer; unsigned int oldstat; unsigned int oldstat; bool blockend; bool dataend; /* pio stuff */ /* pio stuff */ struct sg_mapping_iter sg_miter; struct sg_mapping_iter sg_miter; unsigned int size; unsigned int size; Loading Loading
drivers/mmc/host/mmci.c +20 −78 Original line number Original line Diff line number Diff line Loading @@ -46,10 +46,6 @@ static unsigned int fmax = 515633; * is asserted (likewise for RX) * is asserted (likewise for RX) * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY * is asserted (likewise for RX) * is asserted (likewise for RX) * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware * and will not work at all. * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when * using DMA. * @sdio: variant supports SDIO * @sdio: variant supports SDIO * @st_clkdiv: true if using a ST-specific clock divider algorithm * @st_clkdiv: true if using a ST-specific clock divider algorithm */ */ Loading @@ -59,8 +55,6 @@ struct variant_data { unsigned int datalength_bits; unsigned int datalength_bits; unsigned int fifosize; unsigned int fifosize; unsigned int fifohalfsize; unsigned int fifohalfsize; bool broken_blockend; bool broken_blockend_dma; bool sdio; bool sdio; bool st_clkdiv; bool st_clkdiv; }; }; Loading @@ -76,7 +70,6 @@ static struct variant_data variant_u300 = { .fifohalfsize = 8 * 4, .fifohalfsize = 8 * 4, .clkreg_enable = 1 << 13, /* HWFCEN */ .clkreg_enable = 1 << 13, /* HWFCEN */ .datalength_bits = 16, .datalength_bits = 16, .broken_blockend_dma = true, .sdio = true, .sdio = true, }; }; Loading @@ -86,7 +79,6 @@ static struct variant_data variant_ux500 = { .clkreg = MCI_CLK_ENABLE, .clkreg = MCI_CLK_ENABLE, .clkreg_enable = 1 << 14, /* HWFCEN */ .clkreg_enable = 1 << 14, /* HWFCEN */ .datalength_bits = 24, .datalength_bits = 24, .broken_blockend = true, .sdio = true, .sdio = true, .st_clkdiv = true, .st_clkdiv = true, }; }; Loading Loading @@ -210,8 +202,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) host->data = data; host->data = data; host->size = data->blksz * data->blocks; host->size = data->blksz * data->blocks; host->data_xfered = 0; host->data_xfered = 0; host->blockend = false; host->dataend = false; mmci_init_sg(host, data); mmci_init_sg(host, data); Loading Loading @@ -288,21 +278,26 @@ static void mmci_data_irq(struct mmci_host *host, struct mmc_data *data, mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) unsigned int status) { { struct variant_data *variant = host->variant; /* First check for errors */ /* First check for errors */ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { u32 remain, success; /* Calculate how far we are into the transfer */ remain = readl(host->base + MMCIDATACNT) << 2; success = data->blksz * data->blocks - remain; dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); if (status & MCI_DATACRCFAIL) if (status & MCI_DATACRCFAIL) { /* Last block was not successful */ host->data_xfered = ((success / data->blksz) - 1 * data->blksz); data->error = -EILSEQ; data->error = -EILSEQ; else if (status & MCI_DATATIMEOUT) } else if (status & MCI_DATATIMEOUT) { host->data_xfered = success; data->error = -ETIMEDOUT; data->error = -ETIMEDOUT; else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) } else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) { host->data_xfered = success; data->error = -EIO; data->error = -EIO; } /* Force-complete the transaction */ host->blockend = true; host->dataend = true; /* /* * We hit an error condition. Ensure that any data * We hit an error condition. Ensure that any data Loading @@ -321,61 +316,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, } } } } /* if (status & MCI_DATABLOCKEND) * On ARM variants in PIO mode, MCI_DATABLOCKEND dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); * is always sent first, and we increase the * transfered number of bytes for that IRQ. Then * MCI_DATAEND follows and we conclude the transaction. * * On the Ux500 single-IRQ variant MCI_DATABLOCKEND * doesn't seem to immediately clear from the status, * so we can't use it keep count when only one irq is * used because the irq will hit for other reasons, and * then the flag is still up. So we use the MCI_DATAEND * IRQ at the end of the entire transfer because * MCI_DATABLOCKEND is broken. * * In the U300, the IRQs can arrive out-of-order, * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND, * so for this case we use the flags "blockend" and * "dataend" to make sure both IRQs have arrived before * concluding the transaction. (This does not apply * to the Ux500 which doesn't fire MCI_DATABLOCKEND * at all.) In DMA mode it suffers from the same problem * as the Ux500. */ if (status & MCI_DATABLOCKEND) { /* * Just being a little over-cautious, we do not * use this progressive update if the hardware blockend * flag is unreliable: since it can stay high between * IRQs it will corrupt the transfer counter. */ if (!variant->broken_blockend) host->data_xfered += data->blksz; host->blockend = true; } if (status & MCI_DATAEND) host->dataend = true; /* if (status & MCI_DATAEND) { * On variants with broken blockend we shall only wait for dataend, * on others we must sync with the blockend signal since they can * appear out-of-order. */ if (host->dataend && (host->blockend || variant->broken_blockend)) { mmci_stop_data(host); mmci_stop_data(host); /* Reset these flags */ if (!data->error) host->blockend = false; /* The error clause is handled above, success! */ host->dataend = false; /* * Variants with broken blockend flags need to handle the * end of the entire transfer here. */ if (variant->broken_blockend && !data->error) host->data_xfered += data->blksz * data->blocks; host->data_xfered += data->blksz * data->blocks; if (!data->stop) { if (!data->stop) { Loading Loading @@ -770,7 +718,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) struct variant_data *variant = id->data; struct variant_data *variant = id->data; struct mmci_host *host; struct mmci_host *host; struct mmc_host *mmc; struct mmc_host *mmc; unsigned int mask; int ret; int ret; /* must have platform data */ /* must have platform data */ Loading Loading @@ -951,12 +898,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto irq0_free; goto irq0_free; } } mask = MCI_IRQENABLE; writel(MCI_IRQENABLE, host->base + MMCIMASK0); /* Don't use the datablockend flag if it's broken */ if (variant->broken_blockend) mask &= ~MCI_DATABLOCKEND; writel(mask, host->base + MMCIMASK0); amba_set_drvdata(dev, mmc); amba_set_drvdata(dev, mmc); Loading
drivers/mmc/host/mmci.h +1 −4 Original line number Original line Diff line number Diff line Loading @@ -137,7 +137,7 @@ #define MCI_IRQENABLE \ #define MCI_IRQENABLE \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) MCI_CMDRESPENDMASK|MCI_CMDSENTMASK) /* These interrupts are directed to IRQ1 when two IRQ lines are available */ /* These interrupts are directed to IRQ1 when two IRQ lines are available */ #define MCI_IRQ1MASK \ #define MCI_IRQ1MASK \ Loading Loading @@ -177,9 +177,6 @@ struct mmci_host { struct timer_list timer; struct timer_list timer; unsigned int oldstat; unsigned int oldstat; bool blockend; bool dataend; /* pio stuff */ /* pio stuff */ struct sg_mapping_iter sg_miter; struct sg_mapping_iter sg_miter; unsigned int size; unsigned int size; Loading