Skip to contentSkip to conversation

ARM: socfpga: enable big endian for secondary core(s)

PATCH New Ben Dooks 2 participants 9 messages Mar 25, 2015 – Mar 26, 2015 1 message not in the archive

Subsystems (6)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Ben Dooks

author
#1 lore raw

PATCH 2/7 ARM: socfpga: enable big endian for secondary core(s)

Update the secondary code to allow the secondary boot to work when the system is running big endian.

--
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>

---
 arch/arm/mach-socfpga/headsmp.S | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm/mach-socfpga/headsmp.S +4 -1
index f65ea0a..a580dcd 100644
@@ -10,6 +10,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/memory.h>
+#include <asm/assembler.h>
 
 	.arch	armv7-a
 
@@ -18,12 +19,14 @@ ENTRY(secondary_trampoline)
 	 * Thus, we can just subtract the PAGE_OFFSET to get the physical
 	 * address of &cpu1start_addr. This would not work for platforms
 	 * where the physical memory does not start at 0x0.
-	 */
+	*/
+ARM_BE8(setend	be)
 	adr	r0, 1f
 	ldmia	r0, {r1, r2}
 	sub	r2, r2, #PAGE_OFFSET
 	ldr	r3, [r2]
 	ldr	r4, [r3]
+ARM_BE8(rev	r4, r4)
 	bx	r4
 
 	.align
Signature · 1 line
2.1.4
author
#2 lore raw

PATCH 3/7 ARM: socfpga: support big endian for socfpga

In reply to a message not in the archive

Now the debug and platsmp.S are fixed for big endian, the architecture can now advertise big endian support.

--
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>

---
 arch/arm/mach-socfpga/Kconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-socfpga/Kconfig +1 -0
index b5f8d75..f420a1b 100644
@@ -1,5 +1,6 @@
 config ARCH_SOCFPGA
 	bool "Altera SOCFPGA family" if ARCH_MULTI_V7
+	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
 	select CACHE_L2X0
Signature · 1 line
2.1.4
author
#3 lore raw

PATCH 4/7 clocksource: dw_apb_timer_of: make IO endian agnostic

In reply to a message not in the archive

The dw_apb_timer_of timer is using __raw_readl to access the timer register, which is causing issues when the system is running in big endian mode. Fix this by using readl_relaxed() which should account for the endian settings.

This fixes issues where the time jumps around in the dmesg output due to returnling __le32 values.

For an example, these two console lines show time running backwards:

[   49.882572] CPU1: failed to come online
[   43.282457] Brought up 1 CPUs

--
CC: Daniel Lezcano <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>

---
 drivers/clocksource/dw_apb_timer_of.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clocksource/dw_apb_timer_of.c +1 -1
index d305fb0..a19a3f6 100644
@@ -108,7 +108,7 @@ static void __init add_clocksource(struct device_node *source_timer)
 
 static u64 notrace read_sched_clock(void)
 {
-	return ~__raw_readl(sched_io_base);
+	return ~readl_relaxed(sched_io_base);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
Signature · 1 line
2.1.4
#4 lore raw

PATCH 4/7 clocksource: dw_apb_timer_of: make IO endian agnostic

Quoted 8 lines · Ben Dooks

The dw_apb_timer_of timer is using __raw_readl to access the timer register, which is causing issues when the system is running in big endian mode. Fix this by using readl_relaxed() which should account for the endian settings.

This fixes issues where the time jumps around in the dmesg output due to returnling __le32 values.

Quoted 6 lines

For an example, these two console lines show time running backwards:

[   49.882572] CPU1: failed to come online
[   43.282457] Brought up 1 CPUs

Hi Ben,

Through which tree this patch is supposed to go ?

Quoted 23 lines

--
CC: Daniel Lezcano <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>

---
  drivers/clocksource/dw_apb_timer_of.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clocksource/dw_apb_timer_of.c +1 -1
index d305fb0..a19a3f6 100644
@@ -108,7 +108,7 @@ static void __init add_clocksource(struct device_node *source_timer)
 
  static u64 notrace read_sched_clock(void)
  {
-	return ~__raw_readl(sched_io_base);
+	return ~readl_relaxed(sched_io_base);
  }
 
  static const struct of_device_id sptimer_ids[] __initconst = {
Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
author
#5 lore raw

PATCH 4/7 clocksource: dw_apb_timer_of: make IO endian agnostic

Quoted 11 lines · Daniel Lezcano
Quoted 10 lines · Ben Dooks

The dw_apb_timer_of timer is using __raw_readl to access the timer register, which is causing issues when the system is running in big endian mode. Fix this by using readl_relaxed() which should account for the endian settings.

This fixes issues where the time jumps around in the dmesg output due to returnling __le32 values.

For an example, these two console lines show time running backwards:

Quoted 8 lines
Quoted 4 lines
[   49.882572] CPU1: failed to come online
[   43.282457] Brought up 1 CPUs

Hi Ben,

Through which tree this patch is supposed to go ?

I think yours is probably the best one for it, it doesn't depend on anything else in the series.

Signature · 2 lines
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius
#6 lore raw

PATCH 4/7 clocksource: dw_apb_timer_of: make IO endian agnostic

Quoted 15 lines · Ben Dooks
Quoted 14 lines · Daniel Lezcano
Quoted 13 lines · Ben Dooks

The dw_apb_timer_of timer is using __raw_readl to access the timer register, which is causing issues when the system is running in big endian mode. Fix this by using readl_relaxed() which should account for the endian settings.

This fixes issues where the time jumps around in the dmesg output due to returnling __le32 values.

For an example, these two console lines show time running backwards:

[   49.882572] CPU1: failed to come online
[   43.282457] Brought up 1 CPUs
Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Hi Ben,

Through which tree this patch is supposed to go ?

I think yours is probably the best one for it, it doesn't depend on anything else in the series.

Ok, thanks.

-- Daniel

Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
author
#7 lore raw

PATCH 5/7 mmc: host: dw_mmc make IO accessors endian agnostic

In reply to a message not in the archive

The dw_mmc driver does not use endian agnostic IO accessors, so fix the use of __raw reads and writes to be the relaxed versions.

This fixes the dw_mmc driver initialisation on Altera socfpga in big endian.

--
CC: Linux MMC <[email protected]>
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>
CC: Chris Ball <[email protected]>
CC: Ulf Hansson <[email protected]>
CC: Jaehoon Chung <[email protected]>
CC: Seungwon Jeon <[email protected]>

---
 drivers/mmc/host/dw_mmc.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/mmc/host/dw_mmc.h +6 -6
index 18c4afe..46efdc5 100644
@@ -171,22 +171,22 @@
 
 /* Register access macros */
 #define mci_readl(dev, reg)			\
-	__raw_readl((dev)->regs + SDMMC_##reg)
+	readl_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writel(dev, reg, value)			\
-	__raw_writel((value), (dev)->regs + SDMMC_##reg)
+	writel_relaxed((value), (dev)->regs + SDMMC_##reg)
 
 /* 16-bit FIFO access macros */
 #define mci_readw(dev, reg)			\
-	__raw_readw((dev)->regs + SDMMC_##reg)
+	readw_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writew(dev, reg, value)			\
-	__raw_writew((value), (dev)->regs + SDMMC_##reg)
+	writew_relaxed((value), (dev)->regs + SDMMC_##reg)
 
 /* 64-bit FIFO access macros */
 #ifdef readq
 #define mci_readq(dev, reg)			\
-	__raw_readq((dev)->regs + SDMMC_##reg)
+	readq_relaxed((dev)->regs + SDMMC_##reg)
 #define mci_writeq(dev, reg, value)			\
-	__raw_writeq((value), (dev)->regs + SDMMC_##reg)
+	writeq_relaxed((value), (dev)->regs + SDMMC_##reg)
 #else
 /*
  * Dummy readq implementation for architectures that don't define it.
Signature · 1 line
2.1.4
author
#8 lore raw

PATCH 6/7 mmc: host: dw_mmc: change idmac descriptor files to __le32

In reply to a message not in the archive

The dw_mmc driver does not take into account the processor may be in big endian when writing the descriptors. Change the descriptors for the 32bit IDMA to use __le32 and ensure they are suitably swapped before writing.

Note, this has not been tested as the socfpga driver does not try to use idma.

--
CC: Linux MCC <[email protected]>
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>
CC: Chris Ball <[email protected]>
CC: Ulf Hansson <[email protected]>
CC: Jaehoon Chung <[email protected]>
CC: Seungwon Jeon <[email protected]>

---
 drivers/mmc/host/dw_mmc.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/mmc/host/dw_mmc.c +15 -15
index 4d2e3c2..12e681c 100644
@@ -69,7 +69,7 @@ struct idmac_desc_64addr {
 
 	u32		des2;	/*Buffer sizes */
 #define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
-	((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+	((d)->des2 = ((d)->des2 & cpu_to_le32(0x03ffe000)) | ((cpu_to_le32(s)) & cpu_to_le32(0x1fff)))
 
 	u32		des3;	/* Reserved */
 
@@ -81,7 +81,7 @@ struct idmac_desc_64addr {
 };
 
 struct idmac_desc {
-	u32		des0;	/* Control Descriptor */
+	__le32		des0;	/* Control Descriptor */
 #define IDMAC_DES0_DIC	BIT(1)
 #define IDMAC_DES0_LD	BIT(2)
 #define IDMAC_DES0_FD	BIT(3)
@@ -90,13 +90,13 @@ struct idmac_desc {
 #define IDMAC_DES0_CES	BIT(30)
 #define IDMAC_DES0_OWN	BIT(31)
 
-	u32		des1;	/* Buffer sizes */
+	__le32		des1;	/* Buffer sizes */
 #define IDMAC_SET_BUFFER1_SIZE(d, s) \
 	((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff))
 
-	u32		des2;	/* buffer 1 physical address */
+	__le32		des2;	/* buffer 1 physical address */
 
-	u32		des3;	/* buffer 2 physical address */
+	__le32		des3;	/* buffer 2 physical address */
 };
 #endif /* CONFIG_MMC_DW_IDMAC */
 
@@ -477,23 +477,23 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
 			 * Set the OWN bit and disable interrupts for this
 			 * descriptor
 			 */
-			desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
-						IDMAC_DES0_CH;
+			desc->des0 = cpu_to_le32(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;
+			desc->des2 = cpu_to_le32(mem_addr);
 		}
 
 		/* Set first descriptor */
 		desc = host->sg_cpu;
-		desc->des0 |= IDMAC_DES0_FD;
+		desc->des0 |= cpu_to_le32(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;
+		desc->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | IDMAC_DES0_DIC));
+		desc->des0 |= cpu_to_le32(IDMAC_DES0_LD);
 	}
 
 	wmb();
@@ -562,12 +562,12 @@ static int dw_mci_idmac_init(struct dw_mci *host)
 
 		/* 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));
+			p->des3 = cpu_to_le32(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;
+		p->des3 = cpu_to_le32(host->sg_dma);
+		p->des0 = cpu_to_le32(IDMAC_DES0_ER);
 	}
 
 	dw_mci_idmac_reset(host);
Signature · 1 line
2.1.4
author
#9 lore raw

PATCH 7/7 mmc: host: dw_mmc: fix fifo ordering in big endian

In reply to a message not in the archive

The dw_mmc driver changes to make the IO accesors endian agnostic did not take into account the fifo accesses do not need to be swapped. To fix this add a mmci_fifo_read/write wrapper to allow these to be passed through the IO without being swapped.

Since these are now specific functions, it would be easier just to store the pointer to the fifo registers in the host block instead of the offset to them. So change the host->data_offset to host->fifo_reg (which also means we catch all the places this is read or written).

--
CC: Linux MMC <[email protected]>
CC: Linux ARM Kernel <[email protected]>
CC: Dinh Nguyen <[email protected]>
CC: Chris Ball <[email protected]>
CC: Ulf Hansson <[email protected]>
CC: Jaehoon Chung <[email protected]>
CC: Seungwon Jeon <[email protected]>

---
 drivers/mmc/host/dw_mmc.c  | 59 +++++++++++++++++++---------------------------
 drivers/mmc/host/dw_mmc.h  | 14 +++++++++++
 include/linux/mmc/dw_mmc.h |  4 ++--
 3 files changed, 40 insertions(+), 37 deletions(-)
drivers/mmc/host/dw_mmc.c +24 -35
index 12e681c..98f0c92 100644
@@ -1685,8 +1685,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
 		buf += len;
 		cnt -= len;
 		if (host->part_buf_count == 2) {
-			mci_writew(host, DATA(host->data_offset),
-					host->part_buf16);
+			mci_fifo_writew(host->fifo_reg, host->part_buf16);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1703,15 +1702,14 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writew(host, DATA(host->data_offset),
-						aligned_buf[i]);
+				mci_fifo_writew(host->fifo_reg, aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u16 *pdata = buf;
 		for (; cnt >= 2; cnt -= 2)
-			mci_writew(host, DATA(host->data_offset), *pdata++);
+			mci_fifo_writew(host->fifo_reg, *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
@@ -1720,8 +1718,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt)
 		 /* Push data if we have reached the expected data length */
 		if ((data->bytes_xfered + init_cnt) ==
 		    (data->blksz * data->blocks))
-			mci_writew(host, DATA(host->data_offset),
-				   host->part_buf16);
+			mci_fifo_writew(host->fifo_reg, host->part_buf16);
 	}
 }
 
@@ -1736,8 +1733,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
 			int items = len >> 1;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readw(host,
-						DATA(host->data_offset));
+				aligned_buf[i] = mci_fifo_readw(host->fifo_reg);
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1748,11 +1744,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt)
 	{
 		u16 *pdata = buf;
 		for (; cnt >= 2; cnt -= 2)
-			*pdata++ = mci_readw(host, DATA(host->data_offset));
+			*pdata++ = mci_fifo_readw(host->fifo_reg);
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf16 = mci_readw(host, DATA(host->data_offset));
+		host->part_buf16 = mci_fifo_readw(host->fifo_reg);
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -1768,8 +1764,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 		buf += len;
 		cnt -= len;
 		if (host->part_buf_count == 4) {
-			mci_writel(host, DATA(host->data_offset),
-					host->part_buf32);
+			mci_fifo_writel(host->fifo_reg,	host->part_buf32);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1786,15 +1781,14 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writel(host, DATA(host->data_offset),
-						aligned_buf[i]);
+				mci_fifo_writel(host->fifo_reg,	aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u32 *pdata = buf;
 		for (; cnt >= 4; cnt -= 4)
-			mci_writel(host, DATA(host->data_offset), *pdata++);
+			mci_fifo_writel(host->fifo_reg, *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
@@ -1803,8 +1797,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt)
 		 /* Push data if we have reached the expected data length */
 		if ((data->bytes_xfered + init_cnt) ==
 		    (data->blksz * data->blocks))
-			mci_writel(host, DATA(host->data_offset),
-				   host->part_buf32);
+			mci_fifo_writel(host->fifo_reg, host->part_buf32);
 	}
 }
 
@@ -1819,8 +1812,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
 			int items = len >> 2;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readl(host,
-						DATA(host->data_offset));
+				aligned_buf[i] = mci_fifo_readl(host->fifo_reg);
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1831,11 +1823,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt)
 	{
 		u32 *pdata = buf;
 		for (; cnt >= 4; cnt -= 4)
-			*pdata++ = mci_readl(host, DATA(host->data_offset));
+			*pdata++ = mci_fifo_readl(host->fifo_reg);
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf32 = mci_readl(host, DATA(host->data_offset));
+		host->part_buf32 = mci_fifo_readl(host->fifo_reg);
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -1852,8 +1844,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 		cnt -= len;
 
 		if (host->part_buf_count == 8) {
-			mci_writeq(host, DATA(host->data_offset),
-					host->part_buf);
+			mci_fifo_writeq(host->fifo_reg,	host->part_buf);
 			host->part_buf_count = 0;
 		}
 	}
@@ -1870,15 +1861,14 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 			cnt -= len;
 			/* push data from aligned buffer into fifo */
 			for (i = 0; i < items; ++i)
-				mci_writeq(host, DATA(host->data_offset),
-						aligned_buf[i]);
+				mci_fifo_writeq(host->fifo_reg,	aligned_buf[i]);
 		}
 	} else
 #endif
 	{
 		u64 *pdata = buf;
 		for (; cnt >= 8; cnt -= 8)
-			mci_writeq(host, DATA(host->data_offset), *pdata++);
+			mci_fifo_writeq(host->fifo_reg, *pdata++);
 		buf = pdata;
 	}
 	/* put anything remaining in the part_buf */
@@ -1887,8 +1877,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt)
 		/* Push data if we have reached the expected data length */
 		if ((data->bytes_xfered + init_cnt) ==
 		    (data->blksz * data->blocks))
-			mci_writeq(host, DATA(host->data_offset),
-				   host->part_buf);
+			mci_fifo_writeq(host->fifo_reg, host->part_buf);
 	}
 }
 
@@ -1903,8 +1892,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
 			int items = len >> 3;
 			int i;
 			for (i = 0; i < items; ++i)
-				aligned_buf[i] = mci_readq(host,
-						DATA(host->data_offset));
+				aligned_buf[i] = mci_fifo_readq(host->fifo_reg);
+
 			/* memcpy from aligned buffer into output buffer */
 			memcpy(buf, aligned_buf, len);
 			buf += len;
@@ -1915,11 +1904,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt)
 	{
 		u64 *pdata = buf;
 		for (; cnt >= 8; cnt -= 8)
-			*pdata++ = mci_readq(host, DATA(host->data_offset));
+			*pdata++ = mci_fifo_readq(host->fifo_reg);
 		buf = pdata;
 	}
 	if (cnt) {
-		host->part_buf = mci_readq(host, DATA(host->data_offset));
+		host->part_buf = mci_fifo_readq(host->fifo_reg);
 		dw_mci_pull_final_bytes(host, buf, cnt);
 	}
 }
@@ -2731,9 +2720,9 @@ int dw_mci_probe(struct dw_mci *host)
 	dev_info(host->dev, "Version ID is %04x\n", host->verid);
 
 	if (host->verid < DW_MMC_240A)
-		host->data_offset = DATA_OFFSET;
+		host->fifo_reg = host->regs + DATA_OFFSET;
 	else
-		host->data_offset = DATA_240A_OFFSET;
+		host->fifo_reg = host->regs + DATA_240A_OFFSET;
 
 	tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
 	ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
drivers/mmc/host/dw_mmc.h +14 -0
index 46efdc5..2eebe48 100644
@@ -169,6 +169,16 @@
 #define SDMMC_CTRL_ALL_RESET_FLAGS \
 	(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
 
+/* FIFO register access macros. These should not change the data endian-ness
+ * as they are written to memory to be dealt with by the upper layers */
+#define mci_fifo_readw(__reg)	__raw_readw(__reg)
+#define mci_fifo_readl(__reg)	__raw_readl(__reg)
+#define mci_fifo_readq(__reg)	__raw_readq(__reg)
+
+#define mci_fifo_writew(__value, __reg)	__raw_writew(__reg, __value)
+#define mci_fifo_writel(__value, __reg)	__raw_writel(__reg, __value)
+#define mci_fifo_writeq(__value, __reg)	__raw_writeq(__reg, __value)
+
 /* Register access macros */
 #define mci_readl(dev, reg)			\
 	readl_relaxed((dev)->regs + SDMMC_##reg)
@@ -200,6 +210,10 @@
 	(*(volatile u64 __force *)((dev)->regs + SDMMC_##reg))
 #define mci_writeq(dev, reg, value)			\
 	(*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value))
+
+#define __raw_writeq(__value, __reg) \
+	(*(volatile u64 __force *)(__reg)= (__value))
+#define __raw_readq(__reg) (*(volatile u64 __force *)(__reg))
 #endif
 
 extern int dw_mci_probe(struct dw_mci *host);
include/linux/mmc/dw_mmc.h +2 -2
index 471fb31..49addec 100644
@@ -44,6 +44,7 @@ struct mmc_data;
  * struct dw_mci - MMC controller state shared between all slots
  * @lock: Spinlock protecting the queue and associated data.
  * @regs: Pointer to MMIO registers.
+ * @fifo_reg: Pointer to MMIO registers for data FIFO
  * @sg: Scatterlist entry currently being processed by PIO code, if any.
  * @sg_miter: PIO mapping scatterlist iterator.
  * @cur_slot: The slot which is currently using the controller.
@@ -79,7 +80,6 @@ struct mmc_data;
  * @current_speed: Configured rate of the controller.
  * @num_slots: Number of slots available.
  * @verid: Denote Version ID.
- * @data_offset: Set the offset of DATA register according to VERID.
  * @dev: Device associated with the MMC controller.
  * @pdata: Platform data associated with the MMC controller.
  * @drv_data: Driver specific data for identified variant of the controller
@@ -132,6 +132,7 @@ struct dw_mci {
 	spinlock_t		lock;
 	spinlock_t		irq_lock;
 	void __iomem		*regs;
+	void __iomem		*fifo_reg;
 
 	struct scatterlist	*sg;
 	struct sg_mapping_iter	sg_miter;
@@ -172,7 +173,6 @@ struct dw_mci {
 	u32			num_slots;
 	u32			fifoth_val;
 	u16			verid;
-	u16			data_offset;
 	struct device		*dev;
 	struct dw_mci_board	*pdata;
 	const struct dw_mci_drv_data	*drv_data;
Signature · 1 line
2.1.4