Discussion:
[PATCH v6] mmc: dw_mmc: Add IDMAC 64-bit address mode support
Prabu Thangamuthu
2014-10-09 07:39:54 UTC
Permalink
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit address mode from IP version 2.70a onwards.
Updated the driver to support IDMAC 64-bit addressing mode.

Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-51 setup and driver is working fine.

Signed-off-by: Prabu Thangamuthu <***@synopsys.com>
---
Change log v6:
- Updated with review comment.

Change log v5:
- Recreated the patch against linux-next as this patch is required for another patch http://www.spinics.net/lists/arm-kernel/msg357985.html

Change log v4:
- Add the dynamic support for 32-bit and 64-bit address mode based on hw configuration.
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.

drivers/mmc/host/dw_mmc.c | 195 +++++++++++++++++++++++++++++++++++---------
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
SDMMC_IDMAC_INT_TI)

+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
+
+ u32 des2; /*Buffer sizes */
+#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
+ ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+
+ u32 des3; /* Reserved */
+
+ u32 des4; /* Lower 32-bits of Buffer Address Pointer 1*/
+ u32 des5; /* Upper 32-bits of Buffer Address Pointer 1*/
+
+ u32 des6; /* Lower 32-bits of Next Descriptor Address */
+ u32 des7; /* Upper 32-bits of Next Descriptor Address */
+};
+
struct idmac_desc {
u32 des0; /* Control Descriptor */
#define IDMAC_DES0_DIC BIT(1)
@@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
unsigned int sg_len)
{
int i;
- struct idmac_desc *desc = host->sg_cpu;
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *desc = host->sg_cpu;

- for (i = 0; i < sg_len; i++, desc++) {
- unsigned int length = sg_dma_len(&data->sg[i]);
- u32 mem_addr = sg_dma_address(&data->sg[i]);
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u64 mem_addr = sg_dma_address(&data->sg[i]);

- /* Set the OWN bit and disable interrupts for this descriptor */
- desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des4 = mem_addr & 0xffffffff;
+ desc->des5 = mem_addr >> 32;
+ }

- /* Buffer length */
- IDMAC_SET_BUFFER1_SIZE(desc, length);
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;

- /* Physical address to DMA to/from */
- desc->des2 = mem_addr;
- }
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) *
+ sizeof(struct idmac_desc_64addr);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+
+ } else {
+ struct idmac_desc *desc = host->sg_cpu;
+
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u32 mem_addr = sg_dma_address(&data->sg[i]);
+
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des2 = mem_addr;
+ }

- /* Set first descriptor */
- desc = host->sg_cpu;
- desc->des0 |= IDMAC_DES0_FD;
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;

- /* Set last descriptor */
- desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
- desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
- desc->des0 |= IDMAC_DES0_LD;
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+ }

wmb();
}
@@ -466,29 +520,67 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)

static int dw_mci_idmac_init(struct dw_mci *host)
{
- struct idmac_desc *p;
int i;

- /* Number of descriptors in the ring buffer */
- host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr);
+
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1;
+ i++, p++) {
+ p->des6 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) & 0xffffffff;
+
+ p->des7 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) >> 32;
+ }
+
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des6 = host->sg_dma & 0xffffffff;
+ p->des7 = host->sg_dma >> 32;
+ p->des0 = IDMAC_DES0_ER;
+
+ } else {
+ struct idmac_desc *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);

- /* Forward link the descriptor list */
- for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
- p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) *
+ (i + 1));

- /* Set the last descriptor as the end-of-ring descriptor */
- p->des3 = host->sg_dma;
- p->des0 = IDMAC_DES0_ER;
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des3 = host->sg_dma;
+ p->des0 = IDMAC_DES0_ER;
+ }

dw_mci_idmac_reset(host);

- /* Mask out interrupts - get Tx & Rx complete only */
- mci_writel(host, IDSTS, IDMAC_INT_CLR);
- mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
- SDMMC_IDMAC_INT_TI);
+ if (host->dma_64bit_address == 1) {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS64, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff);
+ mci_writel(host, DBADDRU, host->sg_dma >> 32);
+
+ } else {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDR, host->sg_dma);
+ }

- /* Set the descriptor base address */
- mci_writel(host, DBADDR, host->sg_dma);
return 0;
}

@@ -2045,11 +2137,22 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)

#ifdef CONFIG_MMC_DW_IDMAC
/* Handle DMA interrupts */
- pending = mci_readl(host, IDSTS);
- if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ if (host->dma_64bit_address == 1) {
+ pending = mci_readl(host, IDSTS64);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
+ } else {
+ pending = mci_readl(host, IDSTS);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
}
#endif

@@ -2309,6 +2412,22 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)

static void dw_mci_init_dma(struct dw_mci *host)
{
+ int addr_config;
+ /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */
+ addr_config = (mci_readl(host, HCON) >> 27) & 0x01;
+
+ if (addr_config == 1) {
+ /* host supports IDMAC in 64-bit address mode */
+ host->dma_64bit_address = 1;
+ dev_info(host->dev, "IDMAC supports 64-bit address mode.\n");
+ if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+ dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64));
+ } else {
+ /* host supports IDMAC in 32-bit address mode */
+ host->dma_64bit_address = 0;
+ dev_info(host->dev, "IDMAC supports 32-bit address mode.\n");
+ }
+
/* Alloc memory for sg translation */
host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8..64b04aa 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -55,6 +55,17 @@
#define SDMMC_BUFADDR 0x098
#define SDMMC_CDTHRCTL 0x100
#define SDMMC_DATA(x) (x)
+/*
+* Registers to support idmac 64-bit address mode
+*/
+#define SDMMC_DBADDRL 0x088
+#define SDMMC_DBADDRU 0x08c
+#define SDMMC_IDSTS64 0x090
+#define SDMMC_IDINTEN64 0x094
+#define SDMMC_DSCADDRL 0x098
+#define SDMMC_DSCADDRU 0x09c
+#define SDMMC_BUFADDRL 0x0A0
+#define SDMMC_BUFADDRU 0x0A4

/*
* Data offset is difference according to Version
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 0013669..9e6eabb 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -54,6 +54,7 @@ struct mmc_data;
* transfer is in progress.
* @use_dma: Whether DMA channel is initialized or not.
* @using_dma: Whether DMA is in use for the current transfer.
+ * @dma_64bit_address: Whether DMA supports 64-bit address mode or not.
* @sg_dma: Bus address of DMA buffer.
* @sg_cpu: Virtual address of DMA buffer.
* @dma_ops: Pointer to platform-specific DMA callbacks.
@@ -140,6 +141,7 @@ struct dw_mci {
/* DMA interface members*/
int use_dma;
int using_dma;
+ int dma_64bit_address;

dma_addr_t sg_dma;
void *sg_cpu;
--
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Alim Akhtar
2014-10-14 12:11:56 UTC
Permalink
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
Post by Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit address mode from IP version 2.70a onwards.
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-51 setup and driver is working fine.
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch is required for another patch http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address mode based on hw configuration.
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195 +++++++++++++++++++++++++++++++++++---------
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As these
are pointers, do you thing initializing then to zero make sense?
Post by Prabu Thangamuthu
+
+ u32 des2; /*Buffer sizes */
+#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
+ ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+
+ u32 des3; /* Reserved */
+
+ u32 des4; /* Lower 32-bits of Buffer Address Pointer 1*/
+ u32 des5; /* Upper 32-bits of Buffer Address Pointer 1*/
+
+ u32 des6; /* Lower 32-bits of Next Descriptor Address */
+ u32 des7; /* Upper 32-bits of Next Descriptor Address */
+};
+
struct idmac_desc {
u32 des0; /* Control Descriptor */
#define IDMAC_DES0_DIC BIT(1)
@@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
unsigned int sg_len)
{
int i;
- struct idmac_desc *desc = host->sg_cpu;
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *desc = host->sg_cpu;
- for (i = 0; i < sg_len; i++, desc++) {
- unsigned int length = sg_dma_len(&data->sg[i]);
- u32 mem_addr = sg_dma_address(&data->sg[i]);
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u64 mem_addr = sg_dma_address(&data->sg[i]);
- /* Set the OWN bit and disable interrupts for this descriptor */
- desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des4 = mem_addr & 0xffffffff;
+ desc->des5 = mem_addr >> 32;
+ }
- /* Buffer length */
- IDMAC_SET_BUFFER1_SIZE(desc, length);
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;
- /* Physical address to DMA to/from */
- desc->des2 = mem_addr;
- }
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) *
+ sizeof(struct idmac_desc_64addr);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+
+ } else {
+ struct idmac_desc *desc = host->sg_cpu;
+
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u32 mem_addr = sg_dma_address(&data->sg[i]);
+
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des2 = mem_addr;
+ }
- /* Set first descriptor */
- desc = host->sg_cpu;
- desc->des0 |= IDMAC_DES0_FD;
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;
- /* Set last descriptor */
- desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
- desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
- desc->des0 |= IDMAC_DES0_LD;
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+ }
wmb();
}
@@ -466,29 +520,67 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
static int dw_mci_idmac_init(struct dw_mci *host)
{
- struct idmac_desc *p;
int i;
- /* Number of descriptors in the ring buffer */
- host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr);
+
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1;
+ i++, p++) {
+ p->des6 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) & 0xffffffff;
+
+ p->des7 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) >> 32;
+ }
+
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des6 = host->sg_dma & 0xffffffff;
+ p->des7 = host->sg_dma >> 32;
+ p->des0 = IDMAC_DES0_ER;
+
+ } else {
+ struct idmac_desc *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
- /* Forward link the descriptor list */
- for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
- p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) *
+ (i + 1));
- /* Set the last descriptor as the end-of-ring descriptor */
- p->des3 = host->sg_dma;
- p->des0 = IDMAC_DES0_ER;
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des3 = host->sg_dma;
+ p->des0 = IDMAC_DES0_ER;
+ }
dw_mci_idmac_reset(host);
- /* Mask out interrupts - get Tx & Rx complete only */
- mci_writel(host, IDSTS, IDMAC_INT_CLR);
- mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
- SDMMC_IDMAC_INT_TI);
+ if (host->dma_64bit_address == 1) {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS64, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff);
+ mci_writel(host, DBADDRU, host->sg_dma >> 32);
+
+ } else {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDR, host->sg_dma);
+ }
- /* Set the descriptor base address */
- mci_writel(host, DBADDR, host->sg_dma);
return 0;
}
@@ -2045,11 +2137,22 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
#ifdef CONFIG_MMC_DW_IDMAC
/* Handle DMA interrupts */
- pending = mci_readl(host, IDSTS);
- if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ if (host->dma_64bit_address == 1) {
+ pending = mci_readl(host, IDSTS64);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
+ } else {
+ pending = mci_readl(host, IDSTS);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
}
#endif
@@ -2309,6 +2412,22 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
static void dw_mci_init_dma(struct dw_mci *host)
{
+ int addr_config;
+ /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */
+ addr_config = (mci_readl(host, HCON) >> 27) & 0x01;
+
+ if (addr_config == 1) {
+ /* host supports IDMAC in 64-bit address mode */
+ host->dma_64bit_address = 1;
+ dev_info(host->dev, "IDMAC supports 64-bit address mode.\n");
+ if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+ dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64));
+ } else {
+ /* host supports IDMAC in 32-bit address mode */
+ host->dma_64bit_address = 0;
+ dev_info(host->dev, "IDMAC supports 32-bit address mode.\n");
+ }
+
/* Alloc memory for sg translation */
host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8..64b04aa 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -55,6 +55,17 @@
#define SDMMC_BUFADDR 0x098
#define SDMMC_CDTHRCTL 0x100
#define SDMMC_DATA(x) (x)
+/*
+* Registers to support idmac 64-bit address mode
+*/
+#define SDMMC_DBADDRL 0x088
+#define SDMMC_DBADDRU 0x08c
+#define SDMMC_IDSTS64 0x090
+#define SDMMC_IDINTEN64 0x094
+#define SDMMC_DSCADDRL 0x098
+#define SDMMC_DSCADDRU 0x09c
+#define SDMMC_BUFADDRL 0x0A0
+#define SDMMC_BUFADDRU 0x0A4
/*
* Data offset is difference according to Version
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 0013669..9e6eabb 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -54,6 +54,7 @@ struct mmc_data;
* transfer is in progress.
@@ -140,6 +141,7 @@ struct dw_mci {
/* DMA interface members*/
int use_dma;
int using_dma;
+ int dma_64bit_address;
dma_addr_t sg_dma;
void *sg_cpu;
--
1.7.6.5
--
Regards,
Alim
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Vivek Gautam
2014-10-15 12:05:44 UTC
Permalink
Hi Prabu,
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
Post by Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit address mode from IP version 2.70a onwards.
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-51 setup and driver is working fine.
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch is required for another patch http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address mode based on hw configuration.
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195 +++++++++++++++++++++++++++++++++++---------
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As these
are pointers, do you thing initializing then to zero make sense?
I think the default reset value of these descriptors will depend on
how dwmmc is integrated in h/w and how these descriptors are then
configured.

So it makes sense to initialize these descriptors to zero before use.
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
Post by Alim Akhtar
Post by Prabu Thangamuthu
+
+ u32 des2; /*Buffer sizes */
+#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
+ ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+
+ u32 des3; /* Reserved */
+
+ u32 des4; /* Lower 32-bits of Buffer Address Pointer 1*/
+ u32 des5; /* Upper 32-bits of Buffer Address Pointer 1*/
+
+ u32 des6; /* Lower 32-bits of Next Descriptor Address */
+ u32 des7; /* Upper 32-bits of Next Descriptor Address */
+};
+
struct idmac_desc {
u32 des0; /* Control Descriptor */
#define IDMAC_DES0_DIC BIT(1)
@@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
unsigned int sg_len)
{
int i;
- struct idmac_desc *desc = host->sg_cpu;
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *desc = host->sg_cpu;
- for (i = 0; i < sg_len; i++, desc++) {
- unsigned int length = sg_dma_len(&data->sg[i]);
- u32 mem_addr = sg_dma_address(&data->sg[i]);
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u64 mem_addr = sg_dma_address(&data->sg[i]);
- /* Set the OWN bit and disable interrupts for this descriptor */
- desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des4 = mem_addr & 0xffffffff;
+ desc->des5 = mem_addr >> 32;
+ }
- /* Buffer length */
- IDMAC_SET_BUFFER1_SIZE(desc, length);
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;
- /* Physical address to DMA to/from */
- desc->des2 = mem_addr;
- }
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) *
+ sizeof(struct idmac_desc_64addr);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+
+ } else {
+ struct idmac_desc *desc = host->sg_cpu;
+
+ for (i = 0; i < sg_len; i++, desc++) {
+ unsigned int length = sg_dma_len(&data->sg[i]);
+ u32 mem_addr = sg_dma_address(&data->sg[i]);
+
+ /*
+ * Set the OWN bit and disable interrupts for this
+ * descriptor
+ */
+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des2 = mem_addr;
+ }
- /* Set first descriptor */
- desc = host->sg_cpu;
- desc->des0 |= IDMAC_DES0_FD;
+ /* Set first descriptor */
+ desc = host->sg_cpu;
+ desc->des0 |= IDMAC_DES0_FD;
- /* Set last descriptor */
- desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
- desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
- desc->des0 |= IDMAC_DES0_LD;
+ /* Set last descriptor */
+ desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |= IDMAC_DES0_LD;
+ }
wmb();
}
@@ -466,29 +520,67 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
static int dw_mci_idmac_init(struct dw_mci *host)
{
- struct idmac_desc *p;
int i;
- /* Number of descriptors in the ring buffer */
- host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
+ if (host->dma_64bit_address == 1) {
+ struct idmac_desc_64addr *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr);
+
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1;
+ i++, p++) {
+ p->des6 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) & 0xffffffff;
+
+ p->des7 = (host->sg_dma +
+ (sizeof(struct idmac_desc_64addr) *
+ (i + 1))) >> 32;
+ }
+
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des6 = host->sg_dma & 0xffffffff;
+ p->des7 = host->sg_dma >> 32;
+ p->des0 = IDMAC_DES0_ER;
+
+ } else {
+ struct idmac_desc *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
- /* Forward link the descriptor list */
- for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
- p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
+ /* Forward link the descriptor list */
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) *
+ (i + 1));
- /* Set the last descriptor as the end-of-ring descriptor */
- p->des3 = host->sg_dma;
- p->des0 = IDMAC_DES0_ER;
+ /* Set the last descriptor as the end-of-ring descriptor */
+ p->des3 = host->sg_dma;
+ p->des0 = IDMAC_DES0_ER;
+ }
dw_mci_idmac_reset(host);
- /* Mask out interrupts - get Tx & Rx complete only */
- mci_writel(host, IDSTS, IDMAC_INT_CLR);
- mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
- SDMMC_IDMAC_INT_TI);
+ if (host->dma_64bit_address == 1) {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS64, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff);
+ mci_writel(host, DBADDRU, host->sg_dma >> 32);
+
+ } else {
+ /* Mask out interrupts - get Tx & Rx complete only */
+ mci_writel(host, IDSTS, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDR, host->sg_dma);
+ }
- /* Set the descriptor base address */
- mci_writel(host, DBADDR, host->sg_dma);
return 0;
}
@@ -2045,11 +2137,22 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
#ifdef CONFIG_MMC_DW_IDMAC
/* Handle DMA interrupts */
- pending = mci_readl(host, IDSTS);
- if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ if (host->dma_64bit_address == 1) {
+ pending = mci_readl(host, IDSTS64);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
+ } else {
+ pending = mci_readl(host, IDSTS);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
+ SDMMC_IDMAC_INT_RI);
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+ host->dma_ops->complete(host);
+ }
}
#endif
@@ -2309,6 +2412,22 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
static void dw_mci_init_dma(struct dw_mci *host)
{
+ int addr_config;
+ /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */
+ addr_config = (mci_readl(host, HCON) >> 27) & 0x01;
+
+ if (addr_config == 1) {
+ /* host supports IDMAC in 64-bit address mode */
+ host->dma_64bit_address = 1;
+ dev_info(host->dev, "IDMAC supports 64-bit address mode.\n");
+ if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+ dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64));
+ } else {
+ /* host supports IDMAC in 32-bit address mode */
+ host->dma_64bit_address = 0;
+ dev_info(host->dev, "IDMAC supports 32-bit address mode.\n");
+ }
+
/* Alloc memory for sg translation */
host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8..64b04aa 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -55,6 +55,17 @@
#define SDMMC_BUFADDR 0x098
#define SDMMC_CDTHRCTL 0x100
#define SDMMC_DATA(x) (x)
+/*
+* Registers to support idmac 64-bit address mode
+*/
+#define SDMMC_DBADDRL 0x088
+#define SDMMC_DBADDRU 0x08c
+#define SDMMC_IDSTS64 0x090
+#define SDMMC_IDINTEN64 0x094
+#define SDMMC_DSCADDRL 0x098
+#define SDMMC_DSCADDRU 0x09c
+#define SDMMC_BUFADDRL 0x0A0
+#define SDMMC_BUFADDRU 0x0A4
/*
* Data offset is difference according to Version
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 0013669..9e6eabb 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -54,6 +54,7 @@ struct mmc_data;
* transfer is in progress.
@@ -140,6 +141,7 @@ struct dw_mci {
/* DMA interface members*/
int use_dma;
int using_dma;
+ int dma_64bit_address;
dma_addr_t sg_dma;
void *sg_cpu;
--
1.7.6.5
--
Regards,
Alim
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
--
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Jaehoon Chung
2014-10-16 06:49:55 UTC
Permalink
Hi, Prabu.
Post by Vivek Gautam
Hi Prabu,
=20
=20
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bi=
t address mode from IP version 2.70a onwards.
Post by Vivek Gautam
Post by Alim Akhtar
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-51 s=
etup and driver is working fine.
Post by Vivek Gautam
Post by Alim Akhtar
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch is r=
equired for another patch http://www.spinics.net/lists/arm-kernel/msg35=
7985.html
Post by Vivek Gautam
Post by Alim Akhtar
- Add the dynamic support for 32-bit and 64-bit address mod=
e based on hw configuration.
Post by Vivek Gautam
Post by Alim Akhtar
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195 ++++++++++++++++++++++++++++++++=
+++---------
Post by Vivek Gautam
Post by Alim Akhtar
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_=
INT_RI | \
Post by Vivek Gautam
Post by Alim Akhtar
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As these
are pointers, do you thing initializing then to zero make sense?
=20
I think the default reset value of these descriptors will depend on
how dwmmc is integrated in h/w and how these descriptors are then
configured.
=20
So it makes sense to initialize these descriptors to zero before use.
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
I agreed with Vivek and Alim's comment.

And I think you can fix the below compile warning.

drivers/mmc/host/dw_mmc.c: In function =E2=80=98dw_mci_idmac_init=E2=80=
=99:
drivers/mmc/host/dw_mmc.c:542:21: warning: right shift count >=3D width=
of type [enabled by default]
drivers/mmc/host/dw_mmc.c:547:3: warning: right shift count >=3D width =
of type [enabled by default]
drivers/mmc/host/dw_mmc.c:575:3: warning: right shift count >=3D width =
of type [enabled by default]

I will check this patch with 2.70a and other version.

Best Regards,
Jaehoon Chung
Post by Vivek Gautam
=20
Post by Alim Akhtar
+
+ u32 des2; /*Buffer sizes */
+#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
+ ((d)->des2 =3D ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+
+ u32 des3; /* Reserved */
+
+ u32 des4; /* Lower 32-bits of Buffer Address =
Pointer 1*/
Post by Vivek Gautam
Post by Alim Akhtar
+ u32 des5; /* Upper 32-bits of Buffer Address =
Pointer 1*/
Post by Vivek Gautam
Post by Alim Akhtar
+
+ u32 des6; /* Lower 32-bits of Next Descriptor=
Address */
Post by Vivek Gautam
Post by Alim Akhtar
+ u32 des7; /* Upper 32-bits of Next Descriptor=
Address */
Post by Vivek Gautam
Post by Alim Akhtar
+};
+
struct idmac_desc {
u32 des0; /* Control Descriptor */
#define IDMAC_DES0_DIC BIT(1)
@@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw=
_mci *host, struct mmc_data *data,
Post by Vivek Gautam
Post by Alim Akhtar
unsigned int sg_len)
{
int i;
- struct idmac_desc *desc =3D host->sg_cpu;
+ if (host->dma_64bit_address =3D=3D 1) {
+ struct idmac_desc_64addr *desc =3D host->sg_cpu;
- for (i =3D 0; i < sg_len; i++, desc++) {
- unsigned int length =3D sg_dma_len(&data->sg[i]);
- u32 mem_addr =3D sg_dma_address(&data->sg[i]);
+ for (i =3D 0; i < sg_len; i++, desc++) {
+ unsigned int length =3D sg_dma_len(&data->s=
g[i]);
Post by Vivek Gautam
Post by Alim Akhtar
+ u64 mem_addr =3D sg_dma_address(&data->sg[i=
]);
Post by Vivek Gautam
Post by Alim Akhtar
- /* Set the OWN bit and disable interrupts for this =
descriptor */
Post by Vivek Gautam
Post by Alim Akhtar
- desc->des0 =3D IDMAC_DES0_OWN | IDMAC_DES0_DIC | ID=
MAC_DES0_CH;
Post by Vivek Gautam
Post by Alim Akhtar
+ /*
+ * Set the OWN bit and disable interrupts f=
or this
Post by Vivek Gautam
Post by Alim Akhtar
+ * descriptor
+ */
+ desc->des0 =3D IDMAC_DES0_OWN | IDMAC_DES0_=
DIC |
Post by Vivek Gautam
Post by Alim Akhtar
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length)=
;
Post by Vivek Gautam
Post by Alim Akhtar
+
+ /* Physical address to DMA to/from */
+ desc->des4 =3D mem_addr & 0xffffffff;
+ desc->des5 =3D mem_addr >> 32;
+ }
- /* Buffer length */
- IDMAC_SET_BUFFER1_SIZE(desc, length);
+ /* Set first descriptor */
+ desc =3D host->sg_cpu;
+ desc->des0 |=3D IDMAC_DES0_FD;
- /* Physical address to DMA to/from */
- desc->des2 =3D mem_addr;
- }
+ /* Set last descriptor */
+ desc =3D host->sg_cpu + (i - 1) *
+ sizeof(struct idmac_desc_64addr);
+ desc->des0 &=3D ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |=3D IDMAC_DES0_LD;
+
+ } else {
+ struct idmac_desc *desc =3D host->sg_cpu;
+
+ for (i =3D 0; i < sg_len; i++, desc++) {
+ unsigned int length =3D sg_dma_len(&data->s=
g[i]);
Post by Vivek Gautam
Post by Alim Akhtar
+ u32 mem_addr =3D sg_dma_address(&data->sg[i=
]);
Post by Vivek Gautam
Post by Alim Akhtar
+
+ /*
+ * Set the OWN bit and disable interrupts f=
or this
Post by Vivek Gautam
Post by Alim Akhtar
+ * descriptor
+ */
+ desc->des0 =3D IDMAC_DES0_OWN | IDMAC_DES0_=
DIC |
Post by Vivek Gautam
Post by Alim Akhtar
+ IDMAC_DES0_CH;
+ /* Buffer length */
+ IDMAC_SET_BUFFER1_SIZE(desc, length);
+
+ /* Physical address to DMA to/from */
+ desc->des2 =3D mem_addr;
+ }
- /* Set first descriptor */
- desc =3D host->sg_cpu;
- desc->des0 |=3D IDMAC_DES0_FD;
+ /* Set first descriptor */
+ desc =3D host->sg_cpu;
+ desc->des0 |=3D IDMAC_DES0_FD;
- /* Set last descriptor */
- desc =3D host->sg_cpu + (i - 1) * sizeof(struct idmac_desc)=
;
Post by Vivek Gautam
Post by Alim Akhtar
- desc->des0 &=3D ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
- desc->des0 |=3D IDMAC_DES0_LD;
+ /* Set last descriptor */
+ desc =3D host->sg_cpu + (i - 1) * sizeof(struct idm=
ac_desc);
Post by Vivek Gautam
Post by Alim Akhtar
+ desc->des0 &=3D ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+ desc->des0 |=3D IDMAC_DES0_LD;
+ }
wmb();
}
@@ -466,29 +520,67 @@ static void dw_mci_idmac_start_dma(struct dw_=
mci *host, unsigned int sg_len)
Post by Vivek Gautam
Post by Alim Akhtar
static int dw_mci_idmac_init(struct dw_mci *host)
{
- struct idmac_desc *p;
int i;
- /* Number of descriptors in the ring buffer */
- host->ring_size =3D PAGE_SIZE / sizeof(struct idmac_desc);
+ if (host->dma_64bit_address =3D=3D 1) {
+ struct idmac_desc_64addr *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size =3D PAGE_SIZE / sizeof(struct idmac=
_desc_64addr);
Post by Vivek Gautam
Post by Alim Akhtar
+
+ /* Forward link the descriptor list */
+ for (i =3D 0, p =3D host->sg_cpu; i < host->ring_si=
ze - 1;
Post by Vivek Gautam
Post by Alim Akhtar
+ i++=
, p++) {
Post by Vivek Gautam
Post by Alim Akhtar
+ p->des6 =3D (host->sg_dma +
+ (sizeof(struct idmac_desc_6=
4addr) *
Post by Vivek Gautam
Post by Alim Akhtar
+ (i + 1))) &=
0xffffffff;
Post by Vivek Gautam
Post by Alim Akhtar
+
+ p->des7 =3D (host->sg_dma +
+ (sizeof(struct idmac_desc_6=
4addr) *
Post by Vivek Gautam
Post by Alim Akhtar
+ (i + 1))) >=
32;
Post by Alim Akhtar
+ }
+
+ /* Set the last descriptor as the end-of-ring descr=
iptor */
Post by Vivek Gautam
Post by Alim Akhtar
+ p->des6 =3D host->sg_dma & 0xffffffff;
+ p->des7 =3D host->sg_dma >> 32;
+ p->des0 =3D IDMAC_DES0_ER;
+
+ } else {
+ struct idmac_desc *p;
+ /* Number of descriptors in the ring buffer */
+ host->ring_size =3D PAGE_SIZE / sizeof(struct idmac=
_desc);
Post by Vivek Gautam
Post by Alim Akhtar
- /* Forward link the descriptor list */
- for (i =3D 0, p =3D host->sg_cpu; i < host->ring_size - 1; =
i++, p++)
Post by Vivek Gautam
Post by Alim Akhtar
- p->des3 =3D host->sg_dma + (sizeof(struct idmac_des=
c) * (i + 1));
Post by Vivek Gautam
Post by Alim Akhtar
+ /* Forward link the descriptor list */
+ for (i =3D 0, p =3D host->sg_cpu; i < host->ring_si=
ze - 1; i++, p++)
Post by Vivek Gautam
Post by Alim Akhtar
+ p->des3 =3D host->sg_dma + (sizeof(struct i=
dmac_desc) *
Post by Vivek Gautam
Post by Alim Akhtar
+ (i =
+ 1));
Post by Vivek Gautam
Post by Alim Akhtar
- /* Set the last descriptor as the end-of-ring descriptor */
- p->des3 =3D host->sg_dma;
- p->des0 =3D IDMAC_DES0_ER;
+ /* Set the last descriptor as the end-of-ring descr=
iptor */
Post by Vivek Gautam
Post by Alim Akhtar
+ p->des3 =3D host->sg_dma;
+ p->des0 =3D IDMAC_DES0_ER;
+ }
dw_mci_idmac_reset(host);
- /* Mask out interrupts - get Tx & Rx complete only */
- mci_writel(host, IDSTS, IDMAC_INT_CLR);
- mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_=
INT_RI |
Post by Vivek Gautam
Post by Alim Akhtar
- SDMMC_IDMAC_INT_TI);
+ if (host->dma_64bit_address =3D=3D 1) {
+ /* Mask out interrupts - get Tx & Rx complete only =
*/
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS64, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_IN=
T_TI);
Post by Vivek Gautam
Post by Alim Akhtar
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff=
);
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, DBADDRU, host->sg_dma >> 32);
+
+ } else {
+ /* Mask out interrupts - get Tx & Rx complete only =
*/
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS, IDMAC_INT_CLR);
+ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI |
+ SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_IN=
T_TI);
Post by Vivek Gautam
Post by Alim Akhtar
+
+ /* Set the descriptor base address */
+ mci_writel(host, DBADDR, host->sg_dma);
+ }
- /* Set the descriptor base address */
- mci_writel(host, DBADDR, host->sg_dma);
return 0;
}
@@ -2045,11 +2137,22 @@ static irqreturn_t dw_mci_interrupt(int irq=
, void *dev_id)
Post by Vivek Gautam
Post by Alim Akhtar
#ifdef CONFIG_MMC_DW_IDMAC
/* Handle DMA interrupts */
- pending =3D mci_readl(host, IDSTS);
- if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_=
IDMAC_INT_RI);
Post by Vivek Gautam
Post by Alim Akhtar
- mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
- host->dma_ops->complete(host);
+ if (host->dma_64bit_address =3D=3D 1) {
+ pending =3D mci_readl(host, IDSTS64);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT=
_RI)) {
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_T=
I |
Post by Vivek Gautam
Post by Alim Akhtar
+ SDMMC_IDMAC=
_INT_RI);
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_N=
I);
Post by Vivek Gautam
Post by Alim Akhtar
+ host->dma_ops->complete(host);
+ }
+ } else {
+ pending =3D mci_readl(host, IDSTS);
+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT=
_RI)) {
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI =
|
Post by Vivek Gautam
Post by Alim Akhtar
+ SDMMC_IDMAC=
_INT_RI);
Post by Vivek Gautam
Post by Alim Akhtar
+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI)=
;
Post by Vivek Gautam
Post by Alim Akhtar
+ host->dma_ops->complete(host);
+ }
}
#endif
@@ -2309,6 +2412,22 @@ static void dw_mci_cleanup_slot(struct dw_mc=
i_slot *slot, unsigned int id)
Post by Vivek Gautam
Post by Alim Akhtar
static void dw_mci_init_dma(struct dw_mci *host)
{
+ int addr_config;
+ /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus =
width */
Post by Vivek Gautam
Post by Alim Akhtar
+ addr_config =3D (mci_readl(host, HCON) >> 27) & 0x01;
+
+ if (addr_config =3D=3D 1) {
+ /* host supports IDMAC in 64-bit address mode */
+ host->dma_64bit_address =3D 1;
+ dev_info(host->dev, "IDMAC supports 64-bit address =
mode.\n");
Post by Vivek Gautam
Post by Alim Akhtar
+ if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+ dma_set_coherent_mask(host->dev, DMA_BIT_MA=
SK(64));
Post by Vivek Gautam
Post by Alim Akhtar
+ } else {
+ /* host supports IDMAC in 32-bit address mode */
+ host->dma_64bit_address =3D 0;
+ dev_info(host->dev, "IDMAC supports 32-bit address =
mode.\n");
Post by Vivek Gautam
Post by Alim Akhtar
+ }
+
/* Alloc memory for sg translation */
host->sg_cpu =3D dmam_alloc_coherent(host->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL=
);
Post by Vivek Gautam
Post by Alim Akhtar
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8..64b04aa 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -55,6 +55,17 @@
#define SDMMC_BUFADDR 0x098
#define SDMMC_CDTHRCTL 0x100
#define SDMMC_DATA(x) (x)
+/*
+* Registers to support idmac 64-bit address mode
+*/
+#define SDMMC_DBADDRL 0x088
+#define SDMMC_DBADDRU 0x08c
+#define SDMMC_IDSTS64 0x090
+#define SDMMC_IDINTEN64 0x094
+#define SDMMC_DSCADDRL 0x098
+#define SDMMC_DSCADDRU 0x09c
+#define SDMMC_BUFADDRL 0x0A0
+#define SDMMC_BUFADDRU 0x0A4
/*
* Data offset is difference according to Version
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.=
h
Post by Vivek Gautam
Post by Alim Akhtar
index 0013669..9e6eabb 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -54,6 +54,7 @@ struct mmc_data;
* transfer is in progress.
not.
Post by Vivek Gautam
Post by Alim Akhtar
@@ -140,6 +141,7 @@ struct dw_mci {
/* DMA interface members*/
int use_dma;
int using_dma;
+ int dma_64bit_address;
dma_addr_t sg_dma;
void *sg_cpu;
--
1.7.6.5
--
Regards,
Alim
--
To unsubscribe from this list: send the line "unsubscribe linux-kern=
el" in
Post by Vivek Gautam
Post by Alim Akhtar
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
=20
=20
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Prabu Thangamuthu
2014-10-16 10:39:34 UTC
Permalink
Hi Jaehoon, Vivek, Alim,

Thanks for your review comments.
Post by Jaehoon Chung
Hi, Prabu.
Post by Vivek Gautam
Hi Prabu,
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
On Thu, Oct 9, 2014 at 1:09 PM, Prabu Thangamuthu
Post by Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit
address mode from IP version 2.70a onwards.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-51
setup and driver is working fine.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch is
required for another patch
http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address mode based
on hw configuration.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195
+++++++++++++++++++++++++++++++++++---------
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c
b/drivers/mmc/host/dw_mmc.c
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As these
are pointers, do you thing initializing then to zero make sense?
We don't think it's required to assign zero to reserved des field as mobster core not going to use this field's for any operations unless user has modified it.
Also it's working fine in our test set-up without initializing them to zero.
Post by Jaehoon Chung
Post by Vivek Gautam
I think the default reset value of these descriptors will depend on
how dwmmc is integrated in h/w and how these descriptors are then
configured.
So it makes sense to initialize these descriptors to zero before use.
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
It looks like exynos7 is using this reserved fields for some other purposes. To make it generic, we will initialize the reserved fields to zero.

Does exynos7 requires des2 (Buffer sizes) also to be initialized to zero?
Post by Jaehoon Chung
I agreed with Vivek and Alim's comment.
And I think you can fix the below compile warning.
drivers/mmc/host/dw_mmc.c:542:21: warning: right shift count >= width of
type [enabled by default]
drivers/mmc/host/dw_mmc.c:547:3: warning: right shift count >= width of
type [enabled by default]
drivers/mmc/host/dw_mmc.c:575:3: warning: right shift count >= width of
type [enabled by default]
I will check this patch with 2.70a and other version.
We will fix the warnings an
Vivek Gautam
2014-10-16 11:09:08 UTC
Permalink
Hi Prabu,
Post by Prabu Thangamuthu
Hi Jaehoon, Vivek, Alim,
Thanks for your review comments.
Post by Jaehoon Chung
Hi, Prabu.
Post by Vivek Gautam
Hi Prabu,
m>
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
On Thu, Oct 9, 2014 at 1:09 PM, Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64=
-bit
Post by Prabu Thangamuthu
Post by Jaehoon Chung
address mode from IP version 2.70a onwards.
Post by Vivek Gautam
Post by Alim Akhtar
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-5=
1
Post by Prabu Thangamuthu
Post by Jaehoon Chung
setup and driver is working fine.
Post by Vivek Gautam
Post by Alim Akhtar
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch i=
s
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
required for another patch
http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address =
mode based
Post by Prabu Thangamuthu
Post by Jaehoon Chung
on hw configuration.
Post by Vivek Gautam
Post by Alim Akhtar
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195
+++++++++++++++++++++++++++++++++++---------
Post by Vivek Gautam
Post by Alim Akhtar
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c
b/drivers/mmc/host/dw_mmc.c
Post by Vivek Gautam
Post by Alim Akhtar
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDM=
AC_INT_RI | \
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As the=
se
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
are pointers, do you thing initializing then to zero make sense?
We don't think it's required to assign zero to reserved des field as =
mobster core not going to use this field's for any operations unless us=
er has modified it.
Post by Prabu Thangamuthu
Also it's working fine in our test set-up without initializing them t=
o zero.
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
I think the default reset value of these descriptors will depend o=
n
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
how dwmmc is integrated in h/w and how these descriptors are then
configured.
So it makes sense to initialize these descriptors to zero before u=
se.
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
It looks like exynos7 is using this reserved fields for some other pu=
rposes. To make it generic, we will initialize the reserved fields to z=
ero.
Post by Prabu Thangamuthu
Does exynos7 requires des2 (Buffer sizes) also to be initialized to z=
ero?

Yes, we need des2 to be initialized to zero.
One question however, do we have some default reset value set to these
descriptors ? If yes then how can we check this value ?
I just tried printing the value of des1 and des2 in dw_mci_translate_sg=
list()
where we are assigning these descriptors.
Post by Prabu Thangamuthu
Post by Jaehoon Chung
I agreed with Vivek and Alim's comment.
And I think you can fix the below compile warning.
drivers/mmc/host/dw_mmc.c: In function =E2=80=98dw_mci_idmac_init=E2=
drivers/mmc/host/dw_mmc.c:542:21: warning: right shift count >=3D wi=
dth of
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
drivers/mmc/host/dw_mmc.c:547:3: warning: right shift count >=3D wid=
th of
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
drivers/mmc/host/dw_mmc.c:575:3: warning: right shift count >=3D wid=
th of
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
I will check this patch with 2.70a and other version.
We will fix the warnings and post the new patch.
Regards,
Prabu Thangamuthu.
--=20
Best Regards
Vivek Gautam
Samsung R&D Institute, Bangalore
India
Jaehoon Chung
2014-10-16 11:11:35 UTC
Permalink
Post by Vivek Gautam
Hi Prabu,
=20
=20
Post by Prabu Thangamuthu
Hi Jaehoon, Vivek, Alim,
Thanks for your review comments.
Post by Jaehoon Chung
Hi, Prabu.
Post by Vivek Gautam
Hi Prabu,
m>
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
On Thu, Oct 9, 2014 at 1:09 PM, Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64=
-bit
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
address mode from IP version 2.70a onwards.
Post by Vivek Gautam
Post by Alim Akhtar
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-5=
1
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
setup and driver is working fine.
Post by Vivek Gautam
Post by Alim Akhtar
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch i=
s
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
required for another patch
http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address =
mode based
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
on hw configuration.
Post by Vivek Gautam
Post by Alim Akhtar
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS macro.
drivers/mmc/host/dw_mmc.c | 195
+++++++++++++++++++++++++++++++++++---------
Post by Vivek Gautam
Post by Alim Akhtar
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c
b/drivers/mmc/host/dw_mmc.c
Post by Vivek Gautam
Post by Alim Akhtar
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE | SDMMC_IDM=
AC_INT_RI | \
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As the=
se
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
are pointers, do you thing initializing then to zero make sense?
We don't think it's required to assign zero to reserved des field as=
mobster core not going to use this field's for any operations unless u=
ser has modified it.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Also it's working fine in our test set-up without initializing them =
to zero.

Right, it's not required to assign zero to there. And It's working fine=
, because it's not used or referred anywhere.
Just Recommend to initialize to zero.
Actually, i don't understand why des1 is reserved..
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
I think the default reset value of these descriptors will depend o=
n
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
how dwmmc is integrated in h/w and how these descriptors are then
configured.
So it makes sense to initialize these descriptors to zero before u=
se.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
It looks like exynos7 is using this reserved fields for some other p=
urposes. To make it generic, we will initialize the reserved fields to =
zero.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Does exynos7 requires des2 (Buffer sizes) also to be initialized to =
zero?
Post by Vivek Gautam
=20
Yes, we need des2 to be initialized to zero.
One question however, do we have some default reset value set to thes=
e
Post by Vivek Gautam
descriptors ? If yes then how can we check this value ?
I knew it doesn't have the reset value for descriptors.

Best Regards,
Jaehoon Chung
Post by Vivek Gautam
I just tried printing the value of des1 and des2 in dw_mci_translate_=
sglist()
Post by Vivek Gautam
where we are assigning these descriptors.
=20
Post by Prabu Thangamuthu
Post by Jaehoon Chung
I agreed with Vivek and Alim's comment.
And I think you can fix the below compile warning.
drivers/mmc/host/dw_mmc.c: In function =E2=80=98dw_mci_idmac_init=E2=
drivers/mmc/host/dw_mmc.c:542:21: warning: right shift count >=3D w=
idth of
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
drivers/mmc/host/dw_mmc.c:547:3: warning: right shift count >=3D wi=
dth of
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
drivers/mmc/host/dw_mmc.c:575:3: warning: right shift count >=3D wi=
dth of
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
type [enabled by default]
I will check this patch with 2.70a and other version.
We will fix the warnings and post the new patch.
Regards,
Prabu Thangamuthu.
=20
=20
=20
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Prabu Thangamuthu
2014-10-16 12:01:26 UTC
Permalink
Hi,
Post by Prabu Thangamuthu
Post by Vivek Gautam
Hi Prabu,
On Thu, Oct 16, 2014 at 4:09 PM, Prabu Thangamuthu
Post by Prabu Thangamuthu
Hi Jaehoon, Vivek, Alim,
Thanks for your review comments.
On Thu, Oct 16, 2014 at 12:20 PM, Jaehoon Chung
Post by Jaehoon Chung
Hi, Prabu.
Post by Vivek Gautam
Hi Prabu,
On Tue, Oct 14, 2014 at 5:41 PM, Alim Akhtar
Post by Alim Akhtar
Hi Prahu,
Thanks for a quick re-spin o the patch.
One last comment, this is more of a information seek.
On Thu, Oct 9, 2014 at 1:09 PM, Prabu Thangamuthu
Post by Prabu Thangamuthu
Synopsys DW_MMC IP core supports Internal DMA Controller with 64-bit
address mode from IP version 2.70a onwards.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
Updated the driver to support IDMAC 64-bit addressing mode.
Tested the features in DW_MMC core v2.70a and v2.40a with HAPS-
51
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
setup and driver is working fine.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
---
- Updated with review comment.
- Recreated the patch against linux-next as this patch is
required for another patch
http://www.spinics.net/lists/arm-kernel/msg357985.html
- Add the dynamic support for 32-bit and 64-bit address mode based
on hw configuration.
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
- Removed the CONFIG_MMC_DW_IDMAC_64BIT_ADDRESS
macro.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
drivers/mmc/host/dw_mmc.c | 195
+++++++++++++++++++++++++++++++++++---------
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
drivers/mmc/host/dw_mmc.h | 11 +++
include/linux/mmc/dw_mmc.h | 2 +
3 files changed, 170 insertions(+), 38 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c
b/drivers/mmc/host/dw_mmc.c
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
index 69f0cc6..c3b75a5 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -62,6 +62,24 @@
SDMMC_IDMAC_INT_FBE |
SDMMC_IDMAC_INT_RI | \
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
Post by Alim Akhtar
Post by Prabu Thangamuthu
SDMMC_IDMAC_INT_TI)
+struct idmac_desc_64addr {
+ u32 des0; /* Control Descriptor */
+
+ u32 des1; /* Reserved */
What is the default value of these _Reserved_ descriptors? As
these are pointers, do you thing initializing then to zero make sense?
We don't think it's required to assign zero to reserved des field as
mobster core not going to use this field's for any operations unless user has
modified it.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Also it's working fine in our test set-up without initializing them to zero.
Right, it's not required to assign zero to there. And It's working fine, because
it's not used or referred anywhere.
Just Recommend to initialize to zero.
Fine.
Post by Prabu Thangamuthu
Actually, i don't understand why des1 is reserved..
It's reserved for future enhancement.
Post by Prabu Thangamuthu
Post by Vivek Gautam
Post by Prabu Thangamuthu
Post by Jaehoon Chung
Post by Vivek Gautam
I think the default reset value of these descriptors will depend on
how dwmmc is integrated in h/w and how these descriptors are then
configured.
So it makes sense to initialize these descriptors to zero before use.
We have seen on our exynos7 system, that we need to initialize the
descriptors des1 and des2 to zero before we use them further.
It looks like exynos7 is using this reserved fields for some other purposes.
To make it generic, we will initialize the reserved fields to zero.
Post by Vivek Gautam
Post by Prabu Thangamuthu
Does exynos7 requires des2 (Buffer sizes) also to be initialized to zero?
Yes, we need des2 to be initialized to zero.
One question however, do we have some default reset value set to these
descriptors ? If yes then how can we check this value ?
I knew it doesn't have the reset value for descriptors.
Yes, it's correct.


Regards,
Prabu Thangamuthu.
��{.n�+�������+%��lzwm��b�맲��r��zX���r)����w*jg��������ݢj/���z�ޖ�
Loading...