ARM: Initial support for Tegra 114 SoC
Subsystems (6)
v2 cover ARM: Initial support for Tegra 114 SoC
Hi,
This patchset adds initial support for NVIDIA's new Tegra 114 SoC (T114) based on the ARM Cortex-A15 MP. It has the minimal support to allow the kernel to boot up into shell console. This can be used as a basis for adding other device drivers for this SoC. Currently there are 2 evaluation boards available, "Dalmore" and "Pluto".
This patchset is against Stephen Warren's linux-next_common branch:
git://nv-tegra.nvidia.com/user/swarren/linux-2.6 linux-next_common
For those who want to try:
$ make ARCH=arm tegra_defconfig
$ scripts/config -e ARCH_TEGRA_114_SOC -d DRM -d SUSPEND \
-d PM_RUNTIME -d CPU_FREQ -d CPU_IDLE
$ make ARCH=arm menuconfig # if needed to configure more
$ make ARCH=arm all -j9You may also want to enable CONFIG_ARM_APPENDED_DTB and CONFIG_ARM_ATAG_DTB_COMPAT if the bootloader doesn't support DT yet.
Verified that this single image booted up with "Dalmore(T114)", "Pluto(T114)" and "Cardhu(T30)". For "Cardhu(T30)" with this single image, SPI driver doesn't seem to afford the above configuration , it hangs at boot-up. With SPI disabled, it's ok.
v2:
Rebased against the latest Stephen Warren's linux-next_common Add /cpus entry in DT
Add comment to initialize TSC only in secure mode.
Hiroshi Doyu (9):
ARM: tegra: fuse: Add chipid TEGRA114 0x35
HACK: ARM: tegra: Use CLK_IGNORE_UNUSED for Tegra 114 SoC
ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
clocksource: tegra: Reorganize funcs by clock functionarities
clocksource: tegra: Enable ARM arch_timer with TSC
ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
ARM: dt: tegra114: Add new board, Dalmore
ARM: dt: tegra114: Add new board, Pluto
ARM: tegra: Add initial support for Tegra 114 SoC.
.../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 + arch/arm/boot/dts/Makefile | 4 +- arch/arm/boot/dts/tegra114-dalmore.dts | 21 ++ arch/arm/boot/dts/tegra114-pluto.dts | 21 ++ arch/arm/boot/dts/tegra114.dtsi | 118 +++++++++++ arch/arm/mach-tegra/Kconfig | 10 + arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/board-dt-tegra114.c | 48 +++++ arch/arm/mach-tegra/common.c | 1 + arch/arm/mach-tegra/fuse.h | 1 + arch/arm/mach-tegra/platsmp.c | 31 ++- arch/arm/mach-tegra/tegra30_clocks_data.c | 2 + drivers/clocksource/tegra20_timer.c | 223 +++++++++++++------- 13 files changed, 414 insertions(+), 78 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt create mode 100644 arch/arm/boot/dts/tegra114-dalmore.dts create mode 100644 arch/arm/boot/dts/tegra114-pluto.dts create mode 100644 arch/arm/boot/dts/tegra114.dtsi create mode 100644 arch/arm/mach-tegra/board-dt-tegra114.c
Signature · 1 line
1.7.9.5
PATCH v2 1/9 ARM: tegra: fuse: Add chipid TEGRA114 0x35
Add tegra_chip_id TEGRA114 0x35
--- arch/arm/mach-tegra/fuse.h | 1 + 1 file changed, 1 insertion(+)
arch/arm/mach-tegra/fuse.h +1 -0
@@ -37,6 +37,7 @@ enum tegra_revision {#define TEGRA20 0x20#define TEGRA30 0x30 +#define TEGRA114 0x35extern int tegra_sku_id;extern int tegra_cpu_process_id;
Signature · 1 line
1.7.9.5
PATCH v2 2/9 HACK: ARM: tegra: Use CLK_IGNORE_UNUSED for Tegra 114 SoC
In reply to Hiroshi DoyuUse CLK_IGNORE_UNUSED for the Tegra 114 SoC to ensure clk_disable_unused() is not called. Otherwise the system will die, because the usecount of the clocks is incorrect. This patch will be reverted once the Tegra 114 clocks are implemented.
--- arch/arm/mach-tegra/tegra30_clocks_data.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mach-tegra/tegra30_clocks_data.c +2 -0
@@ -1384,6 +1384,8 @@ static void tegra30_init_one_clock(struct clk *c)if (!clk->lookup.dev_id && !clk->lookup.con_id) clk->lookup.con_id = c->name; clk->lookup.clk = c; +if (tegra_chip_id ==TEGRA114 )/* FIXME: Implement T114 clocks */ + c->flags |=CLK_IGNORE_UNUSED ;clkdev_add (&clk->lookup);tegra_clk_add (c); }
Signature · 1 line
1.7.9.5
PATCH v2 2/9 HACK: ARM: tegra: Use CLK_IGNORE_UNUSED for Tegra 114 SoC
arch/arm/mach-tegra/tegra30_clocks_data.c
Quoted 6 lines · Hiroshi Doyu
Use
CLK_IGNORE_UNUSEDfor the Tegra 114 SoC to ensureclk_disable_unused()is not called. Otherwise the system will die, because the usecount of the clocks is incorrect. This patch will be reverted once the Tegra 114 clocks are implemented.arch/arm/mach-tegra/tegra30_clocks_data.c +0
-0
Just as an FYI, I'll almost certainly apply Prashant's common clock conversion before this series, so this patch will need some rework to be applied on top of that.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
In reply to Hiroshi DoyuThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/platsmp.c +28 -3
@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h>
@@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0 +extern void tegra_secondary_startup (void ); -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
@@ -149,7 +154,26 @@ done:*/ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ; +case CPU_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa); + ncores =scu_get_core_count (scu_base); +break ; +default : +BUG (); +break ; + }if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
@@ -166,7 +190,8 @@ static void __init tegra_smp_init_cpus(void)static void __init tegra_smp_prepare_cpus (unsigned int max_cpus) {tegra_cpu_reset_handler_init (); -scu_enable (scu_base); +if (scu_base) +scu_enable (scu_base); }struct smp_operations tegra_smp_ops__initdata = {
Signature · 1 line
1.7.9.5
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 25 lines · Hiroshi Doyu
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +1
-0@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h>
arch/arm/mach-tegra/platsmp.c line 40
Quoted 6 lines
arch/arm/mach-tegra/platsmp.c +3
-0@@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0
NAK. There's some patches around to make this stuff generic, we don't need more ifdefs springing up. We need to get those generic patches in.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Russell King - ARM Linux <[email protected]> wrote @ Tue, 8 Jan 2013 15:26:51 +0100:
Quoted 29 lines · Hiroshi Doyu
Quoted 28 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +1
-0@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> @@ -34,9 +35,13 @@#include "common.h" #include "iomap.h"
Quoted 7 lines
arch/arm/mach-tegra/platsmp.c line 40
Quoted 3 lines
arch/arm/mach-tegra/platsmp.c +3
-0+#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0NAK. There's some patches around to make this stuff generic, we don't need more ifdefs springing up. We need to get those generic patches in.
Does anyone give some pointers to the above patches?
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 39 lines · Hiroshi Doyu
Russell King - ARM Linux <[email protected]> wrote @ Tue, 8 Jan 2013 15:26:51 +0100:
Quoted 29 lines · Hiroshi Doyu
Quoted 28 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +1
-0@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> @@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" Quoted 7 lines
arch/arm/mach-tegra/platsmp.c line 40
Quoted 3 lines
arch/arm/mach-tegra/platsmp.c +3
-0+#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0NAK. There's some patches around to make this stuff generic, we don't need more ifdefs springing up. We need to get those generic patches in.
Quoted 1 line
Does anyone give some pointers to the above patches?
Hi Hiroshi,
Please check "arch/arm/include/asm/cputype.h" in next-20130109. It just be merged.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Hi Joseph,
Joseph Lo <[email protected]> wrote @ Wed, 9 Jan 2013 07:07:41 +0100:
Quoted 40 lines · Hiroshi Doyu
Quoted 39 lines
Russell King - ARM Linux <[email protected]> wrote @ Tue, 8 Jan 2013 15:26:51 +0100:
Quoted 36 lines · Hiroshi Doyu
Quoted 25 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +1
-0@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> arch/arm/mach-tegra/platsmp.c line 40
Quoted 6 lines
arch/arm/mach-tegra/platsmp.c +3
-0@@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0NAK. There's some patches around to make this stuff generic, we don't need more ifdefs springing up. We need to get those generic patches in.
Quoted 6 lines
Quoted 1 line
Does anyone give some pointers to the above patches?
Hi Hiroshi,
Please check "
arch/arm/include/asm/cputype.h" in next-20130109. It just be merged.
I found the following commit. Thanks.
commit cd8dde6fc347b56b6cb9afa7cc0f9073da163176
Author: Christoffer Dall <[email protected]> Date: Tue Dec 18 04:06:37 2012 +0000
ARM: Define CPU part numbers and implementors
Define implementor IDs, part numbers and Xscale architecture versions in cputype.h. Also create accessor functions for reading the implementor, part number, and Xscale architecture versions from the CPUID regiser.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
In reply to Hiroshi DoyuHello,
Quoted 44 lines · Hiroshi Doyu
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +6
-2@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> @@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0 +extern void tegra_secondary_startup (void ); -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)@@ -149,7 +154,26 @@ done:*/ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base);
arch/arm/mach-tegra/platsmp.c done: · line 166
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;
[...]
As mentioned last time [1], you should get this information from the dt instead.
Thanks,
Mark.
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/138319.html
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Hi Mark,
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 60 lines
Hello,
Quoted 54 lines · Hiroshi Doyu
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +16
-2@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> @@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0 +extern void tegra_secondary_startup (void ); -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)@@ -149,7 +154,26 @@ done:*/ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 64 lines · Hiroshi Doyu
Hi Mark,
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 60 lines
Hello,
Quoted 54 lines · Hiroshi Doyu
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)arch/arm/mach-tegra/platsmp.c +16
-2@@ -23,6 +23,7 @@#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> +#include <asm/cputype.h> #include <mach/powergate.h> @@ -34,9 +35,13 @@#include "common.h" #include "iomap.h" +#define CPU_MASK 0xff0ffff0 +#define CPU_CORTEX_A9 0x410fc090 +#define CPU_CORTEX_A15 0x410fc0f0 +extern void tegra_secondary_startup (void ); -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)@@ -149,7 +154,26 @@ done:*/ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 6 lines
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
As far as I can see, there's no other platform which just relies on arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need your smp_init_cpus to call set_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled by arm_dt_init_cpus.
I think the best option would be to have a separate smp_ops for your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), where smp_init_cpus is different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.
Maybe someone else has a better idea?
Thanks,
Mark.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 1 line · Mark Rutland
On Tue, Jan 08, 2013 at 02:53:42PM +0000, Hiroshi Doyu wrote:
[...]
Quoted 29 lines
Quoted 16 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c +10
-1-unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 6 lines
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.
Quoted 7 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Maybe someone else has a better idea?
Have a look at mach-vexpress/platsmp.c (keeping in mind that the GENERIC_SCU case will be refactored/removed since arm_dt_init_cpu_maps() is doing most of the required steps), please let me know what you think.
Thanks,
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Hi Lorenzo,
Lorenzo Pieralisi <[email protected]> wrote @ Tue, 8 Jan 2013 18:11:03 +0100:
Quoted 40 lines · Mark Rutland
Quoted 1 line · Hiroshi Doyu
[...]
Quoted 35 lines
Quoted 16 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 6 lines
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.
Quoted 5 lines
Quoted 1 line
Maybe someone else has a better idea?
Have a look at
mach-vexpress/platsmp.c(keeping in mind that theGENERIC_SCUcase will be refactored/removed sincearm_dt_init_cpu_maps()is doing most of the required steps), please let me know what you think.
In tegra, we don't support non-DT. What about falling back SCU/MRC based detection only when arm_dt_init_cpu_maps() fails?
arch/arm/mach-tegra/platsmp.c +7 -1
@@ -152,7 +152,7 @@ done:* Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ -static void __init tegra_smp_init_cpus (void ) +static void __init tegra_smp_detect_cores (void ) {unsigned int i, cpu_id, ncores;u32 l2ctlr;
@@ -183,6 +183,12 @@ static void __init tegra_smp_init_cpus(void)for (i =0 ; i < ncores; i++)set_cpu_possible (i, true); +} + +static void __init tegra_smp_init_cpus (void ) +{ +if (!num_possible_cpus ()) +tegra_smp_detect_cores ();set_smp_cross_call (gic_raise_softirq); }
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 67 lines · Hiroshi Doyu
Hi Lorenzo,
Lorenzo Pieralisi <[email protected]> wrote @ Tue, 8 Jan 2013 18:11:03 +0100:
Quoted 40 lines · Mark Rutland
Quoted 1 line · Hiroshi Doyu
[...]
Quoted 35 lines
Quoted 16 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 6 lines
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Quoted 5 lines
Quoted 1 line
Maybe someone else has a better idea?
Have a look at
mach-vexpress/platsmp.c(keeping in mind that theGENERIC_SCUcase will be refactored/removed sincearm_dt_init_cpu_maps()is doing most of the required steps), please let me know what you think.In tegra, we don't support non-DT. What about falling back SCU/MRC based detection only when
arm_dt_init_cpu_maps()fails?arch/arm/mach-tegra/platsmp.c +1
-1@@ -152,7 +152,7 @@ done:* Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ -static void __init tegra_smp_init_cpus (void ) +static void __init tegra_smp_detect_cores (void ) {unsigned int i, cpu_id, ncores;u32 l2ctlr;
arch/arm/mach-tegra/platsmp.c static void __init tegra_smp_init_cpus(void) · line 191
Quoted 9 lines
arch/arm/mach-tegra/platsmp.c +6
-0@@ -183,6 +183,12 @@ static void __init tegra_smp_init_cpus(void)for (i =0 ; i < ncores; i++)set_cpu_possible (i, true); +} + +static void __init tegra_smp_init_cpus (void ) +{ +if (!num_possible_cpus ()) +tegra_smp_detect_cores ();
Thought about this, I would prefer writing an inline function that provides this information (DT missing /cpu information or parsing failure) instead of relying on num_possible_cpus to be == 0 as a way to check that.
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
....
Quoted 15 lines
Quoted 15 lines
arch/arm/mach-tegra/platsmp.c +1
-1@@ -152,7 +152,7 @@ done:* Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ -static void __init tegra_smp_init_cpus (void ) +static void __init tegra_smp_detect_cores (void ) {unsigned int i, cpu_id, ncores;u32 l2ctlr;@@ -183,6 +183,12 @@ static void __init tegra_smp_init_cpus(void)
Quoted 12 lines
arch/arm/mach-tegra/platsmp.c static void __init tegra_smp_init_cpus(void) · line 191
Quoted 8 lines
arch/arm/mach-tegra/platsmp.c +6
-0for (i =0 ; i < ncores; i++)set_cpu_possible (i, true); +} + +static void __init tegra_smp_init_cpus (void ) +{ +if (!num_possible_cpus ()) +tegra_smp_detect_cores ();Thought about this, I would prefer writing an inline function that provides this information (DT missing /cpu information or parsing failure) instead of relying on
num_possible_cpusto be == 0 as a way to check that.
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?
Quoted 1 line
From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCU
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
--- arch/arm/mach-tegra/platsmp.c | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-)
arch/arm/mach-tegra/platsmp.c +43 -11
@@ -24,6 +24,8 @@#include <asm/mach-types.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> +#include <asm/cputype.h> +#include <asm/prom.h> #include <mach/powergate.h>
@@ -38,7 +40,7 @@extern void tegra_secondary_startup (void );static cpumask_t tegra_cpu_init_mask; -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
@@ -177,23 +179,52 @@ done:return status; } +static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ; +case ARM_CPU_PART_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa); + ncores =scu_get_core_count (scu_base); +break ; +default : +pr_warn ("Unsupported mpidr\n" ); + ncores =1 ; +break ; + } + +return ncores; +} +/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base); - -if (ncores > nr_cpu_ids) { -pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; +if (!arm_dt_cpu_map_valid ()) { +unsigned int i, ncores; + + ncores =smp_detect_ncores (); +if (ncores > nr_cpu_ids) { +pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } +for (i =0 ; i < ncores; i++) +set_cpu_possible (i, true); } -for (i =0 ; i < ncores; i++) -set_cpu_possible (i, true); -set_smp_cross_call (gic_raise_softirq); }
@@ -202,7 +233,8 @@ static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)/* Always mark the boot CPU (CPU0) as initialized. */ cpumask_set_cpu (0 , &tegra_cpu_init_mask); -scu_enable (scu_base); +if (scu_base) +scu_enable (scu_base); }struct smp_operations tegra_smp_ops__initdata = {
Signature · 1 line
1.7.9.5
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 32 lines · Hiroshi Doyu
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
....
Quoted 15 lines
Quoted 15 lines
arch/arm/mach-tegra/platsmp.c +1
-1@@ -152,7 +152,7 @@ done:* Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ -static void __init tegra_smp_init_cpus (void ) +static void __init tegra_smp_detect_cores (void ) {unsigned int i, cpu_id, ncores;u32 l2ctlr;@@ -183,6 +183,12 @@ static void __init tegra_smp_init_cpus(void)Quoted 12 lines
arch/arm/mach-tegra/platsmp.c static void __init tegra_smp_init_cpus(void) · line 191
Quoted 8 lines
arch/arm/mach-tegra/platsmp.c +6
-0for (i =0 ; i < ncores; i++)set_cpu_possible (i, true); +} + +static void __init tegra_smp_init_cpus (void ) +{ +if (!num_possible_cpus ()) +tegra_smp_detect_cores ();Thought about this, I would prefer writing an inline function that provides this information (DT missing /cpu information or parsing failure) instead of relying on
num_possible_cpusto be == 0 as a way to check that.
Quoted 4 lines
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "
smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?
Possibly, but I have still some comments to add.
Quoted 47 lines
From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCUThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-)arch/arm/mach-tegra/platsmp.c +5
-1@@ -24,6 +24,8 @@#include <asm/mach-types.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> +#include <asm/cputype.h> +#include <asm/prom.h> #include <mach/powergate.h> @@ -38,7 +40,7 @@extern void tegra_secondary_startup (void );static cpumask_t tegra_cpu_init_mask; -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)@@ -177,23 +179,52 @@ done:return status; } +static int __init smp_detect_ncores (void ) +{
arch/arm/mach-tegra/platsmp.c done: · line 193
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;
I do not want to see the case above merged. We keep the existing legacy methods there for legacy reasons and as a fall-back mechanism but I am not keen on adding new HW probing code to detect the number of cores.
Quoted 1 line
From A15/A7 onwards DT-only cpu map initialization is the way to go.
Lorenzo
Quoted 62 lines
arch/arm/mach-tegra/platsmp.c +28
-10+case ARM_CPU_PART_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa); + ncores =scu_get_core_count (scu_base); +break ; +default : +pr_warn ("Unsupported mpidr\n" ); + ncores =1 ; +break ; + } + +return ncores; +} +/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init tegra_smp_init_cpus (void ) { -unsigned int i, ncores =scu_get_core_count (scu_base); - -if (ncores > nr_cpu_ids) { -pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; +if (!arm_dt_cpu_map_valid ()) { +unsigned int i, ncores; + + ncores =smp_detect_ncores (); +if (ncores > nr_cpu_ids) { +pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } +for (i =0 ; i < ncores; i++) +set_cpu_possible (i, true); } -for (i =0 ; i < ncores; i++) -set_cpu_possible (i, true); -set_smp_cross_call (gic_raise_softirq); }@@ -202,7 +233,8 @@ static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)/* Always mark the boot CPU (CPU0) as initialized. */ cpumask_set_cpu (0 , &tegra_cpu_init_mask); -scu_enable (scu_base); +if (scu_base) +scu_enable (scu_base); }struct smp_operations tegra_smp_ops__initdata = {Signature · 1 line
1.7.9.5
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Lorenzo Pieralisi <[email protected]> wrote @ Thu, 10 Jan 2013 14:47:23 +0100:
Quoted 102 lines · Hiroshi Doyu
Quoted 32 lines
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
....
Quoted 15 lines
Quoted 15 lines
arch/arm/mach-tegra/platsmp.c +1
-1@@ -152,7 +152,7 @@ done:* Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ -static void __init tegra_smp_init_cpus (void ) +static void __init tegra_smp_detect_cores (void ) {unsigned int i, cpu_id, ncores;u32 l2ctlr;@@ -183,6 +183,12 @@ static void __init tegra_smp_init_cpus(void)Quoted 12 lines
arch/arm/mach-tegra/platsmp.c static void __init tegra_smp_init_cpus(void) · line 191
Quoted 8 lines
arch/arm/mach-tegra/platsmp.c +6
-0for (i =0 ; i < ncores; i++)set_cpu_possible (i, true); +} + +static void __init tegra_smp_init_cpus (void ) +{ +if (!num_possible_cpus ()) +tegra_smp_detect_cores ();Thought about this, I would prefer writing an inline function that provides this information (DT missing /cpu information or parsing failure) instead of relying on
num_possible_cpusto be == 0 as a way to check that.Quoted 4 lines
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "
smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?Possibly, but I have still some comments to add.
Quoted 47 lines
From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCUThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
Signed-off-by Hiroshi Doyu <[email protected]>--- arch/arm/mach-tegra/platsmp.c | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-)arch/arm/mach-tegra/platsmp.c +5
-1@@ -24,6 +24,8 @@#include <asm/mach-types.h> #include <asm/smp_scu.h> #include <asm/smp_plat.h> +#include <asm/cputype.h> +#include <asm/prom.h> #include <mach/powergate.h> @@ -38,7 +40,7 @@extern void tegra_secondary_startup (void );static cpumask_t tegra_cpu_init_mask; -static void __iomem *scu_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ); +static void __iomem *scu_base;#define EVP_CPU_RESET_VECTOR \ (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)@@ -177,23 +179,52 @@ done:return status; } +static int __init smp_detect_ncores (void ) +{arch/arm/mach-tegra/platsmp.c done: · line 193
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;I do not want to see the case above merged. We keep the existing legacy methods there for legacy reasons and as a fall-back mechanism but I am not keen on adding new HW probing code to detect the number of cores.
Quoted 1 line
From A15/A7 onwards DT-only cpu map initialization is the way to go.
Ok, then, smp_detect_ncores(void) could be...
static int __init smp_detect_ncores(void)
{
unsigned int ncores, mpidr;
phys_addr_t pa;
mpidr = read_cpuid_mpidr();
switch (mpidr) {
case ARM_CPU_PART_CORTEX_A9:
/* Get SCU physical base */
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
scu_base = IO_ADDRESS(pa);
ncores = scu_get_core_count(scu_base);
break;
case ARM_CPU_PART_CORTEX_A15:
default:
pr_warn("Unsupported MPIDR %x\n", mpidr);
ncores = 1;
break;
}
return ncores;
}PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 1 line · Hiroshi Doyu
Lorenzo Pieralisi <[email protected]> wrote @ Thu, 10 Jan 2013 14:47:23 +0100:
[...]
Quoted 19 lines
Quoted 17 lines
arch/arm/mach-tegra/platsmp.c done: · line 193
Quoted 12 lines
arch/arm/mach-tegra/platsmp.c +12
-0+static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;I do not want to see the case above merged. We keep the existing legacy methods there for legacy reasons and as a fall-back mechanism but I am not keen on adding new HW probing code to detect the number of cores.
Quoted 1 line
From A15/A7 onwards DT-only cpu map initialization is the way to go.
Quoted 8 lines
Ok, then,
smp_detect_ncores(void)could be...static int
__initsmp_detect_ncores(void){ unsigned int ncores, mpidr; phys_addr_t pa; mpidr = read_cpuid_mpidr();
Careful, MPIDR is not at all what you want. MIDR is.
Quoted 8 lines
switch (mpidr) {
case ARM_CPU_PART_CORTEX_A9:
/* Get SCU physical base */
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
scu_base = IO_ADDRESS(pa);
ncores = scu_get_core_count(scu_base);
break;
case ARM_CPU_PART_CORTEX_A15:Remove the ARM_CPU_PART_CORTEX_A15 case, I do not see how it helps.
And be careful with the case matching, if I am not mistaken read_cpuid_id() (which is the function you have to use) will return the full MIDR, you need to mask the return value.
Quoted 4 lines
default:
pr_warn("Unsupported MPIDR %x\n", mpidr);
ncores = 1;
break;This is reasonable.
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Lorenzo Pieralisi <[email protected]> wrote @ Thu, 10 Jan 2013 15:33:34 +0100:
Quoted 44 lines · Hiroshi Doyu
Quoted 1 line
Lorenzo Pieralisi <[email protected]> wrote @ Thu, 10 Jan 2013 14:47:23 +0100:
[...]
Quoted 19 lines
Quoted 17 lines
arch/arm/mach-tegra/platsmp.c done: · line 193
Quoted 12 lines
arch/arm/mach-tegra/platsmp.c +12
-0+static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;I do not want to see the case above merged. We keep the existing legacy methods there for legacy reasons and as a fall-back mechanism but I am not keen on adding new HW probing code to detect the number of cores.
Quoted 1 line
From A15/A7 onwards DT-only cpu map initialization is the way to go.
Quoted 8 lines
Ok, then,
smp_detect_ncores(void)could be...static int
__initsmp_detect_ncores(void){ unsigned int ncores, mpidr; phys_addr_t pa; mpidr = read_cpuid_mpidr();Careful, MPIDR is not at all what you want. MIDR is.
Quoted 8 lines
switch (mpidr) { case ARM_CPU_PART_CORTEX_A9: /* Get SCU physical base */ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa)); scu_base = IO_ADDRESS(pa); ncores = scu_get_core_count(scu_base); break; case ARM_CPU_PART_CORTEX_A15:
Quoted 5 lines
Remove the
ARM_CPU_PART_CORTEX_A15case, I do not see how it helps.And be careful with the case matching, if I am not mistaken
read_cpuid_id()(which is the function you have to use) will return the full MIDR, you need to mask the return value.
Oops, I'll fix.
Quoted 6 lines
Quoted 4 lines
default: pr_warn("Unsupported MPIDR %x\n", mpidr); ncores = 1; break;This is reasonable.
Ok, thank you for your reivew, I'll keep this func, "smp_detect_ncores()" in this file since it's mostly for the backward compatibility. Not necessary to be relocated in common place newly..
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
In reply to Hiroshi DoyuQuoted 1 line · Hiroshi Doyu
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
...
Quoted 36 lines
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "
smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCUThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
arch/arm/mach-tegra/platsmp.c +16
-0+static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ; +case ARM_CPU_PART_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa);
arch/arm/mach-tegra/platsmp.c done: · line 207
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+ ncores =scu_get_core_count (scu_base); +break ; +default : +pr_warn ("Unsupported mpidr\n" ); + ncores =1 ; +break ; + } + +return ncores; +}
Why not just remove that function...
Quoted 6 lines
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system. */
static void__inittegra_smp_init_cpus(void)
{
arch/arm/mach-tegra/platsmp.c done: · line 218
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +4
-6-unsigned int i, ncores =scu_get_core_count (scu_base); - -if (ncores > nr_cpu_ids) { -pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; +if (!arm_dt_cpu_map_valid ()) { +unsigned int i, ncores; + + ncores =smp_detect_ncores ();
And just say "ncores = 1" here?
For Tegra, it's trivial to simply put the patch adding the required DT nodes before this patch, and then there's no need for any backwards-compatibility, since the nodes are guaranteed to be there.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 71 lines · Stephen Warren
Quoted 1 line · Hiroshi Doyu
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
...
Quoted 36 lines
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "
smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCUThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
arch/arm/mach-tegra/platsmp.c +16
-0+static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ; +case ARM_CPU_PART_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa);arch/arm/mach-tegra/platsmp.c done: · line 207
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+ ncores =scu_get_core_count (scu_base); +break ; +default : +pr_warn ("Unsupported mpidr\n" ); + ncores =1 ; +break ; + } + +return ncores; +}Why not just remove that function...
Quoted 6 lines
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system. */
static void__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c done: · line 218
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +4
-6-unsigned int i, ncores =scu_get_core_count (scu_base); - -if (ncores > nr_cpu_ids) { -pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; +if (!arm_dt_cpu_map_valid ()) { +unsigned int i, ncores; + + ncores =smp_detect_ncores ();And just say "ncores = 1" here?
Quoted 3 lines
For Tegra, it's trivial to simply put the patch adding the required DT nodes before this patch, and then there's no need for any backwards-compatibility, since the nodes are guaranteed to be there.
If you are willing to accept that your code proposal is perfectly fine by me.
Thanks,
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Lorenzo Pieralisi <[email protected]> wrote @ Fri, 11 Jan 2013 11:11:34 +0100:
Quoted 72 lines · Stephen Warren
Quoted 71 lines · Hiroshi Doyu
Quoted 1 line
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 16:17:00 +0100:
...
Quoted 36 lines
With your "[PATCH] ARM: kernel: DT cpu map validity check helper function", my original patch gets as below. I think that the following "
smp_detect_ncores()" function may be so generic that it could be moved in some common place than platform?From
f5f2a43952ce75fe061b3808b994c3ceb07f1af1Mon Sep 17 00:00:00 2001
From: Hiroshi Doyu <[email protected]>
Date: Mon, 26 Nov 2012 12:25:14 +0200
Subject: [PATCH 1/1] ARM: tegra: # of CPU cores detection w/ & w/o
HAVE_ARM_SCUThe method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
arch/arm/mach-tegra/platsmp.c +16
-0+static int __init smp_detect_ncores (void ) +{ +unsigned int ncores, mpidr; +u32 l2ctlr; +phys_addr_t pa; + + mpidr =read_cpuid_mpidr (); +switch (mpidr) { +case ARM_CPU_PART_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ; +case ARM_CPU_PART_CORTEX_A9 : +/* Get SCU physical base */ + asm("mrc p15, 4, %0, c15, c0, 0" :"=r" (pa)); + scu_base =IO_ADDRESS (pa);arch/arm/mach-tegra/platsmp.c done: · line 207
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+ ncores =scu_get_core_count (scu_base); +break ; +default : +pr_warn ("Unsupported mpidr\n" ); + ncores =1 ; +break ; + } + +return ncores; +}Why not just remove that function...
Quoted 6 lines
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system. */
static void__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c done: · line 218
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +4
-6-unsigned int i, ncores =scu_get_core_count (scu_base); - -if (ncores > nr_cpu_ids) { -pr_warn ("SMP: %u cores greater than maximum (%u), clipping\n" , - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; +if (!arm_dt_cpu_map_valid ()) { +unsigned int i, ncores; + + ncores =smp_detect_ncores ();And just say "ncores = 1" here?
Quoted 5 lines
Quoted 3 lines
For Tegra, it's trivial to simply put the patch adding the required DT nodes before this patch, and then there's no need for any backwards-compatibility, since the nodes are guaranteed to be there.
If you are willing to accept that your code proposal is perfectly fine by me.
That's simple. I'll send ones to add cpu nodes, and then this without detection.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
In reply to Mark RutlandQuoted 9 lines · Mark Rutland
Quoted 8 lines · Hiroshi Doyu
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 29 lines
Quoted 16 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c +10
-1-unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 6 lines
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.
Quoted 5 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.
Tegra doesn't have any non-DT support now.
If we're going to make Tegra114 read the CPU information from DT, then I'd rather just switch over all Tegra platforms to requiring CPU nodes in the DT. We have few enough SoC variants that it should be easy to switch everything to DT before adding Tegra114 support without causing any problems.
But that all said, I'm not convinced it's a good idea to force the information to be present in DT when it's just duplicating stuff that can be runtime-probed from the HW...
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c +10
-1-unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.
True.
Quoted 8 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Tegra doesn't have any non-DT support now.
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can arm_dt_init_cpu_maps() return if it suceeds or not?
Quoted 6 lines
If we're going to make Tegra114 read the CPU information from DT, then I'd rather just switch over all Tegra platforms to requiring CPU nodes in the DT. We have few enough SoC variants that it should be easy to switch everything to DT before adding Tegra114 support without causing any problems.
Possible.
Quoted 3 lines
But that all said, I'm not convinced it's a good idea to force the information to be present in DT when it's just duplicating stuff that can be runtime-probed from the HW...
That's also my concern somewhat.
The main purpose to DT CPU core detection is for multiple CPU clusters. SCU/MRC cannot know anything outside of their own clusters. In tegra, we have 4 Cortex-A9/A15 core plus 1 shadow core. Switching those clusters is done transparently. The last A9/A15 core is transparently switched back and forth to the shadow one. So in this case, SCU/MRC detection seems to work fine.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 53 lines · Hiroshi Doyu
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{arch/arm/mach-tegra/platsmp.c +10
-1-unsigned int i, ncores =scu_get_core_count (scu_base); +unsigned int i, cpu_id, ncores; +u32 l2ctlr; +phys_addr_t pa; + + cpu_id =read_cpuid (CPUID_ID ) &CPU_MASK ; +switch (cpu_id) { +case CPU_CORTEX_A15 : + asm("mrc p15, 1, %0, c9, c0, 2\n" :"=r" (l2ctlr)); + ncores = ((l2ctlr >>24 ) &3 ) +1 ; +break ;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.True.
Quoted 7 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.
Quoted 6 lines
Quoted 1 line
Tegra doesn't have any non-DT support now.
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can
arm_dt_init_cpu_maps()return if it suceeds or not?
I think the best solution to this problem consists in /me adding a function, say, arm_dt_nb_cores(), that returns an error if DT probing failed and the number of cores if it succeeded.
If it fails, you can fall back to SCU detection of cores for legacy reasons (A9), but from A15 onwards I have quite a strong feeling against using L2 as number of cores detection mechanism since it does not work for multi-cluster systems. Fair enough, on Tegra this is not a problem (now) but I do not want this method to propagate to other platforms where multi-cluster number of cores detection will fail if we rely on the L2 mechanism.
This means that if the DT /cpu nodes are updated for all Tegra platforms, DT becomes the mechanism to detect the number of cores for all of them.
If you allow the A9 SCU mechanism to override the DT information (even if it is correct) we might end up in the rather unwieldy situation where there is a disconnect between the cpu_logical_map initialized entries and the HW probed number of cores (if the DT bindings are correct the cpu_logical_map entries are initialized by DT).
The gist is:
- if DT /cpu nodes are there and defined properly, we build the cpu_logical_map and count the number of cores from DT
- if DT /cpu nodes are missing or bogus we rely on the cpu_logical_map in smp_setup_processor_id() and fall back to legacy mechanism to detect the number of cores. This just for legacy boards/SoC.
Let me know if this is reasonable please.
Quoted 14 lines
Quoted 7 lines
If we're going to make Tegra114 read the CPU information from DT, then I'd rather just switch over all Tegra platforms to requiring CPU nodes in the DT. We have few enough SoC variants that it should be easy to switch everything to DT before adding Tegra114 support without causing any problems.
Possible.
Quoted 3 lines
But that all said, I'm not convinced it's a good idea to force the information to be present in DT when it's just duplicating stuff that can be runtime-probed from the HW...
Quoted 8 lines
That's also my concern somewhat.
The main purpose to DT CPU core detection is for multiple CPU clusters. SCU/MRC cannot know anything outside of their own clusters. In tegra, we have 4 Cortex-A9/A15 core plus 1 shadow core. Switching those clusters is done transparently. The last A9/A15 core is transparently switched back and forth to the shadow one. So in this case, SCU/MRC detection seems to work fine.
You can probe the number of cores through SCU but remember
that MPIDRs of existing CPUs are generated, not probed if the DT is not present (smp_setup_processor_id()). cpu_logical_map content, before the DT bindings were introduced, or even now if DT /cpu nodes are bogus, is simply generated as a sequential number but is not *probeable* per-se. To tell the truth, this works well for all existing ARM platforms in the mainline but moving forward we'd better stick at bits of information provided by the DT, at least that's my opinion.
Thoughts ?
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 56 lines · Lorenzo Pieralisi
Quoted 55 lines · Hiroshi Doyu
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.True.
Quoted 8 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Tegra doesn't have any non-DT support now.
Quoted 8 lines
Quoted 4 lines
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can
arm_dt_init_cpu_maps()return if it suceeds or not?I think the best solution to this problem consists in /me adding a function, say,
arm_dt_nb_cores(), that returns an error if DT probing failed and the number of cores if it succeeded.
Well, if the primary mechanism needs to be DT-based going forward, I'd say just require the DT nodes to be present to use the new function, and outright fail if they aren't. That way, everything always works one way. It shouldn't be hard to add the CPU nodes for Tegra, right?
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 62 lines · Stephen Warren
Quoted 61 lines · Lorenzo Pieralisi
Quoted 59 lines · Hiroshi Doyu
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.True.
Quoted 8 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Tegra doesn't have any non-DT support now.
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can
arm_dt_init_cpu_maps()return if it suceeds or not?
Quoted 8 lines
Quoted 3 lines
I think the best solution to this problem consists in /me adding a function, say,
arm_dt_nb_cores(), that returns an error if DT probing failed and the number of cores if it succeeded.Well, if the primary mechanism needs to be DT-based going forward, I'd say just require the DT nodes to be present to use the new function, and outright fail if they aren't. That way, everything always works one way. It shouldn't be hard to add the CPU nodes for Tegra, right?
Adding /cpu nodes to DT is trivial, but I would like to keep a fall back mechanism in place for existing platforms to carry out the transition as smoothly as possible (eg people using new kernels with old DTS).
/cpu nodes will have priority over HW based probing for cores counting.
As discussed with Hiroshi I will post a patch to provide platforms with a DT cpu map validity check so that the fall back mechanism can be triggered properly.
Thank you very much,
Lorenzo
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 19:07:13 +0100:
Quoted 76 lines · Stephen Warren
Quoted 62 lines · Lorenzo Pieralisi
Quoted 61 lines · Hiroshi Doyu
Quoted 59 lines
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.True.
Quoted 8 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Tegra doesn't have any non-DT support now.
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can
arm_dt_init_cpu_maps()return if it suceeds or not?Quoted 8 lines
Quoted 3 lines
I think the best solution to this problem consists in /me adding a function, say,
arm_dt_nb_cores(), that returns an error if DT probing failed and the number of cores if it succeeded.Well, if the primary mechanism needs to be DT-based going forward, I'd say just require the DT nodes to be present to use the new function, and outright fail if they aren't. That way, everything always works one way. It shouldn't be hard to add the CPU nodes for Tegra, right?
Adding /cpu nodes to DT is trivial, but I would like to keep a fall back mechanism in place for existing platforms to carry out the transition as smoothly as possible (eg people using new kernels with old DTS).
Quoted 5 lines
/cpu nodes will have priority over HW based probing for cores counting.
As discussed with Hiroshi I will post a patch to provide platforms with a DT cpu map validity check so that the fall back mechanism can be triggered properly.
I'll add /cpu nodes for all tegra, anyway.
Until your patch comes, I'll make a code just consider a single core if DT fails at first. So T114 initial support patch could be merged as well.
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
In reply to Lorenzo PieralisiLorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 12:34:32 +0100:
Quoted 85 lines · Hiroshi Doyu
Quoted 53 lines
Hi,
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 20:32:32 +0100:
Quoted 34 lines · Mark Rutland
Quoted 9 lines · Hiroshi Doyu
Quoted 8 lines
Mark Rutland <[email protected]> wrote @ Tue, 8 Jan 2013 15:28:28 +0100:
Quoted 7 lines · Hiroshi Doyu
Quoted 6 lines
The method to detect the number of CPU cores on Cortex-A9 MPCore and Cortex-A15 MPCore is different. On Cortex-A9 MPCore we can get this information from the Snoop Control Unit(SCU). On Cortex-A15 MPCore we have to read it from the system coprocessor(CP15), because the SCU on Cortex-A15 MPCore does not have software readable registers. This patch selects the correct method at runtime based on the CPU ID.
...
Quoted 23 lines
Quoted 22 lines
Quoted 16 lines
Quoted 13 lines
static void
__inittegra_smp_init_cpus(void)
{(quoted diff) +10
-1- unsigned int i, ncores = scu_get_core_count(scu_base); + unsigned int i, cpu_id, ncores; + u32 l2ctlr; + phys_addr_t pa; + + cpu_id = read_cpuid(CPUID_ID) & CPU_MASK; + switch (cpu_id) { + case CPU_CORTEX_A15: + asm("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); + ncores = ((l2ctlr >> 24) & 3) + 1; + break;[...]
Quoted 2 lines
As mentioned last time [1], you should get this information from the dt instead.
Most of platsmp.c:.smp_init_cpus() implementations seem just to overwrite # of cores by SCU/MRC detection. Is there any implementation to use the DT's # and skip SCU/MRC detection in .smp_init_cpus()?
Quoted 5 lines
Quoted 5 lines
As far as I can see, there's no other platform which just relies on
arm_dt_init_cpu_maps. Until recently, it didn't exist, so that makes some sense. As far as I can see, for the Tegra 114 you only need yoursmp_init_cpusto callset_smp_cross_call(gic_raise_softirq). Everything else you do seems to be handled byarm_dt_init_cpus.True.
Quoted 7 lines
Quoted 6 lines
I think the best option would be to have a separate
smp_opsfor your dt platforms where we know cpu nodes are populated (e.g. Tegra 114), wheresmp_init_cpusis different to that for non-dt platforms. That way non dt platforms can keep the SCU hack for now, and won't be broken, and the dt platforms are far removed from the SCU hack and just use common infrastructure.Quoted 6 lines
Quoted 1 line
Tegra doesn't have any non-DT support now.
What about falling down to SCU/MRC hack only when DT detection fails or no /cpus entry in DT?
Can
arm_dt_init_cpu_maps()return if it suceeds or not?I think the best solution to this problem consists in /me adding a function, say,
arm_dt_nb_cores(), that returns an error if DT probing failed and the number of cores if it succeeded.If it fails, you can fall back to SCU detection of cores for legacy reasons (A9), but from A15 onwards I have quite a strong feeling against using L2 as number of cores detection mechanism since it does not work for multi-cluster systems. Fair enough, on Tegra this is not a problem (now) but I do not want this method to propagate to other platforms where multi-cluster number of cores detection will fail if we rely on the L2 mechanism.
This means that if the DT /cpu nodes are updated for all Tegra platforms, DT becomes the mechanism to detect the number of cores for all of them.
If you allow the A9 SCU mechanism to override the DT information (even if it is correct) we might end up in the rather unwieldy situation where there is a disconnect between the
cpu_logical_mapinitialized entries and the HW probed number of cores (if the DT bindings are correct thecpu_logical_mapentries are initialized by DT).The gist is:
Quoted 7 lines
- if DT /cpu nodes are there and defined properly, we build the
cpu_logical_mapand count the number of cores from DT
- if DT /cpu nodes are missing or bogus we rely on thecpu_logical_mapinsmp_setup_processor_id()and fall back to legacy mechanism to detect the number of cores. This just for legacy boards/SoC.Let me know if this is reasonable please.
Sounds quite reasonable to me.
Please review another mail which falls back to SCU/MRC detection when arm_dt_init_cpu_maps() fails.
Quoted 21 lines
Quoted 12 lines
Quoted 5 lines
If we're going to make Tegra114 read the CPU information from DT, then I'd rather just switch over all Tegra platforms to requiring CPU nodes in the DT. We have few enough SoC variants that it should be easy to switch everything to DT before adding Tegra114 support without causing any problems.
Possible.
Quoted 3 lines
But that all said, I'm not convinced it's a good idea to force the information to be present in DT when it's just duplicating stuff that can be runtime-probed from the HW...
Quoted 8 lines
That's also my concern somewhat.
The main purpose to DT CPU core detection is for multiple CPU clusters. SCU/MRC cannot know anything outside of their own clusters. In tegra, we have 4 Cortex-A9/A15 core plus 1 shadow core. Switching those clusters is done transparently. The last A9/A15 core is transparently switched back and forth to the shadow one. So in this case, SCU/MRC detection seems to work fine.
Quoted 5 lines
You can probe the number of cores through SCU but remember that MPIDRs of existing CPUs are generated, not probed if the DT is not present (
smp_setup_processor_id()).cpu_logical_mapcontent, before the DT bindings were introduced, or even now if DT /cpu nodes are bogus, is simply generated as a sequential number but is not *probeable* per-se.
Honestly I don't understand the above so well. Could you please explain a little bit more?
PATCH v2 3/9 ARM: tegra: # of CPU cores detection w/ & w/o HAVE_ARM_SCU
Quoted 1 line · Hiroshi Doyu
Lorenzo Pieralisi <[email protected]> wrote @ Wed, 9 Jan 2013 12:34:32 +0100:
[...]
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 3 lines
But that all said, I'm not convinced it's a good idea to force the information to be present in DT when it's just duplicating stuff that can be runtime-probed from the HW...
That's also my concern somewhat.
The main purpose to DT CPU core detection is for multiple CPU clusters. SCU/MRC cannot know anything outside of their own clusters. In tegra, we have 4 Cortex-A9/A15 core plus 1 shadow core. Switching those clusters is done transparently. The last A9/A15 core is transparently switched back and forth to the shadow one. So in this case, SCU/MRC detection seems to work fine.
Quoted 8 lines
Quoted 5 lines
You can probe the number of cores through SCU but remember that MPIDRs of existing CPUs are generated, not probed if the DT is not present (
smp_setup_processor_id()).cpu_logical_mapcontent, before the DT bindings were introduced, or even now if DT /cpu nodes are bogus, is simply generated as a sequential number but is not *probeable* per-se.Honestly I don't understand the above so well. Could you please explain a little bit more?
The DT /cpu bindings provide the kernel with a list of MPIDR ("reg" property) of all CPUs in the system. What I wanted to say is that, you can probe in HW the number of cores in some situations, but the DT provides more information than that, so I was debating the "duplicating stuff that can be runtime probed" point.
In some platforms you can probe the number of cores in HW, but the MPIDR of existing CPUs is "generated" in smp_setup_processor_id() (you cannot probe the MPIDR of CPUs that are off or held in a pen), as a sequential number and stored in the cpu_logical_map. This works well for single cluster systems, since the MPIDR[23:0] of processors in a single cluster system is a sequential number starting from 0 (well, at least MPIDR[7:0], but let's not get bogged down into details).
For multi-cluster systems this fails, and DT comes to the rescue along with its companion parsing function, arm_dt_init_cpu_maps().
The long and short of it is: DT /cpu nodes are not there just for number of cores counting, but there is more. Probably on Tegra this is not needed at the moment, but this provides the groundwork for a generic and solid solution for all upcoming ARM platforms.
I hope this helps, let me know if it is not clear.
Lorenzo
PATCH v2 4/9 clocksource: tegra: Reorganize funcs by clock functionarities
In reply to Hiroshi DoyuRelocate functions by clock functionarities{RTC, TMR}. Also created some new functions as helper.
--- drivers/clocksource/tegra20_timer.c | 160 +++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 74 deletions(-)
drivers/clocksource/tegra20_timer.c +86 -74
@@ -35,6 +35,83 @@#define RTC_SHADOW_SECONDS 0x0c#define RTC_MILLISECONDS 0x10 +static void __iomem *rtc_base; +static struct timespec persistent_ts; +static u64 persistent_ms, last_persistent_ms; + +/* +* tegra_rtc_read - Reads the Tegra RTC registers +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +static u64 tegra_rtc_read_ms (void ) +{ +u32 ms =readl (rtc_base +RTC_MILLISECONDS ); +u32 s =readl (rtc_base +RTC_SHADOW_SECONDS ); +return (u64 )s *MSEC_PER_SEC + ms; +} + +/* +* tegra_read_persistent_clock - Return time from a persistent clock. +* +* Reads the time from a source which isn't disabled during PM, the +* 32k sync timer. Convert the cycles elapsed since last read into +* nsecs and adds to a monotonically increasing timespec. +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +static void tegra_read_persistent_clock (struct timespec *ts) +{ +u64 delta; +struct timespec *tsp = &persistent_ts; + + last_persistent_ms = persistent_ms; + persistent_ms =tegra_rtc_read_ms (); + delta = persistent_ms - last_persistent_ms; + +timespec_add_ns (tsp, delta *NSEC_PER_MSEC ); + *ts = *tsp; +} + +static const struct of_device_id rtc_match[]__initconst = { + { .compatible ="nvidia,tegra20-rtc" }, + {} +}; + +static void __init tegra20_init_rtc (void ) +{ +struct device_node *np; +struct clk *clk; + + np =of_find_matching_node (NULL , rtc_match); +if (!np) { +pr_err ("Failed to find RTC DT node\n" ); +BUG (); + } + + rtc_base =of_iomap (np,0 ); +if (!rtc_base) { +pr_err ("Can't map RTC registers" ); +BUG (); + } + +/* +* rtc registers are used by read_persistent_clock, keep the rtc clock +* enabled +*/ + clk =clk_get_sys ("rtc-tegra" ,NULL ); +if (IS_ERR (clk)) +pr_warn ("Unable to get rtc-tegra clock\n" ); +else +clk_prepare_enable (clk); + +of_node_put (np); + +register_persistent_clock (NULL , tegra_read_persistent_clock); +} +#define TIMERUS_CNTR_1US 0x10#define TIMERUS_USEC_CFG 0x14#define TIMERUS_CNTR_FREEZE 0x4c
@@ -48,10 +125,6 @@#define TIMER_PCR 0x4static void __iomem *timer_reg_base; -static void __iomem *rtc_base; - -static struct timespec persistent_ts; -static u64 persistent_ms, last_persistent_ms;#define timer_writel (value, reg) \ __raw_writel(value, timer_reg_base + (reg))
@@ -103,46 +176,10 @@ static u32 notrace tegra_read_sched_clock(void)return timer_readl (TIMERUS_CNTR_1US ); } -/* -* tegra_rtc_read - Reads the Tegra RTC registers -* Care must be taken that this funciton is not called while the -* tegra_rtc driver could be executing to avoid race conditions -* on the RTC shadow register -*/ -static u64 tegra_rtc_read_ms (void ) -{ -u32 ms =readl (rtc_base +RTC_MILLISECONDS ); -u32 s =readl (rtc_base +RTC_SHADOW_SECONDS ); -return (u64 )s *MSEC_PER_SEC + ms; -} - -/* -* tegra_read_persistent_clock - Return time from a persistent clock. -* -* Reads the time from a source which isn't disabled during PM, the -* 32k sync timer. Convert the cycles elapsed since last read into -* nsecs and adds to a monotonically increasing timespec. -* Care must be taken that this funciton is not called while the -* tegra_rtc driver could be executing to avoid race conditions -* on the RTC shadow register -*/ -static void tegra_read_persistent_clock (struct timespec *ts) -{ -u64 delta; -struct timespec *tsp = &persistent_ts; - - last_persistent_ms = persistent_ms; - persistent_ms =tegra_rtc_read_ms (); - delta = persistent_ms - last_persistent_ms; - -timespec_add_ns (tsp, delta *NSEC_PER_MSEC ); - *ts = *tsp; -} -static irqreturn_t tegra_timer_interrupt (int irq,void *dev_id) {struct clock_event_device *evt = (struct clock_event_device *)dev_id; -timer_writel (1 <<30 ,TIMER3_BASE +TIMER_PCR ); +timer_writel (1 <<30 ,TIMER3_BASE +TIMER_PCR ); evt->event_handler (evt);return IRQ_HANDLED ; }
@@ -159,12 +196,7 @@ static const struct of_device_id timer_match[] __initconst = { {} }; -static const struct of_device_id rtc_match[]__initconst = { - { .compatible ="nvidia,tegra20-rtc" }, - {} -}; - -static void __init tegra20_init_timer (void ) +static void __init tegra20_init_tmr (void ) {struct device_node *np;struct clk *clk;
@@ -200,30 +232,6 @@ static void __init tegra20_init_timer(void)of_node_put (np); - np =of_find_matching_node (NULL , rtc_match); -if (!np) { -pr_err ("Failed to find RTC DT node\n" ); -BUG (); - } - - rtc_base =of_iomap (np,0 ); -if (!rtc_base) { -pr_err ("Can't map RTC registers" ); -BUG (); - } - -/* -* rtc registers are used by read_persistent_clock, keep the rtc clock -* enabled -*/ - clk =clk_get_sys ("rtc-tegra" ,NULL ); -if (IS_ERR (clk)) -pr_warn ("Unable to get rtc-tegra clock\n" ); -else -clk_prepare_enable (clk); - -of_node_put (np); -switch (rate) {case 12000000 :timer_writel (0x000b ,TIMERUS_USEC_CFG );
@@ -241,8 +249,6 @@ static void __init tegra20_init_timer(void)WARN (1 ,"Unknown clock rate" ); } -setup_sched_clock (tegra_read_sched_clock,32 ,1000000 ); -if (clocksource_mmio_init (timer_reg_base +TIMERUS_CNTR_1US ,"timer_us" ,1000000 ,300 ,32 , clocksource_mmio_readl_up)) {pr_err ("Failed to register clocksource\n" );
@@ -263,10 +269,16 @@ static void __init tegra20_init_timer(void) tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq;clockevents_register_device (&tegra_clockevent); +} + +static void __init tegra20_init_timer (void ) +{ +tegra20_init_tmr (); +setup_sched_clock (tegra_read_sched_clock,32 ,1000000 ); +tegra20_init_rtc ();#ifdef CONFIG_HAVE_ARM_TWD twd_local_timer_of_register ();#endif -register_persistent_clock (NULL , tegra_read_persistent_clock); }CLOCKSOURCE_OF_DECLARE (tegra20,"nvidia,tegra20-timer" , tegra20_init_timer);
Signature · 1 line
1.7.9.5
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
In reply to Hiroshi DoyuAdd platform enabler for ARM arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source and sched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.
--- .../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 ++++ drivers/clocksource/tegra20_timer.c | 65 +++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt new file +11 -0
@@ -0,0 +1,11 @@ +NVIDIA Tegra Timer Stamp Counter(TSC) + +Required properties: +- compatible : "nvidia,tegra114-tsc +- reg : Should contain 1 register ranges(address and length) + +Example: + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + };
drivers/clocksource/tegra20_timer.c +64 -1
80 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 49 lines · Hiroshi Doyu
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.Signed-off-by Hiroshi Doyu <[email protected]>--- .../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 ++++ drivers/clocksource/tegra20_timer.c | 65 +++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtDocumentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt new file +11
-0@@ -0,0 +1,11 @@ +NVIDIA Tegra Timer Stamp Counter(TSC) + +Required properties: +- compatible : "nvidia,tegra114-tsc +- reg : Should contain 1 register ranges(address and length) + +Example: + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + };drivers/clocksource/tegra20_timer.c +5
-0@@ -30,6 +30,7 @@#include <asm/mach/time.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> +#include <asm/arch_timer.h> #define RTC_SECONDS 0x08#define RTC_SHADOW_SECONDS 0x0c@@ -271,10 +272,72 @@ static void __init tegra20_init_tmr(void)clockevents_register_device (&tegra_clockevent); } +#define TSC_CNTCR 0/* TSC control registers */ +#define TSC_CNTCR_ENABLE (1 << 0)/* Enable */ +#define TSC_CNTCR_HDBG (1 << 1)/* Halt on debug */ +
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+#define TSC_CNTCV0 0x8/* TSC counter (LSW) */ +#define TSC_CNTCV1 0xc/* TSC counter (MSW) */ +#define TSC_CNTFID0 0x20/* TSC freq id 0 */ + +static const struct of_device_id tegra_tsc_match[]__initconst = { + { .compatible ="nvidia,tegra114-tsc" }, + {} +}; + +/* FIXME: only secure mode is supported. */
And this is a bug, as far as I'm concerned.
Quoted 20 lines
drivers/clocksource/tegra20_timer.c +20
-0+static int tegra_arch_timer_init (void ) +{ +int err; +struct device_node *np; +struct clk *clk; +void __iomem *tsc_base; +u32 freq, val; + + np =of_find_matching_node (NULL , tegra_tsc_match); +if (!np) +return -ENODEV ; + + tsc_base =of_iomap (np,0 ); +if (!tsc_base) +return -ENODEV ; + + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" );
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+ }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 ); + +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);
No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 324
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +6
-0+ + val =readl_relaxed (tsc_base +TSC_CNTCR ); + val |=TSC_CNTCR_ENABLE |TSC_CNTCR_HDBG ; +writel_relaxed (val, tsc_base +TSC_CNTCR ); + + err =arch_timer_of_register ();
What about adding an optional property to the binding, pointing to the required clock? That would solve the above problem in a sensible way, and your kernel wouldn't go bust.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 23 lines · Marc Zyngier
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 8 lines · Hiroshi Doyu
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.drivers/clocksource/tegra20_timer.c +1
-0+/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 11 lines
drivers/clocksource/tegra20_timer.c +10
-0+static int tegra_arch_timer_init (void ) + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" ); + }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 );
Quoted 8 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 5 lines
drivers/clocksource/tegra20_timer.c +5
-0+ +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
OK, so I understand you want to firmware/bootloader/... to write the value into that register instead, so this all works in non-secure mode (which sounds like a fine objection), but ...
Quoted 10 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 324
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +6
-0+ + val =readl_relaxed (tsc_base +TSC_CNTCR ); + val |=TSC_CNTCR_ENABLE |TSC_CNTCR_HDBG ; +writel_relaxed (val, tsc_base +TSC_CNTCR ); + + err =arch_timer_of_register ();What about adding an optional property to the binding, pointing to the required clock? That would solve the above problem in a sensible way, and your kernel wouldn't go bust.
... I'm not sure how the comment about adding a clock to the DT binding is related to that. Sorry for not following the plot!
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 23:41:42 +0100:
Quoted 33 lines · Marc Zyngier
Quoted 23 lines · Hiroshi Doyu
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 8 lines
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.drivers/clocksource/tegra20_timer.c +1
-0+/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 11 lines
drivers/clocksource/tegra20_timer.c +10
-0+static int tegra_arch_timer_init (void ) + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" ); + }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 );Quoted 8 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 5 lines
drivers/clocksource/tegra20_timer.c +5
-0+ +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
Quoted 3 lines
OK, so I understand you want to
firmware/bootloader/... to write the value into that register instead, so this all works in non-secure mode (which sounds like a fine objection), but ...
If possible, I want to run kernel without bootloader initializing TSC . IOW, I want to allow legacy bootloaders to boot kernel with ARM arch timer.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 34 lines · Hiroshi Doyu
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 23:41:42 +0100:
Quoted 33 lines · Marc Zyngier
Quoted 31 lines · Hiroshi Doyu
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 8 lines
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.drivers/clocksource/tegra20_timer.c +1
-0+/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +5
-0+static int tegra_arch_timer_init (void ) + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" );drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+ }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 ); + +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
Quoted 7 lines
Quoted 3 lines
OK, so I understand you want to
firmware/bootloader/... to write the value into that register instead, so this all works in non-secure mode (which sounds like a fine objection), but ...If possible, I want to run kernel without bootloader initializing TSC . IOW, I want to allow legacy bootloaders to boot kernel with ARM arch timer.
Is it really hard to just fix the bootloader? Tegra114 is new enough, and upstream support new enough, it should be fine to require a fixed bootloader in order to run the upstream kernel even if we don't yet do this right in the downstream kernels.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Stephen Warren <[email protected]> wrote @ Wed, 9 Jan 2013 07:40:49 +0100:
Quoted 39 lines · Hiroshi Doyu
Quoted 38 lines
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 23:41:42 +0100:
Quoted 36 lines · Marc Zyngier
Quoted 23 lines · Hiroshi Doyu
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 8 lines
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.drivers/clocksource/tegra20_timer.c +1
-0+/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 11 lines
drivers/clocksource/tegra20_timer.c +10
-0+static int tegra_arch_timer_init (void ) + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" ); + }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 );Quoted 8 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 5 lines
drivers/clocksource/tegra20_timer.c +5
-0+ +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
OK, so I understand you want to
firmware/bootloader/... to write the value into that register instead, so this all works in non-secure mode (which sounds like a fine objection), but ...
Quoted 8 lines
Quoted 3 lines
If possible, I want to run kernel without bootloader initializing TSC . IOW, I want to allow legacy bootloaders to boot kernel with ARM arch timer.
Is it really hard to just fix the bootloader? Tegra114 is new enough, and upstream support new enough, it should be fine to require a fixed bootloader in order to run the upstream kernel even if we don't yet do this right in the downstream kernels.
Ok, I'll drop this part. Still kernel can boot up.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
In reply to Marc ZyngierHi Marc,
Marc Zyngier <[email protected]> wrote @ Tue, 8 Jan 2013 17:07:39 +0100:
Quoted 97 lines · Hiroshi Doyu
Quoted 49 lines
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.Signed-off-by Hiroshi Doyu <[email protected]>--- .../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 ++++ drivers/clocksource/tegra20_timer.c | 65 +++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtDocumentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt new file +11
-0@@ -0,0 +1,11 @@ +NVIDIA Tegra Timer Stamp Counter(TSC) + +Required properties: +- compatible : "nvidia,tegra114-tsc +- reg : Should contain 1 register ranges(address and length) + +Example: + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + };drivers/clocksource/tegra20_timer.c +5
-0@@ -30,6 +30,7 @@#include <asm/mach/time.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> +#include <asm/arch_timer.h> #define RTC_SECONDS 0x08#define RTC_SHADOW_SECONDS 0x0c@@ -271,10 +272,72 @@ static void __init tegra20_init_tmr(void)clockevents_register_device (&tegra_clockevent); } +#define TSC_CNTCR 0/* TSC control registers */ +#define TSC_CNTCR_ENABLE (1 << 0)/* Enable */ +#define TSC_CNTCR_HDBG (1 << 1)/* Halt on debug */ +drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+#define TSC_CNTCV0 0x8/* TSC counter (LSW) */ +#define TSC_CNTCV1 0xc/* TSC counter (MSW) */ +#define TSC_CNTFID0 0x20/* TSC freq id 0 */ + +static const struct of_device_id tegra_tsc_match[]__initconst = { + { .compatible ="nvidia,tegra114-tsc" }, + {} +}; + +/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 20 lines
drivers/clocksource/tegra20_timer.c +20
-0+static int tegra_arch_timer_init (void ) +{ +int err; +struct device_node *np; +struct clk *clk; +void __iomem *tsc_base; +u32 freq, val; + + np =of_find_matching_node (NULL , tegra_tsc_match); +if (!np) +return -ENODEV ; + + tsc_base =of_iomap (np,0 ); +if (!tsc_base) +return -ENODEV ; + + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" );drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+ }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 ); + +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
Quoted 10 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 324
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +6
-0+ + val =readl_relaxed (tsc_base +TSC_CNTCR ); + val |=TSC_CNTCR_ENABLE |TSC_CNTCR_HDBG ; +writel_relaxed (val, tsc_base +TSC_CNTCR ); + + err =arch_timer_of_register ();What about adding an optional property to the binding, pointing to the required clock? That would solve the above problem in a sensible way, and your kernel wouldn't go bust.
Could you explain a bit more? We have the follwing DT entries related to this:
tsc {
compatible = "nvidia,tegra114-tsc";
reg = <0x700f0000 0x20000>;
};
...
timer {
compatible = "arm,armv7-timer";
interrupts = <1 13 0xf08>,
<1 14 0xf08>,
<1 11 0xf08>,
<1 10 0xf08>;
};The above "tsc" is needed for platform specific enabler for ARM arch timer.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 114 lines · Hiroshi Doyu
Hi Marc,
Marc Zyngier <[email protected]> wrote @ Tue, 8 Jan 2013 17:07:39 +0100:
Quoted 97 lines · Hiroshi Doyu
Quoted 49 lines
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine grained timer than TMR0. If it's available, it will be used for clock source andsched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.Signed-off-by Hiroshi Doyu <[email protected]>--- .../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 ++++ drivers/clocksource/tegra20_timer.c | 65 +++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-)create mode 100644
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtDocumentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt new file +11
-0@@ -0,0 +1,11 @@ +NVIDIA Tegra Timer Stamp Counter(TSC) + +Required properties: +- compatible : "nvidia,tegra114-tsc +- reg : Should contain 1 register ranges(address and length) + +Example: + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + };drivers/clocksource/tegra20_timer.c +5
-0@@ -30,6 +30,7 @@#include <asm/mach/time.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> +#include <asm/arch_timer.h> #define RTC_SECONDS 0x08#define RTC_SHADOW_SECONDS 0x0c@@ -271,10 +272,72 @@ static void __init tegra20_init_tmr(void)clockevents_register_device (&tegra_clockevent); } +#define TSC_CNTCR 0/* TSC control registers */ +#define TSC_CNTCR_ENABLE (1 << 0)/* Enable */ +#define TSC_CNTCR_HDBG (1 << 1)/* Halt on debug */ +drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+#define TSC_CNTCV0 0x8/* TSC counter (LSW) */ +#define TSC_CNTCV1 0xc/* TSC counter (MSW) */ +#define TSC_CNTFID0 0x20/* TSC freq id 0 */ + +static const struct of_device_id tegra_tsc_match[]__initconst = { + { .compatible ="nvidia,tegra114-tsc" }, + {} +}; + +/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 20 lines
drivers/clocksource/tegra20_timer.c +20
-0+static int tegra_arch_timer_init (void ) +{ +int err; +struct device_node *np; +struct clk *clk; +void __iomem *tsc_base; +u32 freq, val; + + np =of_find_matching_node (NULL , tegra_tsc_match); +if (!np) +return -ENODEV ; + + tsc_base =of_iomap (np,0 ); +if (!tsc_base) +return -ENODEV ; + + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; +pr_warn ("Unable to get timer clock. Assuming 12Mhz input clock.\n" );drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+ }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 ); + +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
Quoted 10 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 324
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +6
-0+ + val =readl_relaxed (tsc_base +TSC_CNTCR ); + val |=TSC_CNTCR_ENABLE |TSC_CNTCR_HDBG ; +writel_relaxed (val, tsc_base +TSC_CNTCR ); + + err =arch_timer_of_register ();What about adding an optional property to the binding, pointing to the required clock? That would solve the above problem in a sensible way, and your kernel wouldn't go bust.
Could you explain a bit more? We have the follwing DT entries related to this:
Quoted 15 lines
tsc {
compatible = "nvidia,tegra114-tsc";
reg = <0x700f0000 0x20000>;
};
...
timer {
compatible = "arm,armv7-timer";
interrupts = <1 13 0xf08>,
<1 14 0xf08>,
<1 11 0xf08>,
<1 10 0xf08>;
};Arch timer frequency can be specified in DT since the code already has provision to extract it. Below is extract from OMAP5 DT code.
timer {
compatible = "arm,armv7-timer";
interrupts = <1 14 0x308>;
clock-frequency = <6144000>;
};I think thats what Marc is pointing out.
Regards
Santosh
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 8 lines · Santosh Shilimkar
Quoted 7 lines · Hiroshi Doyu
Hi Marc,
Marc Zyngier <[email protected]> wrote @ Tue, 8 Jan 2013 17:07:39 +0100:
Quoted 2 lines · Hiroshi Doyu
Quoted 1 line
Add platform enabler for ARM
arch_timer(TSC). TSC is more fine
grained
Quoted 79 lines
Quoted 79 lines
Quoted 79 lines
Quoted 54 lines
timer than TMR0. If it's available, it will be used for clock source and
sched_clock. Otherwise, TMR0 is used. In any case TMR0 is necessary for clock event.Signed-off-by Hiroshi Doyu <[email protected]>--- .../bindings/arm/tegra/nvidia,tegra114-tsc.txt | 11 ++++ drivers/clocksource/tegra20_timer.c | 65 +++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-)create mode 100644
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtdiff --git
a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtb/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtnew file mode 100644
index 0000000..9de936a
---/dev/null
+++b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txtDocumentation/devicetree/bindings/arm/tegra/nvidia,tegra114-tsc.txt new file +11
-0@@ -0,0 +1,11 @@ +NVIDIA Tegra Timer Stamp Counter(TSC) + +Required properties: +- compatible : "nvidia,tegra114-tsc +- reg : Should contain 1 register ranges(address and length) + +Example: + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + };drivers/clocksource/tegra20_timer.c +5
-0@@ -30,6 +30,7 @@#include <asm/mach/time.h> #include <asm/smp_twd.h> #include <asm/sched_clock.h> +#include <asm/arch_timer.h> #define RTC_SECONDS 0x08#define RTC_SHADOW_SECONDS 0x0c@@ -271,10 +272,72 @@ static void __init tegra20_init_tmr(void)clockevents_register_device (&tegra_clockevent); } +#define TSC_CNTCR 0/* TSC control registers */ +#define TSC_CNTCR_ENABLE (1 << 0)/* Enable */ +#define TSC_CNTCR_HDBG (1 << 1)/* Halt on debug */ +drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 288
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+#define TSC_CNTCV0 0x8/* TSC counter (LSW) */ +#define TSC_CNTCV1 0xc/* TSC counter (MSW) */ +#define TSC_CNTFID0 0x20/* TSC freq id 0 */ + +static const struct of_device_id tegra_tsc_match[]__initconst = { + { .compatible ="nvidia,tegra114-tsc" }, + {} +}; + +/* FIXME: only secure mode is supported. */ And this is a bug, as far as I'm concerned.
Quoted 12 lines
drivers/clocksource/tegra20_timer.c +12
-0+static int tegra_arch_timer_init (void ) +{ +int err; +struct device_node *np; +struct clk *clk; +void __iomem *tsc_base; +u32 freq, val; + + np =of_find_matching_node (NULL , tegra_tsc_match); +if (!np) +return -ENODEV ; +
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void)
Quoted 8 lines
drivers/clocksource/tegra20_timer.c +8
-0+ tsc_base =of_iomap (np,0 ); +if (!tsc_base) +return -ENODEV ; + + clk =clk_get_sys ("clk_m" ,NULL ); +if (IS_ERR (clk)) { + freq =12000000 ; + pr_warn("Unable to get timer clock. Assuming 12Mhz input
clock.\n");
Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 318
Quoted 10 lines
drivers/clocksource/tegra20_timer.c +10
-0+ }else { + freq =clk_get_rate (clk); +clk_put (clk); + } +writel_relaxed (freq, tsc_base +TSC_CNTFID0 ); + +/* CNTFRQ */ + asm("mcr p15, 0, %0, c14, c0, 0\n" : :"r" (freq)); + asm("mrc p15, 0, %0, c14, c0, 0\n" :"=r" (val)); +BUG_ON (val != freq);No, not again! Like I said last year, this won't fly. So instead of trying to work around a broken firmware, let's do the right thing.
drivers/clocksource/tegra20_timer.c static void __init tegra20_init_tmr(void) · line 324
Quoted 6 lines
drivers/clocksource/tegra20_timer.c +6
-0+ + val =readl_relaxed (tsc_base +TSC_CNTCR ); + val |=TSC_CNTCR_ENABLE |TSC_CNTCR_HDBG ; +writel_relaxed (val, tsc_base +TSC_CNTCR ); + + err =arch_timer_of_register ();What about adding an optional property to the binding, pointing to the required clock? That would solve the above problem in a sensible way, and your kernel wouldn't go bust.
Quoted 1 line
Quoted 1 line
Could you explain a bit more? We have the follwing DT entries related
to
Quoted 21 lines
Quoted 17 lines
this:
tsc { compatible = "nvidia,tegra114-tsc"; reg = <0x700f0000 0x20000>; }; ... timer { compatible = "arm,armv7-timer"; interrupts = <1 13 0xf08>, <1 14 0xf08>, <1 11 0xf08>, <1 10 0xf08>; };Arch timer frequency can be specified in DT since the code already has provision to extract it. Below is extract from OMAP5 DT code.
Quoted 8 lines
timer { compatible = "arm,armv7-timer"; interrupts = <1 14 0x308>; clock-frequency = <6144000>; };I think thats what Marc is pointing out.
Almost. I already proposed this in the past, but because the source clock is variable in the Tegra case, this is not flexible enough.
What I was suggesting was to do the following:
timer {
compatible = "arm,armv7-timer";
[...]
clocks = <&tsc>;
}tsc: tsc {
compatible = "nvidia,tegra114-tsc";
reg = <0x700f0000 0x20000>;
freq-range = <... ...>;
clock-output-names = "tsc";
}In the arch_timer code, start searching for the "clocks" property, and use that if there is one. Otherwise, fall back to "clock-frequency", and ultimately to reading CNTFRQ.
This requires some changes (converting the tsc code to be a clock), but this is at least a proper description of the hardware, and should give you the required flexibility.
Thanks,
M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Hi Mark,
Marc Zyngier <[email protected]> wrote @ Wed, 9 Jan 2013 10:01:05 +0100:
Quoted 18 lines
Almost. I already proposed this in the past, but because the source clock is variable in the Tegra case, this is not flexible enough.
What I was suggesting was to do the following:
timer { compatible = "arm,armv7-timer"; [...] clocks = <&tsc>; }tsc: tsc { compatible = "nvidia,tegra114-tsc"; reg = <0x700f0000 0x20000>; freq-range = <... ...>; clock-output-names = "tsc"; }
Quoted 7 lines
In the
arch_timercode, start searching for the "clocks" property, and use that if there is one. Otherwise, fall back to "clock-frequency", and ultimately to reading CNTFRQ.This requires some changes (converting the tsc code to be a clock), but this is at least a proper description of the hardware, and should give you the required flexibility.
The above seems ok to me. I'll drop this original patch from this series for now until T114 clock comes to implement correctly.
PATCH v2 5/9 clocksource: tegra: Enable ARM arch_timer with TSC
Quoted 26 lines · Hiroshi Doyu
Hi Mark,
Marc Zyngier <[email protected]> wrote @ Wed, 9 Jan 2013 10:01:05 +0100:
Quoted 22 lines
Almost. I already proposed this in the past, but because the source clock is variable in the Tegra case, this is not flexible enough.
What I was suggesting was to do the following:
timer { compatible = "arm,armv7-timer"; [...] clocks = <&tsc>; }tsc: tsc { compatible = "nvidia,tegra114-tsc"; reg = <0x700f0000 0x20000>; freq-range = <... ...>; clock-output-names = "tsc"; }In the
arch_timercode, start searching for the "clocks" property, and use that if there is one. Otherwise, fall back to "clock-frequency", and ultimately to reading CNTFRQ.
Quoted 6 lines
Quoted 3 lines
This requires some changes (converting the tsc code to be a clock), but this is at least a proper description of the hardware, and should give you the required flexibility.
The above seems ok to me. I'll drop this original patch from this series for now until T114 clock comes to implement correctly.
Thanks Hiroshi. Please Cc me when you have a patch implementing this functionality.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH v2 6/9 ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
In reply to Hiroshi DoyuInitial support for Tegra 114 SoC. This is expected to be included in the board DTS files, Tegra 114 SoC based evaluation board family.
--- arch/arm/boot/dts/tegra114.dtsi | 118 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra114.dtsi new file +118 -0
@@ -0,0 +1,118 @@ +/include/ "skeleton.dtsi" + +/ { + compatible = "nvidia,tegra114"; + interrupt-parent = <&gic>; + + gic: interrupt-controller { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + reg = <0x50041000 0x1000 + 0x50042000 0x1000>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + timer at 60005000 { + compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer"; + reg = <0x60005000 0x400>; + interrupts = <0 0 0x04 + 0 1 0x04 + 0 41 0x04 + 0 42 0x04 + 0 121 0x04 + 0 122 0x04>; + }; + + serial at 70006000 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006000 0x40>; + reg-shift = <2>; + interrupts = <0 36 0x04>; + status = "disabled"; + }; + + serial at 70006040 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006040 0x40>; + reg-shift = <2>; + interrupts = <0 37 0x04>; + status = "disabled"; + }; + + serial at 70006200 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006200 0x100>; + reg-shift = <2>; + interrupts = <0 46 0x04>; + status = "disabled"; + }; + + serial at 70006300 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006300 0x100>; + reg-shift = <2>; + interrupts = <0 90 0x04>; + status = "disabled"; + }; + + serial at 70006400 { + compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; + reg = <0x70006400 0x100>; + reg-shift = <2>; + interrupts = <0 91 0x04>; + status = "disabled"; + }; + + rtc { + compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc"; + reg = <0x7000e000 0x100>; + interrupts = <0 2 0x04>; + }; + + pmc { + compatible = "nvidia,tegra114-pmc", "nvidia,tegra20-pmc"; + reg = <0x7000e400 0x400>; + }; + + tsc { + compatible = "nvidia,tegra114-tsc"; + reg = <0x700f0000 0x20000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu at 0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; + }; + + cpu at 1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <1>; + }; + + cpu at 2 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <2>; + }; + + cpu at 3 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <3>; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; +};
Signature · 1 line
1.7.9.5
PATCH v2 6/9 ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
arch/arm/boot/dts/tegra114.dtsi line 13
Quoted 12 lines · Hiroshi Doyu
Initial support for Tegra 114 SoC. This is expected to be included in the board DTS files, Tegra 114 SoC based evaluation board family.
arch/arm/boot/dts/tegra114.dtsi +7
-0+ gic: interrupt-controller { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + reg = <0x50041000 0x1000 + 0x50042000 0x1000>; + interrupt-controller; + #interrupt-cells = <3>; + };
Last time around, Marc Zyngier asked:
Quoted 2 lines
If this is indeed an A15 GIC, how about adding the GICH and GICV regions, as well as the VGIC maintenance interrupt?
PATCH v2 6/9 ARM: dt: tegra114: Add new SoC base, Tegra 114 SoC
Stephen Warren <[email protected]> wrote @ Tue, 8 Jan 2013 23:49:27 +0100:
Quoted 6 lines · Hiroshi Doyu
Quoted 4 lines
Initial support for Tegra 114 SoC. This is expected to be included in the board DTS files, Tegra 114 SoC based evaluation board family.
arch/arm/boot/dts/tegra114.dtsi +0
-0
Quoted 12 lines
arch/arm/boot/dts/tegra114.dtsi line 13
Quoted 7 lines
arch/arm/boot/dts/tegra114.dtsi +7
-0+ gic: interrupt-controller { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + reg = <0x50041000 0x1000 + 0x50042000 0x1000>; + interrupt-controller; + #interrupt-cells = <3>; + };Last time around, Marc Zyngier asked:
Quoted 2 lines
If this is indeed an A15 GIC, how about adding the GICH and GICV regions, as well as the VGIC maintenance interrupt?
I missed to update. I'll update v3 as bellow.
gic: interrupt-controller {
compatible = "arm,cortex-a15-gic";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0x50041000 0x1000>,
<0x50042000 0x1000>,
<0x50044000 0x2000>,
<0x50046000 0x2000>;
interrupts = <1 9 0xf04>;
};PATCH v2 7/9 ARM: dt: tegra114: Add new board, Dalmore
In reply to Hiroshi DoyuAdd a new evaluation board, Dalmore for Tegra 114 family.
--- arch/arm/boot/dts/Makefile | 3 ++- arch/arm/boot/dts/tegra114-dalmore.dts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/tegra114-dalmore.dts
arch/arm/boot/dts/Makefile +2 -1
@@ -143,7 +143,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-ventana.dtb \ tegra20-whistler.dtb \ tegra30-cardhu-a02.dtb \ - tegra30-cardhu-a04.dtb + tegra30-cardhu-a04.dtb \ + tegra114-dalmore.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \
arch/arm/boot/dts/tegra114-dalmore.dts new file +21 -0
@@ -0,0 +1,21 @@ +/dts-v1/; + +/include/ "tegra114.dtsi" + +/ { + model = "NVIDIA Tegra114 Dalmore evaluation board"; + compatible = "nvidia,dalmore", "nvidia,tegra114"; + + memory { + reg = <0x80000000 0x40000000>; + }; + + serial at 70006300 { + status = "okay"; + clock-frequency = <408000000>; + }; + + pmc { + nvidia,invert-interrupt; + }; +};
Signature · 1 line
1.7.9.5
PATCH v2 8/9 ARM: dt: tegra114: Add new board, Pluto
In reply to Hiroshi DoyuAdd a new evaluation board, Pluto for Tegra 114 family.
--- arch/arm/boot/dts/Makefile | 3 ++- arch/arm/boot/dts/tegra114-pluto.dts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/tegra114-pluto.dts
arch/arm/boot/dts/Makefile +2 -1
@@ -144,7 +144,8 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-whistler.dtb \ tegra30-cardhu-a02.dtb \ tegra30-cardhu-a04.dtb \ - tegra114-dalmore.dtb + tegra114-dalmore.dtb \ + tegra114-pluto.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \
arch/arm/boot/dts/tegra114-pluto.dts new file +21 -0
@@ -0,0 +1,21 @@ +/dts-v1/; + +/include/ "tegra114.dtsi" + +/ { + model = "NVIDIA Tegra114 Pluto evaluation board"; + compatible = "nvidia,pluto", "nvidia,tegra114"; + + memory { + reg = <0x80000000 0x40000000>; + }; + + serial at 70006300 { + status = "okay"; + clock-frequency = <408000000>; + }; + + pmc { + nvidia,invert-interrupt; + }; +};
Signature · 1 line
1.7.9.5
PATCH v2 9/9 ARM: tegra: Add initial support for Tegra 114 SoC.
In reply to Hiroshi DoyuAdd new Tegra 114 SoC support.
--- arch/arm/mach-tegra/Kconfig | 10 +++++++ arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/board-dt-tegra114.c | 48 +++++++++++++++++++++++++++++++ arch/arm/mach-tegra/common.c | 1 + 4 files changed, 60 insertions(+) create mode 100644 arch/arm/mach-tegra/board-dt-tegra114.c
arch/arm/mach-tegra/Kconfig +10 -0
@@ -61,6 +61,16 @@ config ARCH_TEGRA_3x_SOC Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller +config ARCH_TEGRA_114_SOC + bool "Enable support for Tegra114 family" + select ARM_GIC + select CPU_V7 + select ARM_L1_CACHE_SHIFT_6 + select ARM_ARCH_TIMER + help + Support for NVIDIA Tegra T114 processor family, based on the + ARM CortexA15MP CPU + config TEGRA_PCI bool "PCI Express support" depends on ARCH_TEGRA_2x_SOC
arch/arm/mach-tegra/Makefile +1 -0
@@ -36,6 +36,7 @@ obj-$(CONFIG_TEGRA_PCI) += pcie.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o +obj-$(CONFIG_ARCH_TEGRA_114_SOC) += board-dt-tegra114.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-harmony-pcie.o
arch/arm/mach-tegra/board-dt-tegra114.c new file +48 -0
48 lines not on this page · raw message
arch/arm/mach-tegra/common.c +1 -0
@@ -59,6 +59,7 @@ u32 tegra_uart_config[4] = {#ifdef CONFIG_OF static const struct of_device_id tegra_dt_irq_match[]__initconst = { { .compatible ="arm,cortex-a9-gic" , .data = gic_of_init }, + { .compatible ="arm,cortex-a15-gic" , .data = gic_of_init }, { } };
Signature · 1 line
1.7.9.5
PATCH v2 9/9 ARM: tegra: Add initial support for Tegra 114 SoC.
arch/arm/mach-tegra/common.c u32 tegra_uart_config[4] = { · line 64
Quoted 9 lines · Hiroshi Doyu
Add new Tegra 114 SoC support.
arch/arm/mach-tegra/common.c +1
-0static const struct of_device_id tegra_dt_irq_match[]__initconst = { { .compatible ="arm,cortex-a9-gic" , .data = gic_of_init }, + { .compatible ="arm,cortex-a15-gic" , .data = gic_of_init }, { } };
It'd probably be a good idea to add newer entries at the start of this table. Not so much an issue here perhaps, but at least when instantiating drivers, the earlier entries match first irrespective of the order of compatible values in the DT node, due to a misfeature in the kernel code, which while it's in the process of being fixed, we probably still want to work around.