mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge 3.6-rc6 into tty-next
This pulls in the fixes in 3.6-rc6 Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
commit
7ac3c93e5d
722 changed files with 6030 additions and 3433 deletions
|
|
@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
|
|||
/* complete ongoing async transfer before issuing discard */
|
||||
if (card->host->areq)
|
||||
mmc_blk_issue_rw_rq(mq, NULL);
|
||||
if (req->cmd_flags & REQ_SECURE)
|
||||
if (req->cmd_flags & REQ_SECURE &&
|
||||
!(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
|
||||
ret = mmc_blk_issue_secdiscard_rq(mq, req);
|
||||
else
|
||||
ret = mmc_blk_issue_discard_rq(mq, req);
|
||||
|
|
@ -1716,6 +1717,7 @@ force_ro_fail:
|
|||
#define CID_MANFID_SANDISK 0x2
|
||||
#define CID_MANFID_TOSHIBA 0x11
|
||||
#define CID_MANFID_MICRON 0x13
|
||||
#define CID_MANFID_SAMSUNG 0x15
|
||||
|
||||
static const struct mmc_fixup blk_fixups[] =
|
||||
{
|
||||
|
|
@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] =
|
|||
MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
|
||||
MMC_QUIRK_LONG_READ_TIME),
|
||||
|
||||
/*
|
||||
* On these Samsung MoviNAND parts, performing secure erase or
|
||||
* secure trim can result in unrecoverable corruption due to a
|
||||
* firmware bug.
|
||||
*/
|
||||
MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
|
||||
MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
|
||||
|
||||
END_FIXUP
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ struct atmel_mci_caps {
|
|||
bool has_bad_data_ordering;
|
||||
bool need_reset_after_xfer;
|
||||
bool need_blksz_mul_4;
|
||||
bool need_notbusy_for_read_ops;
|
||||
};
|
||||
|
||||
struct atmel_mci_dma {
|
||||
|
|
@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv)
|
|||
__func__);
|
||||
atmci_set_completed(host, EVENT_XFER_COMPLETE);
|
||||
|
||||
if (host->data->flags & MMC_DATA_WRITE) {
|
||||
if (host->caps.need_notbusy_for_read_ops ||
|
||||
(host->data->flags & MMC_DATA_WRITE)) {
|
||||
atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
|
||||
state = STATE_WAITING_NOTBUSY;
|
||||
} else if (host->mrq->stop) {
|
||||
|
|
@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
|
|||
host->caps.has_bad_data_ordering = 1;
|
||||
host->caps.need_reset_after_xfer = 1;
|
||||
host->caps.need_blksz_mul_4 = 1;
|
||||
host->caps.need_notbusy_for_read_ops = 0;
|
||||
|
||||
/* keep only major version number */
|
||||
switch (version & 0xf00) {
|
||||
|
|
@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
|
|||
case 0x200:
|
||||
host->caps.has_rwproof = 1;
|
||||
host->caps.need_blksz_mul_4 = 0;
|
||||
host->caps.need_notbusy_for_read_ops = 1;
|
||||
case 0x100:
|
||||
host->caps.has_bad_data_ordering = 0;
|
||||
host->caps.need_reset_after_xfer = 0;
|
||||
|
|
|
|||
|
|
@ -49,13 +49,6 @@
|
|||
#define bfin_write_SDH_CFG bfin_write_RSI_CFG
|
||||
#endif
|
||||
|
||||
struct dma_desc_array {
|
||||
unsigned long start_addr;
|
||||
unsigned short cfg;
|
||||
unsigned short x_count;
|
||||
short x_modify;
|
||||
} __packed;
|
||||
|
||||
struct sdh_host {
|
||||
struct mmc_host *mmc;
|
||||
spinlock_t lock;
|
||||
|
|
|
|||
|
|
@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
|
|||
{
|
||||
struct dw_mci *host = slot->host;
|
||||
u32 div;
|
||||
u32 clk_en_a;
|
||||
|
||||
if (slot->clock != host->current_speed) {
|
||||
div = host->bus_hz / slot->clock;
|
||||
|
|
@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
|
|||
mci_send_cmd(slot,
|
||||
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
|
||||
|
||||
/* enable clock */
|
||||
mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
|
||||
SDMMC_CLKEN_LOW_PWR) << slot->id));
|
||||
/* enable clock; only low power if no SDIO */
|
||||
clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
|
||||
if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
|
||||
clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
|
||||
mci_writel(host, CLKENA, clk_en_a);
|
||||
|
||||
/* inform CIU */
|
||||
mci_send_cmd(slot,
|
||||
|
|
@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
|
|||
return present;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable lower power mode.
|
||||
*
|
||||
* Low power mode will stop the card clock when idle. According to the
|
||||
* description of the CLKENA register we should disable low power mode
|
||||
* for SDIO cards if we need SDIO interrupts to work.
|
||||
*
|
||||
* This function is fast if low power mode is already disabled.
|
||||
*/
|
||||
static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
|
||||
{
|
||||
struct dw_mci *host = slot->host;
|
||||
u32 clk_en_a;
|
||||
const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
|
||||
|
||||
clk_en_a = mci_readl(host, CLKENA);
|
||||
|
||||
if (clk_en_a & clken_low_pwr) {
|
||||
mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
|
||||
mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
|
||||
SDMMC_CMD_PRV_DAT_WAIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
|
||||
{
|
||||
struct dw_mci_slot *slot = mmc_priv(mmc);
|
||||
|
|
@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
|
|||
/* Enable/disable Slot Specific SDIO interrupt */
|
||||
int_mask = mci_readl(host, INTMASK);
|
||||
if (enb) {
|
||||
/*
|
||||
* Turn off low power mode if it was enabled. This is a bit of
|
||||
* a heavy operation and we disable / enable IRQs a lot, so
|
||||
* we'll leave low power mode disabled and it will get
|
||||
* re-enabled again in dw_mci_setup_bus().
|
||||
*/
|
||||
dw_mci_disable_low_power(slot);
|
||||
|
||||
mci_writel(host, INTMASK,
|
||||
(int_mask | SDMMC_INT_SDIO(slot->id)));
|
||||
} else {
|
||||
|
|
@ -1429,22 +1464,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
|
|||
nbytes += len;
|
||||
remain -= len;
|
||||
} while (remain);
|
||||
sg_miter->consumed = offset;
|
||||
|
||||
sg_miter->consumed = offset;
|
||||
status = mci_readl(host, MINTSTS);
|
||||
mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
|
||||
if (status & DW_MCI_DATA_ERROR_FLAGS) {
|
||||
host->data_status = status;
|
||||
data->bytes_xfered += nbytes;
|
||||
sg_miter_stop(sg_miter);
|
||||
host->sg = NULL;
|
||||
smp_wmb();
|
||||
|
||||
set_bit(EVENT_DATA_ERROR, &host->pending_events);
|
||||
|
||||
tasklet_schedule(&host->tasklet);
|
||||
return;
|
||||
}
|
||||
} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
|
||||
data->bytes_xfered += nbytes;
|
||||
|
||||
|
|
@ -1497,23 +1520,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
|
|||
nbytes += len;
|
||||
remain -= len;
|
||||
} while (remain);
|
||||
sg_miter->consumed = offset;
|
||||
|
||||
sg_miter->consumed = offset;
|
||||
status = mci_readl(host, MINTSTS);
|
||||
mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
|
||||
if (status & DW_MCI_DATA_ERROR_FLAGS) {
|
||||
host->data_status = status;
|
||||
data->bytes_xfered += nbytes;
|
||||
sg_miter_stop(sg_miter);
|
||||
host->sg = NULL;
|
||||
|
||||
smp_wmb();
|
||||
|
||||
set_bit(EVENT_DATA_ERROR, &host->pending_events);
|
||||
|
||||
tasklet_schedule(&host->tasklet);
|
||||
return;
|
||||
}
|
||||
} while (status & SDMMC_INT_TXDR); /* if TXDR write again */
|
||||
data->bytes_xfered += nbytes;
|
||||
|
||||
|
|
@ -1547,12 +1557,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
|
|||
static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_mci *host = dev_id;
|
||||
u32 status, pending;
|
||||
u32 pending;
|
||||
unsigned int pass_count = 0;
|
||||
int i;
|
||||
|
||||
do {
|
||||
status = mci_readl(host, RINTSTS);
|
||||
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
|
||||
|
||||
/*
|
||||
|
|
@ -1570,7 +1579,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
|||
|
||||
if (pending & DW_MCI_CMD_ERROR_FLAGS) {
|
||||
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
|
||||
host->cmd_status = status;
|
||||
host->cmd_status = pending;
|
||||
smp_wmb();
|
||||
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
|
||||
}
|
||||
|
|
@ -1578,18 +1587,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
|||
if (pending & DW_MCI_DATA_ERROR_FLAGS) {
|
||||
/* if there is an error report DATA_ERROR */
|
||||
mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
|
||||
host->data_status = status;
|
||||
host->data_status = pending;
|
||||
smp_wmb();
|
||||
set_bit(EVENT_DATA_ERROR, &host->pending_events);
|
||||
if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
|
||||
SDMMC_INT_SBE | SDMMC_INT_EBE)))
|
||||
tasklet_schedule(&host->tasklet);
|
||||
tasklet_schedule(&host->tasklet);
|
||||
}
|
||||
|
||||
if (pending & SDMMC_INT_DATA_OVER) {
|
||||
mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
|
||||
if (!host->data_status)
|
||||
host->data_status = status;
|
||||
host->data_status = pending;
|
||||
smp_wmb();
|
||||
if (host->dir_status == DW_MCI_RECV_STATUS) {
|
||||
if (host->sg != NULL)
|
||||
|
|
@ -1613,7 +1620,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
|
|||
|
||||
if (pending & SDMMC_INT_CMD_DONE) {
|
||||
mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
|
||||
dw_mci_cmd_interrupt(host, status);
|
||||
dw_mci_cmd_interrupt(host, pending);
|
||||
}
|
||||
|
||||
if (pending & SDMMC_INT_CD) {
|
||||
|
|
|
|||
|
|
@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
|
|||
writel(stat & MXS_MMC_IRQ_BITS,
|
||||
host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
|
||||
|
||||
spin_unlock(&host->lock);
|
||||
|
||||
if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
|
||||
mmc_signal_sdio_irq(host->mmc);
|
||||
|
||||
spin_unlock(&host->lock);
|
||||
|
||||
if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
|
||||
cmd->error = -ETIMEDOUT;
|
||||
else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
|
||||
|
|
@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
|
|||
host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
|
||||
writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
|
||||
host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
|
||||
|
||||
if (readl(host->base + HW_SSP_STATUS(host)) &
|
||||
BM_SSP_STATUS_SDIO_IRQ)
|
||||
mmc_signal_sdio_irq(host->mmc);
|
||||
|
||||
} else {
|
||||
writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
|
||||
host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
|
||||
|
|
@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
|
|||
}
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
if (enable && readl(host->base + HW_SSP_STATUS(host)) &
|
||||
BM_SSP_STATUS_SDIO_IRQ)
|
||||
mmc_signal_sdio_irq(host->mmc);
|
||||
|
||||
}
|
||||
|
||||
static const struct mmc_host_ops mxs_mmc_ops = {
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data)
|
|||
static void
|
||||
mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
|
||||
{
|
||||
int n;
|
||||
int n, nwords;
|
||||
|
||||
if (host->buffer_bytes_left == 0) {
|
||||
host->sg_idx++;
|
||||
|
|
@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
|
|||
n = 64;
|
||||
if (n > host->buffer_bytes_left)
|
||||
n = host->buffer_bytes_left;
|
||||
|
||||
nwords = n / 2;
|
||||
nwords += n & 1; /* handle odd number of bytes to transfer */
|
||||
|
||||
host->buffer_bytes_left -= n;
|
||||
host->total_bytes_left -= n;
|
||||
host->data->bytes_xfered += n;
|
||||
|
||||
if (write) {
|
||||
__raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
|
||||
__raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA),
|
||||
host->buffer, nwords);
|
||||
} else {
|
||||
__raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
|
||||
__raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA),
|
||||
host->buffer, nwords);
|
||||
}
|
||||
|
||||
host->buffer += nwords;
|
||||
}
|
||||
|
||||
static inline void mmc_omap_report_irq(u16 status)
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
|
|||
int div = 1;
|
||||
u32 temp;
|
||||
|
||||
if (clock == 0)
|
||||
goto out;
|
||||
|
||||
temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
|
||||
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
|
||||
| ESDHC_CLOCK_MASK);
|
||||
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
|
||||
|
||||
if (clock == 0)
|
||||
goto out;
|
||||
|
||||
while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
|
||||
pre_div *= 2;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue