Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/4] ARM: EXYNOS: Remove static mapping of SCU SFR
From: pankaj.dubey @ 2016-11-08  3:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161107175349.GD4865@kozik-lap>

Hi Krzysztof,

On Monday 07 November 2016 11:23 PM, Krzysztof Kozlowski wrote:
> On Fri, Nov 04, 2016 at 09:09:23AM +0530, Pankaj Dubey wrote:
>> Lets remove static mapping of SCU SFR mainly used in CORTEX-A9 SoC based boards.
>> Instead use mapping from device tree node of SCU.
>>
>> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
>> ---
>>  arch/arm/mach-exynos/exynos.c                | 22 ----------------------
>>  arch/arm/mach-exynos/include/mach/map.h      |  2 --
>>  arch/arm/mach-exynos/platsmp.c               | 18 +++++++++++-------
>>  arch/arm/mach-exynos/pm.c                    | 14 +++++++++++---
>>  arch/arm/mach-exynos/suspend.c               | 15 +++++++++++----
>>  arch/arm/plat-samsung/include/plat/map-s5p.h |  4 ----
>>  6 files changed, 33 insertions(+), 42 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
>> index 757fc11..fa08ef9 100644
>> --- a/arch/arm/mach-exynos/exynos.c
>> +++ b/arch/arm/mach-exynos/exynos.c
>> @@ -28,15 +28,6 @@
>>  
>>  #include "common.h"
>>  
>> -static struct map_desc exynos4_iodesc[] __initdata = {
>> -	{
>> -		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
>> -		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
>> -		.length		= SZ_8K,
>> -		.type		= MT_DEVICE,
>> -	},
>> -};
>> -
>>  static struct platform_device exynos_cpuidle = {
>>  	.name              = "exynos_cpuidle",
>>  #ifdef CONFIG_ARM_EXYNOS_CPUIDLE
>> @@ -99,17 +90,6 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
>>  	return 1;
>>  }
>>  
>> -/*
>> - * exynos_map_io
>> - *
>> - * register the standard cpu IO areas
>> - */
>> -static void __init exynos_map_io(void)
>> -{
>> -	if (soc_is_exynos4())
>> -		iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
>> -}
>> -
>>  static void __init exynos_init_io(void)
>>  {
>>  	debug_ll_io_init();
>> @@ -118,8 +98,6 @@ static void __init exynos_init_io(void)
>>  
>>  	/* detect cpu id and rev. */
>>  	s5p_init_cpu(S5P_VA_CHIPID);
>> -
>> -	exynos_map_io();
>>  }
>>  
>>  /*
>> diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
>> index 5fb0040..0eef407 100644
>> --- a/arch/arm/mach-exynos/include/mach/map.h
>> +++ b/arch/arm/mach-exynos/include/mach/map.h
>> @@ -18,6 +18,4 @@
>>  
>>  #define EXYNOS_PA_CHIPID		0x10000000
>>  
>> -#define EXYNOS4_PA_COREPERI		0x10500000
>> -
>>  #endif /* __ASM_ARCH_MAP_H */
>> diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
>> index a5d6841..553d0d9 100644
>> --- a/arch/arm/mach-exynos/platsmp.c
>> +++ b/arch/arm/mach-exynos/platsmp.c
>> @@ -224,11 +224,6 @@ static void write_pen_release(int val)
>>  	sync_cache_w(&pen_release);
>>  }
>>  
>> -static void __iomem *scu_base_addr(void)
>> -{
>> -	return (void __iomem *)(S5P_VA_SCU);
>> -}
>> -
>>  static DEFINE_SPINLOCK(boot_lock);
>>  
>>  static void exynos_secondary_init(unsigned int cpu)
>> @@ -387,14 +382,23 @@ fail:
>>  
>>  static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
>>  {
>> +	struct device_node *np;
>> +	void __iomem *scu_base;
>>  	int i;
>>  
>>  	exynos_sysram_init();
>>  
>>  	exynos_set_delayed_reset_assertion(true);
>>  
>> -	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
>> -		scu_enable(scu_base_addr());
>> +	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
>> +		np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
>> +		scu_base = of_iomap(np, 0);
>> +		if (scu_base) {
>> +			scu_enable(scu_base);
>> +			iounmap(scu_base);
>> +		}
>> +		of_node_put(np);
> 
> I do not like the duplication - this code appears in three places and
> they are the same. Could you split it into separate function?
> 
OK, will do these changes in v2.

Only pm.c and suspend.c file's scu_enable can be moved to single place
without introducing more dependencies between these mach files.

> As you mentioned to Alim, in case of lack of node, it would be nice to notify the
> user (pr_err() etc).
> 
OK, will do these changes in v2.


Thanks,
Pankaj Dubey

> Best regards,
> Krzysztof
> 
> 
> 
> 

^ permalink raw reply

* [PATCH v2 0/2] Remove static mapping of SCU from mach-exynos
From: Pankaj Dubey @ 2016-11-08  3:14 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series is part of patch series [1], which adds support of SCU
device node for Cortex-A9 based Exynos4 SoC. First two patches of the same
has been accepted and hence not included them in v2.

This patch series does some cleanup for Exynos4 SoC based boards.
We are currently statically mapping SCU SFRs in mach-exynos/exynos.c
which can be avoided if map this from device node of SCU. 

This patch introduces exynos_scu_enable in firmware.c file,
which will be called from exynos_resume, which in turn called by pm.c and
suspend.c as firmware_ops.

[1]: https://www.spinics.net/lists/arm-kernel/msg540498.html


This patch series is prepared on Krzysztof's for-next
(SHA_ID: b33c7bb9d59c3f4100d4)

I have tested these patches on Exynos4210 based on Origen board for SMP boot.
Patchset v1 was tested by Marek Szyprowski on Exynos4412-based Odroid U3
for SMP boot and S2R.

To confirm concern raised by Alim, I intentionally removed SCU device node
from exynos4.dtsi and tested on Origen board, I can see code handles this
case gracefully without any crash and system boot was fine. Of-course in such
case only single core will be able to boot.

Following boot message observed on Origen in case of missing SCU node
-------------
[    0.000864] CPU: Testing write buffer coherency: ok
[    0.001068] CPU0: thread -1, cpu 0, socket 9, mpidr 80000900
[    0.001456] exynos_smp_prepare_cpus failed to map scu_base
[    0.001477] Setting up static identity map for 0x40100000 - 0x40100058
[    1.120003] CPU1: failed to come online
[    1.120059] Brought up 1 CPUs
[    1.120068] SMP: Total of 1 processors activated (48.00 BogoMIPS).
[    1.120076] CPU: All CPU(s) started in SVC mode.
-------------

Changes since v1:
 - Address review comments from Krzysztof
 - Moved scu_enable from pm.c and suspend.c to single place in firmware.c,
   as both pm.c and suspend.c needs scu_enable during exynos_resume call. 
 - Added error handling during scu_enable in platsmp.c.
 - Added Reviewed-by tag from Alim.


This patch series is tested on Exynos4210 based Origen board for SMP boot.

Pankaj Dubey (2):
  ARM: EXYNOS: Remove static mapping of SCU SFR
  ARM: EXYNOS: Remove unused soc_is_exynos{4,5}

 arch/arm/mach-exynos/common.h                |  5 -----
 arch/arm/mach-exynos/exynos.c                | 22 ----------------------
 arch/arm/mach-exynos/firmware.c              | 17 +++++++++++++++++
 arch/arm/mach-exynos/include/mach/map.h      |  2 --
 arch/arm/mach-exynos/platsmp.c               | 20 +++++++++++++-------
 arch/arm/mach-exynos/pm.c                    |  4 +---
 arch/arm/mach-exynos/suspend.c               |  5 -----
 arch/arm/plat-samsung/include/plat/map-s5p.h |  4 ----
 8 files changed, 31 insertions(+), 48 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 1/2] ARM: EXYNOS: Remove static mapping of SCU SFR
From: Pankaj Dubey @ 2016-11-08  3:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478574864-24683-1-git-send-email-pankaj.dubey@samsung.com>

Lets remove static mapping of SCU SFR mainly used in CORTEX-A9 SoC based
boards. Instead use mapping from device tree node of SCU.

Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
---
 arch/arm/mach-exynos/exynos.c                | 22 ----------------------
 arch/arm/mach-exynos/firmware.c              | 17 +++++++++++++++++
 arch/arm/mach-exynos/include/mach/map.h      |  2 --
 arch/arm/mach-exynos/platsmp.c               | 20 +++++++++++++-------
 arch/arm/mach-exynos/pm.c                    |  4 +---
 arch/arm/mach-exynos/suspend.c               |  5 -----
 arch/arm/plat-samsung/include/plat/map-s5p.h |  4 ----
 7 files changed, 31 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 757fc11..fa08ef9 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -28,15 +28,6 @@
 
 #include "common.h"
 
-static struct map_desc exynos4_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	},
-};
-
 static struct platform_device exynos_cpuidle = {
 	.name              = "exynos_cpuidle",
 #ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -99,17 +90,6 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
 	return 1;
 }
 
-/*
- * exynos_map_io
- *
- * register the standard cpu IO areas
- */
-static void __init exynos_map_io(void)
-{
-	if (soc_is_exynos4())
-		iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-}
-
 static void __init exynos_init_io(void)
 {
 	debug_ll_io_init();
@@ -118,8 +98,6 @@ static void __init exynos_init_io(void)
 
 	/* detect cpu id and rev. */
 	s5p_init_cpu(S5P_VA_CHIPID);
-
-	exynos_map_io();
 }
 
 /*
diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c
index fd6da54..f33558e 100644
--- a/arch/arm/mach-exynos/firmware.c
+++ b/arch/arm/mach-exynos/firmware.c
@@ -18,6 +18,7 @@
 #include <asm/cputype.h>
 #include <asm/firmware.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/smp_scu.h>
 #include <asm/suspend.h>
 
 #include "common.h"
@@ -141,8 +142,24 @@ static int exynos_suspend(void)
 	return cpu_suspend(0, exynos_cpu_suspend);
 }
 
+static void exynos_scu_enable(void)
+{
+	struct device_node *np;
+	void __iomem *scu_base;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+	scu_base = of_iomap(np, 0);
+	of_node_put(np);
+	if (!scu_base) {
+		pr_err("%s failed to map scu_base\n", __func__);
+		return;
+	}
+}
+
 static int exynos_resume(void)
 {
+	exynos_scu_enable();
+
 	writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
 
 	return 0;
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 5fb0040..0eef407 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -18,6 +18,4 @@
 
 #define EXYNOS_PA_CHIPID		0x10000000
 
-#define EXYNOS4_PA_COREPERI		0x10500000
-
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index a5d6841..a0afa4b 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -224,11 +224,6 @@ static void write_pen_release(int val)
 	sync_cache_w(&pen_release);
 }
 
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)(S5P_VA_SCU);
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 static void exynos_secondary_init(unsigned int cpu)
@@ -387,14 +382,25 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
+	struct device_node *np;
+	void __iomem *scu_base;
 	int i;
 
 	exynos_sysram_init();
 
 	exynos_set_delayed_reset_assertion(true);
 
-	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-		scu_enable(scu_base_addr());
+	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
+		np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+		scu_base = of_iomap(np, 0);
+		of_node_put(np);
+		if (!scu_base) {
+			pr_err("%s failed to map scu_base\n", __func__);
+			return;
+		}
+		scu_enable(scu_base);
+		iounmap(scu_base);
+	}
 
 	/*
 	 * Write the address of secondary startup into the
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 487295f..b8c5565 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -18,6 +18,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/soc/samsung/exynos-regs-pmu.h>
 #include <linux/soc/samsung/exynos-pmu.h>
 
@@ -26,8 +27,6 @@
 #include <asm/suspend.h>
 #include <asm/cacheflush.h>
 
-#include <mach/map.h>
-
 #include "common.h"
 
 static inline void __iomem *exynos_boot_vector_addr(void)
@@ -177,7 +176,6 @@ void exynos_enter_aftr(void)
 	cpu_suspend(0, exynos_aftr_finisher);
 
 	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
-		scu_enable(S5P_VA_SCU);
 		if (call_firmware_op(resume) == -ENOSYS)
 			exynos_cpu_restore_register();
 	}
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 06332f6..6ccd466 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -34,8 +34,6 @@
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
 
-#include <mach/map.h>
-
 #include <plat/pm-common.h>
 
 #include "common.h"
@@ -461,9 +459,6 @@ static void exynos_pm_resume(void)
 	/* For release retention */
 	exynos_pm_release_retention();
 
-	if (cpuid == ARM_CPU_PART_CORTEX_A9)
-		scu_enable(S5P_VA_SCU);
-
 	if (call_firmware_op(resume) == -ENOSYS
 	    && cpuid == ARM_CPU_PART_CORTEX_A9)
 		exynos_cpu_restore_register();
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index 0fe2828..512ed1f 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -15,10 +15,6 @@
 
 #define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
 
-#define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU		S5P_VA_COREPERI(0x0)
-
 #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0			VA_VIC(0)
 #define VA_VIC1			VA_VIC(1)
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/2] ARM: EXYNOS: Remove unused soc_is_exynos{4,5}
From: Pankaj Dubey @ 2016-11-08  3:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478574864-24683-1-git-send-email-pankaj.dubey@samsung.com>

As no more user of soc_is_exynos{4,5} we can safely remove them.

Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
---
 arch/arm/mach-exynos/common.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 9424a8a..d19064b 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -105,11 +105,6 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_exynos5800()	0
 #endif
 
-#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4212() || \
-			  soc_is_exynos4412())
-#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
-			  soc_is_exynos5420() || soc_is_exynos5800())
-
 extern u32 cp15_save_diag;
 extern u32 cp15_save_power;
 
-- 
2.7.4

^ permalink raw reply related

* [GIT PULL] Renesas ARM64 Based SoC Defconfig Updates for v4.10
From: Olof Johansson @ 2016-11-08  3:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1478078567.git.horms+renesas@verge.net.au>

On Wed, Nov 02, 2016 at 10:23:40AM +0100, Simon Horman wrote:
> Hi Olof, Hi Kevin, Hi Arnd,
> 
> Please consider these Renesas ARM64 based SoC defconfig updates for v4.10.
> 
> 
> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> 
>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-arm64-defconfig-for-v4.10
> 
> for you to fetch changes up to 833c97254724a620d1d9fb9a580681fb52536fbf:
> 
>   arm64: defconfig: Enable DRM DU and V4L2 FCP + VSP modules (2016-10-27 09:07:35 +0200)

Merged, thanks.


-Olof

^ permalink raw reply

* [GIT PULL] Renesas ARM Based SoC Defconfig Updates for v4.10
From: Olof Johansson @ 2016-11-08  3:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1478078446.git.horms+renesas@verge.net.au>

On Wed, Nov 02, 2016 at 10:23:53AM +0100, Simon Horman wrote:
> Hi Olof, Hi Kevin, Hi Arnd,
> 
> Please consider these Renesas ARM based SoC defconfig updates for v4.10.
> 
> 
> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> 
>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-defconfig-for-v4.10
> 
> for you to fetch changes up to a604a37d46b80899d5a09d937fdd670e93af690d:
> 
>   ARM: shmobile: defconfig: Enable CONFIG_CGROUPS (2016-10-17 08:24:41 +0200)

Merged, thanks.


-Olof

^ permalink raw reply

* [GIT PULL] Renesas ARM Based SoC Drivers Updates for v4.10
From: Olof Johansson @ 2016-11-08  3:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1478077617.git.horms+renesas@verge.net.au>

On Wed, Nov 02, 2016 at 10:24:05AM +0100, Simon Horman wrote:
> Hi Olof, Hi Kevin, Hi Arnd,
> 
> Please consider these Renesas ARM based SoC drivers updates for v4.10.
> 
> 
> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> 
>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-drivers-for-v4.10
> 
> for you to fetch changes up to 603311ba979fa5bbbf6a8961e5f7a27deafce1b4:
> 
>   soc: renesas: rcar-sysc: add R8A7743 support (2016-10-17 08:21:20 +0200)

Merged, thanks.


-Olof

^ permalink raw reply

* [GIT PULL] DaVinci fix for v4.9-rc
From: Olof Johansson @ 2016-11-08  3:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f57fbfde-89ff-fdac-2a04-e8a4788b4ee5@ti.com>

On Thu, Nov 03, 2016 at 04:48:44PM +0530, Sekhar Nori wrote:
> The following changes since commit a909d3e636995ba7c349e2ca5dbb528154d4ac30:
> 
>   Linux 4.9-rc3 (2016-10-29 13:52:02 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-fixes-for-v4.9
> 
> for you to fetch changes up to 36173c2d023bad4dbad6ed0e6e886fde10ec8f2f:
> 
>   ARM: davinci: da850: Fix pwm name matching (2016-11-01 15:30:03 +0530)
> 
> ----------------------------------------------------------------
> This patch enables usage of multiple eCAP and eHRPWM devices
> using PWM sysfs entries.
> 
> Without this patch, creation of multiple entries fails due
> to name clash.
> 
> This is not a v4.9 regression but it will be nice to fix it
> soon.

Hi,

Merged into next/fixes-non-critical -- we're getting some pushback on fixes
for this cycle, so I'm being a bit more conservative.


-Olof

^ permalink raw reply

* [PATCH v7 1/2] soc: samsung: add exynos chipid driver support
From: pankaj.dubey @ 2016-11-08  3:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cafc255a-3bdb-7eb2-1092-545866752858@samsung.com>

Hi Marek,

On Monday 07 November 2016 01:05 PM, Marek Szyprowski wrote:
> Hi Pankaj,
> 
> 
> On 2016-11-05 13:03, Pankaj Dubey wrote:
>> Exynos SoCs have Chipid, for identification of product IDs
>> and SoC revisions. This patch intends to provide initialization
>> code for all these functionalities, at the same time it provides some
>> sysfs entries for accessing these information to user-space.
>>
>> This driver uses existing binding for exynos-chipid.
>>
>> CC: Grant Likely <grant.likely@linaro.org>
>> CC: Rob Herring <robh+dt@kernel.org>
>> CC: Linus Walleij <linus.walleij@linaro.org>
>> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
>> ---
>>   drivers/soc/samsung/Kconfig         |   5 ++
>>   drivers/soc/samsung/Makefile        |   1 +
>>   drivers/soc/samsung/exynos-chipid.c | 148
>> ++++++++++++++++++++++++++++++++++++
>>   3 files changed, 154 insertions(+)
>>   create mode 100644 drivers/soc/samsung/exynos-chipid.c
>>
>> diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
>> index 2455339..f9ab858 100644
>> --- a/drivers/soc/samsung/Kconfig
>> +++ b/drivers/soc/samsung/Kconfig
>> @@ -14,4 +14,9 @@ config EXYNOS_PM_DOMAINS
>>       bool "Exynos PM domains" if COMPILE_TEST
>>       depends on PM_GENERIC_DOMAINS || COMPILE_TEST
>>   +config EXYNOS_CHIPID
>> +    bool "Exynos Chipid controller driver" if COMPILE_TEST
>> +    depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
>> +    select SOC_BUS
>> +
>>   endif
>> diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
>> index 3619f2e..2a8a85e 100644
>> --- a/drivers/soc/samsung/Makefile
>> +++ b/drivers/soc/samsung/Makefile
>> @@ -1,3 +1,4 @@
>>   obj-$(CONFIG_EXYNOS_PMU)    += exynos-pmu.o exynos3250-pmu.o
>> exynos4-pmu.o \
>>                       exynos5250-pmu.o exynos5420-pmu.o
>>   obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
>> +obj-$(CONFIG_EXYNOS_CHIPID)    += exynos-chipid.o
>> diff --git a/drivers/soc/samsung/exynos-chipid.c
>> b/drivers/soc/samsung/exynos-chipid.c
>> new file mode 100644
>> index 0000000..9761e54
>> --- /dev/null
>> +++ b/drivers/soc/samsung/exynos-chipid.c
>> @@ -0,0 +1,148 @@
>> +/*
>> + * Copyright (c) 2016 Samsung Electronics Co., Ltd.
>> + *          http://www.samsung.com/
>> + *
>> + * EXYNOS - CHIP ID support
>> + * Author: Pankaj Dubey <pankaj.dubey@samsung.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/sys_soc.h>
>> +
>> +#define EXYNOS3250_SOC_ID    0xE3472000
>> +#define EXYNOS4210_SOC_ID    0x43210000
>> +#define EXYNOS4212_SOC_ID    0x43220000
>> +#define EXYNOS4412_SOC_ID    0xE4412000
>> +#define EXYNOS4415_SOC_ID    0xE4415000
>> +#define EXYNOS5250_SOC_ID    0x43520000
>> +#define EXYNOS5260_SOC_ID    0xE5260000
>> +#define EXYNOS5410_SOC_ID    0xE5410000
>> +#define EXYNOS5420_SOC_ID    0xE5420000
>> +#define EXYNOS5440_SOC_ID    0xE5440000
>> +#define EXYNOS5800_SOC_ID    0xE5422000
>> +
>> +#define EXYNOS_SOC_MASK        0xFFFFF000
>> +
>> +#define EXYNOS4210_REV_0    0x0
>> +#define EXYNOS4210_REV_1_0    0x10
>> +#define EXYNOS4210_REV_1_1    0x11
> 
> EXYNOS4210_REV* defines are not used at all in this driver.
> 
>> +
>> +#define EXYNOS_SUBREV_MASK    (0xF << 4)
>> +#define EXYNOS_MAINREV_MASK    (0xF << 0)
>> +#define EXYNOS_REV_MASK        (EXYNOS_SUBREV_MASK |
>> EXYNOS_MAINREV_MASK)
>> +
>> +
>> +static const char * __init product_id_to_soc_id(unsigned int product_id)
>> +{
>> +    const char *soc_name;
>> +    unsigned int soc_id = product_id & EXYNOS_SOC_MASK;
>> +
>> +    switch (soc_id) {
>> +    case EXYNOS3250_SOC_ID:
>> +        soc_name = "EXYNOS3250";
>> +        break;
>> +    case EXYNOS4210_SOC_ID:
>> +        soc_name = "EXYNOS4210";
>> +        break;
>> +    case EXYNOS4212_SOC_ID:
>> +        soc_name = "EXYNOS4212";
>> +        break;
>> +    case EXYNOS4412_SOC_ID:
>> +        soc_name = "EXYNOS4412";
>> +        break;
>> +    case EXYNOS4415_SOC_ID:
>> +        soc_name = "EXYNOS4415";
>> +        break;
>> +    case EXYNOS5250_SOC_ID:
>> +        soc_name = "EXYNOS5250";
>> +        break;
>> +    case EXYNOS5260_SOC_ID:
>> +        soc_name = "EXYNOS5260";
>> +        break;
>> +    case EXYNOS5420_SOC_ID:
>> +        soc_name = "EXYNOS5420";
>> +        break;
>> +    case EXYNOS5440_SOC_ID:
>> +        soc_name = "EXYNOS5440";
>> +        break;
>> +    case EXYNOS5800_SOC_ID:
>> +        soc_name = "EXYNOS5800";
>> +        break;
>> +    default:
>> +        soc_name = "UNKNOWN";
>> +    }
>> +    return soc_name;
>> +}
> 
> This approach is a bit error prone. You have already missed Exynos5410
> and early Exynos 4210 are not detected because of the incorrect SOC MASK.

Yes I missed to update Exynos4210 SoC Mask, thanks for pointing out.

> IMHO you should replace above code and defines with a simple array,
> where each ID is present only once, so it will be much easier to add
> future SoCs:
> 

Well, this looks good to me as well. I will incorporate these changes in
v2 as suggested by you and reuse your code, along with your
Signed-off-by for this part :)

> static const struct exynos_soc_id {
>         const char *name;
>         unsigned int id;
>         unsigned int mask;
> } soc_ids[] = {
>         { "EXYNOS3250", 0xE3472000, 0xFFFFF000 },
>         { "EXYNOS4210", 0x43200000, 0xFFFE0000 },
>         { "EXYNOS4212", 0x43220000, 0xFFFE0000 },
>         { "EXYNOS4412", 0xE4412000, 0xFFFE0000 },
>         { "EXYNOS4415", 0xE4415000, 0xFFFE0000 },
>         { "EXYNOS5250", 0x43520000, 0xFFFFF000 },
>         { "EXYNOS5260", 0xE5260000, 0xFFFFF000 },
>         { "EXYNOS5410", 0xE5410000, 0xFFFFF000 },
>         { "EXYNOS5420", 0xE5420000, 0xFFFFF000 },
>         { "EXYNOS5440", 0xE5440000, 0xFFFFF000 },
>         { "EXYNOS5800", 0xE5422000, 0xFFFFF000 },
> };
> 
> static const char * __init product_id_to_soc_id(unsigned int product_id)
> {
>         int i;
> 
>         for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
>                 if ((product_id & soc_ids[i].mask) == soc_ids[i].id)
>                         return soc_ids[i].name;
>         return "UNKNOWN";
> }
> 
> I'm also not sure about Exynos 4415, which has been scheduled for removal.
> 

As suggested by Arnd, I will keep entry for Exynos 4415 in the driver.


Thanks,
Pankaj Dubey

^ permalink raw reply

* [PATCH V2 2/5] arm64: Allow hw watchpoint at varied offset from base address
From: Will Deacon @ 2016-11-08  3:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <9394621e1b9709178ba54133a1469937fedae355.1476941895.git.panand@redhat.com>

Hi Pratyush,

On Thu, Oct 20, 2016 at 11:18:14AM +0530, Pratyush Anand wrote:
> ARM64 hardware supports watchpoint at any double word aligned address.
> However, it can select any consecutive bytes from offset 0 to 7 from that
> base address. For example, if base address is programmed as 0x420030 and
> byte select is 0x1C, then access of 0x420032,0x420033 and 0x420034 will
> generate a watchpoint exception.
> 
> Currently, we do not have such modularity. We can only program byte,
> halfword, word and double word access exception from any base address.
> 
> This patch adds support to overcome above limitations.
> 
> Signed-off-by: Pratyush Anand <panand@redhat.com>
> ---
>  arch/arm64/include/asm/hw_breakpoint.h |  2 +-
>  arch/arm64/kernel/hw_breakpoint.c      | 45 ++++++++++++++++------------------
>  arch/arm64/kernel/ptrace.c             |  5 ++--
>  3 files changed, 25 insertions(+), 27 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
> index 115ea2a64520..4f4e58bee9bc 100644
> --- a/arch/arm64/include/asm/hw_breakpoint.h
> +++ b/arch/arm64/include/asm/hw_breakpoint.h
> @@ -118,7 +118,7 @@ struct perf_event;
>  struct pmu;
>  
>  extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
> -				  int *gen_len, int *gen_type);
> +				  int *gen_len, int *gen_type, int *offset);
>  extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
>  extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
>  extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
> diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
> index 26a6bf77d272..3c2b96803eba 100644
> --- a/arch/arm64/kernel/hw_breakpoint.c
> +++ b/arch/arm64/kernel/hw_breakpoint.c
> @@ -349,7 +349,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
>   * to generic breakpoint descriptions.
>   */
>  int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
> -			   int *gen_len, int *gen_type)
> +			   int *gen_len, int *gen_type, int *offset)
>  {
>  	/* Type */
>  	switch (ctrl.type) {
> @@ -369,8 +369,10 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
>  		return -EINVAL;
>  	}
>  
> +	*offset = ffs(ctrl.len) - 1;

Do we want to fail the length == 0 case early? If you do add that check,
then you can use __ffs here instead.

>  	/* Len */
> -	switch (ctrl.len) {
> +	switch (ctrl.len >> *offset) {
>  	case ARM_BREAKPOINT_LEN_1:
>  		*gen_len = HW_BREAKPOINT_LEN_1;
>  		break;
> @@ -517,18 +519,17 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
>  		default:
>  			return -EINVAL;
>  		}
> -
> -		info->address &= ~alignment_mask;
> -		info->ctrl.len <<= offset;
>  	} else {
>  		if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
>  			alignment_mask = 0x3;
>  		else
>  			alignment_mask = 0x7;
> -		if (info->address & alignment_mask)
> -			return -EINVAL;
> +		offset = info->address & alignment_mask;
>  	}
>  
> +	info->address &= ~alignment_mask;
> +	info->ctrl.len <<= offset;

Urgh, I really hate all this converting to and fro to keep perf happy.
FWIW, I'm@the point where I would seriously consider ripping out the
hw_breakpoint code and replacing it with a ptrace-specific backend so we
just drop all this crap. The only people that seem to use the perf interface
are those running the (failing) selftests. Given that we have to have
a bloody thread switch notifier *anyway*, all perf seems to give us is
complexity and restrictions.

>  	/*
>  	 * Disallow per-task kernel breakpoints since these would
>  	 * complicate the stepping code.
> @@ -665,8 +666,8 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
>  			      struct pt_regs *regs)
>  {
>  	int i, step = 0, *kernel_step, access;
> -	u32 ctrl_reg;
> -	u64 val, alignment_mask;
> +	u32 ctrl_reg, lens, lene;
> +	u64 val;
>  	struct perf_event *wp, **slots;
>  	struct debug_info *debug_info;
>  	struct arch_hw_breakpoint *info;
> @@ -684,25 +685,21 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
>  			goto unlock;
>  
>  		info = counter_arch_bp(wp);
> -		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
> -		if (is_compat_task()) {
> -			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
> -				alignment_mask = 0x7;
> -			else
> -				alignment_mask = 0x3;
> -		} else {
> -			alignment_mask = 0x7;
> -		}
>  
> -		/* Check if the watchpoint value matches. */
> +		/* Check if the watchpoint value and byte select match. */
>  		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
> -		if (val != (addr & ~alignment_mask))
> -			goto unlock;
> -
> -		/* Possible match, check the byte address select to confirm. */
>  		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
>  		decode_ctrl_reg(ctrl_reg, &ctrl);
> -		if (!((1 << (addr & alignment_mask)) & ctrl.len))
> +		lens = ffs(ctrl.len) - 1;
> +		lene = fls(ctrl.len) - 1;

Again, you can use the '__' variants to avoid the '- 1'.

> +		/*
> +		 * FIXME: reported address can be anywhere between "the
> +		 * lowest address accessed by the memory access that
> +		 * triggered the watchpoint" and "the highest watchpointed
> +		 * address accessed by the memory access". So, it may not
> +		 * lie in the interval of watchpoint address range.
> +		 */
> +		if (addr < val + lens || addr > val + lene)
>  			goto unlock;
>  
>  		/*
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index e0c81da60f76..0eb366a94382 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
>  				     struct arch_hw_breakpoint_ctrl ctrl,
>  				     struct perf_event_attr *attr)
>  {
> -	int err, len, type, disabled = !ctrl.enabled;
> +	int err, len, type, offset, disabled = !ctrl.enabled;
>  
>  	attr->disabled = disabled;
>  	if (disabled)
>  		return 0;
>  
> -	err = arch_bp_generic_fields(ctrl, &len, &type);
> +	err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
>  	if (err)
>  		return err;
>  
> @@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
>  
>  	attr->bp_len	= len;
>  	attr->bp_type	= type;
> +	attr->bp_addr	+= offset;

That's going to look pretty bizarre from userspace if it decides to read
back the address registers to find that they've mysteriously changed.

Perhaps ptrace_hbp_get_addr needs to retrieve the address from the
arch_hw_breakpoint, like we do for the ctrl register. What do you think?

Will

^ permalink raw reply

* [PATCH V2 3/5] arm64: hw_breakpoint: Handle inexact watchpoint addresses
From: Will Deacon @ 2016-11-08  3:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <22f4d20911e39efa0b8a6f7082d6839b80bb16b0.1476941895.git.panand@redhat.com>

On Thu, Oct 20, 2016 at 11:18:15AM +0530, Pratyush Anand wrote:
> From: Pavel Labath <test.tberghammer@gmail.com>
> 
> Arm64 hardware does not always report a watchpoint hit address that
> matches one of the watchpoints set. It can also report an address
> "near" the watchpoint if a single instruction access both watched and
> unwatched addresses. There is no straight-forward way, short of
> disassembling the offending instruction, to map that address back to
> the watchpoint.
> 
> Previously, when the hardware reported a watchpoint hit on an address
> that did not match our watchpoint (this happens in case of instructions
> which access large chunks of memory such as "stp") the process would
> enter a loop where we would be continually resuming it (because we did
> not recognise that watchpoint hit) and it would keep hitting the
> watchpoint again and again. The tracing process would never get
> notified of the watchpoint hit.
> 
> This commit fixes the problem by looking at the watchpoints near the
> address reported by the hardware. If the address does not exactly match
> one of the watchpoints we have set, it attributes the hit to the
> nearest watchpoint we have.  This heuristic is a bit dodgy, but I don't
> think we can do much more, given the hardware limitations.
> 
> [panand: reworked to rebase on his patches]
> 
> Signed-off-by: Pavel Labath <labath@google.com>
> Signed-off-by: Pratyush Anand <panand@redhat.com>
> ---
>  arch/arm64/kernel/hw_breakpoint.c | 94 +++++++++++++++++++++++++++------------
>  1 file changed, 66 insertions(+), 28 deletions(-)
> 
> diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
> index 3c2b96803eba..c57bc90b8286 100644
> --- a/arch/arm64/kernel/hw_breakpoint.c
> +++ b/arch/arm64/kernel/hw_breakpoint.c
> @@ -662,11 +662,46 @@ unlock:
>  }
>  NOKPROBE_SYMBOL(breakpoint_handler);
>  
> +/*
> + * Arm64 hardware does not always report a watchpoint hit address that matches
> + * one of the watchpoints set. It can also report an address "near" the
> + * watchpoint if a single instruction access both watched and unwatched
> + * addresses. There is no straight-forward way, short of disassembling the
> + * offending instruction, to map that address back to the watchpoint. This
> + * function computes the distance of the memory access from the watchpoint as a
> + * heuristic for the likelyhood that a given access triggered the watchpoint.
> + *
> + * See Section D2.10.5 "Determining the memory location that caused a Watchpoint
> + * exception" of ARMv8 Architecture Reference Manual for details.
> + *
> + * The function returns the distance of the address from the bytes watched by
> + * the watchpoint. In case of an exact match, it returns 0.
> + */
> +static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
> +					struct arch_hw_breakpoint_ctrl *ctrl)
> +{
> +	u64 wp_low, wp_high;
> +	u32 lens, lene;
> +
> +	lens = ffs(ctrl->len) - 1;
> +	lene = fls(ctrl->len) - 1;
> +
> +	wp_low = val + lens;
> +	wp_high = val + lene;
> +	if (addr < wp_low)
> +		return wp_low - addr;
> +	else if (addr > wp_high)
> +		return addr - wp_high;
> +	else
> +		return 0;
> +}
> +
>  static int watchpoint_handler(unsigned long addr, unsigned int esr,
>  			      struct pt_regs *regs)
>  {
> -	int i, step = 0, *kernel_step, access;
> -	u32 ctrl_reg, lens, lene;
> +	int i, step = 0, *kernel_step, access, closest_match = 0;
> +	u64 min_dist = -1, dist;
> +	u32 ctrl_reg;
>  	u64 val;
>  	struct perf_event *wp, **slots;
>  	struct debug_info *debug_info;
> @@ -676,31 +711,15 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
>  	slots = this_cpu_ptr(wp_on_reg);
>  	debug_info = &current->thread.debug;
>  
> +	/*
> +	 * Find all watchpoints that match the reported address. If no exact
> +	 * match is found. Attribute the hit to the closest watchpoint.
> +	 */
> +	rcu_read_lock();
>  	for (i = 0; i < core_num_wrps; ++i) {
> -		rcu_read_lock();
> -
>  		wp = slots[i];
> -
>  		if (wp == NULL)
> -			goto unlock;
> -
> -		info = counter_arch_bp(wp);
> -
> -		/* Check if the watchpoint value and byte select match. */
> -		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
> -		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
> -		decode_ctrl_reg(ctrl_reg, &ctrl);
> -		lens = ffs(ctrl.len) - 1;
> -		lene = fls(ctrl.len) - 1;
> -		/*
> -		 * FIXME: reported address can be anywhere between "the
> -		 * lowest address accessed by the memory access that
> -		 * triggered the watchpoint" and "the highest watchpointed
> -		 * address accessed by the memory access". So, it may not
> -		 * lie in the interval of watchpoint address range.
> -		 */
> -		if (addr < val + lens || addr > val + lene)
> -			goto unlock;
> +			continue;
>  
>  		/*
>  		 * Check that the access type matches.
> @@ -709,18 +728,37 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
>  		access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
>  			 HW_BREAKPOINT_R;
>  		if (!(access & hw_breakpoint_type(wp)))
> -			goto unlock;
> +			continue;
> +
> +		/* Check if the watchpoint value and byte select match. */
> +		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
> +		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
> +		decode_ctrl_reg(ctrl_reg, &ctrl);
> +		dist = get_distance_from_watchpoint(addr, val, &ctrl);
> +		if (dist < min_dist) {
> +			min_dist = dist;
> +			closest_match = i;
> +		}
> +		/* Is this an exact match? */
> +		if (dist != 0)
> +			continue;
>  
> +		info = counter_arch_bp(wp);
>  		info->trigger = addr;
>  		perf_bp_event(wp, regs);
>  
>  		/* Do we need to handle the stepping? */
>  		if (is_default_overflow_handler(wp))
>  			step = 1;
> -
> -unlock:
> -		rcu_read_unlock();
>  	}
> +	if (min_dist > 0 && min_dist != -1) {
> +		/* No exact match found. */
> +		wp = slots[closest_match];
> +		info = counter_arch_bp(wp);
> +		info->trigger = addr;
> +		perf_bp_event(wp, regs);
> +	}

Why don't we need to bother with the stepping in the case of a non-exact
match?

Will

^ permalink raw reply

* [PATCH 1/3] ARM: imx6u: add imx6ull support
From: Peter Chen @ 2016-11-08  3:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161105085951.GG5597@dragon>

 

Thanks, Shawn. All comments will be adopted in v2.

Peter

>>
>> In this patch, it moves common dts between imx6ul* and imx6ull* as new
>> files named imx6u*, and the specific part for imx6ul and imx6ull are
>> individual file.
>
>No.  That only helps churn the tree and git history.  Please keep using imx6ul.dtsi and
>simply have it be included by imx6ull.dtsi.
>
>>
>> Signed-off-by: Peter Chen <peter.chen@nxp.com>
>> ---
>>  arch/arm/boot/dts/Makefile              |   3 +-
>>  arch/arm/boot/dts/imx6u-14x14-evk.dts   | 475 ++++++++++++++++
>>  arch/arm/boot/dts/imx6u-14x14-evk.dtsi  | 487 +++++++++++++++++
>>  arch/arm/boot/dts/imx6u.dtsi            | 942
>++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/imx6ul-14x14-evk.dts  | 479 +---------------
>>  arch/arm/boot/dts/imx6ul.dtsi           | 936 +------------------------------
>>  arch/arm/boot/dts/imx6ull-14x14-evk.dts |  17 +
>>  arch/arm/boot/dts/imx6ull-pinfunc.h     |  57 ++
>>  arch/arm/boot/dts/imx6ull.dtsi          |  10 +
>>  9 files changed, 1993 insertions(+), 1413 deletions(-)  create mode
>> 100644 arch/arm/boot/dts/imx6u-14x14-evk.dts
>>  create mode 100644 arch/arm/boot/dts/imx6u-14x14-evk.dtsi
>>  create mode 100644 arch/arm/boot/dts/imx6u.dtsi  create mode 100644
>> arch/arm/boot/dts/imx6ull-14x14-evk.dts
>>  create mode 100644 arch/arm/boot/dts/imx6ull-pinfunc.h
>>  create mode 100644 arch/arm/boot/dts/imx6ull.dtsi
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index befcd26..3d6e199 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -423,7 +423,8 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
>>  	imx6ul-pico-hobbit.dtb \
>>  	imx6ul-tx6ul-0010.dtb \
>>  	imx6ul-tx6ul-0011.dtb \
>> -	imx6ul-tx6ul-mainboard.dtb
>> +	imx6ul-tx6ul-mainboard.dtb \
>> +	imx6ull-14x14-evk.dtb
>>  dtb-$(CONFIG_SOC_IMX7D) += \
>>  	imx7d-cl-som-imx7.dtb \
>>  	imx7d-colibri-eval-v3.dtb \
>> diff --git a/arch/arm/boot/dts/imx6u-14x14-evk.dts
>> b/arch/arm/boot/dts/imx6u-14x14-evk.dts
>> new file mode 100644
>> index 0000000..ba8614c
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6u-14x14-evk.dts
>> @@ -0,0 +1,475 @@
>> +/*
>> + * Copyright (C) 2015 Freescale Semiconductor, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> +modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>
>For new DT files, please consider to use GPL/X11 dual license.  You should be able
>to find a lot of examples in arch/arm/boot/dts.
>
><snip>
>
>> diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h
>> b/arch/arm/boot/dts/imx6ull-pinfunc.h
>> new file mode 100644
>> index 0000000..fca0036
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6ull-pinfunc.h
>> @@ -0,0 +1,57 @@
>> +/*
>> + * Copyright (C) 2016 Freescale Semiconductor, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> +modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __DTS_IMX6ULL_PINFUNC_H
>> +#define __DTS_IMX6ULL_PINFUNC_H
>> +
>> +#include "imx6ul-pinfunc.h"
>> +/*
>> + * The pin function ID is a tuple of
>> + * <mux_reg conf_reg input_reg mux_mode input_val>  */
>> +#define MX6UL_PAD_ENET2_RX_DATA0__EPDC_SDDO08
>0x00E4 0x0370 0x0000 0x9 0x0
>
>Can we name these imx6ull specific defines MX6ULL_xxx, so that we know they
>should only be used in imx6ull specific dts?
>
>> +#define MX6UL_PAD_ENET2_RX_DATA1__EPDC_SDDO09
>0x00E8 0x0374 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_RX_EN__EPDC_SDDO10                       0x00EC
>0x0378 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_TX_DATA0__EPDC_SDDO11
>0x00F0 0x037C 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_TX_DATA1__EPDC_SDDO12
>0x00F4 0x0380 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_TX_EN__EPDC_SDDO13                       0x00F8
>0x0384 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_TX_CLK__EPDC_SDDO14                      0x00FC
>0x0388 0x0000 0x9 0x0
>> +#define MX6UL_PAD_ENET2_RX_ER__EPDC_SDDO15                       0x0100
>0x038C 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_CLK__EPDC_SDCLK                            0x0104
>0x0390 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_ENABLE__EPDC_SDLE                          0x0108
>0x0394 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_HSYNC__EPDC_SDOE                           0x010C
>0x0398 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_VSYNC__EPDC_SDCE0                          0x0110
>0x039C 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_RESET__EPDC_GDOE                           0x0114
>0x03A0 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA00__EPDC_SDDO00                        0x0118
>0x03A4 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA01__EPDC_SDDO01                        0x011C
>0x03A8 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA02__EPDC_SDDO02                        0x0120
>0x03AC 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA03__EPDC_SDDO03                        0x0124
>0x03B0 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA04__EPDC_SDDO04                        0x0128
>0x03B4 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA05__EPDC_SDDO05                        0x012C
>0x03B8 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA06__EPDC_SDDO06                        0x0130
>0x03BC 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA07__EPDC_SDDO07                        0x0134
>0x03C0 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA14__EPDC_SDSHR                         0x0150
>0x03DC 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA15__EPDC_GDRL                          0x0154
>0x03E0 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA16__EPDC_GDCLK                         0x0158
>0x03E4 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA17__EPDC_GDSP                          0x015C
>0x03E8 0x0000 0x9 0x0
>> +#define MX6UL_PAD_LCD_DATA21__EPDC_SDCE1                         0x016C
>0x03F8 0x0000 0x9 0x0
>> +
>
>Why this new line?
>
>Shawn
>

^ permalink raw reply

* [PATCH 3/3] clk: imx: clk-imx6ul: add clk support for imx6ull
From: Peter Chen @ 2016-11-08  3:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161105090506.GH5597@dragon>

Thanks, Shawn. All comments will be adopted in v2.

Peter

>> +"pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg",
>> +}; static const char *epdc_sels[] = { "epdc_podf", "ipp_di0",
>> +"ipp_di1", "ldb_di0", "ldb_di1", };
>> +
>
>The new line is not needed.  There is already one below.
>
>>
>>  static struct clk *clks[IMX6UL_CLK_END];  static struct
>> clk_onecell_data clk_data;
>
 
>> -#define IMX6UL_CLK_END			225
>> +/* For i.MX6ULL */
>> +#define IMX6UL_CLK_ESAI_PRED		225
>> +#define IMX6UL_CLK_ESAI_PODF		226
>> +#define IMX6UL_CLK_ESAI_EXTAL		227
>> +#define IMX6UL_CLK_ESAI_MEM		228
>> +#define IMX6UL_CLK_ESAI_IPG		229
>> +#define IMX6UL_CLK_DCP_CLK		230
>> +#define IMX6UL_CLK_EPDC_PRE_SEL		231
>> +#define IMX6UL_CLK_EPDC_SEL		232
>> +#define IMX6UL_CLK_EPDC_PODF		233
>> +#define IMX6UL_CLK_EPDC_ACLK		234
>> +#define IMX6UL_CLK_EPDC_PIX		235
>> +#define IMX6UL_CLK_ESAI_SEL		236
>
>Can we have these imx6ull only clocks named after IMX6ULL_xxx?
>
>Shawn
 

^ permalink raw reply

* [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

This patch supports the IPMI-bt device attached to the Low-Pin-Count interface
implemented on Hisilicon Hip06 SoC.
	                -----------
			| LPC host|
	                |         |
	                -----------
	                     |
 	        _____________V_______________LPC
                  |			  |
                  V	                  V
			             ------------
			             |  BT(ipmi)|
			             ------------

When master accesses those periperals beneath the Hip06 LPC, a specific LPC
driver is needed to make LPC host generate the standard LPC I/O cycles with
the target periperals'I/O port addresses. But on curent arm64 world, there is
no real I/O accesses. All the I/O operations through in/out pair are based on
MMIO which is not satisfied the I/O mechanism on Hip06 LPC.
To solve this issue and keep the relevant existing peripherals' driver
unchanged, this patch set redefines the in/out pair to support both the IO
operations for Hip06 LPC and the original MMIO. The way specific to Hip06 is
named as indirect-IO in this patchset.

Changes from V4:
  - Some revises based on the comments from Bjorn, Rob on V4;
  - Fixed the compile error on some platforms, such as openrisc;

Changes from V3:
  - UART support deferred to a separate patchset; This patchset only support
  ipmi device under LPC;
  - LPC bus I/O range is fixed to 0 ~ (PCIBIOS_MIN_IO - 1), which is separeted
  from PCI/PCIE PIO space;
  - Based on Arnd's remarks, removed the ranges property from Hip06 lpc dts and
  added a new fixup function, of_isa_indirect_io(), to get the I/O address
  directly from LPC dts configurations;
  - Support in(w,l)/out(w,l) for Hip06 lpc I/O;
  - Decouple the header file dependency on the gerenic io.h by defining in/out
  as normal functions in c file;
  - removed unused macro definitions in the LPC driver;

Changes from V2:
  - Support the PIO retrieval from the linux PIO generated by
  pci_address_to_pio. This method replace the 4K PIO reservation in V2;
  - Support the flat-tree earlycon;
  - Some revises based on Arnd's remarks;
  - Make sure the linux PIO range allocated to Hip06 LPC peripherals starts
  from non-ZERO;

Changes from V1:
  - Support the ACPI LPC device;
  - Optimize the dts LPC driver in ISA compatible mode;
  - Reserve the IO range below 4K in avoid the possible conflict with PCI host
  IO ranges;
  - Support the LPC uart and relevant earlycon;

Signed-off-by: Zhichang Yuan <yuanzhichang@hisilicon.com>

zhichang.yuan (3):
  ARM64 LPC: Indirect ISA port IO introduced
  ARM64 LPC: Add missing range exception for special ISA
  ARM64 LPC: LPC driver implementation on Hip06

 .../arm/hisilicon/hisilicon-low-pin-count.txt      |  31 ++
 MAINTAINERS                                        |   8 +
 arch/arm64/Kconfig                                 |   6 +
 arch/arm64/include/asm/extio.h                     |  94 ++++
 arch/arm64/include/asm/io.h                        |  35 ++
 arch/arm64/kernel/Makefile                         |   1 +
 arch/arm64/kernel/extio.c                          |  52 +++
 drivers/bus/Kconfig                                |   8 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/hisi_lpc.c                             | 501 +++++++++++++++++++++
 drivers/of/address.c                               |  56 ++-
 drivers/pci/pci.c                                  |   6 +-
 include/linux/of_address.h                         |  17 +
 include/linux/pci.h                                |   8 +
 14 files changed, 820 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c
 create mode 100644 drivers/bus/hisi_lpc.c

-- 
1.9.1

^ permalink raw reply

* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478576829-112707-1-git-send-email-yuanzhichang@hisilicon.com>

For arm64, there is no I/O space as other architectural platforms, such as
X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
such as Hip06, when accessing some legacy ISA devices connected to LPC, those
known port addresses are used to control the corresponding target devices, for
example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
normal MMIO mode in using.

To drive these devices, this patch introduces a method named indirect-IO.
In this method the in/out pair in arch/arm64/include/asm/io.h will be
redefined. When upper layer drivers call in/out with those known legacy port
addresses to access the peripherals, the hooking functions corrresponding to
those target peripherals will be called. Through this way, those upper layer
drivers which depend on in/out can run on Hip06 without any changes.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 arch/arm64/Kconfig             |  6 +++
 arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/io.h    | 29 +++++++++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/extio.c      | 27 ++++++++++++
 5 files changed, 157 insertions(+)
 create mode 100644 arch/arm64/include/asm/extio.h
 create mode 100644 arch/arm64/kernel/extio.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..b44070b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
 config ARCH_MMAP_RND_COMPAT_BITS_MAX
        default 16
 
+config ARM64_INDIRECT_PIO
+	bool "access peripherals with legacy I/O port"
+	help
+	  Support special accessors for ISA I/O devices. This is needed for
+	  SoCs that do not support standard read/write for the ISA range.
+
 config NO_IOPORT_MAP
 	def_bool y if !PCI
 
diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
new file mode 100644
index 0000000..6ae0787
--- /dev/null
+++ b/arch/arm64/include/asm/extio.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_EXTIO_H
+#define __LINUX_EXTIO_H
+
+struct extio_ops {
+	unsigned long start;/* inclusive, sys io addr */
+	unsigned long end;/* inclusive, sys io addr */
+
+	u64 (*pfin)(void *devobj, unsigned long ptaddr,	size_t dlen);
+	void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
+					size_t dlen);
+	u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
+				size_t dlen, unsigned int count);
+	void (*pfouts)(void *devobj, unsigned long ptaddr,
+				const void *outbuf, size_t dlen,
+				unsigned int count);
+	void *devpara;
+};
+
+extern struct extio_ops *arm64_extio_ops;
+
+#define DECLARE_EXTIO(bw, type)						\
+extern type in##bw(unsigned long addr);					\
+extern void out##bw(type value, unsigned long addr);			\
+extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
+extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
+
+#define BUILD_EXTIO(bw, type)						\
+type in##bw(unsigned long addr)						\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		return read##bw(PCI_IOBASE + addr);			\
+	return arm64_extio_ops->pfin ?					\
+		arm64_extio_ops->pfin(arm64_extio_ops->devpara,		\
+			addr, sizeof(type)) : -1;			\
+}									\
+									\
+void out##bw(type value, unsigned long addr)				\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		write##bw(value, PCI_IOBASE + addr);			\
+	else								\
+		if (arm64_extio_ops->pfout)				\
+			arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
+				addr, value, sizeof(type));		\
+}									\
+									\
+void ins##bw(unsigned long addr, void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		reads##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfins)				\
+			arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}									\
+									\
+void outs##bw(unsigned long addr, const void *buffer, unsigned int count)	\
+{									\
+	if (!arm64_extio_ops || arm64_extio_ops->start > addr ||	\
+			arm64_extio_ops->end < addr)			\
+		writes##bw(PCI_IOBASE + addr, buffer, count);		\
+	else								\
+		if (arm64_extio_ops->pfouts)				\
+			arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
+				addr, buffer, sizeof(type), count);	\
+}
+
+static inline void arm64_set_extops(struct extio_ops *ops)
+{
+	if (ops)
+		WRITE_ONCE(arm64_extio_ops, ops);
+}
+
+#endif /* __LINUX_EXTIO_H*/
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427..136735d 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -31,6 +31,7 @@
 #include <asm/early_ioremap.h>
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
+#include <asm/extio.h>
 
 #include <xen/xen.h>
 
@@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT		(PCI_IO_SIZE - 1)
 #define PCI_IOBASE		((void __iomem *)PCI_IO_START)
 
+
+/*
+ * redefine the in(s)b/out(s)b for indirect-IO.
+ */
+#ifdef CONFIG_ARM64_INDIRECT_PIO
+#define inb inb
+#define outb outb
+#define insb insb
+#define outsb outsb
+/* external declaration */
+DECLARE_EXTIO(b, u8)
+
+#define inw inw
+#define outw outw
+#define insw insw
+#define outsw outsw
+
+DECLARE_EXTIO(w, u16)
+
+#define inl inl
+#define outl outl
+#define insl insl
+#define outsl outsl
+
+DECLARE_EXTIO(l, u32)
+#endif
+
+
 /*
  * String version of I/O memory access operations.
  */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d66bba..60e0482 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO)	+= extio.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
new file mode 100644
index 0000000..647b3fa
--- /dev/null
+++ b/arch/arm64/kernel/extio.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+
+struct extio_ops *arm64_extio_ops;
+
+
+BUILD_EXTIO(b, u8)
+
+BUILD_EXTIO(w, u16)
+
+BUILD_EXTIO(l, u32)
-- 
1.9.1

^ permalink raw reply related

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478576829-112707-1-git-send-email-yuanzhichang@hisilicon.com>

This patch solves two issues:
1) parse and get the right I/O range from DTS node whose parent does not
define the corresponding ranges property;

There are some special ISA/LPC devices that work on a specific I/O range where
it is not correct to specify a ranges property in DTS parent node as cpu
addresses translated from DTS node are only for memory space on some
architectures, such as Arm64. Without the parent 'ranges' property, current
of_translate_address() return an error.
Here we add a fixup function, of_get_isa_indirect_io(). During the OF address
translation, this fixup will be called to check the 'reg' address to be
translating is for those sepcial ISA/LPC devices and get the I/O range
directly from the 'reg' property.

2) eliminate the I/O range conflict risk with PCI/PCIE leagecy I/O device;

The current __of_address_to_resource() always translates the I/O range to PIO.
But this processing is not suitable for our ISA/LPC devices whose I/O range is
not cpu address(Arnd had stressed this in his comments on V2,V3 patch-set).
Here, we bypass the mapping between cpu address and PIO for the special
ISA/LPC devices. But to drive these ISA/LPC devices, a I/O port address below
PCIBIOS_MIN_IO is needed by in*/out*(). Which means there is conflict risk
between I/O range of [0, PCIBIOS_MIN_IO) and PCI/PCIE legacy I/O range of [0,
IO_SPACE_LIMIT).
To avoid the I/O conflict, this patch reserve the I/O range below
PCIBIOS_MIN_IO.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 .../arm/hisilicon/hisilicon-low-pin-count.txt      | 31 ++++++++++++
 arch/arm64/include/asm/io.h                        |  6 +++
 arch/arm64/kernel/extio.c                          | 25 ++++++++++
 drivers/of/address.c                               | 56 +++++++++++++++++++++-
 drivers/pci/pci.c                                  |  6 +--
 include/linux/of_address.h                         | 17 +++++++
 include/linux/pci.h                                |  8 ++++
 7 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
new file mode 100644
index 0000000..13c8ddd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
@@ -0,0 +1,31 @@
+Hisilicon Hip06 low-pin-count device
+  Usually LPC controller is part of PCI host bridge, so the legacy ISA ports
+  locate on LPC bus can be accessed direclty. But some SoCs have independent
+  LPC controller, and access the legacy ports by triggering LPC I/O cycles.
+  Hisilicon Hip06 implements this LPC device.
+
+Required properties:
+- compatible: should be "hisilicon,low-pin-count"
+- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
+- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
+- reg: base memory range where the register set of this device is mapped.
+
+Note:
+  The node name before '@' must be "isa" to represent the binding stick to the
+  ISA/EISA binding specification.
+
+Example:
+
+isa at a01b0000 {
+	compatible = "hisilicom,low-pin-count";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+	ipmi0: bt at e4 {
+		compatible = "ipmi-bt";
+		device_type = "ipmi";
+		reg = <0x01 0xe4 0x04>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 136735d..c26b7cc 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -175,6 +175,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define outsl outsl
 
 DECLARE_EXTIO(l, u32)
+
+#define indirect_io_enabled indirect_io_enabled
+extern bool indirect_io_enabled(void);
+
+#define addr_is_indirect_io addr_is_indirect_io
+extern int addr_is_indirect_io(u64 taddr);
 #endif
 
 
diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
index 647b3fa..3d45fa8 100644
--- a/arch/arm64/kernel/extio.c
+++ b/arch/arm64/kernel/extio.c
@@ -19,6 +19,31 @@
 
 struct extio_ops *arm64_extio_ops;
 
+/**
+ * indirect_io_enabled - check whether indirectIO is enabled.
+ *	arm64_extio_ops will be set only when indirectIO mechanism had been
+ *	initialized.
+ *
+ * Returns true when indirectIO is enabled.
+ */
+bool indirect_io_enabled(void)
+{
+	return arm64_extio_ops ? true : false;
+}
+
+/**
+ * addr_is_indirect_io - check whether the input taddr is for indirectIO.
+ * @taddr: the io address to be checked.
+ *
+ * Returns 1 when taddr is in the range; otherwise return 0.
+ */
+int addr_is_indirect_io(u64 taddr)
+{
+	if (arm64_extio_ops->start > taddr || arm64_extio_ops->end < taddr)
+		return 0;
+
+	return 1;
+}
 
 BUILD_EXTIO(b, u8)
 
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..cc2a05d 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -479,6 +479,50 @@ static int of_empty_ranges_quirk(struct device_node *np)
 	return false;
 }
 
+
+/*
+ * of_isa_indirect_io - get the IO address from some isa reg property value.
+ *	For some isa/lpc devices, no ranges property in ancestor node.
+ *	The device addresses are described directly in their regs property.
+ *	This fixup function will be called to get the IO address of isa/lpc
+ *	devices when the normal of_translation failed.
+ *
+ * @parent:	points to the parent dts node;
+ * @bus:		points to the of_bus which can be used to parse address;
+ * @addr:	the address from reg property;
+ * @na:		the address cell counter of @addr;
+ * @presult:	store the address paresed from @addr;
+ *
+ * return 1 when successfully get the I/O address;
+ * 0 will return for some failures.
+ */
+static int of_get_isa_indirect_io(struct device_node *parent,
+				struct of_bus *bus, __be32 *addr,
+				int na, u64 *presult)
+{
+	unsigned int flags;
+	unsigned int rlen;
+
+	/* whether support indirectIO */
+	if (!indirect_io_enabled())
+		return 0;
+
+	if (!of_bus_isa_match(parent))
+		return 0;
+
+	flags = bus->get_flags(addr);
+	if (!(flags & IORESOURCE_IO))
+		return 0;
+
+	/* there is ranges property, apply the normal translation directly. */
+	if (of_get_property(parent, "ranges", &rlen))
+		return 0;
+
+	*presult = of_read_number(addr + 1, na - 1);
+	/* this fixup is only valid for specific I/O range. */
+	return addr_is_indirect_io(*presult);
+}
+
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, __be32 *addr,
 			    int na, int ns, int pna, const char *rprop)
@@ -595,6 +639,15 @@ static u64 __of_translate_address(struct device_node *dev,
 			result = of_read_number(addr, na);
 			break;
 		}
+		/*
+		 * For indirectIO device which has no ranges property, get
+		 * the address from reg directly.
+		 */
+		if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
+			pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
+				of_node_full_name(dev), result);
+			break;
+		}
 
 		/* Get new parent bus and counts */
 		pbus = of_match_bus(parent);
@@ -688,8 +741,9 @@ static int __of_address_to_resource(struct device_node *dev,
 	if (taddr == OF_BAD_ADDR)
 		return -EINVAL;
 	memset(r, 0, sizeof(struct resource));
-	if (flags & IORESOURCE_IO) {
+	if (flags & IORESOURCE_IO && taddr >= PCIBIOS_MIN_IO) {
 		unsigned long port;
+
 		port = pci_address_to_pio(taddr);
 		if (port == (unsigned long)-1)
 			return -EINVAL;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ba34907..1a08511 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3263,7 +3263,7 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
 
 #ifdef PCI_IOBASE
 	struct io_range *range;
-	resource_size_t allocated_size = 0;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	/* check if the range hasn't been previously recorded */
 	spin_lock(&io_range_lock);
@@ -3312,7 +3312,7 @@ phys_addr_t pci_pio_to_address(unsigned long pio)
 
 #ifdef PCI_IOBASE
 	struct io_range *range;
-	resource_size_t allocated_size = 0;
+	resource_size_t allocated_size = PCIBIOS_MIN_IO;
 
 	if (pio > IO_SPACE_LIMIT)
 		return address;
@@ -3335,7 +3335,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
 #ifdef PCI_IOBASE
 	struct io_range *res;
-	resource_size_t offset = 0;
+	resource_size_t offset = PCIBIOS_MIN_IO;
 	unsigned long addr = -1;
 
 	spin_lock(&io_range_lock);
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 3786473..deec469 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -24,6 +24,23 @@ struct of_pci_range {
 #define for_each_of_pci_range(parser, range) \
 	for (; of_pci_range_parser_one(parser, range);)
 
+
+#ifndef indirect_io_enabled
+#define indirect_io_enabled indirect_io_enabled
+static inline bool indirect_io_enabled(void)
+{
+	return false;
+}
+#endif
+
+#ifndef addr_is_indirect_io
+#define addr_is_indirect_io addr_is_indirect_io
+static inline int addr_is_indirect_io(u64 taddr)
+{
+	return 0;
+}
+#endif
+
 /* Translate a DMA address from device space to CPU space */
 extern u64 of_translate_dma_address(struct device_node *dev,
 				    const __be32 *in_addr);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0e49f70..7f6bbb6 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2130,4 +2130,12 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 /* provide the legacy pci_dma_* API */
 #include <linux/pci-dma-compat.h>
 
+/*
+ * define this macro here to refrain from compilation error for some
+ * platforms. Please keep this macro at the end of this header file.
+ */
+#ifndef PCIBIOS_MIN_IO
+#define PCIBIOS_MIN_IO		0
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
1.9.1

^ permalink raw reply related

* [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: zhichang.yuan @ 2016-11-08  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478576829-112707-1-git-send-email-yuanzhichang@hisilicon.com>

On hip06, the accesses to LPC peripherals work in an indirect way. A
corresponding LPC driver configure some registers in LPC master at first, then
the real accesses on LPC slave devices are finished by the LPC master, which
is transparent to LPC driver.
This patch implement the relevant driver for Hip06 LPC. Cooperating with
indirect-IO, ipmi messages is in service without any changes on ipmi driver.

Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
---
 MAINTAINERS            |   8 +
 drivers/bus/Kconfig    |   8 +
 drivers/bus/Makefile   |   1 +
 drivers/bus/hisi_lpc.c | 501 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 drivers/bus/hisi_lpc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ccae35b..4c7a350 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5729,6 +5729,14 @@ F:	include/uapi/linux/if_hippi.h
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON LPC BUS DRIVER
+M:	Zhichang Yuan <yuanzhichang@hisilicon.com>
+L:	linux-arm-kernel at lists.infradead.org
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/bus/hisi_lpc.c
+F:	Documentation/devicetree/bindings/arm/hisilicon/hisilicon-low-pin-count.txt
+
 HISILICON NETWORK SUBSYSTEM DRIVER
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..4fa8ab4 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -64,6 +64,14 @@ config BRCMSTB_GISB_ARB
 	  arbiter. This driver provides timeout and target abort error handling
 	  and internal bus master decoding.
 
+config HISILICON_LPC
+	bool "Workaround for nonstandard ISA I/O space on Hisilicon Hip0X"
+	depends on (ARCH_HISI || COMPILE_TEST) && ARM64
+	select ARM64_INDIRECT_PIO
+	help
+	  Driver needed for some legacy ISA devices attached to Low-Pin-Count
+	  on Hisilicon Hip0X SoC.
+
 config IMX_WEIM
 	bool "Freescale EIM DRIVER"
 	depends on ARCH_MXC
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..10b4983 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
 obj-$(CONFIG_ARM_CCN)		+= arm-ccn.o
 
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
+obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_IMX_WEIM)		+= imx-weim.o
 obj-$(CONFIG_MIPS_CDMM)		+= mips_cdmm.o
 obj-$(CONFIG_MVEBU_MBUS) 	+= mvebu-mbus.o
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
new file mode 100644
index 0000000..47dc081
--- /dev/null
+++ b/drivers/bus/hisi_lpc.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
+ * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
+ * Author: Zou Rongrong <zourongrong@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+/*
+ * setting this bit means each IO operation will target to different port address;
+ * 0 means repeatly IO operations will be sticked on the same port, such as BT;
+ */
+#define FG_INCRADDR_LPC		0x02
+
+struct lpc_cycle_para {
+	unsigned int opflags;
+	unsigned int csize; /* the data length of each operation */
+};
+
+struct hisilpc_dev {
+	spinlock_t cycle_lock;
+	void __iomem  *membase;
+	struct extio_ops io_ops;
+};
+
+
+/* The maximum continous operations*/
+#define LPC_MAX_OPCNT	16
+/* only support IO data unit length is four at maximum */
+#define LPC_MAX_DULEN	4
+#if LPC_MAX_DULEN > LPC_MAX_OPCNT
+#error "LPC.. MAX_DULEN must be not bigger than MAX_OPCNT!"
+#endif
+
+#define LPC_REG_START		0x00 /* start a new LPC cycle */
+#define LPC_REG_OP_STATUS	0x04 /* the current LPC status */
+#define LPC_REG_IRQ_ST		0x08 /* interrupt enable&status */
+#define LPC_REG_OP_LEN		0x10 /* how many LPC cycles each start */
+#define LPC_REG_CMD		0x14 /* command for the required LPC cycle */
+#define LPC_REG_ADDR		0x20 /* LPC target address */
+#define LPC_REG_WDATA		0x24 /* data to be written */
+#define LPC_REG_RDATA		0x28 /* data coming from peer */
+
+
+/* The command register fields*/
+#define LPC_CMD_SAMEADDR	0x08
+#define LPC_CMD_TYPE_IO		0x00
+#define LPC_CMD_WRITE		0x01
+#define LPC_CMD_READ		0x00
+/* the bit attribute is W1C. 1 represents OK. */
+#define LPC_STAT_BYIRQ		0x02
+
+#define LPC_STATUS_IDLE		0x01
+#define LPC_OP_FINISHED		0x02
+
+#define START_WORK		0x01
+
+/*
+ * The minimal waiting interval... Suggest it is not less than 10.
+ * Bigger value probably will lower the performance.
+ */
+#define LPC_NSEC_PERWAIT	100
+/*
+ * The maximum waiting time is about 128us.
+ * The fastest IO cycle time is about 390ns, but the worst case will wait
+ * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum
+ * burst cycles is 16. So, the maximum waiting time is about 128us under
+ * worst case.
+ * choose 1300 as the maximum.
+ */
+#define LPC_MAX_WAITCNT		1300
+/* About 10us. This is specfic for single IO operation, such as inb. */
+#define LPC_PEROP_WAITCNT	100
+
+
+static inline int wait_lpc_idle(unsigned char *mbase,
+				unsigned int waitcnt) {
+	u32 opstatus;
+
+	while (waitcnt--) {
+		ndelay(LPC_NSEC_PERWAIT);
+		opstatus = readl(mbase + LPC_REG_OP_STATUS);
+		if (opstatus & LPC_STATUS_IDLE)
+			return (opstatus & LPC_OP_FINISHED) ? 0 : (-EIO);
+	}
+	return -ETIME;
+}
+
+/**
+ * hisilpc_target_in - trigger a series of lpc cycles to read required data
+ *		  from target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the read back data is stored
+ * @opcnt: how many I/O operations required in this calling
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_in(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr, unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt  > LPC_MAX_OPCNT)
+		return -EINVAL;
+
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_READ;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		/* whole operation must be atomic */
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+		if (!ret) {
+			opcnt -= cnt_per_trans;
+			for (; cnt_per_trans--; buf++)
+				*buf = readl(lpcdev->membase + LPC_REG_RDATA);
+		}
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_target_out - trigger a series of lpc cycles to write required data
+ *		  to target periperal.
+ * @pdev: pointer to hisi lpc device
+ * @para: some paramerters used to control the lpc I/O operations
+ * @ptaddr: the lpc I/O target port address
+ * @buf: where the data to be written is stored
+ * @opcnt: how many I/O operations required
+ *
+ * only one byte data is read each I/O operation.
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_target_out(struct hisilpc_dev *lpcdev,
+				struct lpc_cycle_para *para,
+				unsigned long ptaddr,
+				const unsigned char *buf,
+				unsigned long opcnt)
+{
+	unsigned long cnt_per_trans;
+	unsigned int cmd_word;
+	unsigned int waitcnt;
+	int ret;
+
+	if (!buf || !opcnt || !para || !lpcdev)
+		return -EINVAL;
+
+	if (opcnt > LPC_MAX_OPCNT)
+		return -EINVAL;
+	/* default is increasing address */
+	cmd_word = LPC_CMD_TYPE_IO | LPC_CMD_WRITE;
+	waitcnt = (LPC_PEROP_WAITCNT);
+	if (!(para->opflags & FG_INCRADDR_LPC)) {
+		cmd_word |= LPC_CMD_SAMEADDR;
+		waitcnt = LPC_MAX_WAITCNT;
+	}
+
+	ret = 0;
+	cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
+	for (; opcnt && !ret; cnt_per_trans = para->csize) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&lpcdev->cycle_lock, flags);
+
+		writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
+		opcnt -= cnt_per_trans;
+		for (; cnt_per_trans--; buf++)
+			writel(*buf, lpcdev->membase + LPC_REG_WDATA);
+
+		writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
+
+		writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
+
+		writel(START_WORK, lpcdev->membase + LPC_REG_START);
+
+		/* whether the operation is finished */
+		ret = wait_lpc_idle(lpcdev->membase, waitcnt);
+
+		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
+	}
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_in - read/input the data from the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required to read from the target I/O port.
+ *
+ * when succeed, the data read back is stored in buffer pointed by inbuf.
+ * For inb, return the data read from I/O or -1 when error occur.
+ */
+static u64 hisilpc_comm_in(void *devobj, unsigned long ptaddr, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	u32 rd_data;
+	unsigned char *newbuf;
+	int ret = 0;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN ||	(dlen & (dlen - 1)))
+		return -1;
+
+	/* the local buffer must be enough for one data unit */
+	if (sizeof(rd_data) < dlen)
+		return -1;
+
+	newbuf = (unsigned char *)&rd_data;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf, dlen);
+	if (ret)
+		return -1;
+
+	return le32_to_cpu(rd_data);
+}
+
+/**
+ * hisilpc_comm_out - write/output the data whose maximal length is four bytes to
+ *		the I/O peripheral through LPC.
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @outval: a value to be outputed from caller, maximum is four bytes.
+ * @ptaddr: the target I/O port address.
+ * @dlen: the data length required writing to the target I/O port .
+ *
+ * This function is corresponding to out(b,w,l) only
+ *
+ */
+static void hisilpc_comm_out(void *devobj, unsigned long ptaddr,
+				u32 outval, size_t dlen)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+
+	if (!devobj || !dlen || dlen > LPC_MAX_DULEN)
+		return;
+
+	if (sizeof(outval) < dlen)
+		return;
+
+	outval = cpu_to_le32(outval);
+
+	newbuf = (const unsigned char *)&outval;
+	lpcdev = (struct hisilpc_dev *)devobj;
+
+	iopara.opflags = FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf, dlen);
+}
+
+/**
+ * hisilpc_comm_ins - read/input the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to ins(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @inbuf: a buffer where read/input data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port.
+ * @count: how many data units whose length is dlen will be read.
+ *
+ */
+static u64 hisilpc_comm_ins(void *devobj, unsigned long ptaddr,
+			void *inbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !inbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return -1;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)inbuf;
+	/*
+	 * ensure data stream whose length is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_in(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+
+	return ret;
+}
+
+/**
+ * hisilpc_comm_outs - write/output the data in buffer to the I/O peripheral
+ *		    through LPC, it corresponds to outs(b,w,l)
+ * @devobj: pointer to the device information relevant to LPC controller.
+ * @ptaddr: the target I/O port address.
+ * @outbuf: a buffer where write/output data bytes are stored.
+ * @dlen: the data length required writing to the target I/O port .
+ * @count: how many data units whose length is dlen will be written.
+ *
+ */
+static void hisilpc_comm_outs(void *devobj, unsigned long ptaddr,
+			const void *outbuf, size_t dlen, unsigned int count)
+{
+	struct hisilpc_dev *lpcdev;
+	struct lpc_cycle_para iopara;
+	const unsigned char *newbuf;
+	unsigned int loopcnt, cntleft;
+	unsigned int max_perburst;
+	int ret = 0;
+
+	if (!devobj || !outbuf || !count || !dlen ||
+			dlen > LPC_MAX_DULEN || (dlen & (dlen - 1)))
+		return;
+
+	iopara.opflags = 0;
+	if (dlen > 1)
+		iopara.opflags |= FG_INCRADDR_LPC;
+	iopara.csize = dlen;
+
+	lpcdev = (struct hisilpc_dev *)devobj;
+	newbuf = (unsigned char *)outbuf;
+	/*
+	 * ensure data stream whose lenght is multiple of dlen to be processed
+	 * each IO input
+	 */
+	max_perburst = LPC_MAX_OPCNT & (~(dlen - 1));
+	cntleft = count * dlen;
+	do {
+		loopcnt = (cntleft >= max_perburst) ? max_perburst : cntleft;
+		ret = hisilpc_target_out(lpcdev, &iopara, ptaddr, newbuf,
+						loopcnt);
+		if (ret)
+			break;
+		newbuf += loopcnt;
+		cntleft -= loopcnt;
+	} while (cntleft);
+}
+
+/**
+ * hisilpc_probe - the probe callback function for hisi lpc device,
+ *		will finish all the intialization.
+ * @pdev: the platform device corresponding to hisi lpc
+ *
+ * Returns 0 on success, non-zero on fail.
+ *
+ */
+static int hisilpc_probe(struct platform_device *pdev)
+{
+	struct resource *iores;
+	struct hisilpc_dev *lpcdev;
+	int ret;
+
+	dev_info(&pdev->dev, "probing hslpc...\n");
+
+	lpcdev = devm_kzalloc(&pdev->dev,
+				sizeof(struct hisilpc_dev), GFP_KERNEL);
+	if (!lpcdev)
+		return -ENOMEM;
+
+	spin_lock_init(&lpcdev->cycle_lock);
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpcdev->membase = devm_ioremap_resource(&pdev->dev, iores);
+	if (IS_ERR(lpcdev->membase)) {
+		dev_err(&pdev->dev, "ioremap memory FAIL(%d)!\n",
+				PTR_ERR(lpcdev->membase));
+		return PTR_ERR(lpcdev->membase);
+	}
+	/*
+	 * The first PCIBIOS_MIN_IO is reserved specifically for indirectIO.
+	 * It will separate indirectIO range from pci host bridge to
+	 * avoid the possible PIO conflict.
+	 * Set the indirectIO range directly here.
+	 */
+	lpcdev->io_ops.start = 0;
+	lpcdev->io_ops.end = PCIBIOS_MIN_IO - 1;
+	lpcdev->io_ops.devpara = lpcdev;
+	lpcdev->io_ops.pfin = hisilpc_comm_in;
+	lpcdev->io_ops.pfout = hisilpc_comm_out;
+	lpcdev->io_ops.pfins = hisilpc_comm_ins;
+	lpcdev->io_ops.pfouts = hisilpc_comm_outs;
+
+	platform_set_drvdata(pdev, lpcdev);
+
+	arm64_set_extops(&lpcdev->io_ops);
+
+	/*
+	 * The children scanning is only for dts mode. For ACPI children,
+	 * the corresponding devices had be created during acpi scanning.
+	 */
+	ret = 0;
+	if (!has_acpi_companion(&pdev->dev))
+		ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+				&pdev->dev);
+
+	if (!ret)
+		dev_info(&pdev->dev, "hslpc end probing. range[0x%lx - %lx]\n",
+			arm64_extio_ops->start, arm64_extio_ops->end);
+	else
+		dev_info(&pdev->dev, "hslpc probing is fail(%d)\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id hisilpc_of_match[] = {
+	{
+		.compatible = "hisilicon,hip06-lpc",
+	},
+	{},
+};
+
+static const struct acpi_device_id hisilpc_acpi_match[] = {
+	{"HISI0191", },
+	{},
+};
+
+static struct platform_driver hisilpc_driver = {
+	.driver = {
+		.name           = "hisi_lpc",
+		.of_match_table = hisilpc_of_match,
+		.acpi_match_table = hisilpc_acpi_match,
+	},
+	.probe = hisilpc_probe,
+};
+
+
+builtin_platform_driver(hisilpc_driver);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 0/2] Remove static mapping of SCU from mach-exynos
From: pankaj.dubey @ 2016-11-08  4:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478574864-24683-1-git-send-email-pankaj.dubey@samsung.com>

Hi,

On Tuesday 08 November 2016 08:44 AM, Pankaj Dubey wrote:
> This patch series is part of patch series [1], which adds support of SCU
> device node for Cortex-A9 based Exynos4 SoC. First two patches of the same
> has been accepted and hence not included them in v2.
> 
> This patch series does some cleanup for Exynos4 SoC based boards.
> We are currently statically mapping SCU SFRs in mach-exynos/exynos.c
> which can be avoided if map this from device node of SCU. 
> 
> This patch introduces exynos_scu_enable in firmware.c file,
> which will be called from exynos_resume, which in turn called by pm.c and
> suspend.c as firmware_ops.
> 

Please ignore this patchset as just noticed that firmware_ops needs not
be present for all boards, in that case exynos_resume ops won't be
defined in some of Exynos4 based boards and scu_enable won't be called.
I will think about some other approach and submit again.

Sorry for noise.

Thanks,
Pankaj Dubey

^ permalink raw reply

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: kbuild test robot @ 2016-11-08  5:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478576829-112707-3-git-send-email-yuanzhichang@hisilicon.com>

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: mips-ath25_defconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All error/warnings (new ones prefixed by >>):

   In file included from arch/mips/pci/pci.c:18:0:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
>> arch/mips/pci/pci.c:34:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    unsigned long PCIBIOS_MIN_IO;
                  ^~~~~~~~~~~~~~
   In file included from include/linux/linkage.h:6:0,
                    from include/linux/kernel.h:6,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from arch/mips/pci/pci.c:11:
>> include/linux/pci.h:2113:25: error: expected identifier or '(' before numeric constant
    #define PCIBIOS_MIN_IO  0
                            ^
   include/linux/export.h:57:21: note: in definition of macro '___EXPORT_SYMBOL'
     extern typeof(sym) sym;     \
                        ^~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~
   arch/mips/pci/pci.c:326:15: note: in expansion of macro 'PCIBIOS_MIN_IO'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
                  ^~~~~~~~~~~~~~
>> include/linux/export.h:66:21: error: lvalue required as unary '&' operand
     = { (unsigned long)&sym, __kstrtab_##sym }
                        ^
>> include/linux/export.h:94:25: note: in expansion of macro '___EXPORT_SYMBOL'
    #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
                            ^~~~~~~~~~~~~~~~
   include/linux/export.h:98:2: note: in expansion of macro '__EXPORT_SYMBOL'
     __EXPORT_SYMBOL(sym, "")
     ^~~~~~~~~~~~~~~
>> arch/mips/pci/pci.c:326:1: note: in expansion of macro 'EXPORT_SYMBOL'
    EXPORT_SYMBOL(PCIBIOS_MIN_IO);
    ^~~~~~~~~~~~~

vim +2113 include/linux/pci.h

  2107	
  2108	/*
  2109	 * define this macro here to refrain from compilation error for some
  2110	 * platforms. Please keep this macro at the end of this header file.
  2111	 */
  2112	#ifndef PCIBIOS_MIN_IO
> 2113	#define PCIBIOS_MIN_IO		0
  2114	#endif
  2115	
  2116	#endif /* LINUX_PCI_H */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 11431 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/33074cfc/attachment-0001.gz>

^ permalink raw reply

* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: kbuild test robot @ 2016-11-08  5:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478576829-112707-3-git-send-email-yuanzhichang@hisilicon.com>

Hi zhichang.yuan,

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on v4.9-rc4 next-20161028]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zhichang-yuan/ARM64-LPC-legacy-ISA-I-O-support/20161108-114742
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
config: arm-sunxi_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `of_address_to_resource':
>> sunxi_sid.c:(.text+0x18af5c): undefined reference to `pcibios_min_io'
   sunxi_sid.c:(.text+0x18af60): undefined reference to `pcibios_min_io'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 20012 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/cbd550e2/attachment-0001.gz>

^ permalink raw reply

* [PATCH v2 0/2] arm64: fix the bugs found in the hugetlb test
From: Huang Shijie @ 2016-11-08  5:44 UTC (permalink / raw)
  To: linux-arm-kernel

(1) Backgroud
   For the arm64, the hugetlb page size can be 32M (PMD + Contiguous bit).
   In the 4K page environment, the max page order is 10 (max_order - 1),
   so 32M page is the gigantic page.    

   The arm64 MMU supports a Contiguous bit which is a hint that the PTE
   is one of a set of contiguous entries which can be cached in a single
   TLB entry.  Please refer to the arm64v8 mannul :
       DDI0487A_f_armv8_arm.pdf (in page D4-1811)

(2) The bugs   
   After I tested the libhugetlbfs, I found several bugs in arm64 code.
   This patch set has all the bug fixes for the arm64.
   
(3) The test result in the Softiron and Juno-r1 boards:

   This detail test result shows below (both the "make func" & "make stress"):

    4KB granule:

        1.1) PTE + Contiguous bit : 4K x 16 = 64K (per huge page size)
             Test result          : PASS

        1.2) PMD                  : 2M x  1 = 2M  (per huge page size)
             Test result          : PASS

        1.3) PMD + Contiguous bit : 2M x 16 = 32M (per huge page size)
             Test result          : PASS

    64KB granule:

        3.1) PTE + Contiguous bit : 64K x 32 = 2M (per huge page size)
             Test result          : PASS

        3.2) PMD + Contiguous bit : 512M x 32 = 16G (per huge page size)
             Test result          : no hardware to support this test

v1 -- > v2:
    1.) remove the redundant checks for PGD/PUD


Huang Shijie (2):
  arm64: hugetlb: remove the wrong pmd check in find_num_contig()
  arm64: hugetlb: fix the wrong address for several functions

 arch/arm64/mm/hugetlbpage.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

-- 
2.5.5

^ permalink raw reply

* [PATCH v2 1/2] arm64: hugetlb: remove the wrong pmd check in find_num_contig()
From: Huang Shijie @ 2016-11-08  5:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478583879-14654-1-git-send-email-shijie.huang@arm.com>

The find_num_contig() will return 1 when the pmd is not present.
It will cause a kernel dead loop in the following scenaro:

   1.) pmd entry is not present.

   2.) the page fault occurs:
       ... hugetlb_fault() --> hugetlb_no_page() --> set_huge_pte_at()

   3.) set_huge_pte_at() will only set the first PMD entry, since the
       find_num_contig just return 1 in this case. So the PMD entries
       are all empty except the first one.

   4.) when kernel accesses the address mapped by the second PMD entry,
       a new page fault occurs:
       ... hugetlb_fault() --> huge_ptep_set_access_flags()

       The second PMD entry is still empty now.

   5.) When the kernel returns, the access will cause a page fault again.
       The kernel will run like the "4)" above.
       We will see a dead loop since here.

The dead loop is caught in the 32M hugetlb page (2M PMD + Contiguous bit).

This patch removes wrong pmd check, and fixes this dead loop.

This patch also removes the redundant checks for PGD/PUD in
the find_num_contig().

Acked-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
 arch/arm64/mm/hugetlbpage.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 2e49bd2..b0d3f8b 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -51,20 +51,8 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
 	*pgsize = PAGE_SIZE;
 	if (!pte_cont(pte))
 		return 1;
-	if (!pgd_present(*pgd)) {
-		VM_BUG_ON(!pgd_present(*pgd));
-		return 1;
-	}
 	pud = pud_offset(pgd, addr);
-	if (!pud_present(*pud)) {
-		VM_BUG_ON(!pud_present(*pud));
-		return 1;
-	}
 	pmd = pmd_offset(pud, addr);
-	if (!pmd_present(*pmd)) {
-		VM_BUG_ON(!pmd_present(*pmd));
-		return 1;
-	}
 	if ((pte_t *)pmd == ptep) {
 		*pgsize = PMD_SIZE;
 		return CONT_PMDS;
-- 
2.5.5

^ permalink raw reply related

* [PATCH v2 2/2] arm64: hugetlb: fix the wrong address for several functions
From: Huang Shijie @ 2016-11-08  5:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478583879-14654-1-git-send-email-shijie.huang@arm.com>

The libhugetlbfs meets several failures since the following functions
do not use the correct address:
   huge_ptep_get_and_clear()
   huge_ptep_set_access_flags()
   huge_ptep_set_wrprotect()
   huge_ptep_clear_flush()

This patch fixes the wrong address for them.

Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
 arch/arm64/mm/hugetlbpage.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index b0d3f8b..fd96ba7 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -200,7 +200,7 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
 		/* save the 1st pte to return */
 		pte = ptep_get_and_clear(mm, addr, cpte);
-		for (i = 1; i < ncontig; ++i) {
+		for (i = 1, addr += pgsize; i < ncontig; ++i, addr += pgsize) {
 			/*
 			 * If HW_AFDBM is enabled, then the HW could
 			 * turn on the dirty bit for any of the page
@@ -238,7 +238,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 		pfn = pte_pfn(*cpte);
 		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
 					  *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte) {
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
 			changed = ptep_set_access_flags(vma, addr, cpte,
 							pfn_pte(pfn,
 								hugeprot),
@@ -261,7 +261,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm,
 
 		cpte = huge_pte_offset(mm, addr);
 		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte)
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize)
 			ptep_set_wrprotect(mm, addr, cpte);
 	} else {
 		ptep_set_wrprotect(mm, addr, ptep);
@@ -279,7 +279,7 @@ void huge_ptep_clear_flush(struct vm_area_struct *vma,
 		cpte = huge_pte_offset(vma->vm_mm, addr);
 		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
 					  *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte)
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize)
 			ptep_clear_flush(vma, addr, cpte);
 	} else {
 		ptep_clear_flush(vma, addr, ptep);
-- 
2.5.5

^ permalink raw reply related

* [PATCH v2 0/3] imx: add imx6ull support
From: Peter Chen @ 2016-11-08  5:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn,

In this series, it adds support for imx6ull SoC which is a derived SoC
from imx6ul, and imx6ull is pin-to-pin compatible with imx6ul, the
basic functions are tested at imx6ull 14x14 evk, and imx6ul 14x14 evk
is tested too to avoid regression.

Changes for v2:
- Keep imx6ul.dtsi unchanging, and using GPL/X11 dual license
  for new dts file. [Patch 1/3]
- Using IMX6ULL prefix for both imx6ull dedicated pin and clock name.
  [Patch 1/3, 3/3]
- Delete useless changes for patch 2/3.
- Delete blank line for patch 3/3.
- Using assigned-clocks for imx6ull 14x14 evk. [Patch 1/3, 3/3]


Bai Ping (1):
  clk: imx: clk-imx6ul: add clk support for imx6ull

Peter Chen (2):
  ARM: imx6ull: add imx6ull support
  ARM: imx: mach-imx6ul: add imx6ull support

 arch/arm/boot/dts/Makefile               |   3 +-
 arch/arm/boot/dts/imx6u-14x14-evk.dtsi   | 487 +++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx6ul-14x14-evk.dts   | 479 +-----------------------------
 arch/arm/boot/dts/imx6ull-14x14-evk.dts  |  55 ++++
 arch/arm/boot/dts/imx6ull-pinfunc.h      |  56 ++++
 arch/arm/boot/dts/imx6ull.dtsi           |  43 +++
 arch/arm/mach-imx/mach-imx6ul.c          |   1 +
 drivers/clk/imx/clk-imx6ul.c             |  72 ++++-
 include/dt-bindings/clock/imx6ul-clock.h |  15 +-
 9 files changed, 720 insertions(+), 491 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx6u-14x14-evk.dtsi
 create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk.dts
 create mode 100644 arch/arm/boot/dts/imx6ull-pinfunc.h
 create mode 100644 arch/arm/boot/dts/imx6ull.dtsi

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 1/3] ARM: imx6ull: add imx6ull support
From: Peter Chen @ 2016-11-08  5:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478584614-12054-1-git-send-email-peter.chen@nxp.com>

It is the 10th processor in the well-known imx6 series, and derived
from imx6ul but cost optimized. The more information about imx6ull
can be found at:

http://www.nxp.com/products/microcontrollers-and-processors/
arm-processors/i.mx-applications-processors/i.mx-6-processors
/i.mx6qp/i.mx-6ull-single-core-processor-with-arm-cortex-a7-core
:i.MX6ULL

In this patch, for SoC part, the imx6ull.dtsi includes imx6ul.dtsi;
for board part (imx6ul/imx6ull 14x14 evk), it has a common board
file imx6u-14x14-evk.dtsi, and this file is included by both
imx6ul-14x14-evk.dts and imx6ull-14x14-evk.dts.

Signed-off-by: Peter Chen <peter.chen@nxp.com>
---
 arch/arm/boot/dts/Makefile              |   3 +-
 arch/arm/boot/dts/imx6u-14x14-evk.dtsi  | 487 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx6ul-14x14-evk.dts  | 479 +------------------------------
 arch/arm/boot/dts/imx6ull-14x14-evk.dts |  55 ++++
 arch/arm/boot/dts/imx6ull-pinfunc.h     |  56 ++++
 arch/arm/boot/dts/imx6ull.dtsi          |  43 +++
 6 files changed, 644 insertions(+), 479 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx6u-14x14-evk.dtsi
 create mode 100644 arch/arm/boot/dts/imx6ull-14x14-evk.dts
 create mode 100644 arch/arm/boot/dts/imx6ull-pinfunc.h
 create mode 100644 arch/arm/boot/dts/imx6ull.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index befcd26..3d6e199 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -423,7 +423,8 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
 	imx6ul-pico-hobbit.dtb \
 	imx6ul-tx6ul-0010.dtb \
 	imx6ul-tx6ul-0011.dtb \
-	imx6ul-tx6ul-mainboard.dtb
+	imx6ul-tx6ul-mainboard.dtb \
+	imx6ull-14x14-evk.dtb
 dtb-$(CONFIG_SOC_IMX7D) += \
 	imx7d-cl-som-imx7.dtb \
 	imx7d-colibri-eval-v3.dtb \
diff --git a/arch/arm/boot/dts/imx6u-14x14-evk.dtsi b/arch/arm/boot/dts/imx6u-14x14-evk.dtsi
new file mode 100644
index 0000000..c80a214
--- /dev/null
+++ b/arch/arm/boot/dts/imx6u-14x14-evk.dtsi
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory {
+		reg = <0x80000000 0x20000000>;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_sd1_vmmc: sd1_regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "VSD_3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "mx6ul-wm8960";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Speaker", "Speaker",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Speaker", "SPK_LP",
+			"Speaker", "SPK_LN",
+			"Speaker", "SPK_RP",
+			"Speaker", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"LINPUT3", "Mic Jack",
+			"RINPUT1", "Mic Jack",
+			"RINPUT2", "Mic Jack";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&codec>;
+			clocks = <&clks IMX6UL_CLK_SAI2>;
+		};
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
+};
+
+&cpu0 {
+	arm-supply = <&reg_arm>;
+	soc-supply = <&reg_soc>;
+};
+
+&i2c2 {
+	clock_frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8960 at 1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+		wlf,shared-lrclk;
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	status = "okay";
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 2 {
+			reg = <2>;
+		};
+
+		ethphy1: ethernet-phy at 1 {
+			reg = <1>;
+		};
+	};
+};
+
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif_dat
+		     &pinctrl_lcdif_ctrl>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display {
+		bits-per-pixel = <16>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+
+			timing0: timing0 {
+				clock-frequency = <9200000>;
+				hactive = <480>;
+				vactive = <272>;
+				hfront-porch = <8>;
+				hback-porch = <4>;
+				hsync-len = <41>;
+				vback-porch = <2>;
+				vfront-porch = <4>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&qspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_qspi>;
+	status = "okay";
+
+	flash0: n25q256a at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "micron,n25q256a";
+		spi-max-frequency = <29000000>;
+		reg = <0>;
+	};
+};
+
+&sai2 {
+	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+			  <&clks IMX6UL_CLK_SAI2>;
+	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>, <12288000>;
+	fsl,sai-mclk-direction-output;
+	status = "disabled";
+};
+
+&snvs_poweroff {
+	status = "okay";
+};
+
+&tsc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_tsc>;
+	xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+	measure-delay-time = <0xffff>;
+	pre-charge-time = <0xfff>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbphy1 {
+	fsl,tx-d-cal = <106>;
+};
+
+&usbphy2 {
+	fsl,tx-d-cal = <106>;
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+	keep-power-in-suspend;
+	wakeup-source;
+	vmmc-supply = <&reg_sd1_vmmc>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+
+	pinctrl_csi1: csi1grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
+			MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
+			MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
+			MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
+			MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
+			MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
+			MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
+			MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
+			MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
+			MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
+			MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
+			MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+		>;
+	};
+
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
+			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
+			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
+			MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x17059
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp{
+		fsl,pins = <
+			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
+			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp{
+		fsl,pins = <
+			MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020
+			MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+			MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
+			MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
+		>;
+	};
+
+	pinctrl_lcdif_dat: lcdifdatgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
+			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
+			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
+			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
+			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
+			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
+			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
+			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
+			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
+			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
+			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
+			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
+			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
+			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
+			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
+			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
+			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
+			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
+			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
+			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
+			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
+			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
+			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
+			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
+		>;
+	};
+
+	pinctrl_lcdif_ctrl: lcdifctrlgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
+			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
+			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
+			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
+			/* used for lcd reset */
+			MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79
+		>;
+	};
+
+	pinctrl_qspi: qspigrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK	0x70a1
+			MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00	0x70a1
+			MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01	0x70a1
+			MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02	0x70a1
+			MX6UL_PAD_NAND_CLE__QSPI_A_DATA03	0x70a1
+			MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B	0x70a1
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
+		>;
+	};
+
+	pinctrl_sim2: sim2grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD		0xb808
+			MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK		0x31
+			MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B		0xb808
+			MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN		0xb808
+			MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD		0xb809
+			MX6UL_PAD_CSI_DATA02__GPIO4_IO23		0x3008
+		>;
+	};
+
+	pinctrl_tsc: tscgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO01__GPIO1_IO01		0xb0
+			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02		0xb0
+			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03		0xb0
+			MX6UL_PAD_GPIO1_IO04__GPIO1_IO04		0xb0
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
+			MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1
+			MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD     	0x17059
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK     	0x10059
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 	0x17059
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 	0x17059
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 	0x17059
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 	0x17059
+			MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059 /* SD1 CD */
+			MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT    0x17059 /* SD1 VSELECT */
+			MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
+
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x17059
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
+		>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 1867c69..f423f0c 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -9,486 +9,9 @@
 /dts-v1/;
 
 #include "imx6ul.dtsi"
+#include "imx6u-14x14-evk.dtsi"
 
 / {
 	model = "Freescale i.MX6 UltraLite 14x14 EVK Board";
 	compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";
-
-	chosen {
-		stdout-path = &uart1;
-	};
-
-	memory {
-		reg = <0x80000000 0x20000000>;
-	};
-
-	backlight {
-		compatible = "pwm-backlight";
-		pwms = <&pwm1 0 5000000>;
-		brightness-levels = <0 4 8 16 32 64 128 255>;
-		default-brightness-level = <6>;
-		status = "okay";
-	};
-
-	regulators {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		reg_sd1_vmmc: sd1_regulator {
-			compatible = "regulator-fixed";
-			regulator-name = "VSD_3V3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-		};
-	};
-
-	sound {
-		compatible = "simple-audio-card";
-		simple-audio-card,name = "mx6ul-wm8960";
-		simple-audio-card,format = "i2s";
-		simple-audio-card,bitclock-master = <&dailink_master>;
-		simple-audio-card,frame-master = <&dailink_master>;
-		simple-audio-card,widgets =
-			"Microphone", "Mic Jack",
-			"Line", "Line In",
-			"Line", "Line Out",
-			"Speaker", "Speaker",
-			"Headphone", "Headphone Jack";
-		simple-audio-card,routing =
-			"Headphone Jack", "HP_L",
-			"Headphone Jack", "HP_R",
-			"Speaker", "SPK_LP",
-			"Speaker", "SPK_LN",
-			"Speaker", "SPK_RP",
-			"Speaker", "SPK_RN",
-			"LINPUT1", "Mic Jack",
-			"LINPUT3", "Mic Jack",
-			"RINPUT1", "Mic Jack",
-			"RINPUT2", "Mic Jack";
-
-		simple-audio-card,cpu {
-			sound-dai = <&sai2>;
-		};
-
-		dailink_master: simple-audio-card,codec {
-			sound-dai = <&codec>;
-			clocks = <&clks IMX6UL_CLK_SAI2>;
-		};
-	};
-};
-
-&clks {
-	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
-	assigned-clock-rates = <786432000>;
-};
-
-&cpu0 {
-	arm-supply = <&reg_arm>;
-	soc-supply = <&reg_soc>;
-};
-
-&i2c2 {
-	clock_frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c2>;
-	status = "okay";
-
-	codec: wm8960 at 1a {
-		#sound-dai-cells = <0>;
-		compatible = "wlf,wm8960";
-		reg = <0x1a>;
-		wlf,shared-lrclk;
-	};
-};
-
-&fec1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet1>;
-	phy-mode = "rmii";
-	phy-handle = <&ethphy0>;
-	status = "okay";
-};
-
-&fec2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet2>;
-	phy-mode = "rmii";
-	phy-handle = <&ethphy1>;
-	status = "okay";
-
-	mdio {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ethphy0: ethernet-phy at 2 {
-			reg = <2>;
-		};
-
-		ethphy1: ethernet-phy at 1 {
-			reg = <1>;
-		};
-	};
-};
-
-
-&lcdif {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_lcdif_dat
-		     &pinctrl_lcdif_ctrl>;
-	display = <&display0>;
-	status = "okay";
-
-	display0: display {
-		bits-per-pixel = <16>;
-		bus-width = <24>;
-
-		display-timings {
-			native-mode = <&timing0>;
-
-			timing0: timing0 {
-				clock-frequency = <9200000>;
-				hactive = <480>;
-				vactive = <272>;
-				hfront-porch = <8>;
-				hback-porch = <4>;
-				hsync-len = <41>;
-				vback-porch = <2>;
-				vfront-porch = <4>;
-				vsync-len = <10>;
-				hsync-active = <0>;
-				vsync-active = <0>;
-				de-active = <1>;
-				pixelclk-active = <0>;
-			};
-		};
-	};
-};
-
-&pwm1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm1>;
-	status = "okay";
-};
-
-&qspi {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_qspi>;
-	status = "okay";
-
-	flash0: n25q256a at 0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "micron,n25q256a";
-		spi-max-frequency = <29000000>;
-		reg = <0>;
-	};
-};
-
-&sai2 {
-	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
-			  <&clks IMX6UL_CLK_SAI2>;
-	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
-	assigned-clock-rates = <0>, <12288000>;
-	fsl,sai-mclk-direction-output;
-	status = "disabled";
-};
-
-&snvs_poweroff {
-	status = "okay";
-};
-
-&tsc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_tsc>;
-	xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
-	measure-delay-time = <0xffff>;
-	pre-charge-time = <0xfff>;
-	status = "okay";
-};
-
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1>;
-	status = "okay";
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	uart-has-rtscts;
-	status = "okay";
-};
-
-&usbotg1 {
-	dr_mode = "otg";
-	status = "okay";
-};
-
-&usbotg2 {
-	dr_mode = "host";
-	disable-over-current;
-	status = "okay";
-};
-
-&usbphy1 {
-	fsl,tx-d-cal = <106>;
-};
-
-&usbphy2 {
-	fsl,tx-d-cal = <106>;
-};
-
-&usdhc1 {
-	pinctrl-names = "default", "state_100mhz", "state_200mhz";
-	pinctrl-0 = <&pinctrl_usdhc1>;
-	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
-	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
-	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
-	keep-power-in-suspend;
-	wakeup-source;
-	vmmc-supply = <&reg_sd1_vmmc>;
-	status = "okay";
-};
-
-&usdhc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc2>;
-	no-1-8-v;
-	keep-power-in-suspend;
-	wakeup-source;
-	status = "okay";
-};
-
-&wdog1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_wdog>;
-	fsl,ext-reset-output;
-};
-
-&iomuxc {
-	pinctrl-names = "default";
-
-	pinctrl_csi1: csi1grp {
-		fsl,pins = <
-			MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
-			MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
-			MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
-			MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
-			MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
-			MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
-			MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
-			MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
-			MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
-			MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
-			MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
-			MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
-		>;
-	};
-
-	pinctrl_enet1: enet1grp {
-		fsl,pins = <
-			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
-			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
-			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
-			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
-			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
-			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
-			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
-			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
-		>;
-	};
-
-	pinctrl_enet2: enet2grp {
-		fsl,pins = <
-			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
-			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
-			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
-			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
-			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
-			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
-			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
-			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
-			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
-			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
-			MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x17059
-		>;
-	};
-
-	pinctrl_flexcan1: flexcan1grp{
-		fsl,pins = <
-			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
-			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
-		>;
-	};
-
-	pinctrl_flexcan2: flexcan2grp{
-		fsl,pins = <
-			MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020
-			MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020
-		>;
-	};
-
-	pinctrl_i2c1: i2c1grp {
-		fsl,pins = <
-			MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
-			MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
-		>;
-	};
-
-	pinctrl_i2c2: i2c2grp {
-		fsl,pins = <
-			MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
-			MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
-		>;
-	};
-
-	pinctrl_lcdif_dat: lcdifdatgrp {
-		fsl,pins = <
-			MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
-			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
-			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
-			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
-			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
-			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
-			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
-			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
-			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
-			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
-			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
-			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
-			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
-			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
-			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
-			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
-			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
-			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
-			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
-			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
-			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
-			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
-			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
-			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
-		>;
-	};
-
-	pinctrl_lcdif_ctrl: lcdifctrlgrp {
-		fsl,pins = <
-			MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
-			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
-			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
-			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
-			/* used for lcd reset */
-			MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79
-		>;
-	};
-
-	pinctrl_qspi: qspigrp {
-		fsl,pins = <
-			MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK	0x70a1
-			MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00	0x70a1
-			MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01	0x70a1
-			MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02	0x70a1
-			MX6UL_PAD_NAND_CLE__QSPI_A_DATA03	0x70a1
-			MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B	0x70a1
-		>;
-	};
-
-	pinctrl_pwm1: pwm1grp {
-		fsl,pins = <
-			MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
-		>;
-	};
-
-	pinctrl_sim2: sim2grp {
-		fsl,pins = <
-			MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD		0xb808
-			MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK		0x31
-			MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B		0xb808
-			MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN		0xb808
-			MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD		0xb809
-			MX6UL_PAD_CSI_DATA02__GPIO4_IO23		0x3008
-		>;
-	};
-
-	pinctrl_tsc: tscgrp {
-		fsl,pins = <
-			MX6UL_PAD_GPIO1_IO01__GPIO1_IO01		0xb0
-			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02		0xb0
-			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03		0xb0
-			MX6UL_PAD_GPIO1_IO04__GPIO1_IO04		0xb0
-		>;
-	};
-
-	pinctrl_uart1: uart1grp {
-		fsl,pins = <
-			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
-			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
-		>;
-	};
-
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
-			MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
-			MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1
-			MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1
-		>;
-	};
-
-	pinctrl_usdhc1: usdhc1grp {
-		fsl,pins = <
-			MX6UL_PAD_SD1_CMD__USDHC1_CMD     	0x17059
-			MX6UL_PAD_SD1_CLK__USDHC1_CLK     	0x10059
-			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 	0x17059
-			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 	0x17059
-			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 	0x17059
-			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 	0x17059
-			MX6UL_PAD_UART1_RTS_B__GPIO1_IO19       0x17059 /* SD1 CD */
-			MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT    0x17059 /* SD1 VSELECT */
-			MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
-		>;
-	};
-
-	pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
-		fsl,pins = <
-			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
-			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
-			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
-			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
-			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
-			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
-
-		>;
-	};
-
-	pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
-		fsl,pins = <
-			MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
-			MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
-			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
-			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
-			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
-			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
-		>;
-	};
-
-	pinctrl_usdhc2: usdhc2grp {
-		fsl,pins = <
-			MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x17059
-			MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
-			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
-			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
-			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
-			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
-		>;
-	};
-
-	pinctrl_wdog: wdoggrp {
-		fsl,pins = <
-			MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
-		>;
-	};
 };
diff --git a/arch/arm/boot/dts/imx6ull-14x14-evk.dts b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
new file mode 100644
index 0000000..992adde
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-14x14-evk.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6ull.dtsi"
+#include "imx6u-14x14-evk.dtsi"
+
+/ {
+	model = "Freescale i.MX6 UlltraLite 14x14 EVK Board";
+	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>;
+	assigned-clock-rates = <320000000>;
+};
diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h
new file mode 100644
index 0000000..580b5c3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-pinfunc.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DTS_IMX6ULL_PINFUNC_H
+#define __DTS_IMX6ULL_PINFUNC_H
+
+#include "imx6ul-pinfunc.h"
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6ULL_PAD_ENET2_RX_DATA0__EPDC_SDDO08                    0x00E4 0x0370 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_DATA1__EPDC_SDDO09                    0x00E8 0x0374 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_EN__EPDC_SDDO10                       0x00EC 0x0378 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_DATA0__EPDC_SDDO11                    0x00F0 0x037C 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_DATA1__EPDC_SDDO12                    0x00F4 0x0380 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_EN__EPDC_SDDO13                       0x00F8 0x0384 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_CLK__EPDC_SDDO14                      0x00FC 0x0388 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_ER__EPDC_SDDO15                       0x0100 0x038C 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_CLK__EPDC_SDCLK                            0x0104 0x0390 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_ENABLE__EPDC_SDLE                          0x0108 0x0394 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_HSYNC__EPDC_SDOE                           0x010C 0x0398 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_VSYNC__EPDC_SDCE0                          0x0110 0x039C 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_RESET__EPDC_GDOE                           0x0114 0x03A0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA00__EPDC_SDDO00                        0x0118 0x03A4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA01__EPDC_SDDO01                        0x011C 0x03A8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA02__EPDC_SDDO02                        0x0120 0x03AC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA03__EPDC_SDDO03                        0x0124 0x03B0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA04__EPDC_SDDO04                        0x0128 0x03B4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA05__EPDC_SDDO05                        0x012C 0x03B8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA06__EPDC_SDDO06                        0x0130 0x03BC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA07__EPDC_SDDO07                        0x0134 0x03C0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA14__EPDC_SDSHR                         0x0150 0x03DC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA15__EPDC_GDRL                          0x0154 0x03E0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA16__EPDC_GDCLK                         0x0158 0x03E4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA17__EPDC_GDSP                          0x015C 0x03E8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA21__EPDC_SDCE1                         0x016C 0x03F8 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_MCLK__ESAI_TX3_RX2                          0x01D4 0x0460 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_PIXCLK__ESAI_TX2_RX3                        0x01D8 0x0464 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_VSYNC__ESAI_TX4_RX1                         0x01DC 0x0468 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_HSYNC__ESAI_TX1                             0x01E0 0x046C 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA00__ESAI_TX_HF_CLK                      0x01E4 0x0470 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA01__ESAI_RX_HF_CLK                      0x01E8 0x0474 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA02__ESAI_RX_FS                          0x01EC 0x0478 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA03__ESAI_RX_CLK                         0x01F0 0x047C 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS                          0x01F4 0x0480 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK                         0x01F8 0x0484 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0                        0x01FC 0x0488 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA07__ESAI_T0                             0x0200 0x048C 0x0000 0x9 0x0
+
+#endif /* __DTS_IMX6ULL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
new file mode 100644
index 0000000..dee8ab8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "imx6ul.dtsi"
+#include "imx6ull-pinfunc.h"
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox