|
@@ -117,10 +117,17 @@ static void sdhci_dumpregs(struct sdhci_host *host)
|
|
pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
|
|
pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
|
|
sdhci_readw(host, SDHCI_HOST_CONTROL2));
|
|
sdhci_readw(host, SDHCI_HOST_CONTROL2));
|
|
|
|
|
|
- if (host->flags & SDHCI_USE_ADMA)
|
|
|
|
- pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
|
|
|
|
- readl(host->ioaddr + SDHCI_ADMA_ERROR),
|
|
|
|
- readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
|
|
|
|
|
|
+ if (host->flags & SDHCI_USE_ADMA) {
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n",
|
|
|
|
+ readl(host->ioaddr + SDHCI_ADMA_ERROR),
|
|
|
|
+ readl(host->ioaddr + SDHCI_ADMA_ADDRESS_HI),
|
|
|
|
+ readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
|
|
|
|
+ else
|
|
|
|
+ pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
|
|
|
|
+ readl(host->ioaddr + SDHCI_ADMA_ERROR),
|
|
|
|
+ readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
|
|
|
|
+ }
|
|
|
|
|
|
pr_debug(DRIVER_NAME ": ===========================================\n");
|
|
pr_debug(DRIVER_NAME ": ===========================================\n");
|
|
}
|
|
}
|
|
@@ -446,19 +453,25 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
|
|
local_irq_restore(*flags);
|
|
local_irq_restore(*flags);
|
|
}
|
|
}
|
|
|
|
|
|
-static void sdhci_adma_write_desc(void *desc, u32 addr, int len, unsigned cmd)
|
|
|
|
|
|
+static void sdhci_adma_write_desc(struct sdhci_host *host, void *desc,
|
|
|
|
+ dma_addr_t addr, int len, unsigned cmd)
|
|
{
|
|
{
|
|
- struct sdhci_adma2_32_desc *dma_desc = desc;
|
|
|
|
|
|
+ struct sdhci_adma2_64_desc *dma_desc = desc;
|
|
|
|
|
|
|
|
+ /* 32-bit and 64-bit descriptors have these members in same position */
|
|
dma_desc->cmd = cpu_to_le16(cmd);
|
|
dma_desc->cmd = cpu_to_le16(cmd);
|
|
dma_desc->len = cpu_to_le16(len);
|
|
dma_desc->len = cpu_to_le16(len);
|
|
- dma_desc->addr = cpu_to_le32(addr);
|
|
|
|
|
|
+ dma_desc->addr_lo = cpu_to_le32((u32)addr);
|
|
|
|
+
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32);
|
|
}
|
|
}
|
|
|
|
|
|
static void sdhci_adma_mark_end(void *desc)
|
|
static void sdhci_adma_mark_end(void *desc)
|
|
{
|
|
{
|
|
- struct sdhci_adma2_32_desc *dma_desc = desc;
|
|
|
|
|
|
+ struct sdhci_adma2_64_desc *dma_desc = desc;
|
|
|
|
|
|
|
|
+ /* 32-bit and 64-bit descriptors have 'cmd' in same position */
|
|
dma_desc->cmd |= cpu_to_le16(ADMA2_END);
|
|
dma_desc->cmd |= cpu_to_le16(ADMA2_END);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -527,7 +540,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
|
|
}
|
|
}
|
|
|
|
|
|
/* tran, valid */
|
|
/* tran, valid */
|
|
- sdhci_adma_write_desc(desc, align_addr, offset,
|
|
|
|
|
|
+ sdhci_adma_write_desc(host, desc, align_addr, offset,
|
|
ADMA2_TRAN_VALID);
|
|
ADMA2_TRAN_VALID);
|
|
|
|
|
|
BUG_ON(offset > 65536);
|
|
BUG_ON(offset > 65536);
|
|
@@ -544,7 +557,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
|
|
BUG_ON(len > 65536);
|
|
BUG_ON(len > 65536);
|
|
|
|
|
|
/* tran, valid */
|
|
/* tran, valid */
|
|
- sdhci_adma_write_desc(desc, addr, len, ADMA2_TRAN_VALID);
|
|
|
|
|
|
+ sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
|
|
desc += host->desc_sz;
|
|
desc += host->desc_sz;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -568,7 +581,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
|
|
*/
|
|
*/
|
|
|
|
|
|
/* nop, end, valid */
|
|
/* nop, end, valid */
|
|
- sdhci_adma_write_desc(desc, 0, 0, ADMA2_NOP_END_VALID);
|
|
|
|
|
|
+ sdhci_adma_write_desc(host, desc, 0, 0, ADMA2_NOP_END_VALID);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -827,6 +840,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
|
|
} else {
|
|
} else {
|
|
sdhci_writel(host, host->adma_addr,
|
|
sdhci_writel(host, host->adma_addr,
|
|
SDHCI_ADMA_ADDRESS);
|
|
SDHCI_ADMA_ADDRESS);
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ sdhci_writel(host,
|
|
|
|
+ (u64)host->adma_addr >> 32,
|
|
|
|
+ SDHCI_ADMA_ADDRESS_HI);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
int sg_cnt;
|
|
int sg_cnt;
|
|
@@ -860,10 +877,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
|
|
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
|
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
|
ctrl &= ~SDHCI_CTRL_DMA_MASK;
|
|
ctrl &= ~SDHCI_CTRL_DMA_MASK;
|
|
if ((host->flags & SDHCI_REQ_USE_DMA) &&
|
|
if ((host->flags & SDHCI_REQ_USE_DMA) &&
|
|
- (host->flags & SDHCI_USE_ADMA))
|
|
|
|
- ctrl |= SDHCI_CTRL_ADMA32;
|
|
|
|
- else
|
|
|
|
|
|
+ (host->flags & SDHCI_USE_ADMA)) {
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ ctrl |= SDHCI_CTRL_ADMA64;
|
|
|
|
+ else
|
|
|
|
+ ctrl |= SDHCI_CTRL_ADMA32;
|
|
|
|
+ } else {
|
|
ctrl |= SDHCI_CTRL_SDMA;
|
|
ctrl |= SDHCI_CTRL_SDMA;
|
|
|
|
+ }
|
|
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
|
|
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2296,12 +2317,19 @@ static void sdhci_adma_show_error(struct sdhci_host *host)
|
|
sdhci_dumpregs(host);
|
|
sdhci_dumpregs(host);
|
|
|
|
|
|
while (true) {
|
|
while (true) {
|
|
- struct sdhci_adma2_32_desc *dma_desc = desc;
|
|
|
|
-
|
|
|
|
- DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
|
|
|
|
- name, desc, le32_to_cpu(dma_desc->addr),
|
|
|
|
- le16_to_cpu(dma_desc->len),
|
|
|
|
- le16_to_cpu(dma_desc->cmd));
|
|
|
|
|
|
+ struct sdhci_adma2_64_desc *dma_desc = desc;
|
|
|
|
+
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ DBG("%s: %p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
|
|
|
|
+ name, desc, le32_to_cpu(dma_desc->addr_hi),
|
|
|
|
+ le32_to_cpu(dma_desc->addr_lo),
|
|
|
|
+ le16_to_cpu(dma_desc->len),
|
|
|
|
+ le16_to_cpu(dma_desc->cmd));
|
|
|
|
+ else
|
|
|
|
+ DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
|
|
|
|
+ name, desc, le32_to_cpu(dma_desc->addr_lo),
|
|
|
|
+ le16_to_cpu(dma_desc->len),
|
|
|
|
+ le16_to_cpu(dma_desc->cmd));
|
|
|
|
|
|
desc += host->desc_sz;
|
|
desc += host->desc_sz;
|
|
|
|
|
|
@@ -2852,6 +2880,16 @@ int sdhci_add_host(struct sdhci_host *host)
|
|
host->flags &= ~SDHCI_USE_ADMA;
|
|
host->flags &= ~SDHCI_USE_ADMA;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * It is assumed that a 64-bit capable device has set a 64-bit DMA mask
|
|
|
|
+ * and *must* do 64-bit DMA. A driver has the opportunity to change
|
|
|
|
+ * that during the first call to ->enable_dma(). Similarly
|
|
|
|
+ * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to
|
|
|
|
+ * implement.
|
|
|
|
+ */
|
|
|
|
+ if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT)
|
|
|
|
+ host->flags |= SDHCI_USE_64_BIT_DMA;
|
|
|
|
+
|
|
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
|
|
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
|
|
if (host->ops->enable_dma) {
|
|
if (host->ops->enable_dma) {
|
|
if (host->ops->enable_dma(host)) {
|
|
if (host->ops->enable_dma(host)) {
|
|
@@ -2863,6 +2901,10 @@ int sdhci_add_host(struct sdhci_host *host)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* SDMA does not support 64-bit DMA */
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
|
|
|
|
+ host->flags &= ~SDHCI_USE_SDMA;
|
|
|
|
+
|
|
if (host->flags & SDHCI_USE_ADMA) {
|
|
if (host->flags & SDHCI_USE_ADMA) {
|
|
/*
|
|
/*
|
|
* The DMA descriptor table size is calculated as the maximum
|
|
* The DMA descriptor table size is calculated as the maximum
|
|
@@ -2870,13 +2912,23 @@ int sdhci_add_host(struct sdhci_host *host)
|
|
* descriptor for each segment, plus 1 for a nop end descriptor,
|
|
* descriptor for each segment, plus 1 for a nop end descriptor,
|
|
* all multipled by the descriptor size.
|
|
* all multipled by the descriptor size.
|
|
*/
|
|
*/
|
|
- host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
|
|
|
|
- SDHCI_ADMA2_32_DESC_SZ;
|
|
|
|
- host->align_buffer_sz = SDHCI_MAX_SEGS *
|
|
|
|
- SDHCI_ADMA2_32_ALIGN;
|
|
|
|
- host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
|
|
|
|
- host->align_sz = SDHCI_ADMA2_32_ALIGN;
|
|
|
|
- host->align_mask = SDHCI_ADMA2_32_ALIGN - 1;
|
|
|
|
|
|
+ if (host->flags & SDHCI_USE_64_BIT_DMA) {
|
|
|
|
+ host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
|
|
|
|
+ SDHCI_ADMA2_64_DESC_SZ;
|
|
|
|
+ host->align_buffer_sz = SDHCI_MAX_SEGS *
|
|
|
|
+ SDHCI_ADMA2_64_ALIGN;
|
|
|
|
+ host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
|
|
|
|
+ host->align_sz = SDHCI_ADMA2_64_ALIGN;
|
|
|
|
+ host->align_mask = SDHCI_ADMA2_64_ALIGN - 1;
|
|
|
|
+ } else {
|
|
|
|
+ host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
|
|
|
|
+ SDHCI_ADMA2_32_DESC_SZ;
|
|
|
|
+ host->align_buffer_sz = SDHCI_MAX_SEGS *
|
|
|
|
+ SDHCI_ADMA2_32_ALIGN;
|
|
|
|
+ host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
|
|
|
|
+ host->align_sz = SDHCI_ADMA2_32_ALIGN;
|
|
|
|
+ host->align_mask = SDHCI_ADMA2_32_ALIGN - 1;
|
|
|
|
+ }
|
|
host->adma_table = dma_alloc_coherent(mmc_dev(mmc),
|
|
host->adma_table = dma_alloc_coherent(mmc_dev(mmc),
|
|
host->adma_table_sz,
|
|
host->adma_table_sz,
|
|
&host->adma_addr,
|
|
&host->adma_addr,
|
|
@@ -3289,7 +3341,8 @@ int sdhci_add_host(struct sdhci_host *host)
|
|
|
|
|
|
pr_info("%s: SDHCI controller on %s [%s] using %s\n",
|
|
pr_info("%s: SDHCI controller on %s [%s] using %s\n",
|
|
mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
|
|
mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
|
|
- (host->flags & SDHCI_USE_ADMA) ? "ADMA" :
|
|
|
|
|
|
+ (host->flags & SDHCI_USE_ADMA) ?
|
|
|
|
+ (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
|
|
(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
|
|
(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
|
|
|
|
|
|
sdhci_enable_card_detection(host);
|
|
sdhci_enable_card_detection(host);
|