Re: [PATCH] clocksource: fix read and iounmap of incorrect variable

2017-06-09 Thread Fu Wei
Hi Frank,

On 10 June 2017 at 08:26,  <frowand.l...@gmail.com> wrote:
> From: Frank Rowand <frank.row...@sony.com>
>
> Fix boot warning 'Trying to vfree() nonexistent vm area'
> from arch_timer_mem_of_init().
>
> Refactored code attempts to read and iounmap using address frame
> instead of address ioremap(frame->cntbase).
>
> Fixes: c389d701dfb70 ("clocksource: arm_arch_timer: split MMIO timer 
> probing.")
>
> Signed-off-by: Frank Rowand <frank.row...@sony.com>

Reviewed-by: Fu Wei <fu@linaro.org>

> ---
>
> WARNING: CPU: 0 PID: 0 at mm/vmalloc.c:1514 iounmap+0x14/0x18
> Trying to vfree() nonexistent vm area (ee821000)
> Modules linked in:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.12.0-rc1-dirty #1
> Hardware name: Generic DT based system
> [] (unwind_backtrace) from [] (show_stack+0x10/0x14)
> [] (show_stack) from [] (dump_stack+0x6c/0x8c)
> [] (dump_stack) from [] (__warn+0xd0/0xf8)
> [] (__warn) from [] (warn_slowpath_fmt+0x38/0x48)
> [] (warn_slowpath_fmt) from [] (iounmap+0x14/0x18)
> [] (iounmap) from [] (arch_timer_mem_of_init+0x224/0x414)
> [] (arch_timer_mem_of_init) from [] 
> (clocksource_probe+0x44/0xa8)
> [] (clocksource_probe) from [] (start_kernel+0x228/0x3a0)
> [] (start_kernel) from [<0020807c>] (0x20807c)
>
>  drivers/clocksource/arm_arch_timer.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c 
> b/drivers/clocksource/arm_arch_timer.c
> index 4bed671e490e..8b5c30062d99 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -1209,9 +1209,9 @@ static int __init arch_timer_of_init(struct device_node 
> *np)
> return 0;
> }
>
> -   rate = readl_relaxed(frame + CNTFRQ);
> +   rate = readl_relaxed(base + CNTFRQ);
>
> -   iounmap(frame);
> +   iounmap(base);

Great thanks for your patch, this is a bug. So sorry for this typo.
It happened in my last v24 patchset: https://lkml.org/lkml/2017/4/14/363

Hope this fix can be merged ASAP.

>
> return rate;
>  }
> --
> Frank Rowand <frank.row...@sony.com>
>



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH] clocksource: fix read and iounmap of incorrect variable

2017-06-09 Thread Fu Wei
Hi Frank,

On 10 June 2017 at 08:26,   wrote:
> From: Frank Rowand 
>
> Fix boot warning 'Trying to vfree() nonexistent vm area'
> from arch_timer_mem_of_init().
>
> Refactored code attempts to read and iounmap using address frame
> instead of address ioremap(frame->cntbase).
>
> Fixes: c389d701dfb70 ("clocksource: arm_arch_timer: split MMIO timer 
> probing.")
>
> Signed-off-by: Frank Rowand 

Reviewed-by: Fu Wei 

> ---
>
> WARNING: CPU: 0 PID: 0 at mm/vmalloc.c:1514 iounmap+0x14/0x18
> Trying to vfree() nonexistent vm area (ee821000)
> Modules linked in:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.12.0-rc1-dirty #1
> Hardware name: Generic DT based system
> [] (unwind_backtrace) from [] (show_stack+0x10/0x14)
> [] (show_stack) from [] (dump_stack+0x6c/0x8c)
> [] (dump_stack) from [] (__warn+0xd0/0xf8)
> [] (__warn) from [] (warn_slowpath_fmt+0x38/0x48)
> [] (warn_slowpath_fmt) from [] (iounmap+0x14/0x18)
> [] (iounmap) from [] (arch_timer_mem_of_init+0x224/0x414)
> [] (arch_timer_mem_of_init) from [] 
> (clocksource_probe+0x44/0xa8)
> [] (clocksource_probe) from [] (start_kernel+0x228/0x3a0)
> [] (start_kernel) from [<0020807c>] (0x20807c)
>
>  drivers/clocksource/arm_arch_timer.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c 
> b/drivers/clocksource/arm_arch_timer.c
> index 4bed671e490e..8b5c30062d99 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -1209,9 +1209,9 @@ static int __init arch_timer_of_init(struct device_node 
> *np)
> return 0;
> }
>
> -   rate = readl_relaxed(frame + CNTFRQ);
> +   rate = readl_relaxed(base + CNTFRQ);
>
> -   iounmap(frame);
> +   iounmap(base);

Great thanks for your patch, this is a bug. So sorry for this typo.
It happened in my last v24 patchset: https://lkml.org/lkml/2017/4/14/363

Hope this fix can be merged ASAP.

>
> return rate;
>  }
> --
> Frank Rowand 
>



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [GIT PULL 00/16] clocksource: arm_arch_timer: GTDT-based MMIO timer support

2017-04-20 Thread Fu Wei
Hi Daniel, Lorenzo, Mark,


On 20 April 2017 at 16:26, Mark Rutland <mark.rutl...@arm.com> wrote:
> On Wed, Apr 19, 2017 at 11:39:44PM +0200, Daniel Lezcano wrote:
>> On Wed, Apr 19, 2017 at 05:44:17PM +0100, Mark Rutland wrote:
>> > Hi Daniel,
>
>> > I realise this is a little late, but I would very much appreciate if you 
>> > could
>> > pull these arch timer GTDT patches for v4.12. The series has been largely 
>> > fine
>> > for a while now, and the major hold-ups were edge cases in error handling 
>> > which
>> > have now been addressed.
>
>> Hi Thomas,
>>
>> the series is ok for me. Is it possible to pull these changes directly in
>> tip/timers/core?
>
> The tip-bot tells me it was.
>
> Many thanks for picking these up, it's much appreciated.

Great thanks to all of you, I very appreciate all the help and
suggestion from you :-)

>
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [GIT PULL 00/16] clocksource: arm_arch_timer: GTDT-based MMIO timer support

2017-04-20 Thread Fu Wei
Hi Daniel, Lorenzo, Mark,


On 20 April 2017 at 16:26, Mark Rutland  wrote:
> On Wed, Apr 19, 2017 at 11:39:44PM +0200, Daniel Lezcano wrote:
>> On Wed, Apr 19, 2017 at 05:44:17PM +0100, Mark Rutland wrote:
>> > Hi Daniel,
>
>> > I realise this is a little late, but I would very much appreciate if you 
>> > could
>> > pull these arch timer GTDT patches for v4.12. The series has been largely 
>> > fine
>> > for a while now, and the major hold-ups were edge cases in error handling 
>> > which
>> > have now been addressed.
>
>> Hi Thomas,
>>
>> the series is ok for me. Is it possible to pull these changes directly in
>> tip/timers/core?
>
> The tip-bot tells me it was.
>
> Many thanks for picking these up, it's much appreciated.

Great thanks to all of you, I very appreciate all the help and
suggestion from you :-)

>
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


[PATCH v24 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
[Mark: verify CNTFRQ, only register the first frame]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 78 ++--
 1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 05f2f7a..8981173 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1385,10 +1385,78 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init
+arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem)
+{
+   struct arch_timer_mem_frame *frame;
+   u32 rate;
+   int i;
+
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   frame = _mem->frame[i];
+
+   if (!frame->valid)
+   continue;
+
+   rate = arch_timer_mem_frame_get_cntfrq(frame);
+   if (rate == arch_timer_rate)
+   continue;
+
+   pr_err(FW_BUG "CNTFRQ mismatch: frame @ %pa: (0x%08lx), CPU: 
(0x%08lx)\n",
+  >cntbase,
+  (unsigned long)rate, (unsigned long)arch_timer_rate);
+
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timers, *timer;
+   struct arch_timer_mem_frame *frame;
+   int timer_count, i, ret = 0;
+
+   timers = kcalloc(platform_timer_count, sizeof(*timers), GFP_KERNEL);
+   if (!timers)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timers, _count);
+   if (ret || !timer_count)
+   goto out;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_verify_cntfrq([i]);
+   if (ret) {
+   pr_err("Disabling MMIO timers due to CNTFRQ 
mismatch\n");
+   goto out;
+   }
+   }
+
+   /*
+* While unlikely, it's theoretically possible that none of the frames
+* in a timer expose the combination of feature we want.
+*/
+   for (i = i; i < timer_count; i++) {
+   timer = [i];
+
+   frame = arch_timer_mem_find_best_frame(timer);
+   if (frame)
+   break;
+   }
+
+   if (frame)
+   ret = arch_timer_mem_frame_register(frame);
+out:
+   kfree(timers);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1397,7 +1465,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1440,6 +1508,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v24 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-04-14 Thread fu . wei
From: Fu Wei 

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
[Mark: verify CNTFRQ, only register the first frame]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 78 ++--
 1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 05f2f7a..8981173 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1385,10 +1385,78 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init
+arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem)
+{
+   struct arch_timer_mem_frame *frame;
+   u32 rate;
+   int i;
+
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   frame = _mem->frame[i];
+
+   if (!frame->valid)
+   continue;
+
+   rate = arch_timer_mem_frame_get_cntfrq(frame);
+   if (rate == arch_timer_rate)
+   continue;
+
+   pr_err(FW_BUG "CNTFRQ mismatch: frame @ %pa: (0x%08lx), CPU: 
(0x%08lx)\n",
+  >cntbase,
+  (unsigned long)rate, (unsigned long)arch_timer_rate);
+
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timers, *timer;
+   struct arch_timer_mem_frame *frame;
+   int timer_count, i, ret = 0;
+
+   timers = kcalloc(platform_timer_count, sizeof(*timers), GFP_KERNEL);
+   if (!timers)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timers, _count);
+   if (ret || !timer_count)
+   goto out;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_verify_cntfrq([i]);
+   if (ret) {
+   pr_err("Disabling MMIO timers due to CNTFRQ 
mismatch\n");
+   goto out;
+   }
+   }
+
+   /*
+* While unlikely, it's theoretically possible that none of the frames
+* in a timer expose the combination of feature we want.
+*/
+   for (i = i; i < timer_count; i++) {
+   timer = [i];
+
+   frame = arch_timer_mem_find_best_frame(timer);
+   if (frame)
+   break;
+   }
+
+   if (frame)
+   ret = arch_timer_mem_frame_register(frame);
+out:
+   kfree(timers);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1397,7 +1465,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1440,6 +1508,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v24 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/acpi/arm64/gtdt.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index c9ef9c2..6ba47ea 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -60,6 +61,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -299,3 +311,94 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver can get device info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   void *platform_timer;
+   struct acpi_table_header *table;
+   int ret, timer_count, gwdt_count = 0;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   /*
+* Note: Even though the global variable acpi_gtdt_desc has been
+* initialized by acpi_gtdt_init() while initializing the arch timers,
+* when we call this function to get SBSA watchdogs info from GTDT, the
+* pointers stashed in it are stale (since they are early temporary
+* mappings carried out before acpi_permanent_mmap is set) and we need
+* to re-initialize them with permanent mapped pointer values to let the
+* GTDT parsing possible.
+*/
+   ret = acpi_gtdt_init(table, _count);
+   if (ret || !timer_count)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, gwdt_count);
+   if (ret)
+   break;
+   gwdt_count++;
+   }
+   }
+
+   if (gwdt_count)
+   pr_info("found %d SBSA generic Watchdog(s).\n", gwdt_count);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



[PATCH v24 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-04-14 Thread fu . wei
From: Fu Wei 

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
Reviewed-by: Lorenzo Pieralisi 
Signed-off-by: Mark Rutland 
---
 drivers/acpi/arm64/gtdt.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index c9ef9c2..6ba47ea 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -60,6 +61,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -299,3 +311,94 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver can get device info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   void *platform_timer;
+   struct acpi_table_header *table;
+   int ret, timer_count, gwdt_count = 0;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   /*
+* Note: Even though the global variable acpi_gtdt_desc has been
+* initialized by acpi_gtdt_init() while initializing the arch timers,
+* when we call this function to get SBSA watchdogs info from GTDT, the
+* pointers stashed in it are stale (since they are early temporary
+* mappings carried out before acpi_permanent_mmap is set) and we need
+* to re-initialize them with permanent mapped pointer values to let the
+* GTDT parsing possible.
+*/
+   ret = acpi_gtdt_init(table, _count);
+   if (ret || !timer_count)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, gwdt_count);
+   if (ret)
+   break;
+   gwdt_count++;
+   }
+   }
+
+   if (gwdt_count)
+   pr_info("found %d SBSA generic Watchdog(s).\n", gwdt_count);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



[PATCH v24 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/acpi/arm64/gtdt.c | 144 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 145 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3d95af8..c9ef9c2 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +178,124 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return 0;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i;
+   struct arch_timer_mem_frame *frame;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   goto error;
+
+   frame = _mem->frame[gtdt_frame->frame_number];
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+
+   if (gtdt_frame->virtual_timer_interrupt) {
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in 
frame %d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+   } else {
+   frame->virt_irq = 0;
+   pr_debug("virtual timer in frame %d not implemented.\n",
+   

[PATCH v24 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-14 Thread fu . wei
From: Fu Wei 

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Signed-off-by: Mark Rutland 
---
 drivers/acpi/arm64/gtdt.c | 144 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 145 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3d95af8..c9ef9c2 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +178,124 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return 0;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i;
+   struct arch_timer_mem_frame *frame;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   goto error;
+
+   frame = _mem->frame[gtdt_frame->frame_number];
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+
+   if (gtdt_frame->virtual_timer_interrupt) {
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in 
frame %d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+   } else {
+   frame->virt_irq = 0;
+   pr_debug("virtual timer in frame %d not implemented.\n",
+gtdt_frame->frame_number);
+   }
+
+   frame->cntbase =

[PATCH v24 08/11] acpi: Introduce acpi_unregister_irq function

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patch introduces acpi_unregister_irq function to free a
linux IRQ number<->GSI mapping by a given linux IRQ number.

Even we have successfully registered the GSI, when some error occurs, we
may need to unmap it for freeing the IRQ resource. But in some cases, we
only have IRQ, but not GSI.

This patch is the preparation for memory-mapped timer support in GTDT
driver.

Signed-off-by: Fu Wei <fu@linaro.org>
---
 drivers/acpi/irq.c   | 10 ++
 include/linux/acpi.h |  7 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 830299a..59de777 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -85,6 +85,16 @@ void acpi_unregister_gsi(u32 gsi)
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 /**
+ * acpi_unregister_irq() - Free a linux IRQ number<->GSI mapping
+ * @irq: linux IRQ number
+ */
+void acpi_unregister_irq(int irq)
+{
+   irq_dispose_mapping(irq);
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_irq);
+
+/**
  * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
  * @source: acpi_resource_source to use for the lookup.
  *
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4b5c146..728d1ed 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -336,6 +336,13 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, 
int *polarity);
  */
 void acpi_unregister_gsi (u32 gsi);
 
+/*
+ * This function undoes the effect of one call to acpi_register_gsi().
+ * The irq should be the return value of acpi_register_gsi().
+ * If the irq is valid, free a linux IRQ number<->GSI mapping.
+ */
+void acpi_unregister_irq(int irq);
+
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-- 
2.9.3



[PATCH v24 08/11] acpi: Introduce acpi_unregister_irq function

2017-04-14 Thread fu . wei
From: Fu Wei 

This patch introduces acpi_unregister_irq function to free a
linux IRQ number<->GSI mapping by a given linux IRQ number.

Even we have successfully registered the GSI, when some error occurs, we
may need to unmap it for freeing the IRQ resource. But in some cases, we
only have IRQ, but not GSI.

This patch is the preparation for memory-mapped timer support in GTDT
driver.

Signed-off-by: Fu Wei 
---
 drivers/acpi/irq.c   | 10 ++
 include/linux/acpi.h |  7 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 830299a..59de777 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -85,6 +85,16 @@ void acpi_unregister_gsi(u32 gsi)
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 /**
+ * acpi_unregister_irq() - Free a linux IRQ number<->GSI mapping
+ * @irq: linux IRQ number
+ */
+void acpi_unregister_irq(int irq)
+{
+   irq_dispose_mapping(irq);
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_irq);
+
+/**
  * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
  * @source: acpi_resource_source to use for the lookup.
  *
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4b5c146..728d1ed 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -336,6 +336,13 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, 
int *polarity);
  */
 void acpi_unregister_gsi (u32 gsi);
 
+/*
+ * This function undoes the effect of one call to acpi_register_gsi().
+ * The irq should be the return value of acpi_register_gsi().
+ * If the irq is valid, free a linux IRQ number<->GSI mapping.
+ */
+void acpi_unregister_irq(int irq);
+
 struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
-- 
2.9.3



[PATCH v24 05/11] clocksource: arm_arch_timer: split MMIO timer probing.

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

Currently the code to probe MMIO architected timers mixes DT parsing with
actual poking of hardware. This makes the code harder than necessary to
understand, and makes it difficult to add support for probing via ACPI.

This patch splits the DT parsing from HW probing. The DT parsing now
lives in arch_timer_mem_of_init(), which fills in an arch_timer_mem
structure that it hands to probing functions that can be reused for ACPI
support.

Since the rate detection logic will be slight different when using ACPI,
the probing is performed as a number of steps. This results in more code
for the moment, and some arguably redundant work, but simplifies matters
considerably when ACPI support is added.

Signed-off-by: Fu Wei <fu@linaro.org>
[Mark: refactor the probing split]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 186 +++
 1 file changed, 143 insertions(+), 43 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index e5e8708..dad0264 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1197,18 +1197,37 @@ static int __init arch_timer_of_init(struct device_node 
*np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
 
-static int __init arch_timer_mem_init(struct device_node *np)
+static u32 __init
+arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
 {
-   struct device_node *frame, *best_frame = NULL;
-   void __iomem *cntctlbase, *base;
-   unsigned int irq, ret = -EINVAL;
-   u32 cnttidr, rate;
+   void __iomem *base;
+   u32 rate;
 
-   arch_timers_present |= ARCH_TIMER_TYPE_MEM;
-   cntctlbase = of_iomap(np, 0);
+   base = ioremap(frame->cntbase, frame->size);
+   if (!base) {
+   pr_err("Unable to map frame @ %pa\n", >cntbase);
+   return 0;
+   }
+
+   rate = readl_relaxed(frame + CNTFRQ);
+
+   iounmap(frame);
+
+   return rate;
+}
+
+static struct arch_timer_mem_frame * __init
+arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem)
+{
+   struct arch_timer_mem_frame *frame, *best_frame = NULL;
+   void __iomem *cntctlbase;
+   u32 cnttidr;
+   int i;
+
+   cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size);
if (!cntctlbase) {
-   pr_err("Can't find CNTCTLBase\n");
-   return -ENXIO;
+   pr_err("Can't map CNTCTLBase @ %pa\n", _mem->cntctlbase);
+   return NULL;
}
 
cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
@@ -1217,25 +1236,20 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
 * Try to find a virtual capable frame. Otherwise fall back to a
 * physical capable frame.
 */
-   for_each_available_child_of_node(np, frame) {
-   int n;
-   u32 cntacr;
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
 
-   if (of_property_read_u32(frame, "frame-number", )) {
-   pr_err("Missing frame-number\n");
-   of_node_put(frame);
-   goto out;
-   }
+   frame = _mem->frame[i];
+   if (!frame->valid)
+   continue;
 
/* Try enabling everything, and see what sticks */
-   cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
-CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
-   writel_relaxed(cntacr, cntctlbase + CNTACR(n));
-   cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+   writel_relaxed(cntacr, cntctlbase + CNTACR(i));
+   cntacr = readl_relaxed(cntctlbase + CNTACR(i));
 
-   if ((cnttidr & CNTTIDR_VIRT(n)) &&
+   if ((cnttidr & CNTTIDR_VIRT(i)) &&
!(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
-   of_node_put(best_frame);
best_frame = frame;
arch_timer_mem_use_virtual = true;
break;
@@ -1244,45 +1258,131 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
continue;
 
-   of_node_put(best_frame);
-   best_frame = of_node_get(frame);
+   best_frame = frame;
}
 
-   ret= -ENXIO;
-   base = arch_counter_base = of_io_request_and_map(best_

[PATCH v24 07/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 40 +---
 1 file changed, 10 insertions(+), 30 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index dad0264..05f2f7a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1384,53 +1384,33 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
@@ -1451,7 +1431,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
 
/* Check for globally applicable workarounds */
arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
-- 
2.9.3



[PATCH v24 06/11] acpi/arm64: Add GTDT table parse driver

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
Acked-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..3d95af8
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
+ * Fu Wei <fu@linaro.org>
+ * Hanjun Guo <hanjun@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Secure state is not managed by the kernel on ARM64 systems.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: true if the timer HW state is lost when a CPU enters a

[PATCH v24 05/11] clocksource: arm_arch_timer: split MMIO timer probing.

2017-04-14 Thread fu . wei
From: Fu Wei 

Currently the code to probe MMIO architected timers mixes DT parsing with
actual poking of hardware. This makes the code harder than necessary to
understand, and makes it difficult to add support for probing via ACPI.

This patch splits the DT parsing from HW probing. The DT parsing now
lives in arch_timer_mem_of_init(), which fills in an arch_timer_mem
structure that it hands to probing functions that can be reused for ACPI
support.

Since the rate detection logic will be slight different when using ACPI,
the probing is performed as a number of steps. This results in more code
for the moment, and some arguably redundant work, but simplifies matters
considerably when ACPI support is added.

Signed-off-by: Fu Wei 
[Mark: refactor the probing split]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 186 +++
 1 file changed, 143 insertions(+), 43 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index e5e8708..dad0264 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1197,18 +1197,37 @@ static int __init arch_timer_of_init(struct device_node 
*np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
 
-static int __init arch_timer_mem_init(struct device_node *np)
+static u32 __init
+arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
 {
-   struct device_node *frame, *best_frame = NULL;
-   void __iomem *cntctlbase, *base;
-   unsigned int irq, ret = -EINVAL;
-   u32 cnttidr, rate;
+   void __iomem *base;
+   u32 rate;
 
-   arch_timers_present |= ARCH_TIMER_TYPE_MEM;
-   cntctlbase = of_iomap(np, 0);
+   base = ioremap(frame->cntbase, frame->size);
+   if (!base) {
+   pr_err("Unable to map frame @ %pa\n", >cntbase);
+   return 0;
+   }
+
+   rate = readl_relaxed(frame + CNTFRQ);
+
+   iounmap(frame);
+
+   return rate;
+}
+
+static struct arch_timer_mem_frame * __init
+arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem)
+{
+   struct arch_timer_mem_frame *frame, *best_frame = NULL;
+   void __iomem *cntctlbase;
+   u32 cnttidr;
+   int i;
+
+   cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size);
if (!cntctlbase) {
-   pr_err("Can't find CNTCTLBase\n");
-   return -ENXIO;
+   pr_err("Can't map CNTCTLBase @ %pa\n", _mem->cntctlbase);
+   return NULL;
}
 
cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
@@ -1217,25 +1236,20 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
 * Try to find a virtual capable frame. Otherwise fall back to a
 * physical capable frame.
 */
-   for_each_available_child_of_node(np, frame) {
-   int n;
-   u32 cntacr;
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
 
-   if (of_property_read_u32(frame, "frame-number", )) {
-   pr_err("Missing frame-number\n");
-   of_node_put(frame);
-   goto out;
-   }
+   frame = _mem->frame[i];
+   if (!frame->valid)
+   continue;
 
/* Try enabling everything, and see what sticks */
-   cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
-CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
-   writel_relaxed(cntacr, cntctlbase + CNTACR(n));
-   cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+   writel_relaxed(cntacr, cntctlbase + CNTACR(i));
+   cntacr = readl_relaxed(cntctlbase + CNTACR(i));
 
-   if ((cnttidr & CNTTIDR_VIRT(n)) &&
+   if ((cnttidr & CNTTIDR_VIRT(i)) &&
!(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
-   of_node_put(best_frame);
best_frame = frame;
arch_timer_mem_use_virtual = true;
break;
@@ -1244,45 +1258,131 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
continue;
 
-   of_node_put(best_frame);
-   best_frame = of_node_get(frame);
+   best_frame = frame;
}
 
-   ret= -ENXIO;
-   base = arch_counter_base = of_io_request_and_map(best_frame, 0,
-   

[PATCH v24 07/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-04-14 Thread fu . wei
From: Fu Wei 

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 40 +---
 1 file changed, 10 insertions(+), 30 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index dad0264..05f2f7a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1384,53 +1384,33 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
@@ -1451,7 +1431,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
 
/* Check for globally applicable workarounds */
arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
-- 
2.9.3



[PATCH v24 06/11] acpi/arm64: Add GTDT table parse driver

2017-04-14 Thread fu . wei
From: Fu Wei 

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Acked-by: Rafael J. Wysocki 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
Acked-by: Lorenzo Pieralisi 
Signed-off-by: Mark Rutland 
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..3d95af8
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano 
+ * Fu Wei 
+ * Hanjun Guo 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Secure state is not managed by the kernel on ARM64 systems.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: true if the timer HW state is lost when a CPU enters an idle state,
+ * false otherwise
+ */
+bool __init acpi_gtdt_c3stop(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+
+   case ARCH_TIMER_VIRT_PPI:
+   ret

[PATCH v24 03/11] clocksource: arm_arch_timer: move arch_timer_needs_of_probing into DT init call

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

To cleanly split code paths specific to ACPI or DT at a higher level,
this patch removes arch_timer_init(), folding the relevant
parts of its logic into existing callers.

This paths the way for further rework, and saves a few lines.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
[Mark: reword commit message]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 46 
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 03d71d6..e5e8708 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1105,9 +1105,6 @@ static bool __init arch_timer_needs_of_probing(void)
 
 static int __init arch_timer_common_init(void)
 {
-   if (acpi_disabled && arch_timer_needs_of_probing())
-   return 0;
-
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
return arch_timer_arch_init();
@@ -1145,26 +1142,9 @@ static enum arch_timer_ppi_nr __init 
arch_timer_select_ppi(void)
return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
-static int __init arch_timer_init(void)
-{
-   int ret;
-
-   ret = arch_timer_register();
-   if (ret)
-   return ret;
-
-   ret = arch_timer_common_init();
-   if (ret)
-   return ret;
-
-   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
-
-   return 0;
-}
-
 static int __init arch_timer_of_init(struct device_node *np)
 {
-   int i;
+   int i, ret;
u32 rate;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1176,6 +1156,8 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
rate = arch_timer_get_cntfrq();
arch_timer_of_configure_rate(rate, np);
 
@@ -1203,7 +1185,14 @@ static int __init arch_timer_of_init(struct device_node 
*np)
arch_counter_suspend_stop = of_property_read_bool(np,
 
"arm,no-tick-in-suspend");
 
-   return arch_timer_init();
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   if (arch_timer_needs_of_probing())
+   return 0;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
@@ -1285,7 +1274,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
if (ret)
goto out;
 
-   return arch_timer_common_init();
+   if (!arch_timer_needs_of_probing())
+   ret = arch_timer_common_init();
 out:
iounmap(cntctlbase);
of_node_put(best_frame);
@@ -1314,6 +1304,7 @@ static int __init map_generic_timer_interrupt(u32 
interrupt, u32 flags)
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
+   int ret;
struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1341,6 +1332,8 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/*
 * When probing via ACPI, we have no mechanism to override the sysreg
 * CNTFRQ value. This *must* be correct.
@@ -1363,8 +1356,11 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
/* Check for globally applicable workarounds */
arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
 
-   arch_timer_init();
-   return 0;
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
 #endif
-- 
2.9.3



[PATCH v24 04/11] clocksource: arm_arch_timer: add structs to describe MMIO timer

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

In preparation for ACPI GTDT support, this patch adds structs to
describe the MMIO timers indepedent of the firmware interface.

Subsequent patches will use these to split the FW/HW probing logic, so
that the HW probing logic can be shared by ACPI and DT.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 include/clocksource/arm_arch_timer.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/clocksource/arm_arch_timer.h 
b/include/clocksource/arm_arch_timer.h
index 4a98c06..cc805b7 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -57,6 +57,8 @@ enum arch_timer_spi_nr {
 #define ARCH_TIMER_MEM_PHYS_ACCESS 2
 #define ARCH_TIMER_MEM_VIRT_ACCESS 3
 
+#define ARCH_TIMER_MEM_MAX_FRAMES  8
+
 #define ARCH_TIMER_USR_PCT_ACCESS_EN   (1 << 0) /* physical counter */
 #define ARCH_TIMER_USR_VCT_ACCESS_EN   (1 << 1) /* virtual counter */
 #define ARCH_TIMER_VIRT_EVT_EN (1 << 2)
@@ -72,6 +74,20 @@ struct arch_timer_kvm_info {
int virtual_irq;
 };
 
+struct arch_timer_mem_frame {
+   bool valid;
+   phys_addr_t cntbase;
+   size_t size;
+   int phys_irq;
+   int virt_irq;
+};
+
+struct arch_timer_mem {
+   phys_addr_t cntctlbase;
+   size_t size;
+   struct arch_timer_mem_frame frame[ARCH_TIMER_MEM_MAX_FRAMES];
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
-- 
2.9.3



[PATCH v24 03/11] clocksource: arm_arch_timer: move arch_timer_needs_of_probing into DT init call

2017-04-14 Thread fu . wei
From: Fu Wei 

To cleanly split code paths specific to ACPI or DT at a higher level,
this patch removes arch_timer_init(), folding the relevant
parts of its logic into existing callers.

This paths the way for further rework, and saves a few lines.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
[Mark: reword commit message]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 46 
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 03d71d6..e5e8708 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1105,9 +1105,6 @@ static bool __init arch_timer_needs_of_probing(void)
 
 static int __init arch_timer_common_init(void)
 {
-   if (acpi_disabled && arch_timer_needs_of_probing())
-   return 0;
-
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
return arch_timer_arch_init();
@@ -1145,26 +1142,9 @@ static enum arch_timer_ppi_nr __init 
arch_timer_select_ppi(void)
return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
-static int __init arch_timer_init(void)
-{
-   int ret;
-
-   ret = arch_timer_register();
-   if (ret)
-   return ret;
-
-   ret = arch_timer_common_init();
-   if (ret)
-   return ret;
-
-   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
-
-   return 0;
-}
-
 static int __init arch_timer_of_init(struct device_node *np)
 {
-   int i;
+   int i, ret;
u32 rate;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1176,6 +1156,8 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
rate = arch_timer_get_cntfrq();
arch_timer_of_configure_rate(rate, np);
 
@@ -1203,7 +1185,14 @@ static int __init arch_timer_of_init(struct device_node 
*np)
arch_counter_suspend_stop = of_property_read_bool(np,
 
"arm,no-tick-in-suspend");
 
-   return arch_timer_init();
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   if (arch_timer_needs_of_probing())
+   return 0;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
@@ -1285,7 +1274,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
if (ret)
goto out;
 
-   return arch_timer_common_init();
+   if (!arch_timer_needs_of_probing())
+   ret = arch_timer_common_init();
 out:
iounmap(cntctlbase);
of_node_put(best_frame);
@@ -1314,6 +1304,7 @@ static int __init map_generic_timer_interrupt(u32 
interrupt, u32 flags)
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
+   int ret;
struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1341,6 +1332,8 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/*
 * When probing via ACPI, we have no mechanism to override the sysreg
 * CNTFRQ value. This *must* be correct.
@@ -1363,8 +1356,11 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
/* Check for globally applicable workarounds */
arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
 
-   arch_timer_init();
-   return 0;
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
 #endif
-- 
2.9.3



[PATCH v24 04/11] clocksource: arm_arch_timer: add structs to describe MMIO timer

2017-04-14 Thread fu . wei
From: Fu Wei 

In preparation for ACPI GTDT support, this patch adds structs to
describe the MMIO timers indepedent of the firmware interface.

Subsequent patches will use these to split the FW/HW probing logic, so
that the HW probing logic can be shared by ACPI and DT.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
Signed-off-by: Mark Rutland 
---
 include/clocksource/arm_arch_timer.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/clocksource/arm_arch_timer.h 
b/include/clocksource/arm_arch_timer.h
index 4a98c06..cc805b7 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -57,6 +57,8 @@ enum arch_timer_spi_nr {
 #define ARCH_TIMER_MEM_PHYS_ACCESS 2
 #define ARCH_TIMER_MEM_VIRT_ACCESS 3
 
+#define ARCH_TIMER_MEM_MAX_FRAMES  8
+
 #define ARCH_TIMER_USR_PCT_ACCESS_EN   (1 << 0) /* physical counter */
 #define ARCH_TIMER_USR_VCT_ACCESS_EN   (1 << 1) /* virtual counter */
 #define ARCH_TIMER_VIRT_EVT_EN (1 << 2)
@@ -72,6 +74,20 @@ struct arch_timer_kvm_info {
int virtual_irq;
 };
 
+struct arch_timer_mem_frame {
+   bool valid;
+   phys_addr_t cntbase;
+   size_t size;
+   int phys_irq;
+   int virt_irq;
+};
+
+struct arch_timer_mem {
+   phys_addr_t cntctlbase;
+   size_t size;
+   struct arch_timer_mem_frame frame[ARCH_TIMER_MEM_MAX_FRAMES];
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
-- 
2.9.3



[PATCH v24 02/11] clocksource: arm_arch_timer: refactor arch_timer_needs_probing

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

When booting with DT, it's possible for timer nodes to be probed in any
order. Some common initialisation needs to occur after all nodes have
been probed, and arch_timer_common_init() has code to detect when this
has happened.

This logic is DT-specific, and it would be best to factor it out of the
common code that will be shared with ACPI.

This patch folds this into the existing arch_timer_needs_probing(),
which is renamed to arch_timer_needs_of_probing(), and no longer takes
any arguments. This is only called when using DT, and not when using
ACPI, which will have a deterministic probe order.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
[Mark: reword commit message]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 0138b0c..03d71d6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1076,15 +1076,28 @@ static const struct of_device_id 
arch_timer_mem_of_match[] __initconst = {
{},
 };
 
-static bool __init
-arch_timer_needs_probing(int type, const struct of_device_id *matches)
+static bool __init arch_timer_needs_of_probing(void)
 {
struct device_node *dn;
bool needs_probing = false;
+   unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
 
-   dn = of_find_matching_node(NULL, matches);
-   if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
+   /* We have two timers, and both device-tree nodes are probed. */
+   if ((arch_timers_present & mask) == mask)
+   return false;
+
+   /*
+* Only one type of timer is probed,
+* check if we have another type of timer node in device-tree.
+*/
+   if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
+   dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
+   else
+   dn = of_find_matching_node(NULL, arch_timer_of_match);
+
+   if (dn && of_device_is_available(dn))
needs_probing = true;
+
of_node_put(dn);
 
return needs_probing;
@@ -1092,17 +1105,8 @@ arch_timer_needs_probing(int type, const struct 
of_device_id *matches)
 
 static int __init arch_timer_common_init(void)
 {
-   unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
-
-   /* Wait until both nodes are probed if we have two timers */
-   if ((arch_timers_present & mask) != mask) {
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM,
-arch_timer_mem_of_match))
-   return 0;
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15,
-arch_timer_of_match))
-   return 0;
-   }
+   if (acpi_disabled && arch_timer_needs_of_probing())
+   return 0;
 
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
-- 
2.9.3



[PATCH v24 02/11] clocksource: arm_arch_timer: refactor arch_timer_needs_probing

2017-04-14 Thread fu . wei
From: Fu Wei 

When booting with DT, it's possible for timer nodes to be probed in any
order. Some common initialisation needs to occur after all nodes have
been probed, and arch_timer_common_init() has code to detect when this
has happened.

This logic is DT-specific, and it would be best to factor it out of the
common code that will be shared with ACPI.

This patch folds this into the existing arch_timer_needs_probing(),
which is renamed to arch_timer_needs_of_probing(), and no longer takes
any arguments. This is only called when using DT, and not when using
ACPI, which will have a deterministic probe order.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
[Mark: reword commit message]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 0138b0c..03d71d6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1076,15 +1076,28 @@ static const struct of_device_id 
arch_timer_mem_of_match[] __initconst = {
{},
 };
 
-static bool __init
-arch_timer_needs_probing(int type, const struct of_device_id *matches)
+static bool __init arch_timer_needs_of_probing(void)
 {
struct device_node *dn;
bool needs_probing = false;
+   unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
 
-   dn = of_find_matching_node(NULL, matches);
-   if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
+   /* We have two timers, and both device-tree nodes are probed. */
+   if ((arch_timers_present & mask) == mask)
+   return false;
+
+   /*
+* Only one type of timer is probed,
+* check if we have another type of timer node in device-tree.
+*/
+   if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
+   dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
+   else
+   dn = of_find_matching_node(NULL, arch_timer_of_match);
+
+   if (dn && of_device_is_available(dn))
needs_probing = true;
+
of_node_put(dn);
 
return needs_probing;
@@ -1092,17 +1105,8 @@ arch_timer_needs_probing(int type, const struct 
of_device_id *matches)
 
 static int __init arch_timer_common_init(void)
 {
-   unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
-
-   /* Wait until both nodes are probed if we have two timers */
-   if ((arch_timers_present & mask) != mask) {
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM,
-arch_timer_mem_of_match))
-   return 0;
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15,
-arch_timer_of_match))
-   return 0;
-   }
+   if (acpi_disabled && arch_timer_needs_of_probing())
+   return 0;
 
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
-- 
2.9.3



[PATCH v24 01/11] clocksource: arm_arch_timer: split dt-only rate handling

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

For historical reasons, rate detection when probing via DT is somewhat
convoluted. We tried to package this up in arch_timer_detect_rate(), but
with the addition of ACPI worse, and gets in the way of stringent rate
checking when ACPI is used.

This patch makes arch_timer_detect_rate() specific to DT, ripping out
ACPI logic. In preparation for rework of the MMIO timer probing, the
reading of the relevant CNTFRQ register is factored out to callers. The
function is then renamed to arch_timer_of_configure_rate(), which better
represents its new place in the world.

Comments are added in the DT and ACPI probe paths to explain this.

Signed-off-by: Fu Wei <fu@linaro.org>
[Mark: reword commit message, TODO: rework comments]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 41 
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 94de018..0138b0c 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -818,24 +818,19 @@ static int arch_timer_starting_cpu(unsigned int cpu)
return 0;
 }
 
-static void
-arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
+/*
+ * For historical reasons, when probing with DT we use whichever (non-zero)
+ * rate was probed first, and don't verify that others match. If the first node
+ * probed has a clock-frequency property, this overrides the HW register.
+ */
+static void arch_timer_of_configure_rate(u32 rate, struct device_node *np)
 {
/* Who has more than one independent system counter? */
if (arch_timer_rate)
return;
 
-   /*
-* Try to determine the frequency from the device tree or CNTFRQ,
-* if ACPI is enabled, get the frequency from CNTFRQ ONLY.
-*/
-   if (!acpi_disabled ||
-   of_property_read_u32(np, "clock-frequency", _timer_rate)) {
-   if (cntbase)
-   arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
-   else
-   arch_timer_rate = arch_timer_get_cntfrq();
-   }
+   if (of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = rate;
 
/* Check the timer frequency. */
if (arch_timer_rate == 0)
@@ -1166,6 +1161,7 @@ static int __init arch_timer_init(void)
 static int __init arch_timer_of_init(struct device_node *np)
 {
int i;
+   u32 rate;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("multiple nodes in dt, skipping\n");
@@ -1176,7 +1172,8 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
-   arch_timer_detect_rate(NULL, np);
+   rate = arch_timer_get_cntfrq();
+   arch_timer_of_configure_rate(rate, np);
 
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
@@ -1212,7 +1209,7 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
struct device_node *frame, *best_frame = NULL;
void __iomem *cntctlbase, *base;
unsigned int irq, ret = -EINVAL;
-   u32 cnttidr;
+   u32 cnttidr, rate;
 
arch_timers_present |= ARCH_TIMER_TYPE_MEM;
cntctlbase = of_iomap(np, 0);
@@ -1278,7 +1275,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
goto out;
}
 
-   arch_timer_detect_rate(base, np);
+   rate = readl(base + CNTFRQ);
+   arch_timer_of_configure_rate(rate, np);
ret = arch_timer_mem_register(base, irq);
if (ret)
goto out;
@@ -1339,8 +1337,15 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
-   /* Get the frequency from CNTFRQ */
-   arch_timer_detect_rate(NULL, NULL);
+   /*
+* When probing via ACPI, we have no mechanism to override the sysreg
+* CNTFRQ value. This *must* be correct.
+*/
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
-- 
2.9.3



[PATCH v24 01/11] clocksource: arm_arch_timer: split dt-only rate handling

2017-04-14 Thread fu . wei
From: Fu Wei 

For historical reasons, rate detection when probing via DT is somewhat
convoluted. We tried to package this up in arch_timer_detect_rate(), but
with the addition of ACPI worse, and gets in the way of stringent rate
checking when ACPI is used.

This patch makes arch_timer_detect_rate() specific to DT, ripping out
ACPI logic. In preparation for rework of the MMIO timer probing, the
reading of the relevant CNTFRQ register is factored out to callers. The
function is then renamed to arch_timer_of_configure_rate(), which better
represents its new place in the world.

Comments are added in the DT and ACPI probe paths to explain this.

Signed-off-by: Fu Wei 
[Mark: reword commit message, TODO: rework comments]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 41 
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 94de018..0138b0c 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -818,24 +818,19 @@ static int arch_timer_starting_cpu(unsigned int cpu)
return 0;
 }
 
-static void
-arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
+/*
+ * For historical reasons, when probing with DT we use whichever (non-zero)
+ * rate was probed first, and don't verify that others match. If the first node
+ * probed has a clock-frequency property, this overrides the HW register.
+ */
+static void arch_timer_of_configure_rate(u32 rate, struct device_node *np)
 {
/* Who has more than one independent system counter? */
if (arch_timer_rate)
return;
 
-   /*
-* Try to determine the frequency from the device tree or CNTFRQ,
-* if ACPI is enabled, get the frequency from CNTFRQ ONLY.
-*/
-   if (!acpi_disabled ||
-   of_property_read_u32(np, "clock-frequency", _timer_rate)) {
-   if (cntbase)
-   arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
-   else
-   arch_timer_rate = arch_timer_get_cntfrq();
-   }
+   if (of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = rate;
 
/* Check the timer frequency. */
if (arch_timer_rate == 0)
@@ -1166,6 +1161,7 @@ static int __init arch_timer_init(void)
 static int __init arch_timer_of_init(struct device_node *np)
 {
int i;
+   u32 rate;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("multiple nodes in dt, skipping\n");
@@ -1176,7 +1172,8 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
-   arch_timer_detect_rate(NULL, np);
+   rate = arch_timer_get_cntfrq();
+   arch_timer_of_configure_rate(rate, np);
 
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
@@ -1212,7 +1209,7 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
struct device_node *frame, *best_frame = NULL;
void __iomem *cntctlbase, *base;
unsigned int irq, ret = -EINVAL;
-   u32 cnttidr;
+   u32 cnttidr, rate;
 
arch_timers_present |= ARCH_TIMER_TYPE_MEM;
cntctlbase = of_iomap(np, 0);
@@ -1278,7 +1275,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
goto out;
}
 
-   arch_timer_detect_rate(base, np);
+   rate = readl(base + CNTFRQ);
+   arch_timer_of_configure_rate(rate, np);
ret = arch_timer_mem_register(base, irq);
if (ret)
goto out;
@@ -1339,8 +1337,15 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
-   /* Get the frequency from CNTFRQ */
-   arch_timer_detect_rate(NULL, NULL);
+   /*
+* When probing via ACPI, we have no mechanism to override the sysreg
+* CNTFRQ value. This *must* be correct.
+*/
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
-- 
2.9.3



[PATCH v24 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-04-14 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patchset:
(1)Preparation for adding GTDT support in arm_arch_timer:
1. Introduce a MMIO CNTFRQ helper.
2. separate out device-tree code from arch_timer_detect_rate
3. replace arch_timer_detect_rate with arch_timer_of_configure_rate
4. Refactor arch_timer_needs_probing, and move it into DT init call
5. Introduce some new structs and refactor the MMIO timer init code
for reusing some common code.

(2)Introduce ACPI GTDT parser: drivers/acpi/arm64/gtdt.c
Parse all kinds of timer in GTDT table of ACPI:arch timer,
memory-mapped timer and SBSA Generic Watchdog timer.
This driver can help to simplify all the relevant timer drivers,
and separate all the ACPI GTDT knowledge from them.

(3)Simplify ACPI code for arm_arch_timer

(4)Add GTDT support for ARM memory-mapped timer.

This patchset has been tested on the following platforms with ACPI enabled:
(1)ARM Foundation v8 model

Changelog:
v24: https://lkml.org/lkml/2017/4/14/
 Mark Rutland:
 Rework comments
 Refactor the probing split
 Verify CNTFRQ:arch_timer_mem_verify_cntfrq
 Only register the first frame:arch_timer_mem_find_best_frame
     Fu Wei:
 Fetches from 
git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arch-timer/gtdt
 Introduces acpi_unregister_irq function, and use it in 
drivers/acpi/arm64/gtdt.c

v23: https://lkml.org/lkml/2017/3/31/629
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
 improve the parser of GT blocks and arch_timer_mem initualization.
 Improve arch_timer_rate detection: sysreg frequency is primary in DT boot
 Improve some comments in GTDT parser driver.
 Improve acpi_gtdt_init function, and make a comment for the multiple calls.
 Improve the unwinding for the irq of timers, when an error occurs.
 Handle the case of virtual timer GSIV is 0.

v22: https://lkml.org/lkml/2017/3/21/523
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
 Merged patch 2,3(about arch_timer_detect_rate).
 Keep arch_timer_rate, do NOT split it for different types of timer.
 Improve  memory-mapped timer support by comments and variable name:
 data-->timer_mem
 frame-->gtdt_frame
 Delete zero check for SBSA watchdog irq.
 Skip secure SBSA watchdog in GTDT driver.
 Delete Kconfig modification for SBSA watchdog driver.
 Delete no_irq, using nr_res instead.

v21: https://lkml.org/lkml/2017/2/6/734
 Introduce two functions to get the frequency from mmio and sysreg.
 Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
 Split arch_timer_rate for different types of timer.
 Skip secure timer frame in GTDT driver.
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 (The first 6 patches in v20 have been merged into arch-timer/cleanup 
branch)

v20: https://lkml.org/lkml/2017/1/18/534
 Reorder the first 4 patches and split the 4th patches.
 Leave CNTHCTL_* as they originally were.
 Fix the bug in arch_timer_select_ppi.
 Split "Rework counter frequency detection" patch.
 Rework the arch_timer_detect_rate function.
 Improve the commit message of "Refactor MMIO timer probing".
 Rebase to 4.10.0-rc4

v19: https://lkml.org/lkml/2016/12/21/25
 Fix a '\n' missing in a error message in arch_timer_mem_init.
 Add "request_mem_region" for ioremapping cntbase, according to
 f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
of_io_request_and_map()
 Rebase to 4.9.0-gfb779ff

v18: https://lkml.org/lkml/2016/12/8/446
 Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
 Rebase to 4.9.0-rc8-g9269898

v17: https://lkml.org/lkml/2016/11/25/140
 Take out some cleanups from 4/15.
 Merge 5/15 and 6/15, improve PPI determination code,
 improve commit message.
 Rework counter frequency detection.
 Move arch_timer_needs_of_probing into DT init call.
 Move Platform Timer scan loop back to timer init call to avoid allocating
 and free memory.
 Improve all the exported functions' comment.

v16: https://lkml.org/lkml/2016/11/16/268
 Fix patchset problem about static enum ppi_nr of 01/13 in v15.
 Refactor arch_timer_detect_rate.
 Refactor arch_timer_needs_probing.

v15: https://lkml.org/lkml/2016/11/15/366
 Re-order patches
 Add arm_arch_timer refactoring patches to prepare for GTDT:
 1. rename some  enums and defines, and some cleanups
 2. separate out arch_timer_uses_ppi init code and fix a potential bug
 3. Improve some new struct

[PATCH v24 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-04-14 Thread fu . wei
From: Fu Wei 

This patchset:
(1)Preparation for adding GTDT support in arm_arch_timer:
1. Introduce a MMIO CNTFRQ helper.
2. separate out device-tree code from arch_timer_detect_rate
3. replace arch_timer_detect_rate with arch_timer_of_configure_rate
4. Refactor arch_timer_needs_probing, and move it into DT init call
5. Introduce some new structs and refactor the MMIO timer init code
for reusing some common code.

(2)Introduce ACPI GTDT parser: drivers/acpi/arm64/gtdt.c
Parse all kinds of timer in GTDT table of ACPI:arch timer,
memory-mapped timer and SBSA Generic Watchdog timer.
This driver can help to simplify all the relevant timer drivers,
and separate all the ACPI GTDT knowledge from them.

(3)Simplify ACPI code for arm_arch_timer

(4)Add GTDT support for ARM memory-mapped timer.

This patchset has been tested on the following platforms with ACPI enabled:
(1)ARM Foundation v8 model

Changelog:
v24: https://lkml.org/lkml/2017/4/14/
 Mark Rutland:
 Rework comments
 Refactor the probing split
 Verify CNTFRQ:arch_timer_mem_verify_cntfrq
 Only register the first frame:arch_timer_mem_find_best_frame
 Fu Wei:
 Fetches from 
git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arch-timer/gtdt
 Introduces acpi_unregister_irq function, and use it in 
drivers/acpi/arm64/gtdt.c

v23: https://lkml.org/lkml/2017/3/31/629
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
 improve the parser of GT blocks and arch_timer_mem initualization.
 Improve arch_timer_rate detection: sysreg frequency is primary in DT boot
 Improve some comments in GTDT parser driver.
 Improve acpi_gtdt_init function, and make a comment for the multiple calls.
 Improve the unwinding for the irq of timers, when an error occurs.
 Handle the case of virtual timer GSIV is 0.

v22: https://lkml.org/lkml/2017/3/21/523
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
 Merged patch 2,3(about arch_timer_detect_rate).
 Keep arch_timer_rate, do NOT split it for different types of timer.
 Improve  memory-mapped timer support by comments and variable name:
 data-->timer_mem
 frame-->gtdt_frame
 Delete zero check for SBSA watchdog irq.
 Skip secure SBSA watchdog in GTDT driver.
 Delete Kconfig modification for SBSA watchdog driver.
 Delete no_irq, using nr_res instead.

v21: https://lkml.org/lkml/2017/2/6/734
 Introduce two functions to get the frequency from mmio and sysreg.
 Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
 Split arch_timer_rate for different types of timer.
 Skip secure timer frame in GTDT driver.
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 (The first 6 patches in v20 have been merged into arch-timer/cleanup 
branch)

v20: https://lkml.org/lkml/2017/1/18/534
 Reorder the first 4 patches and split the 4th patches.
 Leave CNTHCTL_* as they originally were.
 Fix the bug in arch_timer_select_ppi.
 Split "Rework counter frequency detection" patch.
 Rework the arch_timer_detect_rate function.
 Improve the commit message of "Refactor MMIO timer probing".
 Rebase to 4.10.0-rc4

v19: https://lkml.org/lkml/2016/12/21/25
 Fix a '\n' missing in a error message in arch_timer_mem_init.
 Add "request_mem_region" for ioremapping cntbase, according to
 f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
of_io_request_and_map()
 Rebase to 4.9.0-gfb779ff

v18: https://lkml.org/lkml/2016/12/8/446
 Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
 Rebase to 4.9.0-rc8-g9269898

v17: https://lkml.org/lkml/2016/11/25/140
 Take out some cleanups from 4/15.
 Merge 5/15 and 6/15, improve PPI determination code,
 improve commit message.
 Rework counter frequency detection.
 Move arch_timer_needs_of_probing into DT init call.
 Move Platform Timer scan loop back to timer init call to avoid allocating
 and free memory.
 Improve all the exported functions' comment.

v16: https://lkml.org/lkml/2016/11/16/268
 Fix patchset problem about static enum ppi_nr of 01/13 in v15.
 Refactor arch_timer_detect_rate.
 Refactor arch_timer_needs_probing.

v15: https://lkml.org/lkml/2016/11/15/366
 Re-order patches
 Add arm_arch_timer refactoring patches to prepare for GTDT:
 1. rename some  enums and defines, and some cleanups
 2. separate out arch_timer_uses_ppi init code and fix a potential bug
 3. Improve some new structs, refactor the timer in

Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Mark,

On 7 April 2017 at 01:52, Mark Rutland <mark.rutl...@arm.com> wrote:
> On Fri, Apr 07, 2017 at 01:39:09AM +0800, Fu Wei wrote:
>> On 7 April 2017 at 01:24, Mark Rutland <mark.rutl...@arm.com> wrote:
>> > On Fri, Apr 07, 2017 at 12:47:47AM +0800, Fu Wei wrote:
>> >> On 6 April 2017 at 02:38, Mark Rutland <mark.rutl...@arm.com> wrote:
>> >> > On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>
>> > However, I would prefer to simplify this such that we only free the
>> > IRQs in the error path.
>> >
>> > We should be able to iterate over all freams, freeing any non-zero
>> > interrupt, since !valid frames shouldn't have non-zero interrupts.
>>
>> Yes, that is what I am doing :
>>
>>  if (!frame->valid)
>>   continue;
>
> What I meant was that we won't look at the frame->valid flag at all;
> only the interrupts. e.g.
>
> for (int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
> if (frame->phys_irq > 0)
> free_the_phys_irq_somehow();
> if (frame->virt_irq > 0)
> free_the_virt_irq_somehow();
> }

Since we use "kcalloc" to allocate struct arch_timer_mem, this should be OK.

>
> ... where we somehow figure out the GSI, or we introduce an api like
> unregister_gsi_for_irq(irq).

Yes, If you are OK with introducing a new API , this problem is solved :-)

>
> Since the !valid frames should all have zero for their interrupt fields,
> no special handling is necessary.
>
> That way, we only free the IRQs in one place, it's obvious that we
> consistently free all of them, etc.
>
>> Lorenzo addressed the API issue, we may can fix it by getting GSI info
>> from DT, then register it until we figure the best frame.
>> It may need some big change in DT code
>
> I'd prefer to keep this constrained to the ACPI code. ;)
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Mark,

On 7 April 2017 at 01:52, Mark Rutland  wrote:
> On Fri, Apr 07, 2017 at 01:39:09AM +0800, Fu Wei wrote:
>> On 7 April 2017 at 01:24, Mark Rutland  wrote:
>> > On Fri, Apr 07, 2017 at 12:47:47AM +0800, Fu Wei wrote:
>> >> On 6 April 2017 at 02:38, Mark Rutland  wrote:
>> >> > On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>
>> > However, I would prefer to simplify this such that we only free the
>> > IRQs in the error path.
>> >
>> > We should be able to iterate over all freams, freeing any non-zero
>> > interrupt, since !valid frames shouldn't have non-zero interrupts.
>>
>> Yes, that is what I am doing :
>>
>>  if (!frame->valid)
>>   continue;
>
> What I meant was that we won't look at the frame->valid flag at all;
> only the interrupts. e.g.
>
> for (int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
> if (frame->phys_irq > 0)
> free_the_phys_irq_somehow();
> if (frame->virt_irq > 0)
> free_the_virt_irq_somehow();
> }

Since we use "kcalloc" to allocate struct arch_timer_mem, this should be OK.

>
> ... where we somehow figure out the GSI, or we introduce an api like
> unregister_gsi_for_irq(irq).

Yes, If you are OK with introducing a new API , this problem is solved :-)

>
> Since the !valid frames should all have zero for their interrupt fields,
> no special handling is necessary.
>
> That way, we only free the IRQs in one place, it's obvious that we
> consistently free all of them, etc.
>
>> Lorenzo addressed the API issue, we may can fix it by getting GSI info
>> from DT, then register it until we figure the best frame.
>> It may need some big change in DT code
>
> I'd prefer to keep this constrained to the ACPI code. ;)
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Mark

On 7 April 2017 at 01:24, Mark Rutland <mark.rutl...@arm.com> wrote:
> On Fri, Apr 07, 2017 at 12:47:47AM +0800, Fu Wei wrote:
>> On 6 April 2017 at 02:38, Mark Rutland <mark.rutl...@arm.com> wrote:
>> > On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>> >> + /*
>> >> +  * Get the GT timer Frame data for every GT Block Timer
>> >> +  */
>> >> + for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
>> >> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> >> + continue;
>> >> +
>> >> + if (!gtdt_frame->base_address || 
>> >> !gtdt_frame->timer_interrupt)
>> >> + goto error;
>> >> +
>> >> + frame = _mem->frame[gtdt_frame->frame_number];
>> >> + frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
>> >> +  gtdt_frame->timer_flags);
>> >> + if (frame->phys_irq <= 0) {
>> >> + pr_warn("failed to map physical timer irq in frame 
>> >> %d.\n",
>> >> + gtdt_frame->frame_number);
>> >> + goto error;
>> >> + }
>> >> +
>> >> + if (gtdt_frame->virtual_timer_interrupt) {
>> >> + frame->virt_irq =
>> >> + 
>> >> map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
>> >> +gtdt_frame->virtual_timer_flags);
>> >> + if (frame->virt_irq <= 0) {
>> >> + pr_warn("failed to map virtual timer irq in 
>> >> frame %d.\n",
>> >> + gtdt_frame->frame_number);
>> >> + 
>> >> acpi_unregister_gsi(gtdt_frame->timer_interrupt);
>> >> + goto error;
>> >> + }
>> >> + } else {
>> >> + frame->virt_irq = 0;
>> >> + pr_debug("virtual timer in frame %d not 
>> >> implemented.\n",
>> >> +  gtdt_frame->frame_number);
>> >> + }
>> >> +
>> >> + frame->cntbase = gtdt_frame->base_address;
>> >> + /*
>> >> +  * The CNTBaseN frame is 4KB (register offsets 0x000 - 
>> >> 0xFFC).
>> >> +  * See ARM DDI 0487A.k_iss10775, page I1-5130, Table I1-4
>> >> +  * "CNTBaseN memory map".
>> >> +  */
>> >> + frame->size = SZ_4K;
>> >> + frame->valid = true;
>> >> + }
>> >> +
>> >> + return 0;
>> >> +
>> >> +error:
>> >> + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
>> >> + frame = _mem->frame[i];
>> >> + if (!frame->valid)
>> >> + continue;
>> >> + irq_dispose_mapping(frame->phys_irq);
>> >> + if (frame->virt_irq)
>> >> + irq_dispose_mapping(frame->virt_irq);
>> >> + }
>> >
>> > We assign interrupts and may goto error before setting valid, so here we
>>
>> yes, I mean to do it.(setting valid at the end of loop)
>>
>> > won't free the interrupts of the last frame we parsed.
>>
>> that won't  be a problem, we may assign two interrupts in a round:
>> First of all, if  the assignment goes  wrong, that means the current
>> interrupt haven't been successfully assigned.
>> (1)if the first goes wrong, the we goto error to unwind  the irqs
>> assigned in previous rounds.
>> (2)if the second one goes wrong , we acpi_unregister_gsi the first one
>> and then  goto error to unwind  the irqs assigned in previous rounds.
>> (3)If the two assignments are successful, set up valid flag
>>
>> So we won't miss freeing the interrupts of the last frame we parsed.
>>
>> Did I miss something?
>
> No; you are correct, and I was mistaken.
>
> However, I would prefer to simplify this such that we only free the
> IRQs in the error path.
>
> We should be able to iterate over all freams, freeing any non-zero
> interrupt, since !valid frames shouldn't have non-zero interrupts.

Yes, that is what I am doing :

 if (!frame->valid)
  continue;

phys_irq must be non-zero, otherwise it was registered incorrectly (an error)
but we need to check virt_irq, it maybe 0 because, this timer frame
may not implement virt timer.
Can we simplify it? any idear?

Lorenzo addressed the API issue, we may can fix it by getting GSI info
from DT, then register it until we figure the best frame.
It may need some big change in DT code

I can do it in V24 , any thought?

Great thanks for your review and help! :-)

>
> I can make that update locally; no need to respin.
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Mark

On 7 April 2017 at 01:24, Mark Rutland  wrote:
> On Fri, Apr 07, 2017 at 12:47:47AM +0800, Fu Wei wrote:
>> On 6 April 2017 at 02:38, Mark Rutland  wrote:
>> > On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>> >> + /*
>> >> +  * Get the GT timer Frame data for every GT Block Timer
>> >> +  */
>> >> + for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
>> >> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> >> + continue;
>> >> +
>> >> + if (!gtdt_frame->base_address || 
>> >> !gtdt_frame->timer_interrupt)
>> >> + goto error;
>> >> +
>> >> + frame = _mem->frame[gtdt_frame->frame_number];
>> >> + frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
>> >> +  gtdt_frame->timer_flags);
>> >> + if (frame->phys_irq <= 0) {
>> >> + pr_warn("failed to map physical timer irq in frame 
>> >> %d.\n",
>> >> + gtdt_frame->frame_number);
>> >> + goto error;
>> >> + }
>> >> +
>> >> + if (gtdt_frame->virtual_timer_interrupt) {
>> >> + frame->virt_irq =
>> >> + 
>> >> map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
>> >> +gtdt_frame->virtual_timer_flags);
>> >> + if (frame->virt_irq <= 0) {
>> >> + pr_warn("failed to map virtual timer irq in 
>> >> frame %d.\n",
>> >> + gtdt_frame->frame_number);
>> >> + 
>> >> acpi_unregister_gsi(gtdt_frame->timer_interrupt);
>> >> + goto error;
>> >> + }
>> >> + } else {
>> >> + frame->virt_irq = 0;
>> >> + pr_debug("virtual timer in frame %d not 
>> >> implemented.\n",
>> >> +  gtdt_frame->frame_number);
>> >> + }
>> >> +
>> >> + frame->cntbase = gtdt_frame->base_address;
>> >> + /*
>> >> +  * The CNTBaseN frame is 4KB (register offsets 0x000 - 
>> >> 0xFFC).
>> >> +  * See ARM DDI 0487A.k_iss10775, page I1-5130, Table I1-4
>> >> +  * "CNTBaseN memory map".
>> >> +  */
>> >> + frame->size = SZ_4K;
>> >> + frame->valid = true;
>> >> + }
>> >> +
>> >> + return 0;
>> >> +
>> >> +error:
>> >> + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
>> >> + frame = _mem->frame[i];
>> >> + if (!frame->valid)
>> >> + continue;
>> >> + irq_dispose_mapping(frame->phys_irq);
>> >> + if (frame->virt_irq)
>> >> + irq_dispose_mapping(frame->virt_irq);
>> >> + }
>> >
>> > We assign interrupts and may goto error before setting valid, so here we
>>
>> yes, I mean to do it.(setting valid at the end of loop)
>>
>> > won't free the interrupts of the last frame we parsed.
>>
>> that won't  be a problem, we may assign two interrupts in a round:
>> First of all, if  the assignment goes  wrong, that means the current
>> interrupt haven't been successfully assigned.
>> (1)if the first goes wrong, the we goto error to unwind  the irqs
>> assigned in previous rounds.
>> (2)if the second one goes wrong , we acpi_unregister_gsi the first one
>> and then  goto error to unwind  the irqs assigned in previous rounds.
>> (3)If the two assignments are successful, set up valid flag
>>
>> So we won't miss freeing the interrupts of the last frame we parsed.
>>
>> Did I miss something?
>
> No; you are correct, and I was mistaken.
>
> However, I would prefer to simplify this such that we only free the
> IRQs in the error path.
>
> We should be able to iterate over all freams, freeing any non-zero
> interrupt, since !valid frames shouldn't have non-zero interrupts.

Yes, that is what I am doing :

 if (!frame->valid)
  continue;

phys_irq must be non-zero, otherwise it was registered incorrectly (an error)
but we need to check virt_irq, it maybe 0 because, this timer frame
may not implement virt timer.
Can we simplify it? any idear?

Lorenzo addressed the API issue, we may can fix it by getting GSI info
from DT, then register it until we figure the best frame.
It may need some big change in DT code

I can do it in V24 , any thought?

Great thanks for your review and help! :-)

>
> I can make that update locally; no need to respin.
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Lorenzo,

On 3 April 2017 at 18:45, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> On platforms booting with ACPI, architected memory-mapped timers'
>> configuration data is provided by firmware through the ACPI GTDT
>> static table.
>>
>> The clocksource architected timer kernel driver requires a firmware
>> interface to collect timer configuration and configure its driver.
>> this infrastructure is present for device tree systems, but it is
>> missing on systems booting with ACPI.
>>
>> Implement the kernel infrastructure required to parse the static
>> ACPI GTDT table so that the architected timer clocksource driver can
>> make use of it on systems booting with ACPI, therefore enabling
>> the corresponding timers configuration.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>> ---
>>  drivers/acpi/arm64/gtdt.c | 146 
>> ++
>>  include/linux/acpi.h  |   1 +
>>  2 files changed, 147 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index 3d95af8..3dd33f3 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -13,6 +13,7 @@
>>
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>
>>  #include 
>> @@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
>>
>>  static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>
>> +static inline void *next_platform_timer(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + platform_timer += gh->length;
>> + if (platform_timer < acpi_gtdt_desc.gtdt_end)
>> + return platform_timer;
>> +
>> + return NULL;
>> +}
>> +
>> +#define for_each_platform_timer(_g)  \
>> + for (_g = acpi_gtdt_desc.platform_timer; _g;\
>> +  _g = next_platform_timer(_g))
>> +
>> +static inline bool is_timer_block(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -155,3 +178,126 @@ int __init acpi_gtdt_init(struct acpi_table_header 
>> *table,
>>
>>   return 0;
>>  }
>> +
>> +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block 
>> *block,
>> +  struct arch_timer_mem *timer_mem)
>> +{
>> + int i;
>> + struct arch_timer_mem_frame *frame;
>> + struct acpi_gtdt_timer_entry *gtdt_frame;
>> +
>> + if (!block->timer_count) {
>> + pr_err(FW_BUG "GT block present, but frame count is zero.");
>> + return -ENODEV;
>> + }
>> +
>> + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
>> + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
>> 8\n",
>> +block->timer_count);
>> + return -EINVAL;
>> + }
>> +
>> + timer_mem->cntctlbase = (phys_addr_t)block->block_address;
>> + /*
>> +  * The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
>> +  * See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
>> +  * "CNTCTLBase memory map".
>> +  */
>> + timer_mem->size = SZ_4K;
>> +
>> + gtdt_frame = (void *)block + block->timer_offset;
>> + if (gtdt_frame + block->timer_count != (void *)block + 
>> block->header.length)
>> + return -EINVAL;
>> +
>> + /*
>> +  * Get the GT timer Frame data for every GT Block Timer
>> +  */
>> + for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
>> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> + continue;
>> +
>> + if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
>> + goto error;
>> +
>> + frame = _mem->frame[gtdt_frame->frame_number];
>> + frame->phys_irq = map_gt_gsi(gtdt_frame

Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
Hi Lorenzo,

On 3 April 2017 at 18:45, Lorenzo Pieralisi  wrote:
> On Sat, Apr 01, 2017 at 01:51:03AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> On platforms booting with ACPI, architected memory-mapped timers'
>> configuration data is provided by firmware through the ACPI GTDT
>> static table.
>>
>> The clocksource architected timer kernel driver requires a firmware
>> interface to collect timer configuration and configure its driver.
>> this infrastructure is present for device tree systems, but it is
>> missing on systems booting with ACPI.
>>
>> Implement the kernel infrastructure required to parse the static
>> ACPI GTDT table so that the architected timer clocksource driver can
>> make use of it on systems booting with ACPI, therefore enabling
>> the corresponding timers configuration.
>>
>> Signed-off-by: Fu Wei 
>> Signed-off-by: Hanjun Guo 
>> ---
>>  drivers/acpi/arm64/gtdt.c | 146 
>> ++
>>  include/linux/acpi.h  |   1 +
>>  2 files changed, 147 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index 3d95af8..3dd33f3 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -13,6 +13,7 @@
>>
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>
>>  #include 
>> @@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
>>
>>  static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>
>> +static inline void *next_platform_timer(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + platform_timer += gh->length;
>> + if (platform_timer < acpi_gtdt_desc.gtdt_end)
>> + return platform_timer;
>> +
>> + return NULL;
>> +}
>> +
>> +#define for_each_platform_timer(_g)  \
>> + for (_g = acpi_gtdt_desc.platform_timer; _g;\
>> +  _g = next_platform_timer(_g))
>> +
>> +static inline bool is_timer_block(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -155,3 +178,126 @@ int __init acpi_gtdt_init(struct acpi_table_header 
>> *table,
>>
>>   return 0;
>>  }
>> +
>> +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block 
>> *block,
>> +  struct arch_timer_mem *timer_mem)
>> +{
>> + int i;
>> + struct arch_timer_mem_frame *frame;
>> + struct acpi_gtdt_timer_entry *gtdt_frame;
>> +
>> + if (!block->timer_count) {
>> + pr_err(FW_BUG "GT block present, but frame count is zero.");
>> + return -ENODEV;
>> + }
>> +
>> + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
>> + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
>> 8\n",
>> +block->timer_count);
>> + return -EINVAL;
>> + }
>> +
>> + timer_mem->cntctlbase = (phys_addr_t)block->block_address;
>> + /*
>> +  * The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
>> +  * See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
>> +  * "CNTCTLBase memory map".
>> +  */
>> + timer_mem->size = SZ_4K;
>> +
>> + gtdt_frame = (void *)block + block->timer_offset;
>> + if (gtdt_frame + block->timer_count != (void *)block + 
>> block->header.length)
>> + return -EINVAL;
>> +
>> + /*
>> +  * Get the GT timer Frame data for every GT Block Timer
>> +  */
>> + for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
>> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> + continue;
>> +
>> + if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
>> + goto error;
>> +
>> + frame = _mem->frame[gtdt_frame->frame_number];
>> + frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
>> +  gtdt_frame->timer_flags);
>> + if (frame->phys_irq <= 0)

Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
nt)
>> +{
>> + int ret;
>> + void *platform_timer;
>> +
>> + *timer_count = 0;
>> + for_each_platform_timer(platform_timer) {
>> + if (is_timer_block(platform_timer)) {
>> + ret = gtdt_parse_timer_block(platform_timer, 
>> timer_mem);
>> + if (ret)
>> + return ret;
>> + timer_mem++;
>> + (*timer_count)++;
>> +         }
>> + }
>
> If we were to have multiple GT blocks, this would leave timer_mem in an
> inconsistent state. In gtdt_parse_timer_block we'll blat any existing
> timer_mem->cntctlbase, and blat some arbitrary set of frames. however,
> *some* frames may have been held over from a previous iteration.
>
> My understanding was that the system level timer had a single CNTCTLBase
> frame, and hence we should only have a single GT block.
>
> Judging by ARM DDI 0487A.k_iss10775, I1.3 "Memory-mapped timer
> components" and I3.4 "Generic Timer memory-mapped registers overview",
> it does appear that the system should only have one CNTCTLBase frame.
>
> What's going on here?
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-04-06 Thread Fu Wei
gt; + int ret;
>> + void *platform_timer;
>> +
>> + *timer_count = 0;
>> + for_each_platform_timer(platform_timer) {
>> + if (is_timer_block(platform_timer)) {
>> + ret = gtdt_parse_timer_block(platform_timer, 
>> timer_mem);
>> + if (ret)
>> + return ret;
>> + timer_mem++;
>> + (*timer_count)++;
>> +         }
>> + }
>
> If we were to have multiple GT blocks, this would leave timer_mem in an
> inconsistent state. In gtdt_parse_timer_block we'll blat any existing
> timer_mem->cntctlbase, and blat some arbitrary set of frames. however,
> *some* frames may have been held over from a previous iteration.
>
> My understanding was that the system level timer had a single CNTCTLBase
> frame, and hence we should only have a single GT block.
>
> Judging by ARM DDI 0487A.k_iss10775, I1.3 "Memory-mapped timer
> components" and I3.4 "Generic Timer memory-mapped registers overview",
> it does appear that the system should only have one CNTCTLBase frame.
>
> What's going on here?
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 06/11] clocksource: arm_arch_timer: refactor MMIO timer probing.

2017-04-06 Thread Fu Wei
Hi Mark,

On 6 April 2017 at 02:42, Mark Rutland <mark.rutl...@arm.com> wrote:
> On Sat, Apr 01, 2017 at 01:51:00AM +0800, fu@linaro.org wrote:
>> + arch_timer_mem_freq = arch_timer_mem_get_cntfrq(base);
>> + if (!arch_timer_rate && arch_timer_mem_freq) {
>> + arch_timer_rate = arch_timer_mem_freq;
>> + } else if (!arch_timer_rate || arch_timer_rate != arch_timer_mem_freq) 
>> {
>> + pr_err(FW_BUG "invalid MMIO frequency.\n");
>> + iounmap(base);
>> + return -EINVAL;
>> + }
>
> I thought I had previously mentioned that this last check has the
> potential to break DT systems, which may be inadvertently relying on the
> probe order.
>
> I agree we must do this check for ACPI, but I think that for DT it needs
> to be relaxed.
>
> I'm happy to rework that locally, if you can address my comments on
> patch 9.

yes, you suggested that we keep the current frequency probing approach for DT,
and use the new approach for ACPI.

Because we try to merge the common code for MMIO timer. this become a little
problem, sorry for that.

I thinks for this code, maybe we can do :

arch_timer_mem_freq = arch_timer_mem_get_cntfrq(base);
if (!arch_timer_rate && arch_timer_mem_freq) {
arch_timer_rate = arch_timer_mem_freq;
} else if (!acpi_disabled && arch_timer_rate != arch_timer_mem_freq) {
pr_err(FW_BUG "invalid MMIO frequency.\n");
iounmap(base);
return -EINVAL;
}

Please correct me, if I miss something.

Thanks :-)

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 06/11] clocksource: arm_arch_timer: refactor MMIO timer probing.

2017-04-06 Thread Fu Wei
Hi Mark,

On 6 April 2017 at 02:42, Mark Rutland  wrote:
> On Sat, Apr 01, 2017 at 01:51:00AM +0800, fu@linaro.org wrote:
>> + arch_timer_mem_freq = arch_timer_mem_get_cntfrq(base);
>> + if (!arch_timer_rate && arch_timer_mem_freq) {
>> + arch_timer_rate = arch_timer_mem_freq;
>> + } else if (!arch_timer_rate || arch_timer_rate != arch_timer_mem_freq) 
>> {
>> + pr_err(FW_BUG "invalid MMIO frequency.\n");
>> + iounmap(base);
>> + return -EINVAL;
>> + }
>
> I thought I had previously mentioned that this last check has the
> potential to break DT systems, which may be inadvertently relying on the
> probe order.
>
> I agree we must do this check for ACPI, but I think that for DT it needs
> to be relaxed.
>
> I'm happy to rework that locally, if you can address my comments on
> patch 9.

yes, you suggested that we keep the current frequency probing approach for DT,
and use the new approach for ACPI.

Because we try to merge the common code for MMIO timer. this become a little
problem, sorry for that.

I thinks for this code, maybe we can do :

arch_timer_mem_freq = arch_timer_mem_get_cntfrq(base);
if (!arch_timer_rate && arch_timer_mem_freq) {
arch_timer_rate = arch_timer_mem_freq;
} else if (!acpi_disabled && arch_timer_rate != arch_timer_mem_freq) {
pr_err(FW_BUG "invalid MMIO frequency.\n");
iounmap(base);
return -EINVAL;
}

Please correct me, if I miss something.

Thanks :-)

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v23 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread Fu Wei
Hi Xiongfeng Wang,

On 1 April 2017 at 10:14, Xiongfeng Wang <wangxiongfe...@huawei.com> wrote:
>
>
> On 2017/4/1 1:50, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> This patchset:
>> (1)Preparation for adding GTDT support in arm_arch_timer:
>> 1. Introduce a MMIO CNTFRQ helper.
>> 2. separate out device-tree code from arch_timer_detect_rate
>> 3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
>> 4. Refactor arch_timer_needs_probing, and move it into DT init call
>> 5. Introduce some new structs and refactor the MMIO timer init code
>> for reusing some common code.
>>
>> (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>> Parse all kinds of timer in GTDT table of ACPI:arch timer,
>> memory-mapped timer and SBSA Generic Watchdog timer.
>> This driver can help to simplify all the relevant timer drivers,
>> and separate all the ACPI GTDT knowledge from them.
>>
>> (3)Simplify ACPI code for arm_arch_timer
>>
>> (4)Add GTDT support for ARM memory-mapped timer.
>>
>> This patchset has been tested on the following platforms with ACPI enabled:
>> (1)ARM Foundation v8 model
>>
>
> for arm_arch_timer(not memory-mapped) and sbsa watchdog part,  Tested-by: 
> wangxiongfe...@huawei.com

Great thanks for your testing :-)

>
>
>
>
>
> Thanks,
>
> Wang Xiongfeng
> .
>
>> Changelog:
>> v23: https://lkml.org/lkml/2017/3/31/
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
>>  improve the parser of GT blocks and arch_timer_mem initualization.
>>  Improve arch_timer_rate detection: sysreg frequency is primary in DT 
>> boot
>>  Improve some comments in GTDT parser driver.
>>  Improve acpi_gtdt_init function, and make a comment for the multiple 
>> calls.
>>  Improve the unwinding for the irq of timers, when an error occurs.
>>  Handle the case of virtual timer GSIV is 0.
>>
>> v22: https://lkml.org/lkml/2017/3/21/523
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
>>  Merged patch 2,3(about arch_timer_detect_rate).
>>  Keep arch_timer_rate, do NOT split it for different types of timer.
>>  Improve  memory-mapped timer support by comments and variable name:
>>  data-->timer_mem
>>  frame-->gtdt_frame
>>  Delete zero check for SBSA watchdog irq.
>>  Skip secure SBSA watchdog in GTDT driver.
>>  Delete Kconfig modification for SBSA watchdog driver.
>>  Delete no_irq, using nr_res instead.
>>
>> v21: https://lkml.org/lkml/2017/2/6/734
>>  Introduce two functions to get the frequency from mmio and sysreg.
>>  Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
>>  Split arch_timer_rate for different types of timer.
>>  Skip secure timer frame in GTDT driver.
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  (The first 6 patches in v20 have been merged into arch-timer/cleanup 
>> branch)
>>
>> v20: https://lkml.org/lkml/2017/1/18/534
>>  Reorder the first 4 patches and split the 4th patches.
>>  Leave CNTHCTL_* as they originally were.
>>  Fix the bug in arch_timer_select_ppi.
>>  Split "Rework counter frequency detection" patch.
>>  Rework the arch_timer_detect_rate function.
>>  Improve the commit message of "Refactor MMIO timer probing".
>>  Rebase to 4.10.0-rc4
>>
>> v19: https://lkml.org/lkml/2016/12/21/25
>>  Fix a '\n' missing in a error message in arch_timer_mem_init.
>>  Add "request_mem_region" for ioremapping cntbase, according to
>>  f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
>> of_io_request_and_map()
>>  Rebase to 4.9.0-gfb779ff
>>
>> v18: https://lkml.org/lkml/2016/12/8/446
>>  Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
>>  Rebase to 4.9.0-rc8-g9269898
>>
>> v17: https://lkml.org/lkml/2016/11/25/140
>>  Take out some cleanups from 4/15.
>>  Merge 5/15 and 6/15, improve PPI determination code,
>>  improve commit message.
>>  Rework counter freque

Re: [PATCH v23 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread Fu Wei
Hi Xiongfeng Wang,

On 1 April 2017 at 10:14, Xiongfeng Wang  wrote:
>
>
> On 2017/4/1 1:50, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> This patchset:
>> (1)Preparation for adding GTDT support in arm_arch_timer:
>> 1. Introduce a MMIO CNTFRQ helper.
>> 2. separate out device-tree code from arch_timer_detect_rate
>> 3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
>> 4. Refactor arch_timer_needs_probing, and move it into DT init call
>> 5. Introduce some new structs and refactor the MMIO timer init code
>> for reusing some common code.
>>
>> (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>> Parse all kinds of timer in GTDT table of ACPI:arch timer,
>> memory-mapped timer and SBSA Generic Watchdog timer.
>> This driver can help to simplify all the relevant timer drivers,
>> and separate all the ACPI GTDT knowledge from them.
>>
>> (3)Simplify ACPI code for arm_arch_timer
>>
>> (4)Add GTDT support for ARM memory-mapped timer.
>>
>> This patchset has been tested on the following platforms with ACPI enabled:
>> (1)ARM Foundation v8 model
>>
>
> for arm_arch_timer(not memory-mapped) and sbsa watchdog part,  Tested-by: 
> wangxiongfe...@huawei.com

Great thanks for your testing :-)

>
>
>
>
>
> Thanks,
>
> Wang Xiongfeng
> .
>
>> Changelog:
>> v23: https://lkml.org/lkml/2017/3/31/
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
>>  improve the parser of GT blocks and arch_timer_mem initualization.
>>  Improve arch_timer_rate detection: sysreg frequency is primary in DT 
>> boot
>>  Improve some comments in GTDT parser driver.
>>  Improve acpi_gtdt_init function, and make a comment for the multiple 
>> calls.
>>  Improve the unwinding for the irq of timers, when an error occurs.
>>  Handle the case of virtual timer GSIV is 0.
>>
>> v22: https://lkml.org/lkml/2017/3/21/523
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
>>  Merged patch 2,3(about arch_timer_detect_rate).
>>  Keep arch_timer_rate, do NOT split it for different types of timer.
>>  Improve  memory-mapped timer support by comments and variable name:
>>  data-->timer_mem
>>  frame-->gtdt_frame
>>  Delete zero check for SBSA watchdog irq.
>>  Skip secure SBSA watchdog in GTDT driver.
>>  Delete Kconfig modification for SBSA watchdog driver.
>>  Delete no_irq, using nr_res instead.
>>
>> v21: https://lkml.org/lkml/2017/2/6/734
>>  Introduce two functions to get the frequency from mmio and sysreg.
>>  Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
>>  Split arch_timer_rate for different types of timer.
>>  Skip secure timer frame in GTDT driver.
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  (The first 6 patches in v20 have been merged into arch-timer/cleanup 
>> branch)
>>
>> v20: https://lkml.org/lkml/2017/1/18/534
>>  Reorder the first 4 patches and split the 4th patches.
>>  Leave CNTHCTL_* as they originally were.
>>  Fix the bug in arch_timer_select_ppi.
>>  Split "Rework counter frequency detection" patch.
>>  Rework the arch_timer_detect_rate function.
>>  Improve the commit message of "Refactor MMIO timer probing".
>>  Rebase to 4.10.0-rc4
>>
>> v19: https://lkml.org/lkml/2016/12/21/25
>>  Fix a '\n' missing in a error message in arch_timer_mem_init.
>>  Add "request_mem_region" for ioremapping cntbase, according to
>>  f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
>> of_io_request_and_map()
>>  Rebase to 4.9.0-gfb779ff
>>
>> v18: https://lkml.org/lkml/2016/12/8/446
>>  Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
>>  Rebase to 4.9.0-rc8-g9269898
>>
>> v17: https://lkml.org/lkml/2016/11/25/140
>>  Take out some cleanups from 4/15.
>>  Merge 5/15 and 6/15, improve PPI determination code,
>>  improve commit message.
>>  Rework counter frequency detection.
>>  Move arch_timer_needs_of_probi

Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread Fu Wei
Hi Mark,

On 28 March 2017 at 22:53, Mark Rutland <mark.rutl...@arm.com> wrote:
> Hi,
>
> On Tue, Mar 28, 2017 at 10:29:10PM +0800, Fu Wei wrote:
>> On 28 March 2017 at 21:05, Mark Rutland <mark.rutl...@arm.com> wrote:
>> > Sorry for the delay; I have not had the time to focus on this as I would
>> > like to. I'm happy with patches 1-4, but from patch 5 onwards, there's
>> > one change I'd like to see.
>> >
>> > I'd prefer that mmio timer frame rame N was always stored at
>> > arch_timer_mem::frame[N], rather than arch_timer_mem::frame[] being in
>> > an arbitrary order. That will make arch_timer_mem_frame::frame_nr
>> > redundant.
>> >
>> > To allow arch_timer_mem::frame[] this to be sparse, I'm happy to have a
>> > bool arch_timer_mem_frame::valid field that we set when probing each
>> > frame. Then we don't need arch_timer_mem::num_frames.
>> >
>> > This will make iterating over the frames far less confusing, and makes
>> > it simple to detect when a frame number is erroneously reused.
>> >
>> > Otherwise, I'm largely happy to pick the rest and apply any fixups
>> > myself.
>>
>> Great thanks for your feedback!
>> I will follow your suggestion to improve my patches, then post it in a day.
>
> Thanks, that is much appreciated.
>
>> So I will rebase my patchset on arch-timer/gtdt branch of your REPO
>> https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt
>
> Yes please! The current HEAD should be:
>
> ebbfe8889cffa12f ("clocksource: arm_arch_timer: move 
> arch_timer_needs_of_probing into DT init call").

Because there are some improvements on the first 4 patches, so I
fetched your gtdt branch, then rebase my v23  to the
arch-timer/cleanup

Thanks for your help! :-)

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread Fu Wei
Hi Mark,

On 28 March 2017 at 22:53, Mark Rutland  wrote:
> Hi,
>
> On Tue, Mar 28, 2017 at 10:29:10PM +0800, Fu Wei wrote:
>> On 28 March 2017 at 21:05, Mark Rutland  wrote:
>> > Sorry for the delay; I have not had the time to focus on this as I would
>> > like to. I'm happy with patches 1-4, but from patch 5 onwards, there's
>> > one change I'd like to see.
>> >
>> > I'd prefer that mmio timer frame rame N was always stored at
>> > arch_timer_mem::frame[N], rather than arch_timer_mem::frame[] being in
>> > an arbitrary order. That will make arch_timer_mem_frame::frame_nr
>> > redundant.
>> >
>> > To allow arch_timer_mem::frame[] this to be sparse, I'm happy to have a
>> > bool arch_timer_mem_frame::valid field that we set when probing each
>> > frame. Then we don't need arch_timer_mem::num_frames.
>> >
>> > This will make iterating over the frames far less confusing, and makes
>> > it simple to detect when a frame number is erroneously reused.
>> >
>> > Otherwise, I'm largely happy to pick the rest and apply any fixups
>> > myself.
>>
>> Great thanks for your feedback!
>> I will follow your suggestion to improve my patches, then post it in a day.
>
> Thanks, that is much appreciated.
>
>> So I will rebase my patchset on arch-timer/gtdt branch of your REPO
>> https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt
>
> Yes please! The current HEAD should be:
>
> ebbfe8889cffa12f ("clocksource: arm_arch_timer: move 
> arch_timer_needs_of_probing into DT init call").

Because there are some improvements on the first 4 patches, so I
fetched your gtdt branch, then rebase my v23  to the
arch-timer/cleanup

Thanks for your help! :-)

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


[PATCH v23 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
---
 drivers/acpi/arm64/gtdt.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3dd33f3..d73bb16 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -60,6 +61,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -301,3 +313,94 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver can get device info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   void *platform_timer;
+   struct acpi_table_header *table;
+   int ret, timer_count, gwdt_count = 0;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   /*
+* Note: Even though the global variable acpi_gtdt_desc has been
+* initialized by acpi_gtdt_init() while initializing the arch timers,
+* when we call this function to get SBSA watchdogs info from GTDT, the
+* pointers stashed in it are stale (since they are early temporary
+* mappings carried out before acpi_permanent_mmap is set) and we need
+* to re-initialize them with permanent mapped pointer values to let the
+* GTDT parsing possible.
+*/
+   ret = acpi_gtdt_init(table, _count);
+   if (ret || !timer_count)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, gwdt_count);
+   if (ret)
+   break;
+   gwdt_count++;
+   }
+   }
+
+   if (gwdt_count)
+   pr_info("found %d SBSA generic Watchdog(s).\n", gwdt_count);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



[PATCH v23 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-31 Thread fu . wei
From: Fu Wei 

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
Reviewed-by: Lorenzo Pieralisi 
---
 drivers/acpi/arm64/gtdt.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3dd33f3..d73bb16 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -60,6 +61,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -301,3 +313,94 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver can get device info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   void *platform_timer;
+   struct acpi_table_header *table;
+   int ret, timer_count, gwdt_count = 0;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   /*
+* Note: Even though the global variable acpi_gtdt_desc has been
+* initialized by acpi_gtdt_init() while initializing the arch timers,
+* when we call this function to get SBSA watchdogs info from GTDT, the
+* pointers stashed in it are stale (since they are early temporary
+* mappings carried out before acpi_permanent_mmap is set) and we need
+* to re-initialize them with permanent mapped pointer values to let the
+* GTDT parsing possible.
+*/
+   ret = acpi_gtdt_init(table, _count);
+   if (ret || !timer_count)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, gwdt_count);
+   if (ret)
+   break;
+   gwdt_count++;
+   }
+   }
+
+   if (gwdt_count)
+   pr_info("found %d SBSA generic Watchdog(s).\n", gwdt_count);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



[PATCH v23 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 35 ---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 415e30a..c722bb5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1150,10 +1150,35 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timer_mem;
+   int timer_count, i, ret;
+
+   timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
+   GFP_KERNEL);
+   if (!timer_mem)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timer_mem, _count);
+   if (ret || !timer_count)
+   goto error;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_init(timer_mem + i);
+   if (!ret)
+   break;
+   }
+
+error:
+   kfree(timer_mem);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1162,7 +1187,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1199,6 +1224,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v23 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-03-31 Thread fu . wei
From: Fu Wei 

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
---
 drivers/clocksource/arm_arch_timer.c | 35 ---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 415e30a..c722bb5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1150,10 +1150,35 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timer_mem;
+   int timer_count, i, ret;
+
+   timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
+   GFP_KERNEL);
+   if (!timer_mem)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timer_mem, _count);
+   if (ret || !timer_count)
+   goto error;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_init(timer_mem + i);
+   if (!ret)
+   break;
+   }
+
+error:
+   kfree(timer_mem);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1162,7 +1187,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1199,6 +1224,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/acpi/arm64/gtdt.c | 146 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 147 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3d95af8..3dd33f3 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +178,126 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return 0;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i;
+   struct arch_timer_mem_frame *frame;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   goto error;
+
+   frame = _mem->frame[gtdt_frame->frame_number];
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+
+   if (gtdt_frame->virtual_timer_interrupt) {
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in 
frame %d.\n",
+   gtdt_frame->frame_number);
+   
acpi_unregister_gsi(gtdt_frame->timer_interrupt);
+   goto error;
+   }
+   } else {
+   frame->virt_irq = 0;
+   pr_debug("vi

[PATCH v23 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-31 Thread fu . wei
From: Fu Wei 

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
---
 drivers/acpi/arm64/gtdt.c | 146 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 147 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 3d95af8..3dd33f3 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -13,6 +13,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -37,6 +38,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +178,126 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return 0;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i;
+   struct arch_timer_mem_frame *frame;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0; i < block->timer_count; i++, gtdt_frame++) {
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   goto error;
+
+   frame = _mem->frame[gtdt_frame->frame_number];
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   gtdt_frame->frame_number);
+   goto error;
+   }
+
+   if (gtdt_frame->virtual_timer_interrupt) {
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in 
frame %d.\n",
+   gtdt_frame->frame_number);
+   
acpi_unregister_gsi(gtdt_frame->timer_interrupt);
+   goto error;
+   }
+   } else {
+   frame->virt_irq = 0;
+   pr_debug("virtual timer in frame %d not implemented.\n",
+gtdt_frame->frame_num

[PATCH v23 08/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 54 
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 4aaebe7..415e30a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1149,63 +1149,36 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
-   /* Get the frequency from the sysreg CNTFRQ */
-   arch_timer_rate = arch_timer_get_cntfrq();
-   if (!arch_timer_rate) {
-   pr_err(FW_BUG "frequency not available.\n");
-   return -EINVAL;
-   }
-
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
pr_err("No interrupt available, giving up\n");
@@ -1213,7 +1186,14 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
+
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
ret = arch_timer_register();
if (ret)
-- 
2.9.3



[PATCH v23 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
Acked-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..3d95af8
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
+ * Fu Wei <fu@linaro.org>
+ * Hanjun Guo <hanjun@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Secure state is not managed by the kernel on ARM64 systems.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: true if the timer HW state is lost when a CPU enters an idle state,
+ * false otherwise
+ */
+bool __init 

[PATCH v23 08/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-03-31 Thread fu . wei
From: Fu Wei 

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
---
 drivers/clocksource/arm_arch_timer.c | 54 
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 4aaebe7..415e30a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1149,63 +1149,36 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
-   /* Get the frequency from the sysreg CNTFRQ */
-   arch_timer_rate = arch_timer_get_cntfrq();
-   if (!arch_timer_rate) {
-   pr_err(FW_BUG "frequency not available.\n");
-   return -EINVAL;
-   }
-
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
pr_err("No interrupt available, giving up\n");
@@ -1213,7 +1186,14 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
+
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
ret = arch_timer_register();
if (ret)
-- 
2.9.3



[PATCH v23 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-31 Thread fu . wei
From: Fu Wei 

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Acked-by: Rafael J. Wysocki 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
Acked-by: Lorenzo Pieralisi 
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..3d95af8
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano 
+ * Fu Wei 
+ * Hanjun Guo 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Secure state is not managed by the kernel on ARM64 systems.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: true if the timer HW state is lost when a CPU enters an idle state,
+ * false otherwise
+ */
+bool __init acpi_gtdt_c3stop(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+
+   case ARCH_TIMER_VIRT_PPI:
+   return !(gtdt->vi

[PATCH v23 06/11] clocksource: arm_arch_timer: refactor MMIO timer probing.

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

Currently the code to probe MMIO architected timers mixes DT parsing with
actual poking of hardware. This makes the code harder than necessary to
understand, and makes it difficult to add support for probing via ACPI.

This patch factors all the DT-specific logic out of arch_timer_mem_init(),
into a new function arch_timer_mem_of_init().
The former pokes the hardware and determines the suitablility of frames
based on a datastructure populated by the latter.

This cleanly separates the two and will make it possible to add probing
using the ACPI GTDT in subsequent patches.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 170 +--
 1 file changed, 122 insertions(+), 48 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 9433276..4aaebe7 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -977,17 +977,17 @@ static int __init arch_timer_of_init(struct device_node 
*np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
 
-static int __init arch_timer_mem_init(struct device_node *np)
+static int __init arch_timer_mem_init(struct arch_timer_mem *timer_mem)
 {
-   struct device_node *frame, *best_frame = NULL;
+   struct arch_timer_mem_frame *best_frame = NULL;
+   u32 cnttidr, arch_timer_mem_freq;
void __iomem *cntctlbase, *base;
-   unsigned int irq, ret = -EINVAL;
-   u32 cnttidr;
+   unsigned int irq;
+   int i, ret;
 
-   arch_timers_present |= ARCH_TIMER_TYPE_MEM;
-   cntctlbase = of_iomap(np, 0);
+   cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size);
if (!cntctlbase) {
-   pr_err("Can't find CNTCTLBase\n");
+   pr_err("Can't map CNTCTLBase.\n");
return -ENXIO;
}
 
@@ -997,25 +997,20 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
 * Try to find a virtual capable frame. Otherwise fall back to a
 * physical capable frame.
 */
-   for_each_available_child_of_node(np, frame) {
-   int n;
-   u32 cntacr;
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
+   struct arch_timer_mem_frame *frame = _mem->frame[i];
 
-   if (of_property_read_u32(frame, "frame-number", )) {
-   pr_err("Missing frame-number\n");
-   of_node_put(frame);
-   goto out;
-   }
+   if (!frame->valid)
+   continue;
 
/* Try enabling everything, and see what sticks */
-   cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
-CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
-   writel_relaxed(cntacr, cntctlbase + CNTACR(n));
-   cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+   writel_relaxed(cntacr, cntctlbase + CNTACR(i));
+   cntacr = readl_relaxed(cntctlbase + CNTACR(i));
 
-   if ((cnttidr & CNTTIDR_VIRT(n)) &&
+   if ((cnttidr & CNTTIDR_VIRT(i)) &&
!(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
-   of_node_put(best_frame);
best_frame = frame;
arch_timer_mem_use_virtual = true;
break;
@@ -1024,56 +1019,135 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
continue;
 
-   of_node_put(best_frame);
-   best_frame = of_node_get(frame);
+   best_frame = frame;
}
+   iounmap(cntctlbase);
 
-   ret= -ENXIO;
-   base = arch_counter_base = of_io_request_and_map(best_frame, 0,
-"arch_mem_timer");
-   if (IS_ERR(base)) {
-   pr_err("Can't map frame's registers\n");
-   goto out;
+   if (!best_frame) {
+   pr_err("Can't find frame for register\n");
+   return -EINVAL;
}
 
if (arch_timer_mem_use_virtual)
-   irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_VIRT_SPI);
+   irq = best_frame->virt_irq;
else
-   irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_PHYS_SPI);
+   irq = best_frame->phys_irq;
 
-   ret = -EINVAL;
 

[PATCH v23 06/11] clocksource: arm_arch_timer: refactor MMIO timer probing.

2017-03-31 Thread fu . wei
From: Fu Wei 

Currently the code to probe MMIO architected timers mixes DT parsing with
actual poking of hardware. This makes the code harder than necessary to
understand, and makes it difficult to add support for probing via ACPI.

This patch factors all the DT-specific logic out of arch_timer_mem_init(),
into a new function arch_timer_mem_of_init().
The former pokes the hardware and determines the suitablility of frames
based on a datastructure populated by the latter.

This cleanly separates the two and will make it possible to add probing
using the ACPI GTDT in subsequent patches.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
---
 drivers/clocksource/arm_arch_timer.c | 170 +--
 1 file changed, 122 insertions(+), 48 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 9433276..4aaebe7 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -977,17 +977,17 @@ static int __init arch_timer_of_init(struct device_node 
*np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
 
-static int __init arch_timer_mem_init(struct device_node *np)
+static int __init arch_timer_mem_init(struct arch_timer_mem *timer_mem)
 {
-   struct device_node *frame, *best_frame = NULL;
+   struct arch_timer_mem_frame *best_frame = NULL;
+   u32 cnttidr, arch_timer_mem_freq;
void __iomem *cntctlbase, *base;
-   unsigned int irq, ret = -EINVAL;
-   u32 cnttidr;
+   unsigned int irq;
+   int i, ret;
 
-   arch_timers_present |= ARCH_TIMER_TYPE_MEM;
-   cntctlbase = of_iomap(np, 0);
+   cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size);
if (!cntctlbase) {
-   pr_err("Can't find CNTCTLBase\n");
+   pr_err("Can't map CNTCTLBase.\n");
return -ENXIO;
}
 
@@ -997,25 +997,20 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
 * Try to find a virtual capable frame. Otherwise fall back to a
 * physical capable frame.
 */
-   for_each_available_child_of_node(np, frame) {
-   int n;
-   u32 cntacr;
+   for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
+   u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
+   struct arch_timer_mem_frame *frame = _mem->frame[i];
 
-   if (of_property_read_u32(frame, "frame-number", )) {
-   pr_err("Missing frame-number\n");
-   of_node_put(frame);
-   goto out;
-   }
+   if (!frame->valid)
+   continue;
 
/* Try enabling everything, and see what sticks */
-   cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
-CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
-   writel_relaxed(cntacr, cntctlbase + CNTACR(n));
-   cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+   writel_relaxed(cntacr, cntctlbase + CNTACR(i));
+   cntacr = readl_relaxed(cntctlbase + CNTACR(i));
 
-   if ((cnttidr & CNTTIDR_VIRT(n)) &&
+   if ((cnttidr & CNTTIDR_VIRT(i)) &&
!(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
-   of_node_put(best_frame);
best_frame = frame;
arch_timer_mem_use_virtual = true;
break;
@@ -1024,56 +1019,135 @@ static int __init arch_timer_mem_init(struct 
device_node *np)
if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
continue;
 
-   of_node_put(best_frame);
-   best_frame = of_node_get(frame);
+   best_frame = frame;
}
+   iounmap(cntctlbase);
 
-   ret= -ENXIO;
-   base = arch_counter_base = of_io_request_and_map(best_frame, 0,
-"arch_mem_timer");
-   if (IS_ERR(base)) {
-   pr_err("Can't map frame's registers\n");
-   goto out;
+   if (!best_frame) {
+   pr_err("Can't find frame for register\n");
+   return -EINVAL;
}
 
if (arch_timer_mem_use_virtual)
-   irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_VIRT_SPI);
+   irq = best_frame->virt_irq;
else
-   irq = irq_of_parse_and_map(best_frame, ARCH_TIMER_PHYS_SPI);
+   irq = best_frame->phys_irq;
 
-   ret = -EINVAL;
if (!irq) {
pr_err("Frame missing %s irq.\n

[PATCH v23 05/11] clocksource: arm_arch_timer: add structs to describe MMIO timer

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

In preparation for ACPI GTDT support, this patch adds structs to
describe the MMIO timers indepedent of the firmware interface.

Subsequent patches will use these to split the FW/HW probing logic, so
that the HW probing logic can be shared by ACPI and DT.

[Mark: reword commit message]

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
---
 include/clocksource/arm_arch_timer.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/clocksource/arm_arch_timer.h 
b/include/clocksource/arm_arch_timer.h
index 4a98c06..cc805b7 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -57,6 +57,8 @@ enum arch_timer_spi_nr {
 #define ARCH_TIMER_MEM_PHYS_ACCESS 2
 #define ARCH_TIMER_MEM_VIRT_ACCESS 3
 
+#define ARCH_TIMER_MEM_MAX_FRAMES  8
+
 #define ARCH_TIMER_USR_PCT_ACCESS_EN   (1 << 0) /* physical counter */
 #define ARCH_TIMER_USR_VCT_ACCESS_EN   (1 << 1) /* virtual counter */
 #define ARCH_TIMER_VIRT_EVT_EN (1 << 2)
@@ -72,6 +74,20 @@ struct arch_timer_kvm_info {
int virtual_irq;
 };
 
+struct arch_timer_mem_frame {
+   bool valid;
+   phys_addr_t cntbase;
+   size_t size;
+   int phys_irq;
+   int virt_irq;
+};
+
+struct arch_timer_mem {
+   phys_addr_t cntctlbase;
+   size_t size;
+   struct arch_timer_mem_frame frame[ARCH_TIMER_MEM_MAX_FRAMES];
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
-- 
2.9.3



[PATCH v23 03/11] clocksource: arm_arch_timer: refactor arch_timer_needs_probing

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

When booting with DT, it's possible for timer nodes to be probed in any
order. Some common initialisation needs to occur after all nodes have
been probed, and arch_timer_common_init() has code to detect when this
has happened.

This logic is DT-specific, and it would be best to factor it out of the
common code that will be shared with ACPI.

This patch folds this into the existing arch_timer_needs_probing(),
which is renamed to arch_timer_needs_of_probing(), and no longer takes
any arguments. This is only called when using DT, and not when using
ACPI, which will have a deterministic probe order.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
[Mark: reword commit message]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 1b6a7e6..ed215d9 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -839,15 +839,28 @@ static const struct of_device_id 
arch_timer_mem_of_match[] __initconst = {
{},
 };
 
-static bool __init
-arch_timer_needs_probing(int type, const struct of_device_id *matches)
+static bool __init arch_timer_needs_of_probing(void)
 {
struct device_node *dn;
bool needs_probing = false;
+   unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
 
-   dn = of_find_matching_node(NULL, matches);
-   if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
+   /* We have two timers, and both device-tree nodes are probed. */
+   if ((arch_timers_present & mask) == mask)
+   return false;
+
+   /*
+* Only one type of timer is probed,
+* check if we have another type of timer node in device-tree.
+*/
+   if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
+   dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
+   else
+   dn = of_find_matching_node(NULL, arch_timer_of_match);
+
+   if (dn && of_device_is_available(dn))
needs_probing = true;
+
of_node_put(dn);
 
return needs_probing;
@@ -855,17 +868,8 @@ arch_timer_needs_probing(int type, const struct 
of_device_id *matches)
 
 static int __init arch_timer_common_init(void)
 {
-   unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
-
-   /* Wait until both nodes are probed if we have two timers */
-   if ((arch_timers_present & mask) != mask) {
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM,
-arch_timer_mem_of_match))
-   return 0;
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15,
-arch_timer_of_match))
-   return 0;
-   }
+   if (acpi_disabled && arch_timer_needs_of_probing())
+   return 0;
 
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
-- 
2.9.3



[PATCH v23 05/11] clocksource: arm_arch_timer: add structs to describe MMIO timer

2017-03-31 Thread fu . wei
From: Fu Wei 

In preparation for ACPI GTDT support, this patch adds structs to
describe the MMIO timers indepedent of the firmware interface.

Subsequent patches will use these to split the FW/HW probing logic, so
that the HW probing logic can be shared by ACPI and DT.

[Mark: reword commit message]

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
---
 include/clocksource/arm_arch_timer.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/clocksource/arm_arch_timer.h 
b/include/clocksource/arm_arch_timer.h
index 4a98c06..cc805b7 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -57,6 +57,8 @@ enum arch_timer_spi_nr {
 #define ARCH_TIMER_MEM_PHYS_ACCESS 2
 #define ARCH_TIMER_MEM_VIRT_ACCESS 3
 
+#define ARCH_TIMER_MEM_MAX_FRAMES  8
+
 #define ARCH_TIMER_USR_PCT_ACCESS_EN   (1 << 0) /* physical counter */
 #define ARCH_TIMER_USR_VCT_ACCESS_EN   (1 << 1) /* virtual counter */
 #define ARCH_TIMER_VIRT_EVT_EN (1 << 2)
@@ -72,6 +74,20 @@ struct arch_timer_kvm_info {
int virtual_irq;
 };
 
+struct arch_timer_mem_frame {
+   bool valid;
+   phys_addr_t cntbase;
+   size_t size;
+   int phys_irq;
+   int virt_irq;
+};
+
+struct arch_timer_mem {
+   phys_addr_t cntctlbase;
+   size_t size;
+   struct arch_timer_mem_frame frame[ARCH_TIMER_MEM_MAX_FRAMES];
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
-- 
2.9.3



[PATCH v23 03/11] clocksource: arm_arch_timer: refactor arch_timer_needs_probing

2017-03-31 Thread fu . wei
From: Fu Wei 

When booting with DT, it's possible for timer nodes to be probed in any
order. Some common initialisation needs to occur after all nodes have
been probed, and arch_timer_common_init() has code to detect when this
has happened.

This logic is DT-specific, and it would be best to factor it out of the
common code that will be shared with ACPI.

This patch folds this into the existing arch_timer_needs_probing(),
which is renamed to arch_timer_needs_of_probing(), and no longer takes
any arguments. This is only called when using DT, and not when using
ACPI, which will have a deterministic probe order.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
[Mark: reword commit message]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 1b6a7e6..ed215d9 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -839,15 +839,28 @@ static const struct of_device_id 
arch_timer_mem_of_match[] __initconst = {
{},
 };
 
-static bool __init
-arch_timer_needs_probing(int type, const struct of_device_id *matches)
+static bool __init arch_timer_needs_of_probing(void)
 {
struct device_node *dn;
bool needs_probing = false;
+   unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
 
-   dn = of_find_matching_node(NULL, matches);
-   if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
+   /* We have two timers, and both device-tree nodes are probed. */
+   if ((arch_timers_present & mask) == mask)
+   return false;
+
+   /*
+* Only one type of timer is probed,
+* check if we have another type of timer node in device-tree.
+*/
+   if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
+   dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
+   else
+   dn = of_find_matching_node(NULL, arch_timer_of_match);
+
+   if (dn && of_device_is_available(dn))
needs_probing = true;
+
of_node_put(dn);
 
return needs_probing;
@@ -855,17 +868,8 @@ arch_timer_needs_probing(int type, const struct 
of_device_id *matches)
 
 static int __init arch_timer_common_init(void)
 {
-   unsigned mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
-
-   /* Wait until both nodes are probed if we have two timers */
-   if ((arch_timers_present & mask) != mask) {
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_MEM,
-arch_timer_mem_of_match))
-   return 0;
-   if (arch_timer_needs_probing(ARCH_TIMER_TYPE_CP15,
-arch_timer_of_match))
-   return 0;
-   }
+   if (acpi_disabled && arch_timer_needs_of_probing())
+   return 0;
 
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
-- 
2.9.3



[PATCH v23 04/11] clocksource: arm_arch_timer: move arch_timer_needs_of_probing into DT init call

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

To cleanly split code paths specific to ACPI or DT at a higher level,
this patch removes arch_timer_init(), folding the relevant
parts of its logic into existing callers.

This patches the way for further rework, and saves a few lines.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
[Mark: reword commit message]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 46 
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index ed215d9..9433276 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -868,9 +868,6 @@ static bool __init arch_timer_needs_of_probing(void)
 
 static int __init arch_timer_common_init(void)
 {
-   if (acpi_disabled && arch_timer_needs_of_probing())
-   return 0;
-
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
return arch_timer_arch_init();
@@ -908,26 +905,9 @@ static enum arch_timer_ppi_nr __init 
arch_timer_select_ppi(void)
return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
-static int __init arch_timer_init(void)
-{
-   int ret;
-
-   ret = arch_timer_register();
-   if (ret)
-   return ret;
-
-   ret = arch_timer_common_init();
-   if (ret)
-   return ret;
-
-   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
-
-   return 0;
-}
-
 static int __init arch_timer_of_init(struct device_node *np)
 {
-   int i;
+   int i, ret;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("multiple nodes in dt, skipping\n");
@@ -938,6 +918,8 @@ static int __init arch_timer_of_init(struct device_node *np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/*
 * Determine the frequency of system counter:
 * Try to get the frequency from the device tree.
@@ -983,7 +965,14 @@ static int __init arch_timer_of_init(struct device_node 
*np)
arch_counter_suspend_stop = of_property_read_bool(np,
 
"arm,no-tick-in-suspend");
 
-   return arch_timer_init();
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   if (arch_timer_needs_of_probing())
+   return 0;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
@@ -1076,7 +1065,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
if (ret)
goto out;
 
-   return arch_timer_common_init();
+   if (!arch_timer_needs_of_probing())
+   ret = arch_timer_common_init();
 out:
iounmap(cntctlbase);
of_node_put(best_frame);
@@ -1105,6 +1095,7 @@ static int __init map_generic_timer_interrupt(u32 
interrupt, u32 flags)
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
+   int ret;
struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1132,6 +1123,8 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/* Get the frequency from the sysreg CNTFRQ */
arch_timer_rate = arch_timer_get_cntfrq();
if (!arch_timer_rate) {
@@ -1148,8 +1141,11 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
/* Always-on capability */
arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
 
-   arch_timer_init();
-   return 0;
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
 #endif
-- 
2.9.3



[PATCH v23 04/11] clocksource: arm_arch_timer: move arch_timer_needs_of_probing into DT init call

2017-03-31 Thread fu . wei
From: Fu Wei 

To cleanly split code paths specific to ACPI or DT at a higher level,
this patch removes arch_timer_init(), folding the relevant
parts of its logic into existing callers.

This patches the way for further rework, and saves a few lines.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
[Mark: reword commit message]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 46 
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index ed215d9..9433276 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -868,9 +868,6 @@ static bool __init arch_timer_needs_of_probing(void)
 
 static int __init arch_timer_common_init(void)
 {
-   if (acpi_disabled && arch_timer_needs_of_probing())
-   return 0;
-
arch_timer_banner(arch_timers_present);
arch_counter_register(arch_timers_present);
return arch_timer_arch_init();
@@ -908,26 +905,9 @@ static enum arch_timer_ppi_nr __init 
arch_timer_select_ppi(void)
return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
-static int __init arch_timer_init(void)
-{
-   int ret;
-
-   ret = arch_timer_register();
-   if (ret)
-   return ret;
-
-   ret = arch_timer_common_init();
-   if (ret)
-   return ret;
-
-   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
-
-   return 0;
-}
-
 static int __init arch_timer_of_init(struct device_node *np)
 {
-   int i;
+   int i, ret;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("multiple nodes in dt, skipping\n");
@@ -938,6 +918,8 @@ static int __init arch_timer_of_init(struct device_node *np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/*
 * Determine the frequency of system counter:
 * Try to get the frequency from the device tree.
@@ -983,7 +965,14 @@ static int __init arch_timer_of_init(struct device_node 
*np)
arch_counter_suspend_stop = of_property_read_bool(np,
 
"arm,no-tick-in-suspend");
 
-   return arch_timer_init();
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   if (arch_timer_needs_of_probing())
+   return 0;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", 
arch_timer_of_init);
 CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", 
arch_timer_of_init);
@@ -1076,7 +1065,8 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
if (ret)
goto out;
 
-   return arch_timer_common_init();
+   if (!arch_timer_needs_of_probing())
+   ret = arch_timer_common_init();
 out:
iounmap(cntctlbase);
of_node_put(best_frame);
@@ -1105,6 +1095,7 @@ static int __init map_generic_timer_interrupt(u32 
interrupt, u32 flags)
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
+   int ret;
struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
@@ -1132,6 +1123,8 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
+   arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
+
/* Get the frequency from the sysreg CNTFRQ */
arch_timer_rate = arch_timer_get_cntfrq();
if (!arch_timer_rate) {
@@ -1148,8 +1141,11 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
/* Always-on capability */
arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
 
-   arch_timer_init();
-   return 0;
+   ret = arch_timer_register();
+   if (ret)
+   return ret;
+
+   return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
 #endif
-- 
2.9.3



[PATCH v23 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patchset:
(1)Preparation for adding GTDT support in arm_arch_timer:
1. Introduce a MMIO CNTFRQ helper.
2. separate out device-tree code from arch_timer_detect_rate
3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
4. Refactor arch_timer_needs_probing, and move it into DT init call
5. Introduce some new structs and refactor the MMIO timer init code
for reusing some common code.

(2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
Parse all kinds of timer in GTDT table of ACPI:arch timer,
memory-mapped timer and SBSA Generic Watchdog timer.
This driver can help to simplify all the relevant timer drivers,
and separate all the ACPI GTDT knowledge from them.

(3)Simplify ACPI code for arm_arch_timer

(4)Add GTDT support for ARM memory-mapped timer.

This patchset has been tested on the following platforms with ACPI enabled:
(1)ARM Foundation v8 model

Changelog:
v23: https://lkml.org/lkml/2017/3/31/
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
 improve the parser of GT blocks and arch_timer_mem initualization.
 Improve arch_timer_rate detection: sysreg frequency is primary in DT boot
 Improve some comments in GTDT parser driver.
 Improve acpi_gtdt_init function, and make a comment for the multiple calls.
 Improve the unwinding for the irq of timers, when an error occurs.
 Handle the case of virtual timer GSIV is 0.

v22: https://lkml.org/lkml/2017/3/21/523
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
 Merged patch 2,3(about arch_timer_detect_rate).
 Keep arch_timer_rate, do NOT split it for different types of timer.
 Improve  memory-mapped timer support by comments and variable name:
 data-->timer_mem
 frame-->gtdt_frame
 Delete zero check for SBSA watchdog irq.
 Skip secure SBSA watchdog in GTDT driver.
 Delete Kconfig modification for SBSA watchdog driver.
 Delete no_irq, using nr_res instead.

v21: https://lkml.org/lkml/2017/2/6/734
 Introduce two functions to get the frequency from mmio and sysreg.
 Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
 Split arch_timer_rate for different types of timer.
 Skip secure timer frame in GTDT driver.
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 (The first 6 patches in v20 have been merged into arch-timer/cleanup 
branch)

v20: https://lkml.org/lkml/2017/1/18/534
 Reorder the first 4 patches and split the 4th patches.
 Leave CNTHCTL_* as they originally were.
 Fix the bug in arch_timer_select_ppi.
 Split "Rework counter frequency detection" patch.
 Rework the arch_timer_detect_rate function.
 Improve the commit message of "Refactor MMIO timer probing".
 Rebase to 4.10.0-rc4

v19: https://lkml.org/lkml/2016/12/21/25
 Fix a '\n' missing in a error message in arch_timer_mem_init.
 Add "request_mem_region" for ioremapping cntbase, according to
 f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
of_io_request_and_map()
 Rebase to 4.9.0-gfb779ff

v18: https://lkml.org/lkml/2016/12/8/446
 Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
 Rebase to 4.9.0-rc8-g9269898

v17: https://lkml.org/lkml/2016/11/25/140
 Take out some cleanups from 4/15.
 Merge 5/15 and 6/15, improve PPI determination code,
 improve commit message.
 Rework counter frequency detection.
 Move arch_timer_needs_of_probing into DT init call.
 Move Platform Timer scan loop back to timer init call to avoid allocating
 and free memory.
 Improve all the exported functions' comment.

v16: https://lkml.org/lkml/2016/11/16/268
 Fix patchset problem about static enum ppi_nr of 01/13 in v15.
 Refactor arch_timer_detect_rate.
 Refactor arch_timer_needs_probing.

v15: https://lkml.org/lkml/2016/11/15/366
 Re-order patches
 Add arm_arch_timer refactoring patches to prepare for GTDT:
 1. rename some  enums and defines, and some cleanups
 2. separate out arch_timer_uses_ppi init code and fix a potential bug
 3. Improve some new structs, refactor the timer init code.
 Since the some structs have been changed, GTDT parser for memory-mapped
 timer and SBSA Generic Watchdog timer have been update.

v14: https://lkml.org/lkml/2016/9/28/573
 Separate memory-mapped timer GTDT support into two patches
 1. Refactor the timer init code to prepare for GTDT
 2. Add GTDT support for memory-mapped timer

v13: http://www.mail-archive.com/linux-kernel@vger.ke

[PATCH v23 01/11] clocksource: arm_arch_timer: add MMIO CNTFRQ helper

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

We currently open-code the readl() for the MMIO time frequency. To avoid
duplicating the logic with future rework, this patch adds a helepr to
read the MMIO timer frequency, mirroring what we have for the sysreg
timer frequency.

Signed-off-by: Fu Wei <fu@linaro.org>
[Mark: reword commit message]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 3faed19..843f923 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -555,6 +555,11 @@ static int arch_timer_starting_cpu(unsigned int cpu)
return 0;
 }
 
+static u32 arch_timer_mem_get_cntfrq(void __iomem *cntbase)
+{
+   return readl_relaxed(cntbase + CNTFRQ);
+}
+
 static void
 arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
 {
@@ -569,7 +574,7 @@ arch_timer_detect_rate(void __iomem *cntbase, struct 
device_node *np)
if (!acpi_disabled ||
of_property_read_u32(np, "clock-frequency", _timer_rate)) {
if (cntbase)
-   arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
+   arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
else
arch_timer_rate = arch_timer_get_cntfrq();
}
-- 
2.9.3



[PATCH v23 02/11] clocksource: arm_arch_timer: split dt-only rate handling

2017-03-31 Thread fu . wei
From: Fu Wei <fu@linaro.org>

Currently Currently arch_timer_detect_rate() tried to handle both the
sysreg timer and MMIO timer, with DT-specific fallback code. This gets
in the way of implementing deterministic and correct rate probing when
using ACPI.

This patch moves this logic out into the (DT-specific) probe functions,
allowing different logic to be used in the ACPI case, and making it
easier to see which CNTFRQ register is being read in each case.

Signed-off-by: Fu Wei <fu@linaro.org>
[Mark: reword commit message, TODO: rework comments]
Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 58 +++-
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 843f923..1b6a7e6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem *cntbase)
return readl_relaxed(cntbase + CNTFRQ);
 }
 
-static void
-arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
-{
-   /* Who has more than one independent system counter? */
-   if (arch_timer_rate)
-   return;
-
-   /*
-* Try to determine the frequency from the device tree or CNTFRQ,
-* if ACPI is enabled, get the frequency from CNTFRQ ONLY.
-*/
-   if (!acpi_disabled ||
-   of_property_read_u32(np, "clock-frequency", _timer_rate)) {
-   if (cntbase)
-   arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
-   else
-   arch_timer_rate = arch_timer_get_cntfrq();
-   }
-
-   /* Check the timer frequency. */
-   if (arch_timer_rate == 0)
-   pr_warn("frequency not available\n");
-}
-
 static void arch_timer_banner(unsigned type)
 {
pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
@@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
-   arch_timer_detect_rate(NULL, np);
+   /*
+* Determine the frequency of system counter:
+* Try to get the frequency from the device tree.
+* If fail, try the sysreg CNTFRQ. Then verify the frequency.
+*/
+   if (of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
@@ -1069,7 +1055,19 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
goto out;
}
 
-   arch_timer_detect_rate(base, np);
+   /*
+* Try to determine the frequency from the device tree,
+* if fail, get the frequency from the CNTFRQ reg of MMIO timer.
+*/
+   if (!arch_timer_rate &&
+   of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = arch_timer_mem_get_cntfrq(base);
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "MMIO frequency not available.\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
ret = arch_timer_mem_register(base, irq);
if (ret)
goto out;
@@ -1130,8 +1128,12 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
-   /* Get the frequency from CNTFRQ */
-   arch_timer_detect_rate(NULL, NULL);
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
-- 
2.9.3



[PATCH v23 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-31 Thread fu . wei
From: Fu Wei 

This patchset:
(1)Preparation for adding GTDT support in arm_arch_timer:
1. Introduce a MMIO CNTFRQ helper.
2. separate out device-tree code from arch_timer_detect_rate
3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
4. Refactor arch_timer_needs_probing, and move it into DT init call
5. Introduce some new structs and refactor the MMIO timer init code
for reusing some common code.

(2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
Parse all kinds of timer in GTDT table of ACPI:arch timer,
memory-mapped timer and SBSA Generic Watchdog timer.
This driver can help to simplify all the relevant timer drivers,
and separate all the ACPI GTDT knowledge from them.

(3)Simplify ACPI code for arm_arch_timer

(4)Add GTDT support for ARM memory-mapped timer.

This patchset has been tested on the following platforms with ACPI enabled:
(1)ARM Foundation v8 model

Changelog:
v23: https://lkml.org/lkml/2017/3/31/
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Improve the data struct of arch_timer_mem and arch_timer_mem_frame to
 improve the parser of GT blocks and arch_timer_mem initualization.
 Improve arch_timer_rate detection: sysreg frequency is primary in DT boot
 Improve some comments in GTDT parser driver.
 Improve acpi_gtdt_init function, and make a comment for the multiple calls.
 Improve the unwinding for the irq of timers, when an error occurs.
 Handle the case of virtual timer GSIV is 0.

v22: https://lkml.org/lkml/2017/3/21/523
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
 Merged patch 2,3(about arch_timer_detect_rate).
 Keep arch_timer_rate, do NOT split it for different types of timer.
 Improve  memory-mapped timer support by comments and variable name:
 data-->timer_mem
 frame-->gtdt_frame
 Delete zero check for SBSA watchdog irq.
 Skip secure SBSA watchdog in GTDT driver.
 Delete Kconfig modification for SBSA watchdog driver.
 Delete no_irq, using nr_res instead.

v21: https://lkml.org/lkml/2017/2/6/734
 Introduce two functions to get the frequency from mmio and sysreg.
 Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
 Split arch_timer_rate for different types of timer.
 Skip secure timer frame in GTDT driver.
 Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arch-timer/cleanup
 (The first 6 patches in v20 have been merged into arch-timer/cleanup 
branch)

v20: https://lkml.org/lkml/2017/1/18/534
 Reorder the first 4 patches and split the 4th patches.
 Leave CNTHCTL_* as they originally were.
 Fix the bug in arch_timer_select_ppi.
 Split "Rework counter frequency detection" patch.
 Rework the arch_timer_detect_rate function.
 Improve the commit message of "Refactor MMIO timer probing".
 Rebase to 4.10.0-rc4

v19: https://lkml.org/lkml/2016/12/21/25
 Fix a '\n' missing in a error message in arch_timer_mem_init.
 Add "request_mem_region" for ioremapping cntbase, according to
 f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
of_io_request_and_map()
 Rebase to 4.9.0-gfb779ff

v18: https://lkml.org/lkml/2016/12/8/446
 Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
 Rebase to 4.9.0-rc8-g9269898

v17: https://lkml.org/lkml/2016/11/25/140
 Take out some cleanups from 4/15.
 Merge 5/15 and 6/15, improve PPI determination code,
 improve commit message.
 Rework counter frequency detection.
 Move arch_timer_needs_of_probing into DT init call.
 Move Platform Timer scan loop back to timer init call to avoid allocating
 and free memory.
 Improve all the exported functions' comment.

v16: https://lkml.org/lkml/2016/11/16/268
 Fix patchset problem about static enum ppi_nr of 01/13 in v15.
 Refactor arch_timer_detect_rate.
 Refactor arch_timer_needs_probing.

v15: https://lkml.org/lkml/2016/11/15/366
 Re-order patches
 Add arm_arch_timer refactoring patches to prepare for GTDT:
 1. rename some  enums and defines, and some cleanups
 2. separate out arch_timer_uses_ppi init code and fix a potential bug
 3. Improve some new structs, refactor the timer init code.
 Since the some structs have been changed, GTDT parser for memory-mapped
 timer and SBSA Generic Watchdog timer have been update.

v14: https://lkml.org/lkml/2016/9/28/573
 Separate memory-mapped timer GTDT support into two patches
 1. Refactor the timer init code to prepare for GTDT
 2. Add GTDT support for memory-mapped timer

v13: http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1231717.ht

[PATCH v23 01/11] clocksource: arm_arch_timer: add MMIO CNTFRQ helper

2017-03-31 Thread fu . wei
From: Fu Wei 

We currently open-code the readl() for the MMIO time frequency. To avoid
duplicating the logic with future rework, this patch adds a helepr to
read the MMIO timer frequency, mirroring what we have for the sysreg
timer frequency.

Signed-off-by: Fu Wei 
[Mark: reword commit message]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 3faed19..843f923 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -555,6 +555,11 @@ static int arch_timer_starting_cpu(unsigned int cpu)
return 0;
 }
 
+static u32 arch_timer_mem_get_cntfrq(void __iomem *cntbase)
+{
+   return readl_relaxed(cntbase + CNTFRQ);
+}
+
 static void
 arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
 {
@@ -569,7 +574,7 @@ arch_timer_detect_rate(void __iomem *cntbase, struct 
device_node *np)
if (!acpi_disabled ||
of_property_read_u32(np, "clock-frequency", _timer_rate)) {
if (cntbase)
-   arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
+   arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
else
arch_timer_rate = arch_timer_get_cntfrq();
}
-- 
2.9.3



[PATCH v23 02/11] clocksource: arm_arch_timer: split dt-only rate handling

2017-03-31 Thread fu . wei
From: Fu Wei 

Currently Currently arch_timer_detect_rate() tried to handle both the
sysreg timer and MMIO timer, with DT-specific fallback code. This gets
in the way of implementing deterministic and correct rate probing when
using ACPI.

This patch moves this logic out into the (DT-specific) probe functions,
allowing different logic to be used in the ACPI case, and making it
easier to see which CNTFRQ register is being read in each case.

Signed-off-by: Fu Wei 
[Mark: reword commit message, TODO: rework comments]
Signed-off-by: Mark Rutland 
---
 drivers/clocksource/arm_arch_timer.c | 58 +++-
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 843f923..1b6a7e6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem *cntbase)
return readl_relaxed(cntbase + CNTFRQ);
 }
 
-static void
-arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
-{
-   /* Who has more than one independent system counter? */
-   if (arch_timer_rate)
-   return;
-
-   /*
-* Try to determine the frequency from the device tree or CNTFRQ,
-* if ACPI is enabled, get the frequency from CNTFRQ ONLY.
-*/
-   if (!acpi_disabled ||
-   of_property_read_u32(np, "clock-frequency", _timer_rate)) {
-   if (cntbase)
-   arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
-   else
-   arch_timer_rate = arch_timer_get_cntfrq();
-   }
-
-   /* Check the timer frequency. */
-   if (arch_timer_rate == 0)
-   pr_warn("frequency not available\n");
-}
-
 static void arch_timer_banner(unsigned type)
 {
pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
@@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct device_node 
*np)
for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
 
-   arch_timer_detect_rate(NULL, np);
+   /*
+* Determine the frequency of system counter:
+* Try to get the frequency from the device tree.
+* If fail, try the sysreg CNTFRQ. Then verify the frequency.
+*/
+   if (of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
@@ -1069,7 +1055,19 @@ static int __init arch_timer_mem_init(struct device_node 
*np)
goto out;
}
 
-   arch_timer_detect_rate(base, np);
+   /*
+* Try to determine the frequency from the device tree,
+* if fail, get the frequency from the CNTFRQ reg of MMIO timer.
+*/
+   if (!arch_timer_rate &&
+   of_property_read_u32(np, "clock-frequency", _timer_rate))
+   arch_timer_rate = arch_timer_mem_get_cntfrq(base);
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "MMIO frequency not available.\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
ret = arch_timer_mem_register(base, irq);
if (ret)
goto out;
@@ -1130,8 +1128,12 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
gtdt->non_secure_el2_flags);
 
-   /* Get the frequency from CNTFRQ */
-   arch_timer_detect_rate(NULL, NULL);
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
-- 
2.9.3



Re: [PATCH v22 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-31 Thread Fu Wei
Hi Lorenzo,

On 28 March 2017 at 23:41, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 22, 2017 at 12:31:22AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> This driver adds support for parsing SBSA Generic Watchdog timer
>> in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
>> and creating a platform device with that information.
>>
>> This allows the operating system to obtain device data from the
>> resource of platform device. The platform device named "sbsa-gwdt"
>> can be used by the ARM SBSA Generic Watchdog driver.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>> Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
>> ---
>>  drivers/acpi/arm64/gtdt.c | 94 
>> +++
>>  1 file changed, 94 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index f471873..5d167f0 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -14,6 +14,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>
>>  #include 
>>
>> @@ -59,6 +60,17 @@ static inline bool is_timer_block(void *platform_timer)
>>   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>>  }
>>
>> +static inline bool is_non_secure_watchdog(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> + struct acpi_gtdt_watchdog *wd = platform_timer;
>> +
>> + if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
>> + return false;
>> +
>> + return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -285,3 +297,85 @@ int __init acpi_arch_timer_mem_init(struct 
>> arch_timer_mem *timer_mem,
>>
>>   return 0;
>>  }
>> +
>> +/*
>> + * Initialize a SBSA generic Watchdog platform device info from GTDT
>> + */
>> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
>> + int index)
>> +{
>> + struct platform_device *pdev;
>> + int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
>> +
>> + /*
>> +  * According to SBSA specification the size of refresh and control
>> +  * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
>> +  */
>> + struct resource res[] = {
>> + DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
>> + DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
>> + DEFINE_RES_IRQ(irq),
>> + };
>> + int nr_res = ARRAY_SIZE(res);
>> +
>> + pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
>> +  wd->refresh_frame_address, wd->control_frame_address,
>> +  wd->timer_interrupt, wd->timer_flags);
>> +
>> + if (!(wd->refresh_frame_address && wd->control_frame_address)) {
>> + pr_err(FW_BUG "failed to get the Watchdog base address.\n");


+ acpi_unregister_gsi(wd->timer_interrupt);


>> + return -EINVAL;
>
> You should unmap the gsi here.

yes, you are right, fixed it.

>
>> + }
>> +
>> + if (irq <= 0) {
>> + pr_warn("failed to map the Watchdog interrupt.\n");
>> + nr_res--;
>> + }
>> +
>> + /*
>> +  * Add a platform device named "sbsa-gwdt" to match the platform 
>> driver.
>> +  * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
>> +  * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get 
>> device

+  * The platform driver can get device info below by matching this name.

>
> Nit: I would not hardcode drivers paths in comments.


OK, deleted it

>
>> +  * info below by matching this name.
>> +  */
>> + pdev = platform_device_register_simple("sbsa-gwdt", index, res, 
>> nr_res);
>> + if (IS_ERR(pdev)) {
>> + acpi_unregister_gsi(wd->timer_interrupt);
>> + return PTR_ERR(pdev);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int __init gtdt_sbsa_gwdt_init(void)
>> +{
>> + int ret, i = 0;
>

Re: [PATCH v22 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-31 Thread Fu Wei
Hi Lorenzo,

On 28 March 2017 at 23:41, Lorenzo Pieralisi  wrote:
> On Wed, Mar 22, 2017 at 12:31:22AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> This driver adds support for parsing SBSA Generic Watchdog timer
>> in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
>> and creating a platform device with that information.
>>
>> This allows the operating system to obtain device data from the
>> resource of platform device. The platform device named "sbsa-gwdt"
>> can be used by the ARM SBSA Generic Watchdog driver.
>>
>> Signed-off-by: Fu Wei 
>> Signed-off-by: Hanjun Guo 
>> Tested-by: Xiongfeng Wang 
>> ---
>>  drivers/acpi/arm64/gtdt.c | 94 
>> +++
>>  1 file changed, 94 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index f471873..5d167f0 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -14,6 +14,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>
>>  #include 
>>
>> @@ -59,6 +60,17 @@ static inline bool is_timer_block(void *platform_timer)
>>   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>>  }
>>
>> +static inline bool is_non_secure_watchdog(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> + struct acpi_gtdt_watchdog *wd = platform_timer;
>> +
>> + if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
>> + return false;
>> +
>> + return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -285,3 +297,85 @@ int __init acpi_arch_timer_mem_init(struct 
>> arch_timer_mem *timer_mem,
>>
>>   return 0;
>>  }
>> +
>> +/*
>> + * Initialize a SBSA generic Watchdog platform device info from GTDT
>> + */
>> +static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
>> + int index)
>> +{
>> + struct platform_device *pdev;
>> + int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
>> +
>> + /*
>> +  * According to SBSA specification the size of refresh and control
>> +  * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
>> +  */
>> + struct resource res[] = {
>> + DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
>> + DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
>> + DEFINE_RES_IRQ(irq),
>> + };
>> + int nr_res = ARRAY_SIZE(res);
>> +
>> + pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
>> +  wd->refresh_frame_address, wd->control_frame_address,
>> +  wd->timer_interrupt, wd->timer_flags);
>> +
>> + if (!(wd->refresh_frame_address && wd->control_frame_address)) {
>> + pr_err(FW_BUG "failed to get the Watchdog base address.\n");


+ acpi_unregister_gsi(wd->timer_interrupt);


>> + return -EINVAL;
>
> You should unmap the gsi here.

yes, you are right, fixed it.

>
>> + }
>> +
>> + if (irq <= 0) {
>> + pr_warn("failed to map the Watchdog interrupt.\n");
>> + nr_res--;
>> + }
>> +
>> + /*
>> +  * Add a platform device named "sbsa-gwdt" to match the platform 
>> driver.
>> +  * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
>> +  * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get 
>> device

+  * The platform driver can get device info below by matching this name.

>
> Nit: I would not hardcode drivers paths in comments.


OK, deleted it

>
>> +  * info below by matching this name.
>> +  */
>> + pdev = platform_device_register_simple("sbsa-gwdt", index, res, 
>> nr_res);
>> + if (IS_ERR(pdev)) {
>> + acpi_unregister_gsi(wd->timer_interrupt);
>> + return PTR_ERR(pdev);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int __init gtdt_sbsa_gwdt_init(void)
>> +{
>> + int ret, i = 0;
>> + void *platform_timer;
>> + struct acpi_table_header *table;
>> +
>> + if (acpi_disabled)
>> +   

Re: [PATCH v22 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-30 Thread Fu Wei
Hi Lorenzo,

On 30 March 2017 at 00:47, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 22, 2017 at 12:31:20AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> On platforms booting with ACPI, architected memory-mapped timers'
>> configuration data is provided by firmware through the ACPI GTDT
>> static table.
>>
>> The clocksource architected timer kernel driver requires a firmware
>> interface to collect timer configuration and configure its driver.
>> this infrastructure is present for device tree systems, but it is
>> missing on systems booting with ACPI.
>>
>> Implement the kernel infrastructure required to parse the static
>> ACPI GTDT table so that the architected timer clocksource driver can
>> make use of it on systems booting with ACPI, therefore enabling
>> the corresponding timers configuration.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>> ---
>>  drivers/acpi/arm64/gtdt.c | 130 
>> ++
>>  include/linux/acpi.h  |   1 +
>>  2 files changed, 131 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index 8a03b4b..f471873 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor {
>>
>>  static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>
>> +static inline void *next_platform_timer(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + platform_timer += gh->length;
>> + if (platform_timer < acpi_gtdt_desc.gtdt_end)
>> + return platform_timer;
>> +
>> + return NULL;
>> +}
>> +
>> +#define for_each_platform_timer(_g)  \
>> + for (_g = acpi_gtdt_desc.platform_timer; _g;\
>> +  _g = next_platform_timer(_g))
>> +
>> +static inline bool is_timer_block(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -155,3 +177,111 @@ int __init acpi_gtdt_init(struct acpi_table_header 
>> *table,
>>
>>   return ret;
>>  }
>> +
>> +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block 
>> *block,
>> +  struct arch_timer_mem *timer_mem)
>> +{
>> + int i, j;
>> + struct acpi_gtdt_timer_entry *gtdt_frame;
>> +
>> + if (!block->timer_count) {
>> + pr_err(FW_BUG "GT block present, but frame count is zero.");
>> + return -ENODEV;
>> + }
>> +
>> + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
>> + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
>> 8\n",
>> +block->timer_count);
>> + return -EINVAL;
>> + }
>> +
>> + timer_mem->cntctlbase = (phys_addr_t)block->block_address;
>> + /*
>> +  * The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
>> +  * See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
>> +  * "CNTCTLBase memory map".
>> +  */
>> + timer_mem->size = SZ_4K;
>> +
>> + gtdt_frame = (void *)block + block->timer_offset;
>> + if (gtdt_frame + block->timer_count != (void *)block + 
>> block->header.length)
>> + return -EINVAL;
>> +
>> + /*
>> +  * Get the GT timer Frame data for every GT Block Timer
>> +  */
>> + for (i = 0, j = 0; i < block->timer_count; i++, gtdt_frame++) {
>> + struct arch_timer_mem_frame *frame = _mem->frame[j];
>> +
>> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> + continue;
>> +
>> + if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
>> + return -EINVAL;
>> +
>> + frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
>> +  gtdt_frame->timer_flags);
>> + if (frame->phys_irq <= 0) {
>

Re: [PATCH v22 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-30 Thread Fu Wei
Hi Lorenzo,

On 30 March 2017 at 00:47, Lorenzo Pieralisi  wrote:
> On Wed, Mar 22, 2017 at 12:31:20AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> On platforms booting with ACPI, architected memory-mapped timers'
>> configuration data is provided by firmware through the ACPI GTDT
>> static table.
>>
>> The clocksource architected timer kernel driver requires a firmware
>> interface to collect timer configuration and configure its driver.
>> this infrastructure is present for device tree systems, but it is
>> missing on systems booting with ACPI.
>>
>> Implement the kernel infrastructure required to parse the static
>> ACPI GTDT table so that the architected timer clocksource driver can
>> make use of it on systems booting with ACPI, therefore enabling
>> the corresponding timers configuration.
>>
>> Signed-off-by: Fu Wei 
>> Signed-off-by: Hanjun Guo 
>> ---
>>  drivers/acpi/arm64/gtdt.c | 130 
>> ++
>>  include/linux/acpi.h  |   1 +
>>  2 files changed, 131 insertions(+)
>>
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> index 8a03b4b..f471873 100644
>> --- a/drivers/acpi/arm64/gtdt.c
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor {
>>
>>  static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>
>> +static inline void *next_platform_timer(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + platform_timer += gh->length;
>> + if (platform_timer < acpi_gtdt_desc.gtdt_end)
>> + return platform_timer;
>> +
>> + return NULL;
>> +}
>> +
>> +#define for_each_platform_timer(_g)  \
>> + for (_g = acpi_gtdt_desc.platform_timer; _g;\
>> +  _g = next_platform_timer(_g))
>> +
>> +static inline bool is_timer_block(void *platform_timer)
>> +{
>> + struct acpi_gtdt_header *gh = platform_timer;
>> +
>> + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
>> +}
>> +
>>  static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>  {
>>   int trigger, polarity;
>> @@ -155,3 +177,111 @@ int __init acpi_gtdt_init(struct acpi_table_header 
>> *table,
>>
>>   return ret;
>>  }
>> +
>> +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block 
>> *block,
>> +  struct arch_timer_mem *timer_mem)
>> +{
>> + int i, j;
>> + struct acpi_gtdt_timer_entry *gtdt_frame;
>> +
>> + if (!block->timer_count) {
>> + pr_err(FW_BUG "GT block present, but frame count is zero.");
>> + return -ENODEV;
>> + }
>> +
>> + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
>> + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
>> 8\n",
>> +block->timer_count);
>> + return -EINVAL;
>> + }
>> +
>> + timer_mem->cntctlbase = (phys_addr_t)block->block_address;
>> + /*
>> +  * The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
>> +  * See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
>> +  * "CNTCTLBase memory map".
>> +  */
>> + timer_mem->size = SZ_4K;
>> +
>> + gtdt_frame = (void *)block + block->timer_offset;
>> + if (gtdt_frame + block->timer_count != (void *)block + 
>> block->header.length)
>> + return -EINVAL;
>> +
>> + /*
>> +  * Get the GT timer Frame data for every GT Block Timer
>> +  */
>> + for (i = 0, j = 0; i < block->timer_count; i++, gtdt_frame++) {
>> + struct arch_timer_mem_frame *frame = _mem->frame[j];
>> +
>> + if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
>> + continue;
>> +
>> + if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
>> + return -EINVAL;
>> +
>> + frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
>> +  gtdt_frame->timer_flags);
>> + if (frame->phys_irq <= 0) {
>> + pr_warn("failed to map physical timer irq in frame 
>> %d.\n",
>> + i);
>>

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-29 Thread Fu Wei
On 29 March 2017 at 22:41, Daniel Lezcano <daniel.lezc...@linaro.org> wrote:
> On Wed, Mar 29, 2017 at 01:11:58PM +0800, Fu Wei wrote:
>> Hi Daniel,
>>
>> On 29 March 2017 at 11:41, Fu Wei <fu@linaro.org> wrote:
>> > Hi Daniel,
>> >
>> > Great thanks for your review, allow me to answer your question below:
>> >
>> > On 28 March 2017 at 22:58, Daniel Lezcano <daniel.lezc...@linaro.org> 
>> > wrote:
>> >> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu@linaro.org wrote:
>> >>> From: Fu Wei <fu@linaro.org>
>> >>>
>> >>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>> >>> includes getting the frequency from the device-tree property, the per-cpu
>> >>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>> >>> But reading device-tree property will be needed only when system boot 
>> >>> with
>> >>> device-tree, and reading from the per-cpu arch-timer and the 
>> >>> memory-mapped
>> >>> (MMIO) timer interfaces will be needed only when the system initializes
>> >>> the relevant timer.
>> >>>
>> >>> This patch separates out device-tree code, keep them in device-tree init
>> >>> function, and removes arch_timer_detect_rate founction, then uses the
>> >>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>> >>>
>> >>> Signed-off-by: Fu Wei <fu@linaro.org>
>> >>> ---
>> >>>  drivers/clocksource/arm_arch_timer.c | 58 
>> >>> +++-
>> >>>  1 file changed, 30 insertions(+), 28 deletions(-)
>> >>>
>> >>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>> >>> b/drivers/clocksource/arm_arch_timer.c
>> >>> index 843f923..29ca7d6 100644
>> >>> --- a/drivers/clocksource/arm_arch_timer.c
>> >>> +++ b/drivers/clocksource/arm_arch_timer.c
>> >>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>> >>> *cntbase)
>> >>>   return readl_relaxed(cntbase + CNTFRQ);
>> >>>  }
>> >>>
>> >>> -static void
>> >>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>> >>> -{
>> >>> - /* Who has more than one independent system counter? */
>> >>> - if (arch_timer_rate)
>> >>> - return;
>> >>> -
>> >>> - /*
>> >>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>> >>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>> >>> -  */
>> >>> - if (!acpi_disabled ||
>> >>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) 
>> >>> {
>> >>> - if (cntbase)
>> >>> - arch_timer_rate = 
>> >>> arch_timer_mem_get_cntfrq(cntbase);
>> >>> - else
>> >>> - arch_timer_rate = arch_timer_get_cntfrq();
>> >>> - }
>> >>> -
>> >>> - /* Check the timer frequency. */
>> >>> - if (arch_timer_rate == 0)
>> >>> - pr_warn("frequency not available\n");
>> >>> -}
>> >>> -
>> >>>  static void arch_timer_banner(unsigned type)
>> >>>  {
>> >>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>> >>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct 
>> >>> device_node *np)
>> >>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; 
>> >>> i++)
>> >>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>> >>>
>> >>> - arch_timer_detect_rate(NULL, np);
>> >>> + /*
>> >>> +  * Try to determine the frequency from the device tree,
>> >>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>> >>> +  */
>> >>> + if (!arch_timer_rate &&
>> >>
>> >> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" 
>> >> are
>> >> declared together in the DT, right ?

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-29 Thread Fu Wei
On 29 March 2017 at 22:41, Daniel Lezcano  wrote:
> On Wed, Mar 29, 2017 at 01:11:58PM +0800, Fu Wei wrote:
>> Hi Daniel,
>>
>> On 29 March 2017 at 11:41, Fu Wei  wrote:
>> > Hi Daniel,
>> >
>> > Great thanks for your review, allow me to answer your question below:
>> >
>> > On 28 March 2017 at 22:58, Daniel Lezcano  
>> > wrote:
>> >> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu@linaro.org wrote:
>> >>> From: Fu Wei 
>> >>>
>> >>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>> >>> includes getting the frequency from the device-tree property, the per-cpu
>> >>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>> >>> But reading device-tree property will be needed only when system boot 
>> >>> with
>> >>> device-tree, and reading from the per-cpu arch-timer and the 
>> >>> memory-mapped
>> >>> (MMIO) timer interfaces will be needed only when the system initializes
>> >>> the relevant timer.
>> >>>
>> >>> This patch separates out device-tree code, keep them in device-tree init
>> >>> function, and removes arch_timer_detect_rate founction, then uses the
>> >>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>> >>>
>> >>> Signed-off-by: Fu Wei 
>> >>> ---
>> >>>  drivers/clocksource/arm_arch_timer.c | 58 
>> >>> +++-
>> >>>  1 file changed, 30 insertions(+), 28 deletions(-)
>> >>>
>> >>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>> >>> b/drivers/clocksource/arm_arch_timer.c
>> >>> index 843f923..29ca7d6 100644
>> >>> --- a/drivers/clocksource/arm_arch_timer.c
>> >>> +++ b/drivers/clocksource/arm_arch_timer.c
>> >>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>> >>> *cntbase)
>> >>>   return readl_relaxed(cntbase + CNTFRQ);
>> >>>  }
>> >>>
>> >>> -static void
>> >>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>> >>> -{
>> >>> - /* Who has more than one independent system counter? */
>> >>> - if (arch_timer_rate)
>> >>> - return;
>> >>> -
>> >>> - /*
>> >>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>> >>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>> >>> -  */
>> >>> - if (!acpi_disabled ||
>> >>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) 
>> >>> {
>> >>> - if (cntbase)
>> >>> - arch_timer_rate = 
>> >>> arch_timer_mem_get_cntfrq(cntbase);
>> >>> - else
>> >>> - arch_timer_rate = arch_timer_get_cntfrq();
>> >>> - }
>> >>> -
>> >>> - /* Check the timer frequency. */
>> >>> - if (arch_timer_rate == 0)
>> >>> - pr_warn("frequency not available\n");
>> >>> -}
>> >>> -
>> >>>  static void arch_timer_banner(unsigned type)
>> >>>  {
>> >>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>> >>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct 
>> >>> device_node *np)
>> >>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; 
>> >>> i++)
>> >>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>> >>>
>> >>> - arch_timer_detect_rate(NULL, np);
>> >>> + /*
>> >>> +  * Try to determine the frequency from the device tree,
>> >>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>> >>> +  */
>> >>> + if (!arch_timer_rate &&
>> >>
>> >> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" 
>> >> are
>> >> declared together in the DT, right ?
>> >>
>> >> Two declarations for a single variable ? Ignore the !arch_timer_rate.
>> >
>> > In this functio

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
On 29 March 2017 at 22:29, Fu Wei <fu@linaro.org> wrote:
> Hi Lorenzo,
>
> On 28 March 2017 at 19:35, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> 
> wrote:
>> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu....@linaro.org wrote:
>>> From: Fu Wei <fu@linaro.org>
>>>
>>> This patch adds support for parsing arch timer info in GTDT,
>>> provides some kernel APIs to parse all the PPIs and
>>> always-on info in GTDT and export them.
>>>
>>> By this driver, we can simplify arm_arch_timer drivers, and
>>> separate the ACPI GTDT knowledge from it.
>>>
>>> Signed-off-by: Fu Wei <fu@linaro.org>
>>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>>> Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
>>
>> Acked-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
>>
>> Some nits below.
>>
>>> Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
>>> Reviewed-by: Hanjun Guo <hanjun@linaro.org>
>>> Tested-by: Hanjun Guo <hanjun@linaro.org>
>>> ---
>>>  arch/arm64/Kconfig  |   1 +
>>>  drivers/acpi/arm64/Kconfig  |   3 +
>>>  drivers/acpi/arm64/Makefile |   1 +
>>>  drivers/acpi/arm64/gtdt.c   | 157 
>>> 
>>>  include/linux/acpi.h|   6 ++
>>>  5 files changed, 168 insertions(+)
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 3741859..7e2baec 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -2,6 +2,7 @@ config ARM64
>>>   def_bool y
>>>   select ACPI_CCA_REQUIRED if ACPI
>>>   select ACPI_GENERIC_GSI if ACPI
>>> + select ACPI_GTDT if ACPI
>>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>>   select ACPI_MCFG if ACPI
>>>   select ACPI_SPCR_TABLE if ACPI
>>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>>> index 4616da4..5a6f80f 100644
>>> --- a/drivers/acpi/arm64/Kconfig
>>> +++ b/drivers/acpi/arm64/Kconfig
>>> @@ -4,3 +4,6 @@
>>>
>>>  config ACPI_IORT
>>>   bool
>>> +
>>> +config ACPI_GTDT
>>> + bool
>>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>>> index 72331f2..1017def 100644
>>> --- a/drivers/acpi/arm64/Makefile
>>> +++ b/drivers/acpi/arm64/Makefile
>>> @@ -1 +1,2 @@
>>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>>> new file mode 100644
>>> index 000..8a03b4b
>>> --- /dev/null
>>> +++ b/drivers/acpi/arm64/gtdt.c
>>> @@ -0,0 +1,157 @@
>>> +/*
>>> + * ARM Specific GTDT table Support
>>> + *
>>> + * Copyright (C) 2016, Linaro Ltd.
>>> + * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
>>> + * Fu Wei <fu@linaro.org>
>>> + * Hanjun Guo <hanjun@linaro.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include 
>>> +#include 
>>> +#include 
>>> +
>>> +#include 
>>> +
>>> +#undef pr_fmt
>>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>>> +
>>> +/**
>>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>>> functions
>>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>>> + * @gtdt_end:The pointer to the end of GTDT table.
>>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>>> + *
>>> + * The struct store the key info of GTDT table, it should be initialized by
>>> + * acpi_gtdt_init.
>>> + */
>>> +struct acpi_gtdt_descriptor {
>>> + struct acpi_table_gtdt *gtdt;
>>> + void *gtdt_end;
>>> + void *platform_timer;
>>> +};
>>> +
>>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>> +
>>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>> +{
>>> + int trigger, polarity;
>>> +
>>> 

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
On 29 March 2017 at 22:29, Fu Wei  wrote:
> Hi Lorenzo,
>
> On 28 March 2017 at 19:35, Lorenzo Pieralisi  
> wrote:
>> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu@linaro.org wrote:
>>> From: Fu Wei 
>>>
>>> This patch adds support for parsing arch timer info in GTDT,
>>> provides some kernel APIs to parse all the PPIs and
>>> always-on info in GTDT and export them.
>>>
>>> By this driver, we can simplify arm_arch_timer drivers, and
>>> separate the ACPI GTDT knowledge from it.
>>>
>>> Signed-off-by: Fu Wei 
>>> Signed-off-by: Hanjun Guo 
>>> Acked-by: Rafael J. Wysocki 
>>
>> Acked-by: Lorenzo Pieralisi 
>>
>> Some nits below.
>>
>>> Tested-by: Xiongfeng Wang 
>>> Reviewed-by: Hanjun Guo 
>>> Tested-by: Hanjun Guo 
>>> ---
>>>  arch/arm64/Kconfig  |   1 +
>>>  drivers/acpi/arm64/Kconfig  |   3 +
>>>  drivers/acpi/arm64/Makefile |   1 +
>>>  drivers/acpi/arm64/gtdt.c   | 157 
>>> 
>>>  include/linux/acpi.h|   6 ++
>>>  5 files changed, 168 insertions(+)
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 3741859..7e2baec 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -2,6 +2,7 @@ config ARM64
>>>   def_bool y
>>>   select ACPI_CCA_REQUIRED if ACPI
>>>   select ACPI_GENERIC_GSI if ACPI
>>> + select ACPI_GTDT if ACPI
>>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>>   select ACPI_MCFG if ACPI
>>>   select ACPI_SPCR_TABLE if ACPI
>>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>>> index 4616da4..5a6f80f 100644
>>> --- a/drivers/acpi/arm64/Kconfig
>>> +++ b/drivers/acpi/arm64/Kconfig
>>> @@ -4,3 +4,6 @@
>>>
>>>  config ACPI_IORT
>>>   bool
>>> +
>>> +config ACPI_GTDT
>>> + bool
>>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>>> index 72331f2..1017def 100644
>>> --- a/drivers/acpi/arm64/Makefile
>>> +++ b/drivers/acpi/arm64/Makefile
>>> @@ -1 +1,2 @@
>>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>>> new file mode 100644
>>> index 000..8a03b4b
>>> --- /dev/null
>>> +++ b/drivers/acpi/arm64/gtdt.c
>>> @@ -0,0 +1,157 @@
>>> +/*
>>> + * ARM Specific GTDT table Support
>>> + *
>>> + * Copyright (C) 2016, Linaro Ltd.
>>> + * Author: Daniel Lezcano 
>>> + * Fu Wei 
>>> + * Hanjun Guo 
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include 
>>> +#include 
>>> +#include 
>>> +
>>> +#include 
>>> +
>>> +#undef pr_fmt
>>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>>> +
>>> +/**
>>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>>> functions
>>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>>> + * @gtdt_end:The pointer to the end of GTDT table.
>>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>>> + *
>>> + * The struct store the key info of GTDT table, it should be initialized by
>>> + * acpi_gtdt_init.
>>> + */
>>> +struct acpi_gtdt_descriptor {
>>> + struct acpi_table_gtdt *gtdt;
>>> + void *gtdt_end;
>>> + void *platform_timer;
>>> +};
>>> +
>>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>>> +
>>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>>> +{
>>> + int trigger, polarity;
>>> +
>>> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>>> + : ACPI_LEVEL_SENSITIVE;
>>> +
>>> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>>> + : ACPI_ACTIVE_HIGH;
>>> +
>>> + return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>>> +}
>>&g

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 28 March 2017 at 19:35, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> This patch adds support for parsing arch timer info in GTDT,
>> provides some kernel APIs to parse all the PPIs and
>> always-on info in GTDT and export them.
>>
>> By this driver, we can simplify arm_arch_timer drivers, and
>> separate the ACPI GTDT knowledge from it.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>> Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
>
> Acked-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
>
> Some nits below.
>
>> Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
>> Reviewed-by: Hanjun Guo <hanjun@linaro.org>
>> Tested-by: Hanjun Guo <hanjun@linaro.org>
>> ---
>>  arch/arm64/Kconfig  |   1 +
>>  drivers/acpi/arm64/Kconfig  |   3 +
>>  drivers/acpi/arm64/Makefile |   1 +
>>  drivers/acpi/arm64/gtdt.c   | 157 
>> 
>>  include/linux/acpi.h|   6 ++
>>  5 files changed, 168 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 3741859..7e2baec 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2,6 +2,7 @@ config ARM64
>>   def_bool y
>>   select ACPI_CCA_REQUIRED if ACPI
>>   select ACPI_GENERIC_GSI if ACPI
>> + select ACPI_GTDT if ACPI
>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>   select ACPI_MCFG if ACPI
>>   select ACPI_SPCR_TABLE if ACPI
>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>> index 4616da4..5a6f80f 100644
>> --- a/drivers/acpi/arm64/Kconfig
>> +++ b/drivers/acpi/arm64/Kconfig
>> @@ -4,3 +4,6 @@
>>
>>  config ACPI_IORT
>>   bool
>> +
>> +config ACPI_GTDT
>> + bool
>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>> index 72331f2..1017def 100644
>> --- a/drivers/acpi/arm64/Makefile
>> +++ b/drivers/acpi/arm64/Makefile
>> @@ -1 +1,2 @@
>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> new file mode 100644
>> index 000..8a03b4b
>> --- /dev/null
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -0,0 +1,157 @@
>> +/*
>> + * ARM Specific GTDT table Support
>> + *
>> + * Copyright (C) 2016, Linaro Ltd.
>> + * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
>> + * Fu Wei <fu@linaro.org>
>> + * Hanjun Guo <hanjun@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#undef pr_fmt
>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>> +
>> +/**
>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>> functions
>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>> + * @gtdt_end:The pointer to the end of GTDT table.
>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>> + *
>> + * The struct store the key info of GTDT table, it should be initialized by
>> + * acpi_gtdt_init.
>> + */
>> +struct acpi_gtdt_descriptor {
>> + struct acpi_table_gtdt *gtdt;
>> + void *gtdt_end;
>> + void *platform_timer;
>> +};
>> +
>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>> +
>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>> +{
>> + int trigger, polarity;
>> +
>> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>> + : ACPI_LEVEL_SENSITIVE;
>> +
>> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>> + : ACPI_ACTIVE_HIGH;
>> +
>> + return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>> +}
>> +
>> +/**
>> + * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
>> + * @type:the type of PPI.
>> + *
>> + * Note: Linux on arm64 isn't

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 28 March 2017 at 19:35, Lorenzo Pieralisi  wrote:
> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> This patch adds support for parsing arch timer info in GTDT,
>> provides some kernel APIs to parse all the PPIs and
>> always-on info in GTDT and export them.
>>
>> By this driver, we can simplify arm_arch_timer drivers, and
>> separate the ACPI GTDT knowledge from it.
>>
>> Signed-off-by: Fu Wei 
>> Signed-off-by: Hanjun Guo 
>> Acked-by: Rafael J. Wysocki 
>
> Acked-by: Lorenzo Pieralisi 
>
> Some nits below.
>
>> Tested-by: Xiongfeng Wang 
>> Reviewed-by: Hanjun Guo 
>> Tested-by: Hanjun Guo 
>> ---
>>  arch/arm64/Kconfig  |   1 +
>>  drivers/acpi/arm64/Kconfig  |   3 +
>>  drivers/acpi/arm64/Makefile |   1 +
>>  drivers/acpi/arm64/gtdt.c   | 157 
>> 
>>  include/linux/acpi.h|   6 ++
>>  5 files changed, 168 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 3741859..7e2baec 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2,6 +2,7 @@ config ARM64
>>   def_bool y
>>   select ACPI_CCA_REQUIRED if ACPI
>>   select ACPI_GENERIC_GSI if ACPI
>> + select ACPI_GTDT if ACPI
>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>   select ACPI_MCFG if ACPI
>>   select ACPI_SPCR_TABLE if ACPI
>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>> index 4616da4..5a6f80f 100644
>> --- a/drivers/acpi/arm64/Kconfig
>> +++ b/drivers/acpi/arm64/Kconfig
>> @@ -4,3 +4,6 @@
>>
>>  config ACPI_IORT
>>   bool
>> +
>> +config ACPI_GTDT
>> + bool
>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>> index 72331f2..1017def 100644
>> --- a/drivers/acpi/arm64/Makefile
>> +++ b/drivers/acpi/arm64/Makefile
>> @@ -1 +1,2 @@
>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> new file mode 100644
>> index 000..8a03b4b
>> --- /dev/null
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -0,0 +1,157 @@
>> +/*
>> + * ARM Specific GTDT table Support
>> + *
>> + * Copyright (C) 2016, Linaro Ltd.
>> + * Author: Daniel Lezcano 
>> + * Fu Wei 
>> + * Hanjun Guo 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#undef pr_fmt
>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>> +
>> +/**
>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>> functions
>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>> + * @gtdt_end:The pointer to the end of GTDT table.
>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>> + *
>> + * The struct store the key info of GTDT table, it should be initialized by
>> + * acpi_gtdt_init.
>> + */
>> +struct acpi_gtdt_descriptor {
>> + struct acpi_table_gtdt *gtdt;
>> + void *gtdt_end;
>> + void *platform_timer;
>> +};
>> +
>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>> +
>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>> +{
>> + int trigger, polarity;
>> +
>> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>> + : ACPI_LEVEL_SENSITIVE;
>> +
>> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>> + : ACPI_ACTIVE_HIGH;
>> +
>> + return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>> +}
>> +
>> +/**
>> + * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
>> + * @type:the type of PPI.
>> + *
>> + * Note: Linux on arm64 isn't supported on the secure side.
>
> Note: Secure state is not managed by the kernel on ARM64 systems.
>
> Is that what you wanted to say ?
>
>> + * So we only handle the non-secure timer PPIs,
>> + * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
>> + *
>> + * Return: the mapped PPI value, 0 if error.
&

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 29 March 2017 at 19:33, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 29, 2017 at 06:48:26PM +0800, Fu Wei wrote:
>> Hi Lorenzo,
>>
>> On 29 March 2017 at 18:21, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> 
>> wrote:
>> > On Wed, Mar 29, 2017 at 05:48:17PM +0800, Fu Wei wrote:
>> >
>> > [...]
>> >
>> >>  * @platform_timer_count: It points to a integer variable which is used
>> >>  *   for storing the number of platform timers.
>> >>  *   This pointer could be NULL, if the caller
>> >>  *   doesn't need this info.
>> >>
>> >> >
>> >> >> + *
>> >> >> + * Return: 0 if success, -EINVAL if error.
>> >> >> + */
>> >> >> +int __init acpi_gtdt_init(struct acpi_table_header *table,
>> >> >> +   int *platform_timer_count)
>> >> >> +{
>> >> >> + int ret = 0;
>> >> >> + int timer_count = 0;
>> >> >> + void *platform_timer = NULL;
>> >> >> + struct acpi_table_gtdt *gtdt;
>> >> >> +
>> >> >> + gtdt = container_of(table, struct acpi_table_gtdt, header);
>> >> >> + acpi_gtdt_desc.gtdt = gtdt;
>> >> >> + acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
>> >> >> +
>> >> >> + if (table->revision < 2)
>> >> >> + pr_warn("Revision:%d doesn't support Platform Timers.\n",
>> >> >> + table->revision);
>> >> >
>> >> > Ok, two points here. First, I am not sure why you should warn if the
>> >> > table revision is < 2, is that a FW bug ? I do not think it is, you
>> >> > can just return 0.
>> >>
>> >> I used pr_debug here before v20, then I got Hanjun's suggestion:
>> >> ---
>> >> GTDT table revision is updated to 2 in ACPI 5.1, we will
>> >> not support ACPI version under 5.1 and disable ACPI in FADT
>> >> parse before this code is called, so if we get revision
>> >> <2 here, I think we need to print warning (we need to keep
>> >> the firmware stick to the spec on ARM64).
>> >> ---
>> >> https://lkml.org/lkml/2017/1/19/82
>> >>
>> >> So I started to use pr_warn.
>> >
>> > Thanks for the explanation, so it is a FW bug and the warning
>> > is granted :) just leave it there.
>> >
>> > Still, please check my comment on acpi_gtdt_init() being called
>> > multiple times on patch 11.
>>
>> Thanks
>>
>> For calling acpi_gtdt_init() twice:
>> (1) 1st time: in early boot(bootmem), for init arch_timer and
>> memory-mapped timer, we initialize the acpi_gtdt_desc.
>> you can see that all the items in this struct are pointer.
>> (2) 2nd time: when system switch from bootmem to slab, all the
>> pointers in the acpi_gtdt_desc are invalid, so we have to
>> re-initialize(re-map) them.
>>
>> I have tested it, if we don't re-initialize  the acpi_gtdt_desc,
>> system will go wrong.
>
> Ok, that's what I feared. My complaint on patch 11 is that:
>
> 1) Stashing the GTDT pointer in acpi_gtdt_desc is not needed to
>parse SBSA watchdogs

The acpi_gtdt_desc is for sharing the info between acpi_gtdt_init and
acpi_gtdt_c3stop, ;acpi_gtdt_map_ppi
I re-use it in parsing SBSA watchdogs, because I try to re-use acpi_gtdt_init.

> 2) It is not clear at all from the code or the commit log _why_ you
>need to call acpi_gtdt_init() again (ie technically you don't need
>to call it - you grab a valid pointer to the table and parse the
>watchdogs in the _same_ function gtdt_sbsa_gwdt_init())

yes, we can avoid calling acpi_gtdt_init(), do the same thing in
parsing SBSA watchdogs info.
But if we will do the same thing(getting gtdt, platform_timer,
timer_count), why not just re-using the same function?

So my suggestion is that:
Could we re-use acpi_gtdt_init, and a comment at the head of SBSA
watchdogs info parsing function to summarize this issue?
The comment like this

Note: although the global variable acpi_gtdt_desc has been initialized
by acpi_gtdt_init, when we initialized arch_timer. But when we call this
function to get SBSA watchdogs info from GTDT, the system has switch
from bootmem  to slab, so the pointers in acpi_gtdt_desc are dated, we
need to  re-initialize(remap) them. So we call acpi_gtdt_init again here.

Is that OK for you? :-)

>
> I do not think there is much you can do to improve the arch timer gtdt
> interface (and it is too late for that anyway) but in patch 11 it would
> be ideal if you avoid calling acpi_gtdt_init() again, just parse GTDT
> entries and initialize the corresponding watchdogs (ie pointers stashed
> in acpi_gtdt_desc are stale anyway but that's __initdata so I can live
> with that).
>
> You should add comments to summarize this issue so that it can be
> easily understood by anyone maintaining this code, it is not crystal
> clear by reading the code why you need to multiple acpi_gtdt_init()
> calls and that's not a piffling detail.
>
> The ACPI patches are fine with me otherwise, I will complete the
> review shortly.
>
> Thanks !
> Lorenzo



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 29 March 2017 at 19:33, Lorenzo Pieralisi  wrote:
> On Wed, Mar 29, 2017 at 06:48:26PM +0800, Fu Wei wrote:
>> Hi Lorenzo,
>>
>> On 29 March 2017 at 18:21, Lorenzo Pieralisi  
>> wrote:
>> > On Wed, Mar 29, 2017 at 05:48:17PM +0800, Fu Wei wrote:
>> >
>> > [...]
>> >
>> >>  * @platform_timer_count: It points to a integer variable which is used
>> >>  *   for storing the number of platform timers.
>> >>  *   This pointer could be NULL, if the caller
>> >>  *   doesn't need this info.
>> >>
>> >> >
>> >> >> + *
>> >> >> + * Return: 0 if success, -EINVAL if error.
>> >> >> + */
>> >> >> +int __init acpi_gtdt_init(struct acpi_table_header *table,
>> >> >> +   int *platform_timer_count)
>> >> >> +{
>> >> >> + int ret = 0;
>> >> >> + int timer_count = 0;
>> >> >> + void *platform_timer = NULL;
>> >> >> + struct acpi_table_gtdt *gtdt;
>> >> >> +
>> >> >> + gtdt = container_of(table, struct acpi_table_gtdt, header);
>> >> >> + acpi_gtdt_desc.gtdt = gtdt;
>> >> >> + acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
>> >> >> +
>> >> >> + if (table->revision < 2)
>> >> >> + pr_warn("Revision:%d doesn't support Platform Timers.\n",
>> >> >> + table->revision);
>> >> >
>> >> > Ok, two points here. First, I am not sure why you should warn if the
>> >> > table revision is < 2, is that a FW bug ? I do not think it is, you
>> >> > can just return 0.
>> >>
>> >> I used pr_debug here before v20, then I got Hanjun's suggestion:
>> >> ---
>> >> GTDT table revision is updated to 2 in ACPI 5.1, we will
>> >> not support ACPI version under 5.1 and disable ACPI in FADT
>> >> parse before this code is called, so if we get revision
>> >> <2 here, I think we need to print warning (we need to keep
>> >> the firmware stick to the spec on ARM64).
>> >> ---
>> >> https://lkml.org/lkml/2017/1/19/82
>> >>
>> >> So I started to use pr_warn.
>> >
>> > Thanks for the explanation, so it is a FW bug and the warning
>> > is granted :) just leave it there.
>> >
>> > Still, please check my comment on acpi_gtdt_init() being called
>> > multiple times on patch 11.
>>
>> Thanks
>>
>> For calling acpi_gtdt_init() twice:
>> (1) 1st time: in early boot(bootmem), for init arch_timer and
>> memory-mapped timer, we initialize the acpi_gtdt_desc.
>> you can see that all the items in this struct are pointer.
>> (2) 2nd time: when system switch from bootmem to slab, all the
>> pointers in the acpi_gtdt_desc are invalid, so we have to
>> re-initialize(re-map) them.
>>
>> I have tested it, if we don't re-initialize  the acpi_gtdt_desc,
>> system will go wrong.
>
> Ok, that's what I feared. My complaint on patch 11 is that:
>
> 1) Stashing the GTDT pointer in acpi_gtdt_desc is not needed to
>parse SBSA watchdogs

The acpi_gtdt_desc is for sharing the info between acpi_gtdt_init and
acpi_gtdt_c3stop, ;acpi_gtdt_map_ppi
I re-use it in parsing SBSA watchdogs, because I try to re-use acpi_gtdt_init.

> 2) It is not clear at all from the code or the commit log _why_ you
>need to call acpi_gtdt_init() again (ie technically you don't need
>to call it - you grab a valid pointer to the table and parse the
>watchdogs in the _same_ function gtdt_sbsa_gwdt_init())

yes, we can avoid calling acpi_gtdt_init(), do the same thing in
parsing SBSA watchdogs info.
But if we will do the same thing(getting gtdt, platform_timer,
timer_count), why not just re-using the same function?

So my suggestion is that:
Could we re-use acpi_gtdt_init, and a comment at the head of SBSA
watchdogs info parsing function to summarize this issue?
The comment like this

Note: although the global variable acpi_gtdt_desc has been initialized
by acpi_gtdt_init, when we initialized arch_timer. But when we call this
function to get SBSA watchdogs info from GTDT, the system has switch
from bootmem  to slab, so the pointers in acpi_gtdt_desc are dated, we
need to  re-initialize(remap) them. So we call acpi_gtdt_init again here.

Is that OK for you? :-)

>
> I do not think there is much you can do to improve the arch timer gtdt
> interface (and it is too late for that anyway) but in patch 11 it would
> be ideal if you avoid calling acpi_gtdt_init() again, just parse GTDT
> entries and initialize the corresponding watchdogs (ie pointers stashed
> in acpi_gtdt_desc are stale anyway but that's __initdata so I can live
> with that).
>
> You should add comments to summarize this issue so that it can be
> easily understood by anyone maintaining this code, it is not crystal
> clear by reading the code why you need to multiple acpi_gtdt_init()
> calls and that's not a piffling detail.
>
> The ACPI patches are fine with me otherwise, I will complete the
> review shortly.
>
> Thanks !
> Lorenzo



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 29 March 2017 at 18:21, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 29, 2017 at 05:48:17PM +0800, Fu Wei wrote:
>
> [...]
>
>>  * @platform_timer_count: It points to a integer variable which is used
>>  *   for storing the number of platform timers.
>>  *   This pointer could be NULL, if the caller
>>  *   doesn't need this info.
>>
>> >
>> >> + *
>> >> + * Return: 0 if success, -EINVAL if error.
>> >> + */
>> >> +int __init acpi_gtdt_init(struct acpi_table_header *table,
>> >> +   int *platform_timer_count)
>> >> +{
>> >> + int ret = 0;
>> >> + int timer_count = 0;
>> >> + void *platform_timer = NULL;
>> >> + struct acpi_table_gtdt *gtdt;
>> >> +
>> >> + gtdt = container_of(table, struct acpi_table_gtdt, header);
>> >> + acpi_gtdt_desc.gtdt = gtdt;
>> >> + acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
>> >> +
>> >> + if (table->revision < 2)
>> >> + pr_warn("Revision:%d doesn't support Platform Timers.\n",
>> >> + table->revision);
>> >
>> > Ok, two points here. First, I am not sure why you should warn if the
>> > table revision is < 2, is that a FW bug ? I do not think it is, you
>> > can just return 0.
>>
>> I used pr_debug here before v20, then I got Hanjun's suggestion:
>> ---
>> GTDT table revision is updated to 2 in ACPI 5.1, we will
>> not support ACPI version under 5.1 and disable ACPI in FADT
>> parse before this code is called, so if we get revision
>> <2 here, I think we need to print warning (we need to keep
>> the firmware stick to the spec on ARM64).
>> ---
>> https://lkml.org/lkml/2017/1/19/82
>>
>> So I started to use pr_warn.
>
> Thanks for the explanation, so it is a FW bug and the warning
> is granted :) just leave it there.
>
> Still, please check my comment on acpi_gtdt_init() being called
> multiple times on patch 11.

Thanks

For calling acpi_gtdt_init() twice:
(1) 1st time: in early boot(bootmem), for init arch_timer and
memory-mapped timer, we initialize the acpi_gtdt_desc.
you can see that all the items in this struct are pointer.
(2) 2nd time: when system switch from bootmem to slab, all the
pointers in the acpi_gtdt_desc are invalid, so we have to
re-initialize(re-map) them.

I have tested it, if we don't re-initialize  the acpi_gtdt_desc,
system will go wrong.

>
> Thanks,
> Lorenzo



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

On 29 March 2017 at 18:21, Lorenzo Pieralisi  wrote:
> On Wed, Mar 29, 2017 at 05:48:17PM +0800, Fu Wei wrote:
>
> [...]
>
>>  * @platform_timer_count: It points to a integer variable which is used
>>  *   for storing the number of platform timers.
>>  *   This pointer could be NULL, if the caller
>>  *   doesn't need this info.
>>
>> >
>> >> + *
>> >> + * Return: 0 if success, -EINVAL if error.
>> >> + */
>> >> +int __init acpi_gtdt_init(struct acpi_table_header *table,
>> >> +   int *platform_timer_count)
>> >> +{
>> >> + int ret = 0;
>> >> + int timer_count = 0;
>> >> + void *platform_timer = NULL;
>> >> + struct acpi_table_gtdt *gtdt;
>> >> +
>> >> + gtdt = container_of(table, struct acpi_table_gtdt, header);
>> >> + acpi_gtdt_desc.gtdt = gtdt;
>> >> + acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
>> >> +
>> >> + if (table->revision < 2)
>> >> + pr_warn("Revision:%d doesn't support Platform Timers.\n",
>> >> + table->revision);
>> >
>> > Ok, two points here. First, I am not sure why you should warn if the
>> > table revision is < 2, is that a FW bug ? I do not think it is, you
>> > can just return 0.
>>
>> I used pr_debug here before v20, then I got Hanjun's suggestion:
>> ---
>> GTDT table revision is updated to 2 in ACPI 5.1, we will
>> not support ACPI version under 5.1 and disable ACPI in FADT
>> parse before this code is called, so if we get revision
>> <2 here, I think we need to print warning (we need to keep
>> the firmware stick to the spec on ARM64).
>> ---
>> https://lkml.org/lkml/2017/1/19/82
>>
>> So I started to use pr_warn.
>
> Thanks for the explanation, so it is a FW bug and the warning
> is granted :) just leave it there.
>
> Still, please check my comment on acpi_gtdt_init() being called
> multiple times on patch 11.

Thanks

For calling acpi_gtdt_init() twice:
(1) 1st time: in early boot(bootmem), for init arch_timer and
memory-mapped timer, we initialize the acpi_gtdt_desc.
you can see that all the items in this struct are pointer.
(2) 2nd time: when system switch from bootmem to slab, all the
pointers in the acpi_gtdt_desc are invalid, so we have to
re-initialize(re-map) them.

I have tested it, if we don't re-initialize  the acpi_gtdt_desc,
system will go wrong.

>
> Thanks,
> Lorenzo



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

Great thanks for your review and help, I will take most of your suggestions,
But one or two comments have been discussed in previous patchset,
please allow me to explain these. :-)

On 28 March 2017 at 19:35, Lorenzo Pieralisi <lorenzo.pieral...@arm.com> wrote:
> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> This patch adds support for parsing arch timer info in GTDT,
>> provides some kernel APIs to parse all the PPIs and
>> always-on info in GTDT and export them.
>>
>> By this driver, we can simplify arm_arch_timer drivers, and
>> separate the ACPI GTDT knowledge from it.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun@linaro.org>
>> Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
>
> Acked-by: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
>
> Some nits below.

Great thanks!

>
>> Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
>> Reviewed-by: Hanjun Guo <hanjun@linaro.org>
>> Tested-by: Hanjun Guo <hanjun@linaro.org>
>> ---
>>  arch/arm64/Kconfig  |   1 +
>>  drivers/acpi/arm64/Kconfig  |   3 +
>>  drivers/acpi/arm64/Makefile |   1 +
>>  drivers/acpi/arm64/gtdt.c   | 157 
>> 
>>  include/linux/acpi.h|   6 ++
>>  5 files changed, 168 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 3741859..7e2baec 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2,6 +2,7 @@ config ARM64
>>   def_bool y
>>   select ACPI_CCA_REQUIRED if ACPI
>>   select ACPI_GENERIC_GSI if ACPI
>> + select ACPI_GTDT if ACPI
>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>   select ACPI_MCFG if ACPI
>>   select ACPI_SPCR_TABLE if ACPI
>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>> index 4616da4..5a6f80f 100644
>> --- a/drivers/acpi/arm64/Kconfig
>> +++ b/drivers/acpi/arm64/Kconfig
>> @@ -4,3 +4,6 @@
>>
>>  config ACPI_IORT
>>   bool
>> +
>> +config ACPI_GTDT
>> + bool
>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>> index 72331f2..1017def 100644
>> --- a/drivers/acpi/arm64/Makefile
>> +++ b/drivers/acpi/arm64/Makefile
>> @@ -1 +1,2 @@
>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> new file mode 100644
>> index 000..8a03b4b
>> --- /dev/null
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -0,0 +1,157 @@
>> +/*
>> + * ARM Specific GTDT table Support
>> + *
>> + * Copyright (C) 2016, Linaro Ltd.
>> + * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
>> + * Fu Wei <fu@linaro.org>
>> + * Hanjun Guo <hanjun@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#undef pr_fmt
>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>> +
>> +/**
>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>> functions
>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>> + * @gtdt_end:The pointer to the end of GTDT table.
>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>> + *
>> + * The struct store the key info of GTDT table, it should be initialized by
>> + * acpi_gtdt_init.
>> + */
>> +struct acpi_gtdt_descriptor {
>> + struct acpi_table_gtdt *gtdt;
>> + void *gtdt_end;
>> + void *platform_timer;
>> +};
>> +
>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>> +
>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>> +{
>> + int trigger, polarity;
>> +
>> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>> + : ACPI_LEVEL_SENSITIVE;
>> +
>> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>> + : ACPI_ACTIVE_HIGH;
>> +
>> + return acpi_register_gsi(NULL, interrupt, trigger, polarity)

Re: [PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-29 Thread Fu Wei
Hi Lorenzo,

Great thanks for your review and help, I will take most of your suggestions,
But one or two comments have been discussed in previous patchset,
please allow me to explain these. :-)

On 28 March 2017 at 19:35, Lorenzo Pieralisi  wrote:
> On Wed, Mar 22, 2017 at 12:31:18AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> This patch adds support for parsing arch timer info in GTDT,
>> provides some kernel APIs to parse all the PPIs and
>> always-on info in GTDT and export them.
>>
>> By this driver, we can simplify arm_arch_timer drivers, and
>> separate the ACPI GTDT knowledge from it.
>>
>> Signed-off-by: Fu Wei 
>> Signed-off-by: Hanjun Guo 
>> Acked-by: Rafael J. Wysocki 
>
> Acked-by: Lorenzo Pieralisi 
>
> Some nits below.

Great thanks!

>
>> Tested-by: Xiongfeng Wang 
>> Reviewed-by: Hanjun Guo 
>> Tested-by: Hanjun Guo 
>> ---
>>  arch/arm64/Kconfig  |   1 +
>>  drivers/acpi/arm64/Kconfig  |   3 +
>>  drivers/acpi/arm64/Makefile |   1 +
>>  drivers/acpi/arm64/gtdt.c   | 157 
>> 
>>  include/linux/acpi.h|   6 ++
>>  5 files changed, 168 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 3741859..7e2baec 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2,6 +2,7 @@ config ARM64
>>   def_bool y
>>   select ACPI_CCA_REQUIRED if ACPI
>>   select ACPI_GENERIC_GSI if ACPI
>> + select ACPI_GTDT if ACPI
>>   select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>   select ACPI_MCFG if ACPI
>>   select ACPI_SPCR_TABLE if ACPI
>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>> index 4616da4..5a6f80f 100644
>> --- a/drivers/acpi/arm64/Kconfig
>> +++ b/drivers/acpi/arm64/Kconfig
>> @@ -4,3 +4,6 @@
>>
>>  config ACPI_IORT
>>   bool
>> +
>> +config ACPI_GTDT
>> + bool
>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>> index 72331f2..1017def 100644
>> --- a/drivers/acpi/arm64/Makefile
>> +++ b/drivers/acpi/arm64/Makefile
>> @@ -1 +1,2 @@
>>  obj-$(CONFIG_ACPI_IORT)  += iort.o
>> +obj-$(CONFIG_ACPI_GTDT)  += gtdt.o
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> new file mode 100644
>> index 000..8a03b4b
>> --- /dev/null
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -0,0 +1,157 @@
>> +/*
>> + * ARM Specific GTDT table Support
>> + *
>> + * Copyright (C) 2016, Linaro Ltd.
>> + * Author: Daniel Lezcano 
>> + * Fu Wei 
>> + * Hanjun Guo 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#undef pr_fmt
>> +#define pr_fmt(fmt) "ACPI GTDT: " fmt
>> +
>> +/**
>> + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all 
>> functions
>> + * @gtdt:The pointer to the struct acpi_table_gtdt of GTDT table.
>> + * @gtdt_end:The pointer to the end of GTDT table.
>> + * @platform_timer:  The pointer to the start of Platform Timer Structure
>> + *
>> + * The struct store the key info of GTDT table, it should be initialized by
>> + * acpi_gtdt_init.
>> + */
>> +struct acpi_gtdt_descriptor {
>> + struct acpi_table_gtdt *gtdt;
>> + void *gtdt_end;
>> + void *platform_timer;
>> +};
>> +
>> +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
>> +
>> +static int __init map_gt_gsi(u32 interrupt, u32 flags)
>> +{
>> + int trigger, polarity;
>> +
>> + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>> + : ACPI_LEVEL_SENSITIVE;
>> +
>> + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>> + : ACPI_ACTIVE_HIGH;
>> +
>> + return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>> +}
>> +
>> +/**
>> + * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
>> + * @type:the type of PPI.
>> + *
>> + * Note: Linux on arm64 isn't supported on the secure side.
>
> Note: Secure state is not managed by the kernel on ARM64 systems.
>
> Is that what you wan

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-28 Thread Fu Wei
Hi Daniel,

On 29 March 2017 at 11:41, Fu Wei <fu@linaro.org> wrote:
> Hi Daniel,
>
> Great thanks for your review, allow me to answer your question below:
>
> On 28 March 2017 at 22:58, Daniel Lezcano <daniel.lezc...@linaro.org> wrote:
>> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu....@linaro.org wrote:
>>> From: Fu Wei <fu@linaro.org>
>>>
>>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>>> includes getting the frequency from the device-tree property, the per-cpu
>>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>>> But reading device-tree property will be needed only when system boot with
>>> device-tree, and reading from the per-cpu arch-timer and the memory-mapped
>>> (MMIO) timer interfaces will be needed only when the system initializes
>>> the relevant timer.
>>>
>>> This patch separates out device-tree code, keep them in device-tree init
>>> function, and removes arch_timer_detect_rate founction, then uses the
>>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>>>
>>> Signed-off-by: Fu Wei <fu@linaro.org>
>>> ---
>>>  drivers/clocksource/arm_arch_timer.c | 58 
>>> +++-
>>>  1 file changed, 30 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>>> b/drivers/clocksource/arm_arch_timer.c
>>> index 843f923..29ca7d6 100644
>>> --- a/drivers/clocksource/arm_arch_timer.c
>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>>> *cntbase)
>>>   return readl_relaxed(cntbase + CNTFRQ);
>>>  }
>>>
>>> -static void
>>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>>> -{
>>> - /* Who has more than one independent system counter? */
>>> - if (arch_timer_rate)
>>> - return;
>>> -
>>> - /*
>>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>>> -  */
>>> - if (!acpi_disabled ||
>>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) {
>>> - if (cntbase)
>>> - arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
>>> - else
>>> - arch_timer_rate = arch_timer_get_cntfrq();
>>> - }
>>> -
>>> - /* Check the timer frequency. */
>>> - if (arch_timer_rate == 0)
>>> - pr_warn("frequency not available\n");
>>> -}
>>> -
>>>  static void arch_timer_banner(unsigned type)
>>>  {
>>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct 
>>> device_node *np)
>>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; 
>>> i++)
>>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>>>
>>> - arch_timer_detect_rate(NULL, np);
>>> + /*
>>> +  * Try to determine the frequency from the device tree,
>>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>>> +  */
>>> + if (!arch_timer_rate &&
>>
>> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" are
>> declared together in the DT, right ?
>>
>> Two declarations for a single variable ? Ignore the !arch_timer_rate.
>
> In this function, we try to initialize per-CPU arm arch_timer by DT.
> this "!arch_timer_rate" is for testing that if we have got system
> counter frequency from the memory-mapped timer. If so, we just skip
> getting the frequency from DT or sysreg cntfrq again.
> This variable is set only if "arm,armv7-timer-mem" is initialized
> earlier than "arm,armv7-timer", in another word, maybe the node of
> "arm,armv7-timer-mem" is declared earlier than  "arm,armv7-timer-mem"
> one in DT.
>
> we do this check is for keeping the same init logic as before in the
> DT, try to avoid any possibility of  breaking devices which boot by
> DT.
>
>>
>>> + of_property_read_u32(np, "clock-frequency", _timer_rate))
>>> + arch_timer_rate = arch_timer_get_cntf

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-28 Thread Fu Wei
Hi Daniel,

On 29 March 2017 at 11:41, Fu Wei  wrote:
> Hi Daniel,
>
> Great thanks for your review, allow me to answer your question below:
>
> On 28 March 2017 at 22:58, Daniel Lezcano  wrote:
>> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu@linaro.org wrote:
>>> From: Fu Wei 
>>>
>>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>>> includes getting the frequency from the device-tree property, the per-cpu
>>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>>> But reading device-tree property will be needed only when system boot with
>>> device-tree, and reading from the per-cpu arch-timer and the memory-mapped
>>> (MMIO) timer interfaces will be needed only when the system initializes
>>> the relevant timer.
>>>
>>> This patch separates out device-tree code, keep them in device-tree init
>>> function, and removes arch_timer_detect_rate founction, then uses the
>>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>>>
>>> Signed-off-by: Fu Wei 
>>> ---
>>>  drivers/clocksource/arm_arch_timer.c | 58 
>>> +++-
>>>  1 file changed, 30 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>>> b/drivers/clocksource/arm_arch_timer.c
>>> index 843f923..29ca7d6 100644
>>> --- a/drivers/clocksource/arm_arch_timer.c
>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>>> *cntbase)
>>>   return readl_relaxed(cntbase + CNTFRQ);
>>>  }
>>>
>>> -static void
>>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>>> -{
>>> - /* Who has more than one independent system counter? */
>>> - if (arch_timer_rate)
>>> - return;
>>> -
>>> - /*
>>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>>> -  */
>>> - if (!acpi_disabled ||
>>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) {
>>> - if (cntbase)
>>> - arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
>>> - else
>>> - arch_timer_rate = arch_timer_get_cntfrq();
>>> - }
>>> -
>>> - /* Check the timer frequency. */
>>> - if (arch_timer_rate == 0)
>>> - pr_warn("frequency not available\n");
>>> -}
>>> -
>>>  static void arch_timer_banner(unsigned type)
>>>  {
>>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct 
>>> device_node *np)
>>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; 
>>> i++)
>>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>>>
>>> - arch_timer_detect_rate(NULL, np);
>>> + /*
>>> +  * Try to determine the frequency from the device tree,
>>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>>> +  */
>>> + if (!arch_timer_rate &&
>>
>> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" are
>> declared together in the DT, right ?
>>
>> Two declarations for a single variable ? Ignore the !arch_timer_rate.
>
> In this function, we try to initialize per-CPU arm arch_timer by DT.
> this "!arch_timer_rate" is for testing that if we have got system
> counter frequency from the memory-mapped timer. If so, we just skip
> getting the frequency from DT or sysreg cntfrq again.
> This variable is set only if "arm,armv7-timer-mem" is initialized
> earlier than "arm,armv7-timer", in another word, maybe the node of
> "arm,armv7-timer-mem" is declared earlier than  "arm,armv7-timer-mem"
> one in DT.
>
> we do this check is for keeping the same init logic as before in the
> DT, try to avoid any possibility of  breaking devices which boot by
> DT.
>
>>
>>> + of_property_read_u32(np, "clock-frequency", _timer_rate))
>>> + arch_timer_rate = arch_timer_get_cntfrq();
>>> + if (!arch_timer_rate) {
>>> + pr_err(FW_BUG "frequency not available.\n");
&g

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-28 Thread Fu Wei
Hi Daniel,

Great thanks for your review, allow me to answer your question below:

On 28 March 2017 at 22:58, Daniel Lezcano <daniel.lezc...@linaro.org> wrote:
> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>> includes getting the frequency from the device-tree property, the per-cpu
>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>> But reading device-tree property will be needed only when system boot with
>> device-tree, and reading from the per-cpu arch-timer and the memory-mapped
>> (MMIO) timer interfaces will be needed only when the system initializes
>> the relevant timer.
>>
>> This patch separates out device-tree code, keep them in device-tree init
>> function, and removes arch_timer_detect_rate founction, then uses the
>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>>
>> Signed-off-by: Fu Wei <fu@linaro.org>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 58 
>> +++-
>>  1 file changed, 30 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>> b/drivers/clocksource/arm_arch_timer.c
>> index 843f923..29ca7d6 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>> *cntbase)
>>   return readl_relaxed(cntbase + CNTFRQ);
>>  }
>>
>> -static void
>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>> -{
>> - /* Who has more than one independent system counter? */
>> - if (arch_timer_rate)
>> - return;
>> -
>> - /*
>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>> -  */
>> - if (!acpi_disabled ||
>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) {
>> - if (cntbase)
>> - arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
>> - else
>> - arch_timer_rate = arch_timer_get_cntfrq();
>> - }
>> -
>> - /* Check the timer frequency. */
>> - if (arch_timer_rate == 0)
>> - pr_warn("frequency not available\n");
>> -}
>> -
>>  static void arch_timer_banner(unsigned type)
>>  {
>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct device_node 
>> *np)
>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>>
>> - arch_timer_detect_rate(NULL, np);
>> + /*
>> +  * Try to determine the frequency from the device tree,
>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>> +  */
>> + if (!arch_timer_rate &&
>
> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" are
> declared together in the DT, right ?
>
> Two declarations for a single variable ? Ignore the !arch_timer_rate.

In this function, we try to initialize per-CPU arm arch_timer by DT.
this "!arch_timer_rate" is for testing that if we have got system
counter frequency from the memory-mapped timer. If so, we just skip
getting the frequency from DT or sysreg cntfrq again.
This variable is set only if "arm,armv7-timer-mem" is initialized
earlier than "arm,armv7-timer", in another word, maybe the node of
"arm,armv7-timer-mem" is declared earlier than  "arm,armv7-timer-mem"
one in DT.

we do this check is for keeping the same init logic as before in the
DT, try to avoid any possibility of  breaking devices which boot by
DT.

>
>> + of_property_read_u32(np, "clock-frequency", _timer_rate))
>> + arch_timer_rate = arch_timer_get_cntfrq();
>> + if (!arch_timer_rate) {
>> + pr_err(FW_BUG "frequency not available.\n");
>> + return -EINVAL;
>> + }
>
> Please, clarify this block, the conditions are unclear.

this "!arch_timer_rate" is for verifying that if the system counter
frequency we just got from DT or sysreg cntfrq is valid(non-zero).

So here, you can see I check arch_timer_rate twice, but they are for
different cases.

>
>>
>>   arch_timer

Re: [PATCH v22 02/11] clocksource: arm_arch_timer: separate out device-tree code and remove arch_timer_detect_rate

2017-03-28 Thread Fu Wei
Hi Daniel,

Great thanks for your review, allow me to answer your question below:

On 28 March 2017 at 22:58, Daniel Lezcano  wrote:
> On Wed, Mar 22, 2017 at 12:31:13AM +0800, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> Currently, the counter frequency detection call(arch_timer_detect_rate)
>> includes getting the frequency from the device-tree property, the per-cpu
>> arch-timer and the memory-mapped (MMIO) timer interfaces.
>> But reading device-tree property will be needed only when system boot with
>> device-tree, and reading from the per-cpu arch-timer and the memory-mapped
>> (MMIO) timer interfaces will be needed only when the system initializes
>> the relevant timer.
>>
>> This patch separates out device-tree code, keep them in device-tree init
>> function, and removes arch_timer_detect_rate founction, then uses the
>> arch_timer_get_cntfrq and arch_timer_mem_get_cntfrq directly.
>>
>> Signed-off-by: Fu Wei 
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 58 
>> +++-
>>  1 file changed, 30 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c 
>> b/drivers/clocksource/arm_arch_timer.c
>> index 843f923..29ca7d6 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -560,30 +560,6 @@ static u32 arch_timer_mem_get_cntfrq(void __iomem 
>> *cntbase)
>>   return readl_relaxed(cntbase + CNTFRQ);
>>  }
>>
>> -static void
>> -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
>> -{
>> - /* Who has more than one independent system counter? */
>> - if (arch_timer_rate)
>> - return;
>> -
>> - /*
>> -  * Try to determine the frequency from the device tree or CNTFRQ,
>> -  * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
>> -  */
>> - if (!acpi_disabled ||
>> - of_property_read_u32(np, "clock-frequency", _timer_rate)) {
>> - if (cntbase)
>> - arch_timer_rate = arch_timer_mem_get_cntfrq(cntbase);
>> - else
>> - arch_timer_rate = arch_timer_get_cntfrq();
>> - }
>> -
>> - /* Check the timer frequency. */
>> - if (arch_timer_rate == 0)
>> - pr_warn("frequency not available\n");
>> -}
>> -
>>  static void arch_timer_banner(unsigned type)
>>  {
>>   pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
>> @@ -958,7 +934,17 @@ static int __init arch_timer_of_init(struct device_node 
>> *np)
>>   for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++)
>>   arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
>>
>> - arch_timer_detect_rate(NULL, np);
>> + /*
>> +  * Try to determine the frequency from the device tree,
>> +  * if fail, get the frequency from the sysreg CNTFRQ.
>> +  */
>> + if (!arch_timer_rate &&
>
> This variable is set only if "arm,armv7-timer" and "arm,armv7-timer-mem" are
> declared together in the DT, right ?
>
> Two declarations for a single variable ? Ignore the !arch_timer_rate.

In this function, we try to initialize per-CPU arm arch_timer by DT.
this "!arch_timer_rate" is for testing that if we have got system
counter frequency from the memory-mapped timer. If so, we just skip
getting the frequency from DT or sysreg cntfrq again.
This variable is set only if "arm,armv7-timer-mem" is initialized
earlier than "arm,armv7-timer", in another word, maybe the node of
"arm,armv7-timer-mem" is declared earlier than  "arm,armv7-timer-mem"
one in DT.

we do this check is for keeping the same init logic as before in the
DT, try to avoid any possibility of  breaking devices which boot by
DT.

>
>> + of_property_read_u32(np, "clock-frequency", _timer_rate))
>> + arch_timer_rate = arch_timer_get_cntfrq();
>> + if (!arch_timer_rate) {
>> + pr_err(FW_BUG "frequency not available.\n");
>> + return -EINVAL;
>> + }
>
> Please, clarify this block, the conditions are unclear.

this "!arch_timer_rate" is for verifying that if the system counter
frequency we just got from DT or sysreg cntfrq is valid(non-zero).

So here, you can see I check arch_timer_rate twice, but they are for
different cases.

>
>>
>>   arch_timer_c3stop = !of_property_read_bool(np, "always-on");
>>

Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-28 Thread Fu Wei
Hi Mark,

On 28 March 2017 at 21:05, Mark Rutland <mark.rutl...@arm.com> wrote:
> On Tue, Mar 28, 2017 at 08:34:12PM +0800, Fu Wei wrote:
>> Hi Jon,
>>
>> Thanks for your email
>>  An hour ago, I just got some feedback from Lorenzo, will update my
>> patchset ASAP according to his suggestion.
>>
>> But I still need some feedback form Mark, I can see some progress here:
>> https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt
>>
>> I guess I should rebase my patchset to his gtdt branch for v23.
>>
>> So now, I am waiting for Mark's feedback to move on.
>
> Sorry for the delay; I have not had the time to focus on this as I would
> like to. I'm happy with patches 1-4, but from patch 5 onwards, there's
> one change I'd like to see.
>
> I'd prefer that mmio timer frame rame N was always stored at
> arch_timer_mem::frame[N], rather than arch_timer_mem::frame[] being in
> an arbitrary order. That will make arch_timer_mem_frame::frame_nr
> redundant.
>
> To allow arch_timer_mem::frame[] this to be sparse, I'm happy to have a
> bool arch_timer_mem_frame::valid field that we set when probing each
> frame. Then we don't need arch_timer_mem::num_frames.
>
> This will make iterating over the frames far less confusing, and makes
> it simple to detect when a frame number is erroneously reused.
>
> Otherwise, I'm largely happy to pick the rest and apply any fixups
> myself.

Great thanks for your feedback!
I will follow your suggestion to improve my patches, then post it in a day.

So I will rebase my patchset on arch-timer/gtdt branch of your REPO
https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-28 Thread Fu Wei
Hi Mark,

On 28 March 2017 at 21:05, Mark Rutland  wrote:
> On Tue, Mar 28, 2017 at 08:34:12PM +0800, Fu Wei wrote:
>> Hi Jon,
>>
>> Thanks for your email
>>  An hour ago, I just got some feedback from Lorenzo, will update my
>> patchset ASAP according to his suggestion.
>>
>> But I still need some feedback form Mark, I can see some progress here:
>> https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt
>>
>> I guess I should rebase my patchset to his gtdt branch for v23.
>>
>> So now, I am waiting for Mark's feedback to move on.
>
> Sorry for the delay; I have not had the time to focus on this as I would
> like to. I'm happy with patches 1-4, but from patch 5 onwards, there's
> one change I'd like to see.
>
> I'd prefer that mmio timer frame rame N was always stored at
> arch_timer_mem::frame[N], rather than arch_timer_mem::frame[] being in
> an arbitrary order. That will make arch_timer_mem_frame::frame_nr
> redundant.
>
> To allow arch_timer_mem::frame[] this to be sparse, I'm happy to have a
> bool arch_timer_mem_frame::valid field that we set when probing each
> frame. Then we don't need arch_timer_mem::num_frames.
>
> This will make iterating over the frames far less confusing, and makes
> it simple to detect when a frame number is erroneously reused.
>
> Otherwise, I'm largely happy to pick the rest and apply any fixups
> myself.

Great thanks for your feedback!
I will follow your suggestion to improve my patches, then post it in a day.

So I will rebase my patchset on arch-timer/gtdt branch of your REPO
https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt

>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat


Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-28 Thread Fu Wei
Hi Jon,

Thanks for your email
 An hour ago, I just got some feedback from Lorenzo, will update my
patchset ASAP according to his suggestion.

But I still need some feedback form Mark, I can see some progress here:
https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt

I guess I should rebase my patchset to his gtdt branch for v23.

So now, I am waiting for Mark's feedback to move on.

On 28 March 2017 at 19:32, Jon Masters <j...@jonmasters.org> wrote:
> Anyone got review comments for this series?
>
> On 03/21/2017 12:31 PM, fu@linaro.org wrote:
>> From: Fu Wei <fu@linaro.org>
>>
>> This patchset:
>> (1)Preparation for adding GTDT support in arm_arch_timer:
>> 1. Introduce a wrapper function to get the frequency from mmio.
>> 2. separate out device-tree code from arch_timer_detect_rate
>> 3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
>> 4. Refactor arch_timer_needs_probing, and move it into DT init call
>> 5. Introduce some new structs and refactor the MMIO timer init code
>> for reusing some common code.
>>
>> (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>> Parse all kinds of timer in GTDT table of ACPI:arch timer,
>> memory-mapped timer and SBSA Generic Watchdog timer.
>> This driver can help to simplify all the relevant timer drivers,
>> and separate all the ACPI GTDT knowledge from them.
>>
>> (3)Simplify ACPI code for arm_arch_timer
>>
>> (4)Add GTDT support for ARM memory-mapped timer.
>>
>> This patchset has been tested on the following platforms with ACPI enabled:
>> (1)ARM Foundation v8 model
>>
>> Changelog:
>> v22: https://lkml.org/lkml/2017/3/21/
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
>>  Merged patch 2,3(about arch_timer_detect_rate).
>>  Keep arch_timer_rate, do NOT split it for different types of timer.
>>  Improve  memory-mapped timer support by comments and variable name:
>>  data-->timer_mem
>>  frame-->gtdt_frame
>>  Delete zero check for SBSA watchdog irq.
>>  Skip secure SBSA watchdog in GTDT driver.
>>  Delete Kconfig modification for SBSA watchdog driver.
>>  Delete no_irq, using nr_res instead.
>>
>> v21: https://lkml.org/lkml/2017/2/6/734
>>  Introduce two functions to get the frequency from mmio and sysreg.
>>  Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
>>  Split arch_timer_rate for different types of timer.
>>  Skip secure timer frame in GTDT driver.
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  (The first 6 patches in v20 have been merged into arch-timer/cleanup 
>> branch)
>>
>> v20: https://lkml.org/lkml/2017/1/18/534
>>  Reorder the first 4 patches and split the 4th patches.
>>  Leave CNTHCTL_* as they originally were.
>>  Fix the bug in arch_timer_select_ppi.
>>  Split "Rework counter frequency detection" patch.
>>  Rework the arch_timer_detect_rate function.
>>  Improve the commit message of "Refactor MMIO timer probing".
>>  Rebase to 4.10.0-rc4
>>
>> v19: https://lkml.org/lkml/2016/12/21/25
>>  Fix a '\n' missing in a error message in arch_timer_mem_init.
>>  Add "request_mem_region" for ioremapping cntbase, according to
>>  f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
>> of_io_request_and_map()
>>  Rebase to 4.9.0-gfb779ff
>>
>> v18: https://lkml.org/lkml/2016/12/8/446
>>  Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
>>  Rebase to 4.9.0-rc8-g9269898
>>
>> v17: https://lkml.org/lkml/2016/11/25/140
>>  Take out some cleanups from 4/15.
>>  Merge 5/15 and 6/15, improve PPI determination code,
>>  improve commit message.
>>  Rework counter frequency detection.
>>  Move arch_timer_needs_of_probing into DT init call.
>>  Move Platform Timer scan loop back to timer init call to avoid 
>> allocating
>>  and free memory.
>>  Improve all the exported functions' comment.
>>
>> v16: https://lkml.org/lkml/2016/11/16/268
>>  Fix patchset problem about static enum ppi_nr of 01/13 in v15.
>>  Refactor arch_timer_detect_rate.
>>  Refactor arch_tim

Re: [PATCH v22 00/11] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

2017-03-28 Thread Fu Wei
Hi Jon,

Thanks for your email
 An hour ago, I just got some feedback from Lorenzo, will update my
patchset ASAP according to his suggestion.

But I still need some feedback form Mark, I can see some progress here:
https://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git/log/?h=arch-timer/gtdt

I guess I should rebase my patchset to his gtdt branch for v23.

So now, I am waiting for Mark's feedback to move on.

On 28 March 2017 at 19:32, Jon Masters  wrote:
> Anyone got review comments for this series?
>
> On 03/21/2017 12:31 PM, fu@linaro.org wrote:
>> From: Fu Wei 
>>
>> This patchset:
>> (1)Preparation for adding GTDT support in arm_arch_timer:
>> 1. Introduce a wrapper function to get the frequency from mmio.
>> 2. separate out device-tree code from arch_timer_detect_rate
>> 3. remove arch_timer_detect_rate use arch_timer_*get_cntfrq directly
>> 4. Refactor arch_timer_needs_probing, and move it into DT init call
>> 5. Introduce some new structs and refactor the MMIO timer init code
>> for reusing some common code.
>>
>> (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>> Parse all kinds of timer in GTDT table of ACPI:arch timer,
>> memory-mapped timer and SBSA Generic Watchdog timer.
>> This driver can help to simplify all the relevant timer drivers,
>> and separate all the ACPI GTDT knowledge from them.
>>
>> (3)Simplify ACPI code for arm_arch_timer
>>
>> (4)Add GTDT support for ARM memory-mapped timer.
>>
>> This patchset has been tested on the following platforms with ACPI enabled:
>> (1)ARM Foundation v8 model
>>
>> Changelog:
>> v22: https://lkml.org/lkml/2017/3/21/
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  Only Introduce arch_timer_mem_get_cntfrq to get the frequency from mmio.
>>  Merged patch 2,3(about arch_timer_detect_rate).
>>  Keep arch_timer_rate, do NOT split it for different types of timer.
>>  Improve  memory-mapped timer support by comments and variable name:
>>  data-->timer_mem
>>  frame-->gtdt_frame
>>  Delete zero check for SBSA watchdog irq.
>>  Skip secure SBSA watchdog in GTDT driver.
>>  Delete Kconfig modification for SBSA watchdog driver.
>>  Delete no_irq, using nr_res instead.
>>
>> v21: https://lkml.org/lkml/2017/2/6/734
>>  Introduce two functions to get the frequency from mmio and sysreg.
>>  Remove arch_timer_detect_rate use arch_timer_get_*_freq directly
>>  Split arch_timer_rate for different types of timer.
>>  Skip secure timer frame in GTDT driver.
>>  Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
>> arch-timer/cleanup
>>  (The first 6 patches in v20 have been merged into arch-timer/cleanup 
>> branch)
>>
>> v20: https://lkml.org/lkml/2017/1/18/534
>>  Reorder the first 4 patches and split the 4th patches.
>>  Leave CNTHCTL_* as they originally were.
>>  Fix the bug in arch_timer_select_ppi.
>>  Split "Rework counter frequency detection" patch.
>>  Rework the arch_timer_detect_rate function.
>>  Improve the commit message of "Refactor MMIO timer probing".
>>  Rebase to 4.10.0-rc4
>>
>> v19: https://lkml.org/lkml/2016/12/21/25
>>  Fix a '\n' missing in a error message in arch_timer_mem_init.
>>  Add "request_mem_region" for ioremapping cntbase, according to
>>  f947ee1 clocksource/drivers/arm_arch_timer: Map frame with 
>> of_io_request_and_map()
>>  Rebase to 4.9.0-gfb779ff
>>
>> v18: https://lkml.org/lkml/2016/12/8/446
>>  Fix 8/15 patch problem of "int ret;" in arch_timer_acpi_init.
>>  Rebase to 4.9.0-rc8-g9269898
>>
>> v17: https://lkml.org/lkml/2016/11/25/140
>>  Take out some cleanups from 4/15.
>>  Merge 5/15 and 6/15, improve PPI determination code,
>>  improve commit message.
>>  Rework counter frequency detection.
>>  Move arch_timer_needs_of_probing into DT init call.
>>  Move Platform Timer scan loop back to timer init call to avoid 
>> allocating
>>  and free memory.
>>  Improve all the exported functions' comment.
>>
>> v16: https://lkml.org/lkml/2016/11/16/268
>>  Fix patchset problem about static enum ppi_nr of 01/13 in v15.
>>  Refactor arch_timer_detect_rate.
>>  Refactor arch_timer_needs_probing.
>>
>> v15: https://lkml.

[PATCH v22 08/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-03-21 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 54 
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 3ada5dc..ef747f3 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1141,63 +1141,36 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
-   /* Get the frequency from the sysreg CNTFRQ */
-   arch_timer_rate = arch_timer_get_cntfrq();
-   if (!arch_timer_rate) {
-   pr_err(FW_BUG "frequency not available.\n");
-   return -EINVAL;
-   }
-
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
pr_err("No interrupt available, giving up\n");
@@ -1205,7 +1178,14 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
+
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
ret = arch_timer_register();
if (ret)
-- 
2.9.3



[PATCH v22 08/11] clocksource: arm_arch_timer: simplify ACPI support code.

2017-03-21 Thread fu . wei
From: Fu Wei 

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
---
 drivers/clocksource/arm_arch_timer.c | 54 
 1 file changed, 17 insertions(+), 37 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index 3ada5dc..ef747f3 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1141,63 +1141,36 @@ static int __init arch_timer_mem_of_init(struct 
device_node *np)
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-   int trigger, polarity;
-
-   if (!interrupt)
-   return 0;
-
-   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-   : ACPI_LEVEL_SENSITIVE;
-
-   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-   : ACPI_ACTIVE_HIGH;
-
-   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
int ret;
-   struct acpi_table_gtdt *gtdt;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
return -EINVAL;
}
 
-   gtdt = container_of(table, struct acpi_table_gtdt, header);
-
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-   gtdt->secure_el1_flags);
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret) {
+   pr_err("Failed to init GTDT table.\n");
+   return ret;
+   }
 
arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-   gtdt->non_secure_el1_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
 
arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
-   map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-   gtdt->virtual_timer_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
 
arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
-   map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-   gtdt->non_secure_el2_flags);
+   acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
 
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
 
-   /* Get the frequency from the sysreg CNTFRQ */
-   arch_timer_rate = arch_timer_get_cntfrq();
-   if (!arch_timer_rate) {
-   pr_err(FW_BUG "frequency not available.\n");
-   return -EINVAL;
-   }
-
arch_timer_uses_ppi = arch_timer_select_ppi();
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
pr_err("No interrupt available, giving up\n");
@@ -1205,7 +1178,14 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
}
 
/* Always-on capability */
-   arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+   arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
+
+   /* Get the frequency from the sysreg CNTFRQ */
+   arch_timer_rate = arch_timer_get_cntfrq();
+   if (!arch_timer_rate) {
+   pr_err(FW_BUG "frequency not available.\n");
+   return -EINVAL;
+   }
 
ret = arch_timer_register();
if (ret)
-- 
2.9.3



[PATCH v22 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-21 Thread fu . wei
From: Fu Wei <fu@linaro.org>

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/acpi/arm64/gtdt.c | 130 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 131 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 8a03b4b..f471873 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +177,111 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return ret;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i, j;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0, j = 0; i < block->timer_count; i++, gtdt_frame++) {
+   struct arch_timer_mem_frame *frame = _mem->frame[j];
+
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   return -EINVAL;
+
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   i);
+   return -EINVAL;
+   }
+
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in frame 
%d.\n",
+   i);
+   acpi_unregister_gsi(gtdt_frame->timer_interrupt);
+   return -EINVAL;
+   }
+
+   frame->frame_nr = gtdt_frame->frame_number;
+   frame->cntbase = gtdt_frame->base_address;
+   /*
+* The CNTBaseN frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5130, Table I1-4
+* "CNTBaseN memory map".
+*/
+   frame->size = SZ_4K;
+

[PATCH v22 09/11] acpi/arm64: Add memory-mapped timer support in GTDT driver

2017-03-21 Thread fu . wei
From: Fu Wei 

On platforms booting with ACPI, architected memory-mapped timers'
configuration data is provided by firmware through the ACPI GTDT
static table.

The clocksource architected timer kernel driver requires a firmware
interface to collect timer configuration and configure its driver.
this infrastructure is present for device tree systems, but it is
missing on systems booting with ACPI.

Implement the kernel infrastructure required to parse the static
ACPI GTDT table so that the architected timer clocksource driver can
make use of it on systems booting with ACPI, therefore enabling
the corresponding timers configuration.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
---
 drivers/acpi/arm64/gtdt.c | 130 ++
 include/linux/acpi.h  |   1 +
 2 files changed, 131 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 8a03b4b..f471873 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor {
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
+static inline void *next_platform_timer(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   platform_timer += gh->length;
+   if (platform_timer < acpi_gtdt_desc.gtdt_end)
+   return platform_timer;
+
+   return NULL;
+}
+
+#define for_each_platform_timer(_g)\
+   for (_g = acpi_gtdt_desc.platform_timer; _g;\
+_g = next_platform_timer(_g))
+
+static inline bool is_timer_block(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+
+   return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -155,3 +177,111 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 
return ret;
 }
+
+static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
+struct arch_timer_mem *timer_mem)
+{
+   int i, j;
+   struct acpi_gtdt_timer_entry *gtdt_frame;
+
+   if (!block->timer_count) {
+   pr_err(FW_BUG "GT block present, but frame count is zero.");
+   return -ENODEV;
+   }
+
+   if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) {
+   pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 
8\n",
+  block->timer_count);
+   return -EINVAL;
+   }
+
+   timer_mem->cntctlbase = (phys_addr_t)block->block_address;
+   /*
+* The CNTCTLBase frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5129, Table I1-3
+* "CNTCTLBase memory map".
+*/
+   timer_mem->size = SZ_4K;
+
+   gtdt_frame = (void *)block + block->timer_offset;
+   if (gtdt_frame + block->timer_count != (void *)block + 
block->header.length)
+   return -EINVAL;
+
+   /*
+* Get the GT timer Frame data for every GT Block Timer
+*/
+   for (i = 0, j = 0; i < block->timer_count; i++, gtdt_frame++) {
+   struct arch_timer_mem_frame *frame = _mem->frame[j];
+
+   if (gtdt_frame->common_flags & ACPI_GTDT_GT_IS_SECURE_TIMER)
+   continue;
+
+   if (!gtdt_frame->base_address || !gtdt_frame->timer_interrupt)
+   return -EINVAL;
+
+   frame->phys_irq = map_gt_gsi(gtdt_frame->timer_interrupt,
+gtdt_frame->timer_flags);
+   if (frame->phys_irq <= 0) {
+   pr_warn("failed to map physical timer irq in frame 
%d.\n",
+   i);
+   return -EINVAL;
+   }
+
+   frame->virt_irq =
+   map_gt_gsi(gtdt_frame->virtual_timer_interrupt,
+  gtdt_frame->virtual_timer_flags);
+   if (frame->virt_irq <= 0) {
+   pr_warn("failed to map virtual timer irq in frame 
%d.\n",
+   i);
+   acpi_unregister_gsi(gtdt_frame->timer_interrupt);
+   return -EINVAL;
+   }
+
+   frame->frame_nr = gtdt_frame->frame_number;
+   frame->cntbase = gtdt_frame->base_address;
+   /*
+* The CNTBaseN frame is 4KB (register offsets 0x000 - 0xFFC).
+* See ARM DDI 0487A.k_iss10775, page I1-5130, Table I1-4
+* "CNTBaseN memory map".
+*/
+   frame->size = SZ_4K;
+   j++;
+   }
+   timer_mem->num_frames = j;
+
+   retur

[PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-21 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Hanjun Guo <hanjun@linaro.org>
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..8a03b4b
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano <daniel.lezc...@linaro.org>
+ * Fu Wei <fu@linaro.org>
+ * Hanjun Guo <hanjun@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Linux on arm64 isn't supported on the secure side.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: 1 if the timer can be in deep idle state, 0 otherwise.
+ */
+bool __init acpi_gtdt_c3stop(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switc

[PATCH v22 07/11] acpi/arm64: Add GTDT table parse driver

2017-03-21 Thread fu . wei
From: Fu Wei 

This patch adds support for parsing arch timer info in GTDT,
provides some kernel APIs to parse all the PPIs and
always-on info in GTDT and export them.

By this driver, we can simplify arm_arch_timer drivers, and
separate the ACPI GTDT knowledge from it.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Acked-by: Rafael J. Wysocki 
Tested-by: Xiongfeng Wang 
Reviewed-by: Hanjun Guo 
Tested-by: Hanjun Guo 
---
 arch/arm64/Kconfig  |   1 +
 drivers/acpi/arm64/Kconfig  |   3 +
 drivers/acpi/arm64/Makefile |   1 +
 drivers/acpi/arm64/gtdt.c   | 157 
 include/linux/acpi.h|   6 ++
 5 files changed, 168 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3741859..7e2baec 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
def_bool y
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
+   select ACPI_GTDT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if ACPI
select ACPI_SPCR_TABLE if ACPI
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index 4616da4..5a6f80f 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -4,3 +4,6 @@
 
 config ACPI_IORT
bool
+
+config ACPI_GTDT
+   bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 72331f2..1017def 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ACPI_IORT)+= iort.o
+obj-$(CONFIG_ACPI_GTDT)+= gtdt.o
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
new file mode 100644
index 000..8a03b4b
--- /dev/null
+++ b/drivers/acpi/arm64/gtdt.c
@@ -0,0 +1,157 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2016, Linaro Ltd.
+ * Author: Daniel Lezcano 
+ * Fu Wei 
+ * Hanjun Guo 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#undef pr_fmt
+#define pr_fmt(fmt) "ACPI GTDT: " fmt
+
+/**
+ * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions
+ * @gtdt:  The pointer to the struct acpi_table_gtdt of GTDT table.
+ * @gtdt_end:  The pointer to the end of GTDT table.
+ * @platform_timer:The pointer to the start of Platform Timer Structure
+ *
+ * The struct store the key info of GTDT table, it should be initialized by
+ * acpi_gtdt_init.
+ */
+struct acpi_gtdt_descriptor {
+   struct acpi_table_gtdt *gtdt;
+   void *gtdt_end;
+   void *platform_timer;
+};
+
+static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
+
+static int __init map_gt_gsi(u32 interrupt, u32 flags)
+{
+   int trigger, polarity;
+
+   trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+   : ACPI_LEVEL_SENSITIVE;
+
+   polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+   : ACPI_ACTIVE_HIGH;
+
+   return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/**
+ * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer.
+ * @type:  the type of PPI.
+ *
+ * Note: Linux on arm64 isn't supported on the secure side.
+ * So we only handle the non-secure timer PPIs,
+ * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type.
+ *
+ * Return: the mapped PPI value, 0 if error.
+ */
+int __init acpi_gtdt_map_ppi(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return map_gt_gsi(gtdt->non_secure_el1_interrupt,
+ gtdt->non_secure_el1_flags);
+   case ARCH_TIMER_VIRT_PPI:
+   return map_gt_gsi(gtdt->virtual_timer_interrupt,
+ gtdt->virtual_timer_flags);
+
+   case ARCH_TIMER_HYP_PPI:
+   return map_gt_gsi(gtdt->non_secure_el2_interrupt,
+ gtdt->non_secure_el2_flags);
+   default:
+   pr_err("Failed to map timer interrupt: invalid type.\n");
+   }
+
+   return 0;
+}
+
+/**
+ * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI.
+ * @type:  the type of PPI.
+ *
+ * Return: 1 if the timer can be in deep idle state, 0 otherwise.
+ */
+bool __init acpi_gtdt_c3stop(int type)
+{
+   struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt;
+
+   switch (type) {
+   case ARCH_TIMER_PHYS_NONSECURE_PPI:
+   return !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+
+   case ARCH_TIMER_VIRT_PPI:
+   return !(gtdt->virtual_timer_flags & ACPI_GTDT_ALWAYS_ON);
+
+   case ARCH_TIMER_

[PATCH v22 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-03-21 Thread fu . wei
From: Fu Wei <fu@linaro.org>

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei <fu@linaro.org>
Reviewed-by: Hanjun Guo <hanjun@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 35 ---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index ef747f3..f8aa5a0 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1142,10 +1142,35 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timer_mem;
+   int timer_count, i, ret;
+
+   timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
+   GFP_KERNEL);
+   if (!timer_mem)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timer_mem, _count);
+   if (ret || !timer_count)
+   goto error;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_init(timer_mem + i);
+   if (!ret)
+   break;
+   }
+
+error:
+   kfree(timer_mem);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1154,7 +1179,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1191,6 +1216,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v22 10/11] clocksource: arm_arch_timer: add GTDT support for memory-mapped timer

2017-03-21 Thread fu . wei
From: Fu Wei 

The patch add memory-mapped timer register support by using the
information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei 
Reviewed-by: Hanjun Guo 
---
 drivers/clocksource/arm_arch_timer.c | 35 ---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c 
b/drivers/clocksource/arm_arch_timer.c
index ef747f3..f8aa5a0 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1142,10 +1142,35 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, 
"arm,armv7-timer-mem",
   arch_timer_mem_of_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static int __init arch_timer_mem_acpi_init(int platform_timer_count)
+{
+   struct arch_timer_mem *timer_mem;
+   int timer_count, i, ret;
+
+   timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
+   GFP_KERNEL);
+   if (!timer_mem)
+   return -ENOMEM;
+
+   ret = acpi_arch_timer_mem_init(timer_mem, _count);
+   if (ret || !timer_count)
+   goto error;
+
+   for (i = 0; i < timer_count; i++) {
+   ret = arch_timer_mem_init(timer_mem + i);
+   if (!ret)
+   break;
+   }
+
+error:
+   kfree(timer_mem);
+   return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) 
*/
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-   int ret;
+   int ret, platform_timer_count;
 
if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
pr_warn("already initialized, skipping\n");
@@ -1154,7 +1179,7 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
 
arch_timers_present |= ARCH_TIMER_TYPE_CP15;
 
-   ret = acpi_gtdt_init(table, NULL);
+   ret = acpi_gtdt_init(table, _timer_count);
if (ret) {
pr_err("Failed to init GTDT table.\n");
return ret;
@@ -1191,6 +1216,10 @@ static int __init arch_timer_acpi_init(struct 
acpi_table_header *table)
if (ret)
return ret;
 
+   if (platform_timer_count &&
+   arch_timer_mem_acpi_init(platform_timer_count))
+   pr_err("Failed to initialize memory-mapped timer.\n");
+
return arch_timer_common_init();
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.9.3



[PATCH v22 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-21 Thread fu . wei
From: Fu Wei <fu@linaro.org>

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei <fu@linaro.org>
Signed-off-by: Hanjun Guo <hanjun@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfe...@huawei.com>
---
 drivers/acpi/arm64/gtdt.c | 94 +++
 1 file changed, 94 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index f471873..5d167f0 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -59,6 +60,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -285,3 +297,85 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+* info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   int ret, i = 0;
+   void *platform_timer;
+   struct acpi_table_header *table;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, i);
+   if (ret)
+   break;
+   i++;
+   }
+   }
+
+   if (i)
+   pr_info("found %d SBSA generic Watchdog(s).\n", i);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



[PATCH v22 11/11] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

2017-03-21 Thread fu . wei
From: Fu Wei 

This driver adds support for parsing SBSA Generic Watchdog timer
in GTDT, parse all info in SBSA Generic Watchdog Structure in GTDT,
and creating a platform device with that information.

This allows the operating system to obtain device data from the
resource of platform device. The platform device named "sbsa-gwdt"
can be used by the ARM SBSA Generic Watchdog driver.

Signed-off-by: Fu Wei 
Signed-off-by: Hanjun Guo 
Tested-by: Xiongfeng Wang 
---
 drivers/acpi/arm64/gtdt.c | 94 +++
 1 file changed, 94 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index f471873..5d167f0 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -59,6 +60,17 @@ static inline bool is_timer_block(void *platform_timer)
return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_non_secure_watchdog(void *platform_timer)
+{
+   struct acpi_gtdt_header *gh = platform_timer;
+   struct acpi_gtdt_watchdog *wd = platform_timer;
+
+   if (gh->type != ACPI_GTDT_TYPE_WATCHDOG)
+   return false;
+
+   return !(wd->timer_flags & ACPI_GTDT_WATCHDOG_SECURE);
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
int trigger, polarity;
@@ -285,3 +297,85 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem 
*timer_mem,
 
return 0;
 }
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(struct acpi_gtdt_watchdog *wd,
+   int index)
+{
+   struct platform_device *pdev;
+   int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+
+   /*
+* According to SBSA specification the size of refresh and control
+* frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 – 0xFFF).
+*/
+   struct resource res[] = {
+   DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+   DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+   DEFINE_RES_IRQ(irq),
+   };
+   int nr_res = ARRAY_SIZE(res);
+
+   pr_debug("found a Watchdog (0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+wd->refresh_frame_address, wd->control_frame_address,
+wd->timer_interrupt, wd->timer_flags);
+
+   if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+   pr_err(FW_BUG "failed to get the Watchdog base address.\n");
+   return -EINVAL;
+   }
+
+   if (irq <= 0) {
+   pr_warn("failed to map the Watchdog interrupt.\n");
+   nr_res--;
+   }
+
+   /*
+* Add a platform device named "sbsa-gwdt" to match the platform driver.
+* "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+* The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+* info below by matching this name.
+*/
+   pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
+   if (IS_ERR(pdev)) {
+   acpi_unregister_gsi(wd->timer_interrupt);
+   return PTR_ERR(pdev);
+   }
+
+   return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+   int ret, i = 0;
+   void *platform_timer;
+   struct acpi_table_header *table;
+
+   if (acpi_disabled)
+   return 0;
+
+   if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, )))
+   return -EINVAL;
+
+   ret = acpi_gtdt_init(table, NULL);
+   if (ret)
+   return ret;
+
+   for_each_platform_timer(platform_timer) {
+   if (is_non_secure_watchdog(platform_timer)) {
+   ret = gtdt_import_sbsa_gwdt(platform_timer, i);
+   if (ret)
+   break;
+   i++;
+   }
+   }
+
+   if (i)
+   pr_info("found %d SBSA generic Watchdog(s).\n", i);
+
+   return ret;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
-- 
2.9.3



  1   2   3   4   5   6   7   8   9   10   >