[PATCH v2 1/2] ARM: EXYNOS: Map SYSRAM through generic SRAM bindings

Sachin Kamat sachin.kamat at linaro.org
Tue May 6 11:09:30 PDT 2014


Hi Tomasz,

On 6 May 2014 22:14, Tomasz Figa <tomasz.figa at gmail.com> wrote:
> Hi Sachin,
>
> Thanks for addressing the comments. I need to verify few things on Universal
> C210 board first, before I could give my Reviewed-by tag or further
> comments.
>
> I also have some general comments that I missed before, due to limited time
> for review. Please see inline.

Thanks for your review.

>
>
> On 06.05.2014 10:10, Sachin Kamat wrote:
>>
>> Instead of hardcoding the SYSRAM details for each SoC,
>> pass this information through device tree (DT) and make
>> the code SoC agnostic. Generic SRAM bindings are used
>> for achieving this.
>>
>> Signed-off-by: Sachin Kamat <sachin.kamat at linaro.org>
>> Acked-by: Arnd Bergmann <arnd at arndb.de>
>> Acked-by: Heiko Stuebner <heiko at sntech.de>
>> ---
>> Changes since v1:
>> * Addressed Tomasz Figa's comments
>> - Fixed sram node for universal_c210
>> - Check the node status before mapping the address
>>
>> This patch is based on linux next (next-20140501) on top of
>> my Kconfig consolidation patch
>> http://comments.gmane.org/gmane.linux.kernel.samsung-soc/28642
>
>
> [snip]
>
>
>> diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts
>> b/arch/arm/boot/dts/exynos4210-universal_c210.dts
>> index 63e34b24b04f..9813b068cfd8 100644
>> --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
>> +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
>> @@ -28,6 +28,30 @@
>>                 bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5
>> rw rootwait earlyprintk panic=5 maxcpus=1";
>>         };
>>
>> +       sram at 02020000 {
>> +               status = "disabled";
>> +               smp-sram at 0 {
>> +                       status = "disabled";
>> +               };
>> +
>> +               smp-sram at 1f000 {
>> +                       status = "disabled";
>> +               };
>> +       };
>> +
>> +       sram at 02025000 {
>> +               compatible = "mmio-sram";
>> +               reg = <0x02025000 0x1000>;
>> +               #address-cells = <1>;
>> +               #size-cells = <1>;
>> +               ranges = <0 0x02025000 0x1000>;
>> +
>> +               smp-sram at 0 {
>> +                       compatible = "samsung,exynos4210-sram";
>> +                       reg = <0x0 0x1000>;
>> +               };
>> +       };
>
>
> I wonder if this really should be defined like this. 0x2025000 really looks
> just like an offset from the normal SRAM address. This is the thing I need
> to check in documentation and by experiment when I'll return back to work
> tomorrow, but maybe it could be possible to normally use the sram at 02020000
> and just disable smp-sram at 0 and smp-sram at 1f000, replacing them with
> smp-sram at 5000 on Universal C210.

I do not have any info about universal C210 board and need your inputs
for the same :)

>
>
>> +
>>         mct at 10050000 {
>>                 compatible = "none";
>>         };
>
>
> [snip]
>
>
>> diff --git a/arch/arm/mach-exynos/firmware.c
>> b/arch/arm/mach-exynos/firmware.c
>> index 932129ef26c6..7d583cb73850 100644
>> --- a/arch/arm/mach-exynos/firmware.c
>> +++ b/arch/arm/mach-exynos/firmware.c
>> @@ -18,6 +18,7 @@
>>
>>   #include <mach/map.h>
>>
>> +#include "common.h"
>>   #include "smc.h"
>>
>>   static int exynos_do_idle(void)
>> @@ -34,7 +35,12 @@ static int exynos_cpu_boot(int cpu)
>>
>>   static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
>>   {
>> -       void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;
>> +       void __iomem *boot_reg;
>> +
>> +       if (!sram_ns_base_addr)
>> +               return 0;
>
>
> Shouldn't this return an error instead? I'm not sure which one would be
> appropriate, though, probably one of -ENODEV, -ENXIO or -EFAULT.

IIRC, returning error here causes the system to hang and even primary
cpu does not boot.
Since any error or absence of sram nodes should atleast boot the
primary CPU, I thought
this is better.

>
>
>> +
>> +       boot_reg = sram_ns_base_addr + 0x1c + 4*cpu;
>>
>>         __raw_writel(boot_addr, boot_reg);
>>         return 0;
>> diff --git a/arch/arm/mach-exynos/include/mach/map.h
>> b/arch/arm/mach-exynos/include/mach/map.h
>> index 7b046b59d9ec..548269a60634 100644
>> --- a/arch/arm/mach-exynos/include/mach/map.h
>> +++ b/arch/arm/mach-exynos/include/mach/map.h
>> @@ -23,13 +23,6 @@
>>
>>   #include <plat/map-s5p.h>
>>
>> -#define EXYNOS4_PA_SYSRAM0             0x02025000
>> -#define EXYNOS4_PA_SYSRAM1             0x02020000
>> -#define EXYNOS5_PA_SYSRAM              0x02020000
>> -#define EXYNOS4210_PA_SYSRAM_NS                0x0203F000
>> -#define EXYNOS4x12_PA_SYSRAM_NS                0x0204F000
>> -#define EXYNOS5250_PA_SYSRAM_NS                0x0204F000
>> -
>>   #define EXYNOS_PA_CHIPID              0x10000000
>>
>>   #define EXYNOS4_PA_SYSCON             0x10010000
>> diff --git a/arch/arm/mach-exynos/platsmp.c
>> b/arch/arm/mach-exynos/platsmp.c
>> index 03e5e9f94705..ccbcdd7b8a86 100644
>> --- a/arch/arm/mach-exynos/platsmp.c
>> +++ b/arch/arm/mach-exynos/platsmp.c
>> @@ -20,6 +20,7 @@
>>   #include <linux/jiffies.h>
>>   #include <linux/smp.h>
>>   #include <linux/io.h>
>> +#include <linux/of_address.h>
>>
>>   #include <asm/cacheflush.h>
>>   #include <asm/smp_plat.h>
>> @@ -33,11 +34,35 @@
>>
>>   extern void exynos4_secondary_startup(void);
>>
>> +static void __iomem *sram_base_addr;
>> +void __iomem *sram_ns_base_addr;
>
>
> This is probably just a matter of preference, but I'd make this static and
> provide a getter function, like exynos_get_sram_ns_base();
>
> Also this address seems to be used by the firmware code exclusively. If we
> want to make the firmware code more self-contained, maybe the mapping of
> firmware-specific SRAM region could be handled there, instead? This would
> also eliminate the need for having an exported variable or getter function.
> What do you think?

I thought of the same. However 2 reasons prevented me from implementing this.

1. Code duplication
2. This code should be executed only once. I put it in exynos_firmware_init.
However it gave a crash while doing of_iomap. So moved it back to the current
location.

>
>
>> +
>> +static void __init exynos_smp_prepare_sram(void)
>> +{
>> +       struct device_node *node;
>> +
>> +       for_each_compatible_node(node, NULL, "samsung,exynos4210-sram") {
>> +               if (of_device_is_available(node)) {
>> +                       sram_base_addr = of_iomap(node, 0);
>> +                       if (!sram_base_addr)
>> +                               pr_err("Secondary CPU boot address not
>> found\n");
>
>
> I don't think this is an error at this stage. Some platforms might not have
> either of these SRAM reserved regions (such as those using INFORM registers
> instead). Instead, the base address should be checked whenever it is needed
> and errors should be handled then, like in exynos_set_cpu_boot_addr().

Yes. This is more from an information perspective. Probably pr_warn or
pr_info would
be better?

>
>> +               }
>> +       }
>
>
> Also we don't need to look further in DT after we find a matching node
> already. So combining both comments the resulting code would be:
>
> for_each_compatible_node(node, NULL, "samsung,exynos4210-sram") {
>         if (!of_device_is_available(node))
>                 continue;
>         sram_base_addr = of_iomap(node, 0);
>         break;
>
> }

OK.

>
>> +
>> +       for_each_compatible_node(node, NULL, "samsung,exynos4210-sram-ns")
>> {
>> +               if (of_device_is_available(node)) {
>> +                       sram_ns_base_addr = of_iomap(node, 0);
>> +                       if (!sram_ns_base_addr)
>> +                               pr_err("Secondary CPU boot address not
>> found\n");
>> +               }
>> +       }
>
>
> Same comments here.

OK.

>
>
>> +}
>> +
>>   static inline void __iomem *cpu_boot_reg_base(void)
>>   {
>>         if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
>>                 return S5P_INFORM5;
>> -       return S5P_VA_SYSRAM;
>> +       return sram_base_addr;
>>   }
>>
>>   static inline void __iomem *cpu_boot_reg(int cpu)
>> @@ -147,7 +172,8 @@ static int exynos_boot_secondary(unsigned int cpu,
>> struct task_struct *idle)
>>                  * and fall back to boot register if it fails.
>>                  */
>>                 if (call_firmware_op(set_cpu_boot_addr, phys_cpu,
>> boot_addr))
>> -                       __raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
>> +                       if (cpu_boot_reg_base())
>> +                               __raw_writel(boot_addr,
>> cpu_boot_reg(phys_cpu));
>
>
> I'd rework this for proper error handling, e.g.
>
>         int ret;
>
>         /* ... */
>
>         ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr);
>         if (ret && ret != -ENOSYS)
>                 goto fail;
>         if (ret == -ENOSYS) {
>                 /* Fall back to firmware-less way. */
>                 void __iomem *boot_reg = cpu_boot_reg(phys_cpu);
>
>                 if (IS_ERR(boot_reg)) {
>                         ret = PTR_ERR(boot_reg);
>                         goto fail;
>                 }
>         }
>
>         /* ... */
>
> fail:
>         /* Clean-up after error */
>
> Of course, cpu_boot_reg() will need to be converted to follow the ERR_PTR()
> model, but IMHO proper error handling is a good reason to do so.

How about handling this separately outside this patch?

>
>
>>
>>                 call_firmware_op(cpu_boot, phys_cpu);
>>
>> @@ -205,6 +231,8 @@ static void __init exynos_smp_prepare_cpus(unsigned
>> int max_cpus)
>>         if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
>>                 scu_enable(scu_base_addr());
>>
>> +       exynos_smp_prepare_sram();
>> +
>>         /*
>>          * Write the address of secondary startup into the
>>          * system-wide flags register. The boot monitor waits
>> @@ -222,7 +250,8 @@ static void __init exynos_smp_prepare_cpus(unsigned
>> int max_cpus)
>>                 boot_addr = virt_to_phys(exynos4_secondary_startup);
>>
>>                 if (call_firmware_op(set_cpu_boot_addr, phys_cpu,
>> boot_addr))
>> -                       __raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
>> +                       if (cpu_boot_reg_base())
>> +                               __raw_writel(boot_addr,
>> cpu_boot_reg(phys_cpu));
>
>
> I wonder if setting the addresses at this stage is really needed. IMHO doing
> it once in exynos_boot_secondary() should be enough. But this is probably a
> material for further patch.

Sure.

-- 
With warm regards,
Sachin



More information about the linux-arm-kernel mailing list