Skip to contentSkip to conversation

Exynos big-endian fixes

RFC PATCH Applied Matthew Leach 7 participants 36 messages Jun 8, 2016 – Jun 21, 2016

Subsystems (14)

v1 of 2 Applied Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Exynos big-endian fixes

Hi all,

I've been working with Ben Dooks to get a big-endian kernel working on my Exynos 4412 board. Primarily this series consists of:

- Replacing the __raw_{read,write}l accessors, which aren't endian-clean, with their respective {read,write}l_relaxed versions across various drivers.

- Adding endian-aware {set,clear}_bit functions to the Exynos serial driver as the __{set,clear}_bit() functions aren't endian-clean.

- Make the low-level Exynos debug printing macros endian-clean.

There may well be other things that are broken under BE that we've not tested but this series should be enough to allow a board to boot user-space to a login prompt.

Comments/feedback welcome!

Thanks,
Matt

Ben Dooks (9):
ARM: exynos: fixup debug macros for big-endian
ARM: samsung: fixup endian issues in cpu detection
ARM: EXYNOS: fixups for big-endian operation
ARM: EXYNOS: fixup endian in pm/pmu
ARM: EXYNOS: Enable ARCH_SUPPORTS_BIG_ENDIAN explicitly irqchip/s3c24xx: fixup IO accessors for big endian
memory: samsung: endian fixes for IO
hwrng: exynos - fixup IO accesors iommu/exynos: update to use iommu big-endian

Matthew Leach (6):
clock: exynos: fixup endian in pll clk
clocksource: samsung_pwm_timer: fix endian accessors
clk: samsung: exynos4: fixup reg access on be
irqchip: exynos_combiner: fixup reg access on be
tty: serial: samsung: fixup accessors for endian
tty: serial: samsung: add byte-order aware bit functions

 arch/arm/include/debug/samsung.S        |   8 +++
 arch/arm/mach-exynos/Kconfig            |   1 +
 arch/arm/mach-exynos/common.h           |   4 +-
 arch/arm/mach-exynos/firmware.c         |  16 ++---
 arch/arm/mach-exynos/headsmp.S          |   3 +
 arch/arm/mach-exynos/platsmp.c          |   4 +-
 arch/arm/mach-exynos/pm.c               |   4 +-
 arch/arm/mach-exynos/pm_domains.c       |   6 +-
 arch/arm/plat-samsung/cpu.c             |   8 +--
 drivers/char/hw_random/exynos-rng.c     |   4 +-
 drivers/clk/samsung/clk-exynos4.c       |   4 +-
 drivers/clk/samsung/clk-pll.c           | 122 ++++++++++++++++----------------
 drivers/clocksource/samsung_pwm_timer.c |  16 ++---
 drivers/iommu/exynos-iommu.c            |   6 +-
 drivers/irqchip/exynos-combiner.c       |  14 ++--
 drivers/irqchip/irq-s3c24xx.c           |  36 +++++-----
 drivers/memory/samsung/exynos-srom.c    |   6 +-
 drivers/tty/serial/samsung.c            |  16 ++---
 drivers/tty/serial/samsung.h            |  33 ++++++++-
 19 files changed, 177 insertions(+), 134 deletions(-)
Signature · 1 line
2.8.3
#1 lore raw

RFC PATCH 1/15 clock: exynos: fixup endian in pll clk

Fix the clk endian access code to deal with kernels built for big endian operation.

---
CC: Sylwester Nawrocki <[email protected]>
CC: Tomasz Figa <[email protected]>
CC: Michael Turquette <[email protected]>
CC: Stephen Boyd <[email protected]>
CC: linux-samsung-soc at vger.kernel.org
CC: linux-clk at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/clk/samsung/clk-pll.c | 122 +++++++++++++++++++++---------------------
 1 file changed, 61 insertions(+), 61 deletions(-)
drivers/clk/samsung/clk-pll.c +61 -61
index b7dd396..48139bd 100644
@@ -79,7 +79,7 @@ static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
 	u32 pll_con, mdiv, pdiv, sdiv;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
 	pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
 	sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
@@ -112,7 +112,7 @@ static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
 	u32 pll_con, mdiv, pdiv, sdiv;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
 	pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
 	sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
@@ -149,7 +149,7 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
 	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
 	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
@@ -186,19 +186,19 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	tmp = __raw_readl(pll->con_reg);
+	tmp = readl_relaxed(pll->con_reg);
 
 	if (!(samsung_pll35xx_mp_change(rate, tmp))) {
 		/* If only s change, change just s value only*/
 		tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
 		tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
-		__raw_writel(tmp, pll->con_reg);
+		writel_relaxed(tmp, pll->con_reg);
 
 		return 0;
 	}
 
 	/* Set PLL lock time. */
-	__raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+	writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
 			pll->lock_reg);
 
 	/* Change PLL PMS values */
@@ -208,12 +208,12 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
 	tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
 			(rate->pdiv << PLL35XX_PDIV_SHIFT) |
 			(rate->sdiv << PLL35XX_SDIV_SHIFT);
-	__raw_writel(tmp, pll->con_reg);
+	writel_relaxed(tmp, pll->con_reg);
 
 	/* wait_lock_time */
 	do {
 		cpu_relax();
-		tmp = __raw_readl(pll->con_reg);
+		tmp = readl_relaxed(pll->con_reg);
 	} while (!(tmp & (PLL35XX_LOCK_STAT_MASK
 				<< PLL35XX_LOCK_STAT_SHIFT)));
 	return 0;
@@ -253,8 +253,8 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 	s16 kdiv;
 	u64 fvco = parent_rate;
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con1 = __raw_readl(pll->con_reg + 4);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con1 = readl_relaxed(pll->con_reg + 4);
 	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
 	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
 	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
@@ -294,20 +294,20 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con1 = __raw_readl(pll->con_reg + 4);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con1 = readl_relaxed(pll->con_reg + 4);
 
 	if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
 		/* If only s change, change just s value only*/
 		pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
 		pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
-		__raw_writel(pll_con0, pll->con_reg);
+		writel_relaxed(pll_con0, pll->con_reg);
 
 		return 0;
 	}
 
 	/* Set PLL lock time. */
-	__raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+	writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
 
 	 /* Change PLL PMS values */
 	pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
@@ -316,16 +316,16 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
 	pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
 			(rate->pdiv << PLL36XX_PDIV_SHIFT) |
 			(rate->sdiv << PLL36XX_SDIV_SHIFT);
-	__raw_writel(pll_con0, pll->con_reg);
+	writel_relaxed(pll_con0, pll->con_reg);
 
 	pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
 	pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
-	__raw_writel(pll_con1, pll->con_reg + 4);
+	writel_relaxed(pll_con1, pll->con_reg + 4);
 
 	/* wait_lock_time */
 	do {
 		cpu_relax();
-		tmp = __raw_readl(pll->con_reg);
+		tmp = readl_relaxed(pll->con_reg);
 	} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
 
 	return 0;
@@ -366,7 +366,7 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
 	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
 	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
@@ -409,14 +409,14 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	con0 = __raw_readl(pll->con_reg);
-	con1 = __raw_readl(pll->con_reg + 0x4);
+	con0 = readl_relaxed(pll->con_reg);
+	con1 = readl_relaxed(pll->con_reg + 0x4);
 
 	if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
 		/* If only s change, change just s value only*/
 		con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
 		con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
-		__raw_writel(con0, pll->con_reg);
+		writel_relaxed(con0, pll->con_reg);
 
 		return 0;
 	}
@@ -430,29 +430,29 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
 			(rate->sdiv << PLL45XX_SDIV_SHIFT);
 
 	/* Set PLL AFC value. */
-	con1 = __raw_readl(pll->con_reg + 0x4);
+	con1 = readl_relaxed(pll->con_reg + 0x4);
 	con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
 	con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
 
 	/* Set PLL lock time. */
 	switch (pll->type) {
 	case pll_4502:
-		__raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
+		writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
 		break;
 	case pll_4508:
-		__raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
+		writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
 		break;
 	default:
 		break;
 	}
 
 	/* Set new configuration. */
-	__raw_writel(con1, pll->con_reg + 0x4);
-	__raw_writel(con0, pll->con_reg);
+	writel_relaxed(con1, pll->con_reg + 0x4);
+	writel_relaxed(con0, pll->con_reg);
 
 	/* Wait for locking. */
 	start = ktime_get();
-	while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) {
+	while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) {
 		ktime_t delta = ktime_sub(ktime_get(), start);
 
 		if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
@@ -513,8 +513,8 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
 	u64 fvco = parent_rate;
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con1 = __raw_readl(pll->con_reg + 4);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con1 = readl_relaxed(pll->con_reg + 4);
 	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
 				PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
 	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
@@ -560,14 +560,14 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	con0 = __raw_readl(pll->con_reg);
-	con1 = __raw_readl(pll->con_reg + 0x4);
+	con0 = readl_relaxed(pll->con_reg);
+	con1 = readl_relaxed(pll->con_reg + 0x4);
 
 	if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
 		/* If only s change, change just s value only*/
 		con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
 		con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
-		__raw_writel(con0, pll->con_reg);
+		writel_relaxed(con0, pll->con_reg);
 
 		return 0;
 	}
@@ -596,7 +596,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 			(rate->sdiv << PLL46XX_SDIV_SHIFT);
 
 	/* Set PLL K, MFR and MRR values. */
-	con1 = __raw_readl(pll->con_reg + 0x4);
+	con1 = readl_relaxed(pll->con_reg + 0x4);
 	con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
 			(PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
 			(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
@@ -605,13 +605,13 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
 			(rate->mrr << PLL46XX_MRR_SHIFT);
 
 	/* Write configuration to PLL */
-	__raw_writel(lock, pll->lock_reg);
-	__raw_writel(con0, pll->con_reg);
-	__raw_writel(con1, pll->con_reg + 0x4);
+	writel_relaxed(lock, pll->lock_reg);
+	writel_relaxed(con0, pll->con_reg);
+	writel_relaxed(con1, pll->con_reg + 0x4);
 
 	/* Wait for locking. */
 	start = ktime_get();
-	while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) {
+	while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) {
 		ktime_t delta = ktime_sub(ktime_get(), start);
 
 		if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
@@ -656,7 +656,7 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	if (pll->type == pll_6552_s3c2416) {
 		mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
 		pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
@@ -696,8 +696,8 @@ static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
 	u64 fvco = parent_rate;
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con1 = __raw_readl(pll->con_reg + 0x4);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con1 = readl_relaxed(pll->con_reg + 0x4);
 	mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
 	pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
 	sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
@@ -734,7 +734,7 @@ static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
 	u32 pll_con, mdiv, pdiv, sdiv;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
 	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
 	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
@@ -752,7 +752,7 @@ static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
 	u32 pll_con, mdiv, pdiv, sdiv;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
 	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
 	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
@@ -778,7 +778,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	tmp = __raw_readl(pll->con_reg);
+	tmp = readl_relaxed(pll->con_reg);
 
 	/* Change PLL PMS values */
 	tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
@@ -787,7 +787,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 	tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
 			(rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
 			(rate->sdiv << PLLS3C2410_SDIV_SHIFT);
-	__raw_writel(tmp, pll->con_reg);
+	writel_relaxed(tmp, pll->con_reg);
 
 	/* Time to settle according to the manual */
 	udelay(300);
@@ -798,7 +798,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
 static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
 {
 	struct samsung_clk_pll *pll = to_clk_pll(hw);
-	u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+	u32 pll_en = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
 	u32 pll_en_orig = pll_en;
 
 	if (enable)
@@ -806,7 +806,7 @@ static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
 	else
 		pll_en |= BIT(bit);
 
-	__raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
+	writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
 
 	/* if we started the UPLL, then allow to settle */
 	if (enable && (pll_en_orig & BIT(bit)))
@@ -905,7 +905,7 @@ static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
 	u32 r, p, m, s, pll_stat;
 	u64 fvco = parent_rate;
 
-	pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
+	pll_stat = readl_relaxed(pll->reg_base + pll->offset * 3);
 	r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
 	if (!r)
 		return 0;
@@ -983,7 +983,7 @@ static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
-	pll_con = __raw_readl(pll->con_reg);
+	pll_con = readl_relaxed(pll->con_reg);
 	mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
 	pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
 	sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
@@ -1019,19 +1019,19 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	tmp = __raw_readl(pll->con_reg);
+	tmp = readl_relaxed(pll->con_reg);
 
 	if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
 		/* If only s change, change just s value only*/
 		tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
 		tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
-		__raw_writel(tmp, pll->con_reg);
+		writel_relaxed(tmp, pll->con_reg);
 
 		return 0;
 	}
 
 	/* Set PLL lock time. */
-	__raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
+	writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
 
 	/* Change PLL PMS values */
 	tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
@@ -1040,12 +1040,12 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
 	tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
 			(rate->pdiv << PLL2550XX_P_SHIFT) |
 			(rate->sdiv << PLL2550XX_S_SHIFT);
-	__raw_writel(tmp, pll->con_reg);
+	writel_relaxed(tmp, pll->con_reg);
 
 	/* wait_lock_time */
 	do {
 		cpu_relax();
-		tmp = __raw_readl(pll->con_reg);
+		tmp = readl_relaxed(pll->con_reg);
 	} while (!(tmp & (PLL2550XX_LOCK_STAT_MASK
 			<< PLL2550XX_LOCK_STAT_SHIFT)));
 
@@ -1089,8 +1089,8 @@ static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
 	s16 kdiv;
 	u64 fvco = parent_rate;
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con2 = __raw_readl(pll->con_reg + 8);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con2 = readl_relaxed(pll->con_reg + 8);
 	mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
 	pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
 	sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
@@ -1117,8 +1117,8 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
 		return -EINVAL;
 	}
 
-	pll_con0 = __raw_readl(pll->con_reg);
-	pll_con2 = __raw_readl(pll->con_reg + 8);
+	pll_con0 = readl_relaxed(pll->con_reg);
+	pll_con2 = readl_relaxed(pll->con_reg + 8);
 
 	 /* Change PLL PMS values */
 	pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
@@ -1135,13 +1135,13 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
 			<< PLL2650XX_KDIV_SHIFT;
 
 	/* Set PLL lock time. */
-	__raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
+	writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
 
-	__raw_writel(pll_con0, pll->con_reg);
-	__raw_writel(pll_con2, pll->con_reg + 8);
+	writel_relaxed(pll_con0, pll->con_reg);
+	writel_relaxed(pll_con2, pll->con_reg + 8);
 
 	do {
-		tmp = __raw_readl(pll->con_reg);
+		tmp = readl_relaxed(pll->con_reg);
 	} while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT)));
 
 	return 0;
Signature · 1 line
2.8.3
#2 lore raw

Re: [RFC PATCH 01/15] clock: exynos: fixup endian in pll clk

Quoted 4 lines · Matthew Leach

Fix the clk endian access code to deal with kernels built for big endian operation.

We should have gotten rid of those __raw_{readl, writel} calls earlier for other reasons too. Thanks for the fix, patch applied!

Signature · 2 lines
Regards,
Sylwester
#3 lore raw

RFC PATCH 2/15 clocksource: samsung_pwm_timer: fix endian accessors

In reply to Matthew Leach

Fix the Samsung pwm timer access code to deal with kernels built for big endian operation.

---
CC: Daniel Lezcano <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: linux-kernel at vger.kernel.org

---
 drivers/clocksource/samsung_pwm_timer.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/clocksource/samsung_pwm_timer.c +8 -8
index 9502bc4..47e0515 100644
@@ -130,9 +130,9 @@ static void samsung_time_stop(unsigned int channel)
 
 	spin_lock_irqsave(&samsung_pwm_lock, flags);
 
-	tcon = __raw_readl(pwm.base + REG_TCON);
+	tcon = readl_relaxed(pwm.base + REG_TCON);
 	tcon &= ~TCON_START(channel);
-	__raw_writel(tcon, pwm.base + REG_TCON);
+	writel_relaxed(tcon, pwm.base + REG_TCON);
 
 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
@@ -148,14 +148,14 @@ static void samsung_time_setup(unsigned int channel, unsigned long tcnt)
 
 	spin_lock_irqsave(&samsung_pwm_lock, flags);
 
-	tcon = __raw_readl(pwm.base + REG_TCON);
+	tcon = readl_relaxed(pwm.base + REG_TCON);
 
 	tcon &= ~(TCON_START(tcon_chan) | TCON_AUTORELOAD(tcon_chan));
 	tcon |= TCON_MANUALUPDATE(tcon_chan);
 
-	__raw_writel(tcnt, pwm.base + REG_TCNTB(channel));
-	__raw_writel(tcnt, pwm.base + REG_TCMPB(channel));
-	__raw_writel(tcon, pwm.base + REG_TCON);
+	writel_relaxed(tcnt, pwm.base + REG_TCNTB(channel));
+	writel_relaxed(tcnt, pwm.base + REG_TCMPB(channel));
+	writel_relaxed(tcon, pwm.base + REG_TCON);
 
 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
@@ -170,7 +170,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
 
 	spin_lock_irqsave(&samsung_pwm_lock, flags);
 
-	tcon = __raw_readl(pwm.base + REG_TCON);
+	tcon = readl_relaxed(pwm.base + REG_TCON);
 
 	tcon &= ~TCON_MANUALUPDATE(channel);
 	tcon |= TCON_START(channel);
@@ -180,7 +180,7 @@ static void samsung_time_start(unsigned int channel, bool periodic)
 	else
 		tcon &= ~TCON_AUTORELOAD(channel);
 
-	__raw_writel(tcon, pwm.base + REG_TCON);
+	writel_relaxed(tcon, pwm.base + REG_TCON);
 
 	spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
Signature · 1 line
2.8.3
Reviewed-by on v1 2/15
#4 lore raw

Re: [RFC PATCH 02/15] clocksource: samsung_pwm_timer: fix endian accessors

Quoted 11 lines · Matthew Leach

Fix the Samsung pwm timer access code to deal with kernels built for big endian operation.

---
CC: Daniel Lezcano <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: linux-kernel at vger.kernel.org

---
 drivers/clocksource/samsung_pwm_timer.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

Best regards,
Krzysztof

#5 lore raw

Re: [RFC PATCH 02/15] clocksource: samsung_pwm_timer: fix endian accessors

In reply to Matthew Leach
Quoted 9 lines · Matthew Leach

Fix the Samsung pwm timer access code to deal with kernels built for big endian operation.

---
CC: Daniel Lezcano <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: linux-kernel at vger.kernel.org
---

I will pick this patch in my tree.

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
#6 lore raw

RFC PATCH 3/15 clk: samsung: exynos4: fixup reg access on be

In reply to Matthew Leach

Use the byte-order aware big endian accessors, allowing for kernels running under big-endian.

---
CC: Sylwester Nawrocki <[email protected]>
CC: Tomasz Figa <[email protected]>
CC: Michael Turquette <[email protected]>
CC: Stephen Boyd <[email protected]>
CC: Kukjin Kim <[email protected]>
CC: Krzysztof Kozlowski <[email protected]>
CC: linux-samsung-soc at vger.kernel.org
CC: linux-clk at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-kernel at vger.kernel.org

---
 drivers/clk/samsung/clk-exynos4.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/samsung/clk-exynos4.c +2 -2
index 7b3d0f9..35a977d 100644
@@ -1375,12 +1375,12 @@ static void __init exynos4x12_core_down_clock(void)
 	if (num_possible_cpus() == 4)
 		tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
 		       PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
-	__raw_writel(tmp, reg_base + PWR_CTRL1);
+	writel_relaxed(tmp, reg_base + PWR_CTRL1);
 
 	/*
 	 * Disable the clock up feature in case it was enabled by bootloader.
 	 */
-	__raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+	writel_relaxed(0x0, reg_base + E4X12_PWR_CTRL2);
 }
 
 #define E4210_CPU_DIV0(apll, pclk_dbg, atb, periph, corem1, corem0)	\
Signature · 1 line
2.8.3
#7 lore raw

Re: [RFC PATCH 03/15] clk: samsung: exynos4: fixup reg access on be

Quoted 4 lines · Matthew Leach

Use the byte-order aware big endian accessors, allowing for kernels running under big-endian.

Patch applied, thanks.

#8 lore raw

RFC PATCH 4/15 irqchip: exynos_combiner: fixup reg access on be

In reply to Matthew Leach

Use the byte-order aware big endian accessors, allowing for kernels running under big-endian.

---
CC: Thomas Gleixner <[email protected]>
CC: Jason Cooper <[email protected]>
CC: Marc Zyngier <[email protected]>
CC: Kukjin Kim <[email protected]>
CC: Krzysztof Kozlowski <[email protected]>
CC: linux-kernel at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-samsung-soc at vger.kernel.org

---
 drivers/irqchip/exynos-combiner.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/irqchip/exynos-combiner.c +7 -7
index ead15be..b78a169 100644
@@ -55,14 +55,14 @@ static void combiner_mask_irq(struct irq_data *data)
 {
 	u32 mask = 1 << (data->hwirq % 32);
 
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+	writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
 }
 
 static void combiner_unmask_irq(struct irq_data *data)
 {
 	u32 mask = 1 << (data->hwirq % 32);
 
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+	writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
 static void combiner_handle_cascade_irq(struct irq_desc *desc)
@@ -75,7 +75,7 @@ static void combiner_handle_cascade_irq(struct irq_desc *desc)
 	chained_irq_enter(chip, desc);
 
 	spin_lock(&irq_controller_lock);
-	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	status = readl_relaxed(chip_data->base + COMBINER_INT_STATUS);
 	spin_unlock(&irq_controller_lock);
 	status &= chip_data->irq_mask;
 
@@ -135,7 +135,7 @@ static void __init combiner_init_one(struct combiner_chip_data *combiner_data,
 	combiner_data->parent_irq = irq;
 
 	/* Disable all interrupts */
-	__raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
+	writel_relaxed(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
 }
 
 static int combiner_irq_domain_xlate(struct irq_domain *d,
@@ -218,7 +218,7 @@ static int combiner_suspend(void)
 
 	for (i = 0; i < max_nr; i++)
 		combiner_data[i].pm_save =
-			__raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET);
+			readl_relaxed(combiner_data[i].base + COMBINER_ENABLE_SET);
 
 	return 0;
 }
@@ -235,9 +235,9 @@ static void combiner_resume(void)
 	int i;
 
 	for (i = 0; i < max_nr; i++) {
-		__raw_writel(combiner_data[i].irq_mask,
+		writel_relaxed(combiner_data[i].irq_mask,
 			     combiner_data[i].base + COMBINER_ENABLE_CLEAR);
-		__raw_writel(combiner_data[i].pm_save,
+		writel_relaxed(combiner_data[i].pm_save,
 			     combiner_data[i].base + COMBINER_ENABLE_SET);
 	}
 }
Signature · 1 line
2.8.3
Reviewed-by on v1 4/15
#9 lore raw

Re: [RFC PATCH 04/15] irqchip: exynos_combiner: fixup reg access on be

Quoted 66 lines · Matthew Leach

Use the byte-order aware big endian accessors, allowing for kernels running under big-endian.

---
CC: Thomas Gleixner <[email protected]>
CC: Jason Cooper <[email protected]>
CC: Marc Zyngier <[email protected]>
CC: Kukjin Kim <[email protected]>
CC: Krzysztof Kozlowski <[email protected]>
CC: linux-kernel at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-samsung-soc at vger.kernel.org

---
 drivers/irqchip/exynos-combiner.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/irqchip/exynos-combiner.c +5 -5
index ead15be..b78a169 100644
@@ -55,14 +55,14 @@ static void combiner_mask_irq(struct irq_data *data)
 {
 	u32 mask = 1 << (data->hwirq % 32);
 
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+	writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
 }
 
 static void combiner_unmask_irq(struct irq_data *data)
 {
 	u32 mask = 1 << (data->hwirq % 32);
 
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+	writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
 static void combiner_handle_cascade_irq(struct irq_desc *desc)
@@ -75,7 +75,7 @@ static void combiner_handle_cascade_irq(struct irq_desc *desc)
 	chained_irq_enter(chip, desc);
 
 	spin_lock(&irq_controller_lock);
-	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	status = readl_relaxed(chip_data->base + COMBINER_INT_STATUS);
 	spin_unlock(&irq_controller_lock);
 	status &= chip_data->irq_mask;
 
@@ -135,7 +135,7 @@ static void __init combiner_init_one(struct combiner_chip_data *combiner_data,
 	combiner_data->parent_irq = irq;
 
 	/* Disable all interrupts */
-	__raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
+	writel_relaxed(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
 }
 
 static int combiner_irq_domain_xlate(struct irq_domain *d,
@@ -218,7 +218,7 @@ static int combiner_suspend(void)
 
 	for (i = 0; i < max_nr; i++)
 		combiner_data[i].pm_save =
-			__raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET);
+			readl_relaxed(combiner_data[i].base + COMBINER_ENABLE_SET);
 
 	return 0;
 }

drivers/irqchip/exynos-combiner.c static void combiner_resume(void) · line 241

Quoted 9 lines
drivers/irqchip/exynos-combiner.c +2 -2
@@ -235,9 +235,9 @@ static void combiner_resume(void)
 	int i;
 
 	for (i = 0; i < max_nr; i++) {
-		__raw_writel(combiner_data[i].irq_mask,
+		writel_relaxed(combiner_data[i].irq_mask,
 			     combiner_data[i].base + COMBINER_ENABLE_CLEAR);
-		__raw_writel(combiner_data[i].pm_save,
+		writel_relaxed(combiner_data[i].pm_save,
 			     combiner_data[i].base + COMBINER_ENABLE_SET);

Indentation of arguments is broken. I think it was aligned before.

Beside that:

Best regards,
Krzysztof

#10 lore raw

RFC PATCH 5/15 tty: serial: samsung: fixup accessors for endian

In reply to Matthew Leach

Fix the serial access code to deal with kernels built for big endian operation.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/samsung.h +2 -2
index fc5deaa..8818bdd 100644
@@ -118,9 +118,9 @@ struct s3c24xx_uart_port {
 	((unsigned long *)(unsigned long)((port)->membase + (reg)))
 
 #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
-#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
 
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
-#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
+#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
 
 #endif
Signature · 1 line
2.8.3
#11 lore raw

Re: [RFC PATCH 05/15] tty: serial: samsung: fixup accessors for endian

Quoted 18 lines · Matthew Leach

Fix the serial access code to deal with kernels built for big endian operation.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/samsung.h +0 -0
index fc5deaa..8818bdd 100644

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 124

Quoted 9 lines
drivers/tty/serial/samsung.h +2 -2
@@ -118,9 +118,9 @@ struct s3c24xx_uart_port {
 	((unsigned long *)(unsigned long)((port)->membase + (reg)))
 
 #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
-#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))
 
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
-#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
+#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))

I suppose for complete-ness we should have changed the readbs as well.

Signature · 2 lines
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius
Acked-by on v1 5/15
#12 lore raw

Re: [RFC PATCH 05/15] tty: serial: samsung: fixup accessors for endian

In reply to Matthew Leach
Quoted 18 lines · Matthew Leach

Fix the serial access code to deal with kernels built for big endian operation.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/samsung.h +0 -0
index fc5deaa..8818bdd 100644

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 121

Quoted 5 lines
drivers/tty/serial/samsung.h +1 -1
@@ -118,9 +118,9 @@ struct s3c24xx_uart_port {
 	((unsigned long *)(unsigned long)((port)->membase + (reg)))
 
 #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
-#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))

For completeness we should have changed __raw_readb to readb_relaxed

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 124

Quoted 3 lines
drivers/tty/serial/samsung.h +1 -1
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
-#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
+#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
Signature · 2 lines
Ben Dooks				http://www.codethink.co.uk/
Senior Engineer				Codethink - Providing Genius
#13 lore raw

Re: [RFC PATCH 05/15] tty: serial: samsung: fixup accessors for endian

Quoted 27 lines · Ben Dooks
Quoted 18 lines · Matthew Leach

Fix the serial access code to deal with kernels built for big endian operation.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/samsung.h +0 -0
index fc5deaa..8818bdd 100644

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 121

Quoted 5 lines
drivers/tty/serial/samsung.h +1 -1
@@ -118,9 +118,9 @@ struct s3c24xx_uart_port {
 	((unsigned long *)(unsigned long)((port)->membase + (reg)))
 
 #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
-#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))
+#define rd_regl(port, reg) (readl_relaxed(portaddr(port, reg)))

For completeness we should have changed __raw_readb to readb_relaxed

Quoted 5 lines

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 124

Quoted 3 lines
drivers/tty/serial/samsung.h +1 -1
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
-#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
+#define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))

With the readb_relaced change:

Best regards,
Krzysztof

#14 lore raw

RFC PATCH 6/15 tty: serial: samsung: add byte-order aware bit functions

In reply to Matthew Leach

This driver makes use of the __set_bit() and __clear_bit() functions. When running under big-endian, these functions don't convert the bit indexes when working with peripheral registers, leading to the incorrect bits being set and cleared when running big-endian.

Add two new driver functions for setting and clearing bits that are byte-order aware.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.c | 16 +++++++---------
 drivers/tty/serial/samsung.h | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 9 deletions(-)
drivers/tty/serial/samsung.c +7 -9
index 99bb231..e4f53d5 100644
@@ -169,8 +169,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
 		return;
 
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__set_bit(S3C64XX_UINTM_TXD,
-			portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
 	else
 		disable_irq_nosync(ourport->tx_irq);
 
@@ -235,8 +234,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
 
 	/* Mask Tx interrupt */
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__set_bit(S3C64XX_UINTM_TXD,
-			  portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
 	else
 		disable_irq_nosync(ourport->tx_irq);
 
@@ -269,8 +267,8 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
 
 	/* Unmask Tx interrupt */
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__clear_bit(S3C64XX_UINTM_TXD,
-			    portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
+				  S3C64XX_UINTM);
 	else
 		enable_irq(ourport->tx_irq);
 
@@ -397,8 +395,8 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
 	if (rx_enabled(port)) {
 		dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
 		if (s3c24xx_serial_has_interrupt_mask(port))
-			__set_bit(S3C64XX_UINTM_RXD,
-				portaddrl(port, S3C64XX_UINTM));
+			s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
+					S3C64XX_UINTM);
 		else
 			disable_irq_nosync(ourport->rx_irq);
 		rx_enabled(port) = 0;
@@ -1069,7 +1067,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	/* Enable Rx Interrupt */
-	__clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
+	s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
 
 	dbg("s3c64xx_serial_startup ok\n");
 	return ret;
drivers/tty/serial/samsung.h +29 -0
index 8818bdd..e45745a 100644
@@ -111,6 +111,7 @@ struct s3c24xx_uart_port {
 
 #define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
 
+
 /* register access controls */
 
 #define portaddr(port, reg) ((port)->membase + (reg))
@@ -123,4 +124,32 @@ struct s3c24xx_uart_port {
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
 #define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
 
+/* Byte-order aware bit setting/clearing functions. */
+
+static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
+				   unsigned int reg)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = rd_regl(port, reg);
+	val |= (1 << idx);
+	wr_regl(port, reg, val);
+	local_irq_restore(flags);
+}
+
+static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
+				     unsigned int reg)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = rd_regl(port, reg);
+	val &= ~(1 << idx);
+	wr_regl(port, reg, val);
+	local_irq_restore(flags);
+}
+
 #endif
Signature · 1 line
2.8.3
Reviewed-by on v1 6/15
#15 lore raw

Re: [RFC PATCH 06/15] tty: serial: samsung: add byte-order aware bit functions

Quoted 79 lines · Matthew Leach

This driver makes use of the __set_bit() and __clear_bit() functions. When running under big-endian, these functions don't convert the bit indexes when working with peripheral registers, leading to the incorrect bits being set and cleared when running big-endian.

Add two new driver functions for setting and clearing bits that are byte-order aware.

---
CC: Greg Kroah-Hartman <[email protected]>
CC: Jiri Slaby <[email protected]>
CC: linux-serial at vger.kernel.org
CC: linux-kernel at vger.kernel.org

---
 drivers/tty/serial/samsung.c | 16 +++++++---------
 drivers/tty/serial/samsung.h | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 9 deletions(-)
drivers/tty/serial/samsung.c +7 -9
index 99bb231..e4f53d5 100644
@@ -169,8 +169,7 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
 		return;
 
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__set_bit(S3C64XX_UINTM_TXD,
-			portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
 	else
 		disable_irq_nosync(ourport->tx_irq);
 
@@ -235,8 +234,7 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
 
 	/* Mask Tx interrupt */
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__set_bit(S3C64XX_UINTM_TXD,
-			  portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
 	else
 		disable_irq_nosync(ourport->tx_irq);
 
@@ -269,8 +267,8 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
 
 	/* Unmask Tx interrupt */
 	if (s3c24xx_serial_has_interrupt_mask(port))
-		__clear_bit(S3C64XX_UINTM_TXD,
-			    portaddrl(port, S3C64XX_UINTM));
+		s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
+				  S3C64XX_UINTM);
 	else
 		enable_irq(ourport->tx_irq);
 
@@ -397,8 +395,8 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
 	if (rx_enabled(port)) {
 		dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
 		if (s3c24xx_serial_has_interrupt_mask(port))
-			__set_bit(S3C64XX_UINTM_RXD,
-				portaddrl(port, S3C64XX_UINTM));
+			s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
+					S3C64XX_UINTM);
 		else
 			disable_irq_nosync(ourport->rx_irq);
 		rx_enabled(port) = 0;
@@ -1069,7 +1067,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	/* Enable Rx Interrupt */
-	__clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM));
+	s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
 
 	dbg("s3c64xx_serial_startup ok\n");
 	return ret;
drivers/tty/serial/samsung.h +0 -0
index 8818bdd..e45745a 100644

drivers/tty/serial/samsung.h struct s3c24xx_uart_port { · line 114

Quoted 4 lines
drivers/tty/serial/samsung.h +1 -0
@@ -111,6 +111,7 @@ struct s3c24xx_uart_port {
 
 #define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
 
+

This new line looks unnecessary. Beside that it looks okay:

Best regards,
Krzysztof

Quoted 37 lines
drivers/tty/serial/samsung.h +28 -0
 /* register access controls */
 
 #define portaddr(port, reg) ((port)->membase + (reg))
@@ -123,4 +124,32 @@ struct s3c24xx_uart_port {
 #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
 #define wr_regl(port, reg, val) writel_relaxed(val, portaddr(port, reg))
 
+/* Byte-order aware bit setting/clearing functions. */
+
+static inline void s3c24xx_set_bit(struct uart_port *port, int idx,
+				   unsigned int reg)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = rd_regl(port, reg);
+	val |= (1 << idx);
+	wr_regl(port, reg, val);
+	local_irq_restore(flags);
+}
+
+static inline void s3c24xx_clear_bit(struct uart_port *port, int idx,
+				     unsigned int reg)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = rd_regl(port, reg);
+	val &= ~(1 << idx);
+	wr_regl(port, reg, val);
+	local_irq_restore(flags);
+}
+
 #endif
#16 lore raw

RFC PATCH 7/15 ARM: exynos: fixup debug macros for big-endian

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)
arch/arm/include/debug/samsung.S +8 -0
index 8d8d922..f4eeed2 100644
@@ -15,11 +15,13 @@
 
 	.macro fifo_level_s5pv210 rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFSTAT]
+ARM_BE8(rev \rd, \rd)
 		and	\rd, \rd, #S5PV210_UFSTAT_TXMASK
 	.endm
 
 	.macro  fifo_full_s5pv210 rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFSTAT]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S5PV210_UFSTAT_TXFULL
 	.endm
 
@@ -28,6 +30,7 @@
 
 	.macro fifo_level_s3c2440 rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFSTAT]
+ARM_BE8(rev \rd, \rd)
 		and	\rd, \rd, #S3C2440_UFSTAT_TXMASK
 	.endm
 
@@ -37,6 +40,7 @@
 
 	.macro  fifo_full_s3c2440 rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFSTAT]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S3C2440_UFSTAT_TXFULL
 	.endm
 
@@ -50,6 +54,7 @@
 
 	.macro	busyuart, rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFCON]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
 		beq	1001f				@
 		@ FIFO enabled...
@@ -61,6 +66,7 @@
 1001:
 		@ busy waiting for non fifo
 		ldr	\rd, [\rx, # S3C2410_UTRSTAT]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S3C2410_UTRSTAT_TXFE
 		beq	1001b
 
@@ -69,6 +75,7 @@
 
 	.macro	waituart,rd,rx
 		ldr	\rd, [\rx, # S3C2410_UFCON]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
 		beq	1001f				@
 		@ FIFO enabled...
@@ -80,6 +87,7 @@
 1001:
 		@ idle waiting for non fifo
 		ldr	\rd, [\rx, # S3C2410_UTRSTAT]
+ARM_BE8(rev \rd, \rd)
 		tst	\rd, #S3C2410_UTRSTAT_TXFE
 		beq	1001b
 
Signature · 1 line
2.8.3
#17 lore raw

Re: [RFC PATCH 07/15] ARM: exynos: fixup debug macros for big-endian

Quoted 10 lines · Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)

Should this go via the maintainer or to RMK?

If to RMK, then shall I get it submitted (and does anyone else want to ack?)

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

Re: [RFC PATCH 07/15] ARM: exynos: fixup debug macros for big-endian

Quoted 12 lines · Ben Dooks
Quoted 10 lines · Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)
Quoted 4 lines

Should this go via the maintainer or to RMK?

If to RMK, then shall I get it submitted (and does anyone else want to ack?)

If there are no objections, I can take it through samsung-soc with other arch/arm/mach-exynos* patches.

What I am missing here, is Matthew's Signed-off-by.

Matthew, you touched and sent the patch so could you add the Sob?

Best regards,
Krzysztof

#19 lore raw

Re: [RFC PATCH 07/15] ARM: exynos: fixup debug macros for big-endian

Quoted 18 lines · Krzysztof Kozlowski
Quoted 12 lines · Ben Dooks
Quoted 10 lines · Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)
Quoted 4 lines

Should this go via the maintainer or to RMK?

If to RMK, then shall I get it submitted (and does anyone else want to ack?)

Quoted 6 lines

If there are no objections, I can take it through samsung-soc with other arch/arm/mach-exynos* patches.

What I am missing here, is Matthew's Signed-off-by.

Matthew, you touched and sent the patch so could you add the Sob?

Either that or I could just send it from my tree directly.

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

Re: [RFC PATCH 07/15] ARM: exynos: fixup debug macros for big-endian

In reply to Krzysztof Kozlowski
Quoted 18 lines · Krzysztof Kozlowski
Quoted 12 lines · Ben Dooks
Quoted 10 lines · Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)
Quoted 4 lines

Should this go via the maintainer or to RMK?

If to RMK, then shall I get it submitted (and does anyone else want to ack?)

Quoted 6 lines

If there are no objections, I can take it through samsung-soc with other arch/arm/mach-exynos* patches.

What I am missing here, is Matthew's Signed-off-by.

Matthew, you touched and sent the patch so could you add the Sob?

I've asked Matthew to re-send the core patches with the signed-off sorted out. He can also put them on a public facing git server if that would be helpful.

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

Re: [RFC PATCH 07/15] ARM: exynos: fixup debug macros for big-endian

Quoted 22 lines · Ben Dooks
Quoted 21 lines · Krzysztof Kozlowski
Quoted 12 lines · Ben Dooks
Quoted 10 lines · Matthew Leach

From: Ben Dooks <[email protected]>

The exynos low-level debug macros need to be fixed if the system is being built big endian. Add the necessary endian swaps for accessing the registers to get output working again

---
 arch/arm/include/debug/samsung.S | 8 ++++++++
 1 file changed, 8 insertions(+)
Quoted 4 lines

Should this go via the maintainer or to RMK?

If to RMK, then shall I get it submitted (and does anyone else want to ack?)

If there are no objections, I can take it through samsung-soc with other arch/arm/mach-exynos* patches.

Quoted 6 lines
Quoted 3 lines

What I am missing here, is Matthew's Signed-off-by.

Matthew, you touched and sent the patch so could you add the Sob?

I've asked Matthew to re-send the core patches with the signed-off sorted out.

Thanks.

Quoted 2 lines

He can also put them on a public facing git server if that would be helpful.

No need. I think it will go through separate trees anyway. Except the change adding ARCH_SUPPORTS_BIG_ENDIAN, I don't see any dependencies.

As for the ARCH_SUPPORTS_BIG_ENDIAN, I think it should be applied when all necessary drivers are fixed.

Best regards,
Krzysztof

#22 lore raw

RFC PATCH 8/15 ARM: samsung: fixup endian issues in cpu detection

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

If the system is built for big endian, then the cpu identificaiton register will be read in the wrong order. Fix this by using readl_relaxed() on the register.

---
 arch/arm/plat-samsung/cpu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm/plat-samsung/cpu.c +4 -4
index 71333bb..bd12a55 100644
@@ -29,14 +29,14 @@ EXPORT_SYMBOL(samsung_rev);
 
 void __init s3c64xx_init_cpu(void)
 {
-	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
+	samsung_cpu_id = readl_relaxed(S3C_VA_SYS + 0x118);
 	if (!samsung_cpu_id) {
 		/*
 		 * S3C6400 has the ID register in a different place,
 		 * and needs a write before it can be read.
 		 */
-		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
-		samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0xA1C);
+		writel_relaxed(0x0, S3C_VA_SYS + 0xA1C);
+		samsung_cpu_id = readl_relaxed(S3C_VA_SYS + 0xA1C);
 	}
 
 	samsung_cpu_rev = 0;
@@ -46,7 +46,7 @@ void __init s3c64xx_init_cpu(void)
 
 void __init s5p_init_cpu(void __iomem *cpuid_addr)
 {
-	samsung_cpu_id = __raw_readl(cpuid_addr);
+	samsung_cpu_id = readl_relaxed(cpuid_addr);
 	samsung_cpu_rev = samsung_cpu_id & 0xFF;
 
 	pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id);
Signature · 1 line
2.8.3
#23 lore raw

RFC PATCH 9/15 ARM: EXYNOS: fixups for big-endian operation

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

If the kernel is built big endian, then using the __raw read and write IO accessors is not going to work as they end up writing big-endian data to little-endian IO registers. Fix this by using the readl and writel relaxed versions which ensure little endian IO.

---
 arch/arm/mach-exynos/firmware.c | 16 ++++++++--------
 arch/arm/mach-exynos/headsmp.S  |  3 +++
 arch/arm/mach-exynos/platsmp.c  |  4 ++--
 3 files changed, 13 insertions(+), 10 deletions(-)
arch/arm/mach-exynos/firmware.c +8 -8
index 1bfd1b0..96b5e92 100644
@@ -41,9 +41,9 @@ static int exynos_do_idle(unsigned long mode)
 	case FW_DO_IDLE_AFTR:
 		if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 			exynos_save_cp15();
-		__raw_writel(virt_to_phys(exynos_cpu_resume_ns),
+		writel_relaxed(virt_to_phys(exynos_cpu_resume_ns),
 			     sysram_ns_base_addr + 0x24);
-		__raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
+		writel_relaxed(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
 		if (soc_is_exynos3250()) {
 			flush_cache_all();
 			exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
@@ -97,7 +97,7 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 	if (soc_is_exynos4412())
 		boot_reg += 4 * cpu;
 
-	__raw_writel(boot_addr, boot_reg);
+	writel_relaxed(boot_addr, boot_reg);
 	return 0;
 }
 
@@ -113,7 +113,7 @@ static int exynos_get_cpu_boot_addr(int cpu, unsigned long *boot_addr)
 	if (soc_is_exynos4412())
 		boot_reg += 4 * cpu;
 
-	*boot_addr = __raw_readl(boot_reg);
+	*boot_addr = readl_relaxed(boot_reg);
 	return 0;
 }
 
@@ -234,20 +234,20 @@ void exynos_set_boot_flag(unsigned int cpu, unsigned int mode)
 {
 	unsigned int tmp;
 
-	tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
+	tmp = readl_relaxed(REG_CPU_STATE_ADDR + cpu * 4);
 
 	if (mode & BOOT_MODE_MASK)
 		tmp &= ~BOOT_MODE_MASK;
 
 	tmp |= mode;
-	__raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
+	writel_relaxed(tmp, REG_CPU_STATE_ADDR + cpu * 4);
 }
 
 void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode)
 {
 	unsigned int tmp;
 
-	tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
+	tmp = readl_relaxed(REG_CPU_STATE_ADDR + cpu * 4);
 	tmp &= ~mode;
-	__raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
+	writel_relaxed(tmp, REG_CPU_STATE_ADDR + cpu * 4);
 }
arch/arm/mach-exynos/headsmp.S +3 -0
index b54f970..d3d24ab 100644
@@ -12,12 +12,15 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+#include <asm/assembler.h>
+
 /*
  * exynos4 specific entry point for secondary CPUs.  This provides
  * a "holding pen" into which all secondary cores are held until we're
  * ready for them to initialise.
  */
 ENTRY(exynos4_secondary_startup)
+ARM_BE8(setend	be)
 	mrc	p15, 0, r0, c0, c0, 5
 	and	r0, r0, #15
 	adr	r4, 1f
arch/arm/mach-exynos/platsmp.c +2 -2
index 85c3be6..98ffe1e 100644
@@ -264,7 +264,7 @@ int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr)
 			ret = PTR_ERR(boot_reg);
 			goto fail;
 		}
-		__raw_writel(boot_addr, boot_reg);
+		writel_relaxed(boot_addr, boot_reg);
 		ret = 0;
 	}
 fail:
@@ -289,7 +289,7 @@ int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr)
 			ret = PTR_ERR(boot_reg);
 			goto fail;
 		}
-		*boot_addr = __raw_readl(boot_reg);
+		*boot_addr = readl_relaxed(boot_reg);
 		ret = 0;
 	}
 fail:
Signature · 1 line
2.8.3
#24 lore raw

RFC PATCH 10/15 ARM: EXYNOS: fixup endian in pm/pmu

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

Fix the PMU code endian access code to deal with kernels built for big endian operation.

---
 arch/arm/mach-exynos/common.h     | 4 ++--
 arch/arm/mach-exynos/pm.c         | 4 ++--
 arch/arm/mach-exynos/pm_domains.c | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)
arch/arm/mach-exynos/common.h +2 -2
index 5365bf1..19e9d25 100644
@@ -174,12 +174,12 @@ extern int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr);
 
 static inline void pmu_raw_writel(u32 val, u32 offset)
 {
-	__raw_writel(val, pmu_base_addr + offset);
+	writel_relaxed(val, pmu_base_addr + offset);
 }
 
 static inline u32 pmu_raw_readl(u32 offset)
 {
-	return __raw_readl(pmu_base_addr + offset);
+	return readl_relaxed(pmu_base_addr + offset);
 }
 
 #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
arch/arm/mach-exynos/pm.c +2 -2
index c43b776..52d78eb 100644
@@ -132,9 +132,9 @@ static void exynos_set_wakeupmask(long mask)
 
 static void exynos_cpu_set_boot_vector(long flags)
 {
-	__raw_writel(virt_to_phys(exynos_cpu_resume),
+	writel_relaxed(virt_to_phys(exynos_cpu_resume),
 		     exynos_boot_vector_addr());
-	__raw_writel(flags, exynos_boot_vector_flag());
+	writel_relaxed(flags, exynos_boot_vector_flag());
 }
 
 static int exynos_aftr_finisher(unsigned long flags)
arch/arm/mach-exynos/pm_domains.c +3 -3
index 875a2ba..0e075d9 100644
@@ -70,12 +70,12 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
 	}
 
 	pwr = power_on ? INT_LOCAL_PWR_EN : 0;
-	__raw_writel(pwr, base);
+	writel_relaxed(pwr, base);
 
 	/* Wait max 1ms */
 	timeout = 10;
 
-	while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
+	while ((readl_relaxed(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
 		if (!timeout) {
 			op = (power_on) ? "enable" : "disable";
 			pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -185,7 +185,7 @@ static __init int exynos4_pm_init_power_domain(void)
 			clk_put(pd->oscclk);
 
 no_clk:
-		on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
+		on = readl_relaxed(pd->base + 0x4) & INT_LOCAL_PWR_EN;
 
 		pm_genpd_init(&pd->pd, NULL, !on);
 		of_genpd_add_provider_simple(np, &pd->pd);
Signature · 1 line
2.8.3
#25 lore raw

RFC PATCH 11/15 ARM: EXYNOS: Enable ARCH_SUPPORTS_BIG_ENDIAN explicitly

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

Now the initial fixes have the big-endian code working on EXYNOS, make sure we explicitly mark our arch as being big endian capable.

---
 arch/arm/mach-exynos/Kconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-exynos/Kconfig +1 -0
index e65aa7d..14906bf 100644
@@ -13,6 +13,7 @@ menuconfig ARCH_EXYNOS
 	select ARCH_HAS_BANDGAP
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
 	select COMMON_CLK_SAMSUNG
Signature · 1 line
2.8.3
#26 lore raw

RFC PATCH 12/15 irqchip/s3c24xx: fixup IO accessors for big endian

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

Instead of using the __raw accesors, use the _relaxed versions to deal with any issues due to endian-ness of the CPU.

---
CC: Thomas Gleixner <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: Jason Cooper <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: Marc Zyngier <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: linux-kernel at vger.kernel.org (open list:IRQCHIP DRIVERS)
CC: linux-arm-kernel at lists.infradead.org

---
 drivers/irqchip/irq-s3c24xx.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/irqchip/irq-s3c24xx.c +18 -18
index 5dc5a76..c25ce5a 100644
@@ -92,9 +92,9 @@ static void s3c_irq_mask(struct irq_data *data)
 	unsigned long mask;
 	unsigned int irqno;
 
-	mask = __raw_readl(intc->reg_mask);
+	mask = readl_relaxed(intc->reg_mask);
 	mask |= (1UL << irq_data->offset);
-	__raw_writel(mask, intc->reg_mask);
+	writel_relaxed(mask, intc->reg_mask);
 
 	if (parent_intc) {
 		parent_data = &parent_intc->irqs[irq_data->parent_irq];
@@ -119,9 +119,9 @@ static void s3c_irq_unmask(struct irq_data *data)
 	unsigned long mask;
 	unsigned int irqno;
 
-	mask = __raw_readl(intc->reg_mask);
+	mask = readl_relaxed(intc->reg_mask);
 	mask &= ~(1UL << irq_data->offset);
-	__raw_writel(mask, intc->reg_mask);
+	writel_relaxed(mask, intc->reg_mask);
 
 	if (parent_intc) {
 		irqno = irq_find_mapping(parent_intc->domain,
@@ -136,9 +136,9 @@ static inline void s3c_irq_ack(struct irq_data *data)
 	struct s3c_irq_intc *intc = irq_data->intc;
 	unsigned long bitval = 1UL << irq_data->offset;
 
-	__raw_writel(bitval, intc->reg_pending);
+	writel_relaxed(bitval, intc->reg_pending);
 	if (intc->reg_intpnd)
-		__raw_writel(bitval, intc->reg_intpnd);
+		writel_relaxed(bitval, intc->reg_intpnd);
 }
 
 static int s3c_irq_type(struct irq_data *data, unsigned int type)
@@ -172,9 +172,9 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg,
 	unsigned long newvalue = 0, value;
 
 	/* Set the GPIO to external interrupt mode */
-	value = __raw_readl(gpcon_reg);
+	value = readl_relaxed(gpcon_reg);
 	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-	__raw_writel(value, gpcon_reg);
+	writel_relaxed(value, gpcon_reg);
 
 	/* Set the external interrupt to pointed trigger type */
 	switch (type)
@@ -208,9 +208,9 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg,
 			return -EINVAL;
 	}
 
-	value = __raw_readl(extint_reg);
+	value = readl_relaxed(extint_reg);
 	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-	__raw_writel(value, extint_reg);
+	writel_relaxed(value, extint_reg);
 
 	return 0;
 }
@@ -315,8 +315,8 @@ static void s3c_irq_demux(struct irq_desc *desc)
 
 	chained_irq_enter(chip, desc);
 
-	src = __raw_readl(sub_intc->reg_pending);
-	msk = __raw_readl(sub_intc->reg_mask);
+	src = readl_relaxed(sub_intc->reg_pending);
+	msk = readl_relaxed(sub_intc->reg_mask);
 
 	src &= ~msk;
 	src &= irq_data->sub_bits;
@@ -337,7 +337,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
 	int pnd;
 	int offset;
 
-	pnd = __raw_readl(intc->reg_intpnd);
+	pnd = readl_relaxed(intc->reg_intpnd);
 	if (!pnd)
 		return false;
 
@@ -352,7 +352,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
 	 *
 	 * Thanks to Klaus, Shannon, et al for helping to debug this problem
 	 */
-	offset = __raw_readl(intc->reg_intpnd + 4);
+	offset = readl_relaxed(intc->reg_intpnd + 4);
 
 	/* Find the bit manually, when the offset is wrong.
 	 * The pending register only ever contains the one bit of the next
@@ -406,7 +406,7 @@ int s3c24xx_set_fiq(unsigned int irq, bool on)
 		intmod = 0;
 	}
 
-	__raw_writel(intmod, S3C2410_INTMOD);
+	writel_relaxed(intmod, S3C2410_INTMOD);
 	return 0;
 }
 
@@ -508,14 +508,14 @@ static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
 
 	last = 0;
 	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(reg_source);
+		pend = readl_relaxed(reg_source);
 
 		if (pend == 0 || pend == last)
 			break;
 
-		__raw_writel(pend, intc->reg_pending);
+		writel_relaxed(pend, intc->reg_pending);
 		if (intc->reg_intpnd)
-			__raw_writel(pend, intc->reg_intpnd);
+			writel_relaxed(pend, intc->reg_intpnd);
 
 		pr_info("irq: clearing pending status %08x\n", (int)pend);
 		last = pend;
Signature · 1 line
2.8.3
Reviewed-by on v1 12/15
#27 lore raw

Re: [RFC PATCH 12/15] irqchip/s3c24xx: fixup IO accessors for big endian

Quoted 13 lines · Matthew Leach

From: Ben Dooks <[email protected]>

Instead of using the __raw accesors, use the _relaxed versions to deal with any issues due to endian-ness of the CPU.

---
CC: Thomas Gleixner <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: Jason Cooper <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: Marc Zyngier <[email protected]> (maintainer:IRQCHIP DRIVERS)
CC: linux-kernel at vger.kernel.org (open list:IRQCHIP DRIVERS)
CC: linux-arm-kernel at lists.infradead.org

Quoted 3 lines
---
 drivers/irqchip/irq-s3c24xx.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

Best regards,
Krzysztof

#28 lore raw

RFC PATCH 13/15 memory: samsung: endian fixes for IO

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

Use the relaxed versions of the IO accessors to avoid any issues if running in big endian.

---
Cc: Pavel Fedin <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: Pankaj Dubey <[email protected]>
Cc: linux-arm-kernel at lists.codethink.co.uk

---
 drivers/memory/samsung/exynos-srom.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/memory/samsung/exynos-srom.c +3 -3
index 96756fb..ac8f79c 100644
@@ -91,11 +91,11 @@ static int exynos_srom_configure_bank(struct exynos_srom *srom,
 	if (width == 2)
 		cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
 
-	bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW);
+	bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
 	bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
-	__raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW);
+	writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);
 
-	__raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
+	writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
 		    (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
 		    (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
 		    (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
Signature · 1 line
2.8.3
Reviewed-by on v1 13/15
#29 lore raw

Re: [RFC PATCH 13/15] memory: samsung: endian fixes for IO

Quoted 24 lines · Matthew Leach

From: Ben Dooks <[email protected]>

Use the relaxed versions of the IO accessors to avoid any issues if running in big endian.

---
Cc: Pavel Fedin <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: Pankaj Dubey <[email protected]>
Cc: linux-arm-kernel at lists.codethink.co.uk

---
 drivers/memory/samsung/exynos-srom.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/memory/samsung/exynos-srom.c +0 -1
index 96756fb..ac8f79c 100644
@@ -91,11 +91,11 @@ static int exynos_srom_configure_bank(struct exynos_srom *srom,
 	if (width == 2)
 		cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
 
-	bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW);

drivers/memory/samsung/exynos-srom.c static int exynos_srom_configure_bank(struct exynos_srom *srom, · line 101

Quoted 10 lines
drivers/memory/samsung/exynos-srom.c +3 -2
+	bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
 	bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
-	__raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW);
+	writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);
 
-	__raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
+	writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
 		    (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
 		    (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
 		    (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |

It breaks indentation of arguments. With that change and Matthew's SoB:

I can take it through samsung-soc tree after fixing above.

Best regards,
Krzysztof

#30 lore raw

RFC PATCH 14/15 hwrng: exynos - fixup IO accesors

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

The __raw IO functions are not endian safe, so use the readl_relaxed and writel_relaxed versions of these.

---
CC: Matt Mackall <[email protected]>
CC: Krzysztof Kozlowski <[email protected]>
CC: linux-crypto at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-samsung-soc at vger.kernel.org

---
 drivers/char/hw_random/exynos-rng.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/hw_random/exynos-rng.c +2 -2
index ed44561..23d3585 100644
@@ -45,12 +45,12 @@ struct exynos_rng {
 
 static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset)
 {
-	return	__raw_readl(rng->mem + offset);
+	return	readl_relaxed(rng->mem + offset);
 }
 
 static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset)
 {
-	__raw_writel(val, rng->mem + offset);
+	writel_relaxed(val, rng->mem + offset);
 }
 
 static int exynos_rng_configure(struct exynos_rng *exynos_rng)
Signature · 1 line
2.8.3
#31 lore raw

RFC PATCH 15/15 iommu/exynos: update to use iommu big-endian

In reply to Matthew Leach

From: Ben Dooks <[email protected]>

Add initial support for big endian by always writing the pte in le32. Note, revisit if hardware capable of doing big endian fetches.

---
Cc: Marek Szyprowski <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Kukjin Kim <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: iommu at lists.linux-foundation.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-kernel at vger.kernel.org (open list)

---
 drivers/iommu/exynos-iommu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iommu/exynos-iommu.c +5 -1
index 5ecc86c..dd8b3b3 100644
@@ -54,6 +54,10 @@ typedef u32 sysmmu_pte_t;
 #define lv2ent_small(pent) ((*(pent) & 2) == 2)
 #define lv2ent_large(pent) ((*(pent) & 3) == 1)
 
+#ifdef CONFIG_BIG_ENDIAN
+#warning "revisit driver if we can enable big-endian ptes"
+#endif
+
 /*
  * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces
  * v5.0 introduced support for 36bit physical address space by shifting
@@ -716,7 +720,7 @@ static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val)
 {
 	dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent),
 				DMA_TO_DEVICE);
-	*ent = val;
+	*ent = cpu_to_le32(val);
 	dma_sync_single_for_device(dma_dev, virt_to_phys(ent), sizeof(*ent),
 				   DMA_TO_DEVICE);
 }
Signature · 1 line
2.8.3
maintainer Acked-by on v1 15/15
#32 lore raw

Re: [RFC PATCH 15/15] iommu/exynos: update to use iommu big-endian

Hi

Quoted 7 lines · Matthew Leach

From: Ben Dooks <[email protected]>

Add initial support for big endian by always writing the pte in le32. Note, revisit if hardware capable of doing big endian fetches.

Just to keep my curiosity satisfied - what's the reason to use big-endian on ARM?

Good luck with fixing the kernel and userspace codes, which usually assume little-endian is the only possible order!

Quoted 18 lines

---
Cc: Marek Szyprowski <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Kukjin Kim <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: iommu at lists.linux-foundation.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-kernel at vger.kernel.org (open list)

---
  drivers/iommu/exynos-iommu.c | 6 +++++-
  1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iommu/exynos-iommu.c +0 -0
index 5ecc86c..dd8b3b3 100644

drivers/iommu/exynos-iommu.c typedef u32 sysmmu_pte_t; · line 60

Quoted 7 lines
drivers/iommu/exynos-iommu.c +4 -0
@@ -54,6 +54,10 @@ typedef u32 sysmmu_pte_t;
  #define lv2ent_small(pent) ((*(pent) & 2) == 2)
  #define lv2ent_large(pent) ((*(pent) & 3) == 1)
 
+#ifdef CONFIG_BIG_ENDIAN
+#warning "revisit driver if we can enable big-endian ptes"
+#endif
+

This warning can be removed. There is no way to force SYSMMU to operate with big-endian PTEs according to the datasheet.

drivers/iommu/exynos-iommu.c static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val) · line 726

Quoted 12 lines
drivers/iommu/exynos-iommu.c +1 -1
  /*
   * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces
   * v5.0 introduced support for 36bit physical address space by shifting
@@ -716,7 +720,7 @@ static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val)
  {
  	dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent),
  				DMA_TO_DEVICE);
-	*ent = val;
+	*ent = cpu_to_le32(val);
  	dma_sync_single_for_device(dma_dev, virt_to_phys(ent), sizeof(*ent),
  				   DMA_TO_DEVICE);
  }

Best regards

Signature · 2 lines
Marek Szyprowski, PhD
Samsung R&D Institute Poland
#33 lore raw

Re: [RFC PATCH 15/15] iommu/exynos: update to use iommu big-endian

Quoted 10 lines · Marek Szyprowski

Hi

Quoted 6 lines · Matthew Leach

From: Ben Dooks <[email protected]>

Add initial support for big endian by always writing the pte in le32. Note, revisit if hardware capable of doing big endian fetches.

Quoted 6 lines
Quoted 1 line

Just to keep my curiosity satisfied - what's the reason to use big-endian on ARM?

Because we can. It was interesting to try.

Quoted 2 lines

Good luck with fixing the kernel and userspace codes, which usually assume little-endian is the only possible order!

We did a BE8 build of the baserock userspace a year or two ago and found mostly it just worked. I think Matt is using that image for testing the work he's been doing.

I've no idea if we would ever bother trying to build Debian for BE8 or similar, as not sure it would be worth trying.

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

Re: [RFC PATCH 15/15] iommu/exynos: update to use iommu big-endian

In reply to Matthew Leach
Quoted 16 lines · Matthew Leach

From: Ben Dooks <[email protected]>

Add initial support for big endian by always writing the pte in le32. Note, revisit if hardware capable of doing big endian fetches.

---
Cc: Marek Szyprowski <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Kukjin Kim <[email protected]>
Cc: Krzysztof Kozlowski <[email protected]>
Cc: iommu at lists.linux-foundation.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-kernel at vger.kernel.org (open list)

Quoted 3 lines
---
 drivers/iommu/exynos-iommu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Applied, thanks.

#35 lore raw
In reply to Matthew Leach
Quoted 9 lines · Matthew Leach

Hi all,

I've been working with Ben Dooks to get a big-endian kernel working on my Exynos 4412 board. Primarily this series consists of:

- Replacing the __raw_{read,write}l accessors, which aren't endian-clean, with their respective {read,write}l_relaxed versions across various drivers.

Quoted 8 lines

- Adding endian-aware {set,clear}_bit functions to the Exynos serial driver as the __{set,clear}_bit() functions aren't endian-clean.

- Make the low-level Exynos debug printing macros endian-clean.

There may well be other things that are broken under BE that we've not tested but this series should be enough to allow a board to boot user-space to a login prompt.

The only nit is the use of "be", it would be nicer to either use BE8 consistently, or go for "big endian".

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