Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1561785 > unrolled thread

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

Started byfu.wei@linaro.org
First post2017-01-18 14:30 +0100
Last post2017-01-24 06:20 +0100
Articles 20 on this page of 41 — 5 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer fu.wei@linaro.org - 2017-01-18 14:30 +0100
    [PATCH v20 01/17] clocksource/drivers/arm_arch_timer: Improve printk relevant code fu.wei@linaro.org - 2017-01-18 14:30 +0100
    [PATCH v20 02/17] clocksource/drivers/arm_arch_timer: Rename the timer type macros. fu.wei@linaro.org - 2017-01-18 14:30 +0100
    [PATCH v20 06/17] clocksource/drivers/arm_arch_timer: rework PPI determination fu.wei@linaro.org - 2017-01-18 14:30 +0100
    [PATCH v20 12/17] clocksource/drivers/arm_arch_timer: Refactor MMIO timer probing. fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT support for memory-mapped timer fu.wei@linaro.org - 2017-01-18 14:40 +0100
      Re: [PATCH v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT  support for memory-mapped timer Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 10:20 +0100
        Re: [PATCH v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT  support for memory-mapped timer Fu Wei <fu.wei@linaro.org> - 2017-01-19 11:10 +0100
          Re: [PATCH v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT  support for memory-mapped timer Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 13:50 +0100
    [PATCH v20 11/17] clocksource/drivers/arm_arch_timer: Introduce some new structs to prepare for GTDT fu.wei@linaro.org - 2017-01-18 14:40 +0100
      Re: [PATCH v20 11/17] clocksource/drivers/arm_arch_timer: Introduce  some new structs to prepare for GTDT Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 09:30 +0100
        Re: [PATCH v20 11/17] clocksource/drivers/arm_arch_timer: Introduce  some new structs to prepare for GTDT Fu Wei <fu.wei@linaro.org> - 2017-01-19 11:00 +0100
    [PATCH v20 07/17] clocksource/drivers/arm_arch_timer: Separate out device-tree code from arch_timer_detect_rate fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 09/17] clocksource/drivers/arm_arch_timer: Refactor arch_timer_needs_probing fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver fu.wei@linaro.org - 2017-01-18 14:40 +0100
      Re: [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 10:20 +0100
        Re: [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver Fu Wei <fu.wei@linaro.org> - 2017-01-19 11:40 +0100
          Re: [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver Mark Rutland <mark.rutland@arm.com> - 2017-01-19 12:20 +0100
            Re: [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver Fu Wei <fu.wei@linaro.org> - 2017-01-19 13:30 +0100
    [PATCH v20 05/17] clocksource/drivers/arm_arch_timer: Add a new enum for spi type fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection. fu.wei@linaro.org - 2017-01-18 14:40 +0100
      Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 09:10 +0100
        Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Fu Wei <fu.wei@linaro.org> - 2017-01-19 10:50 +0100
          Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 13:50 +0100
      Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Mark Rutland <mark.rutland@arm.com> - 2017-01-24 18:30 +0100
        Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Fu Wei <fu.wei@linaro.org> - 2017-01-25 07:50 +0100
          Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Fu Wei <fu.wei@linaro.org> - 2017-01-25 08:30 +0100
          Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Christopher Covington <cov@codeaurora.org> - 2017-01-25 16:40 +0100
            Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Mark Rutland <mark.rutland@arm.com> - 2017-01-25 18:40 +0100
              Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Fu Wei <fu.wei@linaro.org> - 2017-01-26 07:00 +0100
          Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Mark Rutland <mark.rutland@arm.com> - 2017-01-25 18:30 +0100
            Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Fu Wei <fu.wei@linaro.org> - 2017-01-26 06:50 +0100
              Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework  counter frequency detection. Mark Rutland <mark.rutland@arm.com> - 2017-01-30 19:00 +0100
    [PATCH v20 10/17] clocksource/drivers/arm_arch_timer: Move arch_timer_needs_of_probing into DT init call fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 14/17] clocksource/drivers/arm_arch_timer: Simplify ACPI support code. fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver fu.wei@linaro.org - 2017-01-18 14:40 +0100
    [PATCH v20 17/17] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver fu.wei@linaro.org - 2017-01-18 14:50 +0100
    Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT  support in arm_arch_timer Hanjun Guo <hanjun.guo@linaro.org> - 2017-01-19 10:30 +0100
      Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT  support in arm_arch_timer Fu Wei <fu.wei@linaro.org> - 2017-01-19 12:20 +0100
    Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT  support in arm_arch_timer Mark Rutland <mark.rutland@arm.com> - 2017-01-23 20:00 +0100
      Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT  support in arm_arch_timer Fu Wei <fu.wei@linaro.org> - 2017-01-24 06:20 +0100

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#1561808 — [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

Fromfu.wei@linaro.org
Date2017-01-18 14:40 +0100
Subject[PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t0YD1-4Gk-45@gated-at.bofh.it>
In reply to#1561785
From: Fu Wei <fu.wei@linaro.org>

The counter frequency detection call(arch_timer_detect_rate) combines two
ways to get counter frequency: system coprocessor register and MMIO timer.
But in a specific timer init code, we only need one way to try:
getting frequency from MMIO timer register will be needed only when we
init MMIO timer; getting frequency from system coprocessor register will
be needed only when we init arch timer.

This patch separates paths to determine frequency:
Separate out the MMIO frequency and the sysreg frequency detection call,
and use the appropriate one for the counter.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 40 ++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 6484f84..9482481 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
 	return 0;
 }
 
-static void arch_timer_detect_rate(void __iomem *cntbase)
+static void __arch_timer_determine_rate(u32 rate)
 {
-	/* Who has more than one independent system counter? */
-	if (arch_timer_rate)
-		return;
+	/* Check the timer frequency. */
+	if (!arch_timer_rate) {
+		if (rate)
+			arch_timer_rate = rate;
+		else
+			pr_warn("frequency not available\n");
+	} else if (rate && arch_timer_rate != rate) {
+		pr_warn("got different frequency, keep original.\n");
+	}
+}
 
+static void arch_timer_detect_rate(void)
+{
 	/*
-	 * Try to determine the frequency from the MMIO timer or the sysreg.
+	 * Try to get the timer frequency from the sysreg CNTFRQ.
 	 */
-	if (cntbase)
-		arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
-	else
-		arch_timer_rate = arch_timer_get_cntfrq();
+	__arch_timer_determine_rate(arch_timer_get_cntfrq());
+}
 
-	/* Check the timer frequency. */
-	if (arch_timer_rate == 0)
-		pr_warn("frequency not available\n");
+static void arch_timer_mem_detect_rate(void __iomem *cntbase)
+{
+	/*
+	 * Try to get the timer frequency from the CNTFRQ reg of MMIO timer.
+	 */
+	__arch_timer_determine_rate(readl_relaxed(cntbase + CNTFRQ));
 }
 
 static void arch_timer_banner(unsigned type)
@@ -887,7 +897,7 @@ static int __init arch_timer_of_init(struct device_node *np)
 	 */
 	if (!arch_timer_rate &&
 	    of_property_read_u32(np, "clock-frequency", &arch_timer_rate))
-		arch_timer_detect_rate(NULL);
+		arch_timer_detect_rate();
 
 	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
@@ -1001,7 +1011,7 @@ static int __init arch_timer_mem_init(struct device_node *np)
 	 */
 	if (!arch_timer_rate &&
 	    of_property_read_u32(np, "clock-frequency", &arch_timer_rate))
-		arch_timer_detect_rate(base);
+		arch_timer_mem_detect_rate(base);
 
 	ret = arch_timer_mem_register(base, irq);
 	if (ret)
@@ -1064,7 +1074,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 		gtdt->non_secure_el2_flags);
 
 	/* Get the frequency from the sysreg CNTFRQ */
-	arch_timer_detect_rate(NULL);
+	arch_timer_detect_rate();
 
 	arch_timer_uses_ppi = arch_timer_select_ppi();
 	if (!arch_timer_ppi[arch_timer_uses_ppi]) {
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1562451 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromHanjun Guo <hanjun.guo@linaro.org>
Date2017-01-19 09:10 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t1fXb-7pT-5@gated-at.bofh.it>
In reply to#1561808
Hi Fuwei,

One comments below.

On 2017/1/18 21:25, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> The counter frequency detection call(arch_timer_detect_rate) combines two
> ways to get counter frequency: system coprocessor register and MMIO timer.
> But in a specific timer init code, we only need one way to try:
> getting frequency from MMIO timer register will be needed only when we
> init MMIO timer; getting frequency from system coprocessor register will
> be needed only when we init arch timer.
>
> This patch separates paths to determine frequency:
> Separate out the MMIO frequency and the sysreg frequency detection call,
> and use the appropriate one for the counter.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  drivers/clocksource/arm_arch_timer.c | 40 ++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 6484f84..9482481 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>  	return 0;
>  }
>
> -static void arch_timer_detect_rate(void __iomem *cntbase)
> +static void __arch_timer_determine_rate(u32 rate)
>  {
> -	/* Who has more than one independent system counter? */
> -	if (arch_timer_rate)
> -		return;
> +	/* Check the timer frequency. */
> +	if (!arch_timer_rate) {
> +		if (rate)
> +			arch_timer_rate = rate;
> +		else
> +			pr_warn("frequency not available\n");
> +	} else if (rate && arch_timer_rate != rate) {
                         ^
Typo? I think it's "&" here.

Thanks
Hanjun

[toc] | [prev] | [next] | [standalone]


#1562528 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromFu Wei <fu.wei@linaro.org>
Date2017-01-19 10:50 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t1hvX-8e7-11@gated-at.bofh.it>
In reply to#1562451
Hi Hanjun,

On 19 January 2017 at 16:02, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> Hi Fuwei,
>
> One comments below.
>
>
> On 2017/1/18 21:25, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The counter frequency detection call(arch_timer_detect_rate) combines two
>> ways to get counter frequency: system coprocessor register and MMIO timer.
>> But in a specific timer init code, we only need one way to try:
>> getting frequency from MMIO timer register will be needed only when we
>> init MMIO timer; getting frequency from system coprocessor register will
>> be needed only when we init arch timer.
>>
>> This patch separates paths to determine frequency:
>> Separate out the MMIO frequency and the sysreg frequency detection call,
>> and use the appropriate one for the counter.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 40
>> ++++++++++++++++++++++--------------
>>  1 file changed, 25 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c
>> b/drivers/clocksource/arm_arch_timer.c
>> index 6484f84..9482481 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>>         return 0;
>>  }
>>
>> -static void arch_timer_detect_rate(void __iomem *cntbase)
>> +static void __arch_timer_determine_rate(u32 rate)
>>  {
>> -       /* Who has more than one independent system counter? */
>> -       if (arch_timer_rate)
>> -               return;
>> +       /* Check the timer frequency. */
>> +       if (!arch_timer_rate) {
>> +               if (rate)
>> +                       arch_timer_rate = rate;
>> +               else
>> +                       pr_warn("frequency not available\n");
>> +       } else if (rate && arch_timer_rate != rate) {
>
>                         ^
> Typo? I think it's "&" here.

Not a typo, It's definitely a “&&”  :-)

Here arch_timer_rate is not zero.

If rate is not zero(that means we got a valid rate), and
arch_timer_rate != rate ,
we will print warning message.

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1562690 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromHanjun Guo <hanjun.guo@linaro.org>
Date2017-01-19 13:50 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t1kka-1B7-13@gated-at.bofh.it>
In reply to#1562528
On 2017/1/19 17:44, Fu Wei wrote:
> Hi Hanjun,
>
> On 19 January 2017 at 16:02, Hanjun Guo <hanjun.guo@linaro.org> wrote:
>> Hi Fuwei,
>>
>> One comments below.
>>
>>
>> On 2017/1/18 21:25, fu.wei@linaro.org wrote:
>>>
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> The counter frequency detection call(arch_timer_detect_rate) combines two
>>> ways to get counter frequency: system coprocessor register and MMIO timer.
>>> But in a specific timer init code, we only need one way to try:
>>> getting frequency from MMIO timer register will be needed only when we
>>> init MMIO timer; getting frequency from system coprocessor register will
>>> be needed only when we init arch timer.
>>>
>>> This patch separates paths to determine frequency:
>>> Separate out the MMIO frequency and the sysreg frequency detection call,
>>> and use the appropriate one for the counter.
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  drivers/clocksource/arm_arch_timer.c | 40
>>> ++++++++++++++++++++++--------------
>>>  1 file changed, 25 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/clocksource/arm_arch_timer.c
>>> b/drivers/clocksource/arm_arch_timer.c
>>> index 6484f84..9482481 100644
>>> --- a/drivers/clocksource/arm_arch_timer.c
>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>>>         return 0;
>>>  }
>>>
>>> -static void arch_timer_detect_rate(void __iomem *cntbase)
>>> +static void __arch_timer_determine_rate(u32 rate)
>>>  {
>>> -       /* Who has more than one independent system counter? */
>>> -       if (arch_timer_rate)
>>> -               return;
>>> +       /* Check the timer frequency. */
>>> +       if (!arch_timer_rate) {
>>> +               if (rate)
>>> +                       arch_timer_rate = rate;
>>> +               else
>>> +                       pr_warn("frequency not available\n");
>>> +       } else if (rate && arch_timer_rate != rate) {
>>
>>                         ^
>> Typo? I think it's "&" here.
>
> Not a typo, It's definitely a “&&”  :-)
>
> Here arch_timer_rate is not zero.
>
> If rate is not zero(that means we got a valid rate), and
> arch_timer_rate != rate ,
> we will print warning message.

Ah, misreading the code, thanks for clarify :)

Hanjun

[toc] | [prev] | [next] | [standalone]


#1566017 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromMark Rutland <mark.rutland@arm.com>
Date2017-01-24 18:30 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3d4S-79G-21@gated-at.bofh.it>
In reply to#1561808
On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> The counter frequency detection call(arch_timer_detect_rate) combines two
> ways to get counter frequency: system coprocessor register and MMIO timer.
> But in a specific timer init code, we only need one way to try:
> getting frequency from MMIO timer register will be needed only when we
> init MMIO timer; getting frequency from system coprocessor register will
> be needed only when we init arch timer.

When I mentioned this splitting before, I had mean that we'd completely
separate the two, with separate mmio_rate and sysreg_rate variables.

The probing logic relying on this is complicated and fragile, and I
think these patches are complicating that further (though I appreciate
that's far from the intent).

I believe we need to split the MMIO and sysreg timer code apart
entirely. I've had a look at that today, though it's been fairly painful
so far. It appears some platforms may inadvertently be relying on the
order and manner in which the rates are probed, which is a major
headache.

I will try to attack that some more tomorrow.

> This patch separates paths to determine frequency:
> Separate out the MMIO frequency and the sysreg frequency detection call,
> and use the appropriate one for the counter.
> 
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  drivers/clocksource/arm_arch_timer.c | 40 ++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 6484f84..9482481 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>  	return 0;
>  }
>  
> -static void arch_timer_detect_rate(void __iomem *cntbase)
> +static void __arch_timer_determine_rate(u32 rate)
>  {
> -	/* Who has more than one independent system counter? */
> -	if (arch_timer_rate)
> -		return;
> +	/* Check the timer frequency. */
> +	if (!arch_timer_rate) {
> +		if (rate)
> +			arch_timer_rate = rate;
> +		else
> +			pr_warn("frequency not available\n");
> +	} else if (rate && arch_timer_rate != rate) {
> +		pr_warn("got different frequency, keep original.\n");
> +	}
> +}

This function should be killed off entirely. We need to be able to fail
the probe if we cannot determine the rate, and that means we need error
handling in the ACPI and DT cases anyway.

Thanks,
Mark.

[toc] | [prev] | [next] | [standalone]


#1566346 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromFu Wei <fu.wei@linaro.org>
Date2017-01-25 07:50 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3pz4-6Kn-17@gated-at.bofh.it>
In reply to#1566017
Hi Mark,

On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
> On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The counter frequency detection call(arch_timer_detect_rate) combines two
>> ways to get counter frequency: system coprocessor register and MMIO timer.
>> But in a specific timer init code, we only need one way to try:
>> getting frequency from MMIO timer register will be needed only when we
>> init MMIO timer; getting frequency from system coprocessor register will
>> be needed only when we init arch timer.
>
> When I mentioned this splitting before, I had mean that we'd completely
> separate the two, with separate mmio_rate and sysreg_rate variables.

sorry for misunderstanding.

Are you saying :

diff --git a/drivers/clocksource/arm_arch_timer.c
b/drivers/clocksource/arm_arch_timer.c
index 663a57a..eec92f6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -65,7 +65,8 @@ struct arch_timer {

 #define to_arch_timer(e) container_of(e, struct arch_timer, evt)

-static u32 arch_timer_rate;
+static u32 arch_timer_sysreg_rate ;
+static u32 arch_timer_mmio_rate;
 static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI];

 static struct clock_event_device __percpu *arch_timer_evt;


But what have I learned From ARMv8 ARM is
AArch64 System register CNTFRQ_EL0 is provided so that software can
discover the frequency of the system counter.
CNTFRQ(in CNTCTLBase and CNTBaseN) is provided so that software can
discover the frequency of the system counter.
The bit assignments of the registers are identical in the System
register interface and in the memory-mapped system level interface.
So I think they both contain the same value : the frequency of the
system counter, just in different view, and can be accessed in
different ways.

So do we really need to separate mmio_rate and sysreg_rate variables?

And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
Linux kernel (EL1),
Because ARMv8 ARM says:
In a system that implements both Secure and Non-secure states, this
register is only accessible by Secure accesses.
That means we still need to get the frequency of the system counter
from CNTFRQ_EL0 in MMIO timer code.
This have been proved when I tested this driver on foundation model, I
got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)

So I guess the logic of the original code is
 static u32 arch_timer_rate keeps the frequency of the system counter,
 no matter where the value comes from.
Because  they should be the same value. if we have got the frequency
of the system counter(arch_timer_rate != 0), then we don't need to get
it again, even in anther way.

But  the above is just my thought, and I believe you're the expert of
ARM. So please correct me if I misunderstand something.  :-)

Thanks!
>
> The probing logic relying on this is complicated and fragile, and I
> think these patches are complicating that further (though I appreciate
> that's far from the intent).
>
> I believe we need to split the MMIO and sysreg timer code apart
> entirely. I've had a look at that today, though it's been fairly painful
> so far. It appears some platforms may inadvertently be relying on the
> order and manner in which the rates are probed, which is a major
> headache.
>
> I will try to attack that some more tomorrow.
>
>> This patch separates paths to determine frequency:
>> Separate out the MMIO frequency and the sysreg frequency detection call,
>> and use the appropriate one for the counter.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 40 ++++++++++++++++++++++--------------
>>  1 file changed, 25 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>> index 6484f84..9482481 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>>       return 0;
>>  }
>>
>> -static void arch_timer_detect_rate(void __iomem *cntbase)
>> +static void __arch_timer_determine_rate(u32 rate)
>>  {
>> -     /* Who has more than one independent system counter? */
>> -     if (arch_timer_rate)
>> -             return;
>> +     /* Check the timer frequency. */
>> +     if (!arch_timer_rate) {
>> +             if (rate)
>> +                     arch_timer_rate = rate;
>> +             else
>> +                     pr_warn("frequency not available\n");
>> +     } else if (rate && arch_timer_rate != rate) {
>> +             pr_warn("got different frequency, keep original.\n");
>> +     }
>> +}
>
> This function should be killed off entirely. We need to be able to fail
> the probe if we cannot determine the rate, and that means we need error
> handling in the ACPI and DT cases anyway.
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1566356 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromFu Wei <fu.wei@linaro.org>
Date2017-01-25 08:30 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3qbL-7cP-5@gated-at.bofh.it>
In reply to#1566346
Hi Mark,

On 25 January 2017 at 14:46, Fu Wei <fu.wei@linaro.org> wrote:
> Hi Mark,
>
> On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
>> On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> The counter frequency detection call(arch_timer_detect_rate) combines two
>>> ways to get counter frequency: system coprocessor register and MMIO timer.
>>> But in a specific timer init code, we only need one way to try:
>>> getting frequency from MMIO timer register will be needed only when we
>>> init MMIO timer; getting frequency from system coprocessor register will
>>> be needed only when we init arch timer.
>>
>> When I mentioned this splitting before, I had mean that we'd completely
>> separate the two, with separate mmio_rate and sysreg_rate variables.
>
> sorry for misunderstanding.
>
> Are you saying :
>
> diff --git a/drivers/clocksource/arm_arch_timer.c
> b/drivers/clocksource/arm_arch_timer.c
> index 663a57a..eec92f6 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -65,7 +65,8 @@ struct arch_timer {
>
>  #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
>
> -static u32 arch_timer_rate;
> +static u32 arch_timer_sysreg_rate ;
> +static u32 arch_timer_mmio_rate;
>  static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI];
>
>  static struct clock_event_device __percpu *arch_timer_evt;
>
>
> But what have I learned From ARMv8 ARM is
> AArch64 System register CNTFRQ_EL0 is provided so that software can
> discover the frequency of the system counter.
> CNTFRQ(in CNTCTLBase and CNTBaseN) is provided so that software can
> discover the frequency of the system counter.
> The bit assignments of the registers are identical in the System
> register interface and in the memory-mapped system level interface.
> So I think they both contain the same value : the frequency of the
> system counter, just in different view, and can be accessed in
> different ways.
>
> So do we really need to separate mmio_rate and sysreg_rate variables?
>
> And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
> Linux kernel (EL1),
> Because ARMv8 ARM says:
> In a system that implements both Secure and Non-secure states, this
> register is only accessible by Secure accesses.
> That means we still need to get the frequency of the system counter
> from CNTFRQ_EL0 in MMIO timer code.
> This have been proved when I tested this driver on foundation model, I
> got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)
>
> So I guess the logic of the original code is
>  static u32 arch_timer_rate keeps the frequency of the system counter,
>  no matter where the value comes from.
> Because  they should be the same value. if we have got the frequency
> of the system counter(arch_timer_rate != 0), then we don't need to get
> it again, even in anther way.

*IF*  the above is right,
For ARM32, boot with dtb,  the original logic and this patch work well.
For ARM64, boot with dtb,  if MMIO timer is probed first, and there is
not "clock-frequency" in the node. MMIO timer can't get  the
frequency. Because we will get "0" when we access CNTFRQ from Linux
kernel (Non-secure EL1), that means the original logic and this patch
won't work. To fix this issue, we need to get  the frequency  from
sysreg CNTFRQ_EL0.
For ARM64, boot with ACPI, the original logic and this patch work
well, because we always probe arch_timer first.

So *IF* I understand it correctly, May I suggest that we only get  the
frequency from sysreg CNTFRQ_EL0 in this driver?
I think that can simplify the code and avoid the issue when we boot
ARM64 with dtb.

Again,  please correct me if I misunderstand something.  :-)  Great
thanks for your help!

>
> But  the above is just my thought, and I believe you're the expert of
> ARM. So please correct me if I misunderstand something.  :-)
>
> Thanks!
>>
>> The probing logic relying on this is complicated and fragile, and I
>> think these patches are complicating that further (though I appreciate
>> that's far from the intent).
>>
>> I believe we need to split the MMIO and sysreg timer code apart
>> entirely. I've had a look at that today, though it's been fairly painful
>> so far. It appears some platforms may inadvertently be relying on the
>> order and manner in which the rates are probed, which is a major
>> headache.
>>
>> I will try to attack that some more tomorrow.
>>
>>> This patch separates paths to determine frequency:
>>> Separate out the MMIO frequency and the sysreg frequency detection call,
>>> and use the appropriate one for the counter.
>>>
>>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>>> ---
>>>  drivers/clocksource/arm_arch_timer.c | 40 ++++++++++++++++++++++--------------
>>>  1 file changed, 25 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>>> index 6484f84..9482481 100644
>>> --- a/drivers/clocksource/arm_arch_timer.c
>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>> @@ -488,23 +488,33 @@ static int arch_timer_starting_cpu(unsigned int cpu)
>>>       return 0;
>>>  }
>>>
>>> -static void arch_timer_detect_rate(void __iomem *cntbase)
>>> +static void __arch_timer_determine_rate(u32 rate)
>>>  {
>>> -     /* Who has more than one independent system counter? */
>>> -     if (arch_timer_rate)
>>> -             return;
>>> +     /* Check the timer frequency. */
>>> +     if (!arch_timer_rate) {
>>> +             if (rate)
>>> +                     arch_timer_rate = rate;
>>> +             else
>>> +                     pr_warn("frequency not available\n");
>>> +     } else if (rate && arch_timer_rate != rate) {
>>> +             pr_warn("got different frequency, keep original.\n");
>>> +     }
>>> +}
>>
>> This function should be killed off entirely. We need to be able to fail
>> the probe if we cannot determine the rate, and that means we need error
>> handling in the ACPI and DT cases anyway.
>>
>> Thanks,
>> Mark.
>
>
>
> --
> Best regards,
>
> Fu Wei
> Software Engineer
> Red Hat



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1566696 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromChristopher Covington <cov@codeaurora.org>
Date2017-01-25 16:40 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3xQ0-3w9-59@gated-at.bofh.it>
In reply to#1566346
Hi Fu,

On 01/25/2017 01:46 AM, Fu Wei wrote:
> Hi Mark,
> 
> On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
>> On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
>>> From: Fu Wei <fu.wei@linaro.org>
>>>
>>> The counter frequency detection call(arch_timer_detect_rate) combines two
>>> ways to get counter frequency: system coprocessor register and MMIO timer.
>>> But in a specific timer init code, we only need one way to try:
>>> getting frequency from MMIO timer register will be needed only when we
>>> init MMIO timer; getting frequency from system coprocessor register will
>>> be needed only when we init arch timer.
>>
>> When I mentioned this splitting before, I had mean that we'd completely
>> separate the two, with separate mmio_rate and sysreg_rate variables.
> 
> sorry for misunderstanding.
> 
> Are you saying :
> 
> diff --git a/drivers/clocksource/arm_arch_timer.c
> b/drivers/clocksource/arm_arch_timer.c
> index 663a57a..eec92f6 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -65,7 +65,8 @@ struct arch_timer {
> 
>  #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
> 
> -static u32 arch_timer_rate;
> +static u32 arch_timer_sysreg_rate ;
> +static u32 arch_timer_mmio_rate;
>  static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI];
> 
>  static struct clock_event_device __percpu *arch_timer_evt;
> 
> 
> But what have I learned From ARMv8 ARM is
> AArch64 System register CNTFRQ_EL0 is provided so that software can
> discover the frequency of the system counter.
> CNTFRQ(in CNTCTLBase and CNTBaseN) is provided so that software can
> discover the frequency of the system counter.
> The bit assignments of the registers are identical in the System
> register interface and in the memory-mapped system level interface.
> So I think they both contain the same value : the frequency of the
> system counter, just in different view, and can be accessed in
> different ways.
> 
> So do we really need to separate mmio_rate and sysreg_rate variables?
> 
> And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
> Linux kernel (EL1),
> Because ARMv8 ARM says:
> In a system that implements both Secure and Non-secure states, this
> register is only accessible by Secure accesses.
> That means we still need to get the frequency of the system counter
> from CNTFRQ_EL0 in MMIO timer code.
> This have been proved when I tested this driver on foundation model, I
> got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)

That sounds like a firmware problem. Firmware in EL3 is supposed to write
the value into CNTFRQ. If you're not currently using any firmware, I'd
recommend the bootwrapper on models/simulators/emulators.

http://git.kernel.org/cgit/linux/kernel/git/mark/boot-wrapper-aarch64.git/tree/arch/aarch64/boot.S#n48

Cheers,
Cov

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code
Aurora Forum, a Linux Foundation Collaborative Project.

[toc] | [prev] | [next] | [standalone]


#1566782 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromMark Rutland <mark.rutland@arm.com>
Date2017-01-25 18:40 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3zI6-4Hf-21@gated-at.bofh.it>
In reply to#1566696
On Wed, Jan 25, 2017 at 10:38:01AM -0500, Christopher Covington wrote:
> On 01/25/2017 01:46 AM, Fu Wei wrote:
> > On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
> >> On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
> >>> From: Fu Wei <fu.wei@linaro.org>

> > And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
> > Linux kernel (EL1),
> > Because ARMv8 ARM says:
> > In a system that implements both Secure and Non-secure states, this
> > register is only accessible by Secure accesses.
> > That means we still need to get the frequency of the system counter
> > from CNTFRQ_EL0 in MMIO timer code.
> > This have been proved when I tested this driver on foundation model, I
> > got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)
> 
> That sounds like a firmware problem. Firmware in EL3 is supposed to write
> the value into CNTFRQ.

Definitely. FW *should* program the CNTFRQ_EL0 CPU registers and any
MMIO CNTFRQ registers.

> If you're not currently using any firmware, I'd
> recommend the bootwrapper on models/simulators/emulators.
> 
> http://git.kernel.org/cgit/linux/kernel/git/mark/boot-wrapper-aarch64.git/tree/arch/aarch64/boot.S#n48

Unfortunately, the boot-wrapper only programs the CNTFRQ_EL0 CPU system
registers, and does not program any MMIO CNTFRQ registers.

IIRC the models it was originally written for didn't have any (and we
had no DT binding until far later...). Luckily the model DTs do not
expose any MMIO timer addresses to the kernel currently.

Thanks,
Mark.

[toc] | [prev] | [next] | [standalone]


#1567129 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromFu Wei <fu.wei@linaro.org>
Date2017-01-26 07:00 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3Lge-3vx-13@gated-at.bofh.it>
In reply to#1566782
Hi Mark, Christopher,

On 26 January 2017 at 01:36, Mark Rutland <mark.rutland@arm.com> wrote:
> On Wed, Jan 25, 2017 at 10:38:01AM -0500, Christopher Covington wrote:
>> On 01/25/2017 01:46 AM, Fu Wei wrote:
>> > On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
>> >> On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
>> >>> From: Fu Wei <fu.wei@linaro.org>
>
>> > And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
>> > Linux kernel (EL1),
>> > Because ARMv8 ARM says:
>> > In a system that implements both Secure and Non-secure states, this
>> > register is only accessible by Secure accesses.
>> > That means we still need to get the frequency of the system counter
>> > from CNTFRQ_EL0 in MMIO timer code.
>> > This have been proved when I tested this driver on foundation model, I
>> > got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)
>>
>> That sounds like a firmware problem. Firmware in EL3 is supposed to write
>> the value into CNTFRQ.
>
> Definitely. FW *should* program the CNTFRQ_EL0 CPU registers and any
> MMIO CNTFRQ registers.

Many thanks for the explanation. This might be the problem. Maybe we
can check the UEFI :-)

>
>> If you're not currently using any firmware, I'd
>> recommend the bootwrapper on models/simulators/emulators.
>>
>> http://git.kernel.org/cgit/linux/kernel/git/mark/boot-wrapper-aarch64.git/tree/arch/aarch64/boot.S#n48
>
> Unfortunately, the boot-wrapper only programs the CNTFRQ_EL0 CPU system
> registers, and does not program any MMIO CNTFRQ registers.
>
> IIRC the models it was originally written for didn't have any (and we
> had no DT binding until far later...). Luckily the model DTs do not
> expose any MMIO timer addresses to the kernel currently.

But according to another document(ARMv8-A Foundation Platform User
Guide  ARM DUI0677K), Table 3-2 ARMv8-A Foundation Platform memory
map,
we may have two frames in the Generic timer block, right?


>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1566778 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromMark Rutland <mark.rutland@arm.com>
Date2017-01-25 18:30 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3zyr-4DC-45@gated-at.bofh.it>
In reply to#1566346
On Wed, Jan 25, 2017 at 02:46:12PM +0800, Fu Wei wrote:
> Hi Mark,

Hi,

> On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
> >> From: Fu Wei <fu.wei@linaro.org>
> >>
> >> The counter frequency detection call(arch_timer_detect_rate) combines two
> >> ways to get counter frequency: system coprocessor register and MMIO timer.
> >> But in a specific timer init code, we only need one way to try:
> >> getting frequency from MMIO timer register will be needed only when we
> >> init MMIO timer; getting frequency from system coprocessor register will
> >> be needed only when we init arch timer.
> >
> > When I mentioned this splitting before, I had mean that we'd completely
> > separate the two, with separate mmio_rate and sysreg_rate variables.
> 
> sorry for misunderstanding.
> 
> Are you saying :
> 
> diff --git a/drivers/clocksource/arm_arch_timer.c
> b/drivers/clocksource/arm_arch_timer.c
> index 663a57a..eec92f6 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -65,7 +65,8 @@ struct arch_timer {
> 
>  #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
> 
> -static u32 arch_timer_rate;
> +static u32 arch_timer_sysreg_rate ;
> +static u32 arch_timer_mmio_rate;
>  static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI];
> 
>  static struct clock_event_device __percpu *arch_timer_evt;
> 
> 
> But what have I learned From ARMv8 ARM is
> AArch64 System register CNTFRQ_EL0 is provided so that software can
> discover the frequency of the system counter.
> CNTFRQ(in CNTCTLBase and CNTBaseN) is provided so that software can
> discover the frequency of the system counter.
> The bit assignments of the registers are identical in the System
> register interface and in the memory-mapped system level interface.

This means that the bits in the registers have the same meaning.

However, they are separate registers, and must be written separately. A
write to one does not propagate to the other, and they are not
guaranteed to contain the same value.

> So I think they both contain the same value : the frequency of the
> system counter, just in different view, and can be accessed in
> different ways.

Certainly, in theory, these *should* contain the same value.

Unfortunately, in practice, on several systems, they do not. It is very
easy to forget to initialise one of these registers correctly, and it's
possible for some software to work (masking the issue), while other
software will fail very quickly. I very much suspect we will see the
same class of issue on ACPI systems.

Consider a system where the sysreg CNTFRQ was correct, but the MMIO
CNTFRQ contains an erroneous non-zero value.

If we get the frequency out of CNTFRQ_EL0 first, and assign this to
arch_timer_rate, we won't bother to look at the MMIO registers (which
could contain erroneous values). If we read an erroneous CNTBaseN.CNTFRQ
value first, and assign this to arch_timer_rate, we won't look at
CNTFRQ_EL0.

This is *very* fragile w.r.t. probe order. I don't like the fragility of
setting a common arch_timer_rate depending on which gets probed first,
as this masks a bug, which will adversely affect us later.

This is already a problem for DT systems, and I do not want this problem
to spread to ACPI systems.

For ACPI, the approach I'd personally like to take is to keep the two
rates separate. Probe the sysreg timer first and subsequently probe the
MMIO timers. If the MMIO CNTFRQ (of all frames) does not match the
sysreg CNTFRQ, we log a warning and give up probing the MMIO timers.

For legacy reasons, DT is going to be more complicated, but I believe we
can apply that approach to ACPI.
 
> So do we really need to separate mmio_rate and sysreg_rate variables?
> 
> And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
> Linux kernel (EL1),
> Because ARMv8 ARM says:
> In a system that implements both Secure and Non-secure states, this
> register is only accessible by Secure accesses.

CNTCTLBase.CNTFRQ can only be accessed in secure states. That is clear
from Table I1-3 in ARM DDI 0487A.k_iss10775). I agree that we cannot
access this.

For CNT{,EL0}BaseN.CNTFRQ, I am very concerned by the wording in the
current ARMv8 ARM ARM. This does not match my understanding, nor does it
match the description in the ARMv7 ARM. I believe this may be a
documentation error, and I'm chasing that up internally.

Either the currently logic in the driver which attempts to read
CNT{,EL0}BaseN.CNTFRQ is flawed, or the description in the ARM ARM is
erroneous.

> That means we still need to get the frequency of the system counter
> from CNTFRQ_EL0 in MMIO timer code.
> This have been proved when I tested this driver on foundation model, I
> got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)

As mentioned in I3.5.7, the CNTBase{,EL0}N.CNTFRQ values are UNKNOWN out
of reset, and require configuration by FW.

> So I guess the logic of the original code is
>  static u32 arch_timer_rate keeps the frequency of the system counter,
>  no matter where the value comes from.
> Because  they should be the same value. if we have got the frequency
> of the system counter(arch_timer_rate != 0), then we don't need to get
> it again, even in anther way.

Unfortunately, in practice this is not the case. :(

Thanks,
Mark.

[toc] | [prev] | [next] | [standalone]


#1567121 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromFu Wei <fu.wei@linaro.org>
Date2017-01-26 06:50 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t3L6x-3sr-13@gated-at.bofh.it>
In reply to#1566778
Hi Mark,

On 26 January 2017 at 01:25, Mark Rutland <mark.rutland@arm.com> wrote:
> On Wed, Jan 25, 2017 at 02:46:12PM +0800, Fu Wei wrote:
>> Hi Mark,
>
> Hi,
>
>> On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
>> >> From: Fu Wei <fu.wei@linaro.org>
>> >>
>> >> The counter frequency detection call(arch_timer_detect_rate) combines two
>> >> ways to get counter frequency: system coprocessor register and MMIO timer.
>> >> But in a specific timer init code, we only need one way to try:
>> >> getting frequency from MMIO timer register will be needed only when we
>> >> init MMIO timer; getting frequency from system coprocessor register will
>> >> be needed only when we init arch timer.
>> >
>> > When I mentioned this splitting before, I had mean that we'd completely
>> > separate the two, with separate mmio_rate and sysreg_rate variables.
>>
>> sorry for misunderstanding.
>>
>> Are you saying :
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c
>> b/drivers/clocksource/arm_arch_timer.c
>> index 663a57a..eec92f6 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -65,7 +65,8 @@ struct arch_timer {
>>
>>  #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
>>
>> -static u32 arch_timer_rate;
>> +static u32 arch_timer_sysreg_rate ;
>> +static u32 arch_timer_mmio_rate;
>>  static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI];
>>
>>  static struct clock_event_device __percpu *arch_timer_evt;
>>
>>
>> But what have I learned From ARMv8 ARM is
>> AArch64 System register CNTFRQ_EL0 is provided so that software can
>> discover the frequency of the system counter.
>> CNTFRQ(in CNTCTLBase and CNTBaseN) is provided so that software can
>> discover the frequency of the system counter.
>> The bit assignments of the registers are identical in the System
>> register interface and in the memory-mapped system level interface.
>
> This means that the bits in the registers have the same meaning.
>
> However, they are separate registers, and must be written separately. A
> write to one does not propagate to the other, and they are not
> guaranteed to contain the same value.

Ah, Sorry for misunderstanding this, and thanks for correcting it,
I thought they point to the same register.

>
>> So I think they both contain the same value : the frequency of the
>> system counter, just in different view, and can be accessed in
>> different ways.
>
> Certainly, in theory, these *should* contain the same value.
>
> Unfortunately, in practice, on several systems, they do not. It is very
> easy to forget to initialise one of these registers correctly, and it's
> possible for some software to work (masking the issue), while other
> software will fail very quickly. I very much suspect we will see the
> same class of issue on ACPI systems.

Ah, thanks , that makes sense to me :-)

So can I say:
In normal case, CNTFRQ_EL0, CNTCTLBase.CNTFRQ and CNTBaseN.CNTFRQ
should be set to the same value.
But in some special case, some CNTFRQ maybe set to a different number
for some reason(maybe on purpose).

>
> Consider a system where the sysreg CNTFRQ was correct, but the MMIO
> CNTFRQ contains an erroneous non-zero value.
>
> If we get the frequency out of CNTFRQ_EL0 first, and assign this to
> arch_timer_rate, we won't bother to look at the MMIO registers (which
> could contain erroneous values). If we read an erroneous CNTBaseN.CNTFRQ
> value first, and assign this to arch_timer_rate, we won't look at
> CNTFRQ_EL0.
>
> This is *very* fragile w.r.t. probe order. I don't like the fragility of
> setting a common arch_timer_rate depending on which gets probed first,
> as this masks a bug, which will adversely affect us later.
>
> This is already a problem for DT systems, and I do not want this problem
> to spread to ACPI systems.
>
> For ACPI, the approach I'd personally like to take is to keep the two
> rates separate. Probe the sysreg timer first and subsequently probe the
> MMIO timers. If the MMIO CNTFRQ (of all frames) does not match the
> sysreg CNTFRQ, we log a warning and give up probing the MMIO timers.

OK, I think I got your point, will do this way. Thanks :-)

>
> For legacy reasons, DT is going to be more complicated, but I believe we
> can apply that approach to ACPI.
>
>> So do we really need to separate mmio_rate and sysreg_rate variables?
>>
>> And for CNTFRQ(in CNTCTLBase and CNTBaseN) , we can NOT access it in
>> Linux kernel (EL1),
>> Because ARMv8 ARM says:
>> In a system that implements both Secure and Non-secure states, this
>> register is only accessible by Secure accesses.
>
> CNTCTLBase.CNTFRQ can only be accessed in secure states. That is clear
> from Table I1-3 in ARM DDI 0487A.k_iss10775). I agree that we cannot
> access this.

yes , got it.
And we don't do it in the driver, we try to access  CNTBaseN.CNTFRQ
(in a frame) instead.

>
> For CNT{,EL0}BaseN.CNTFRQ, I am very concerned by the wording in the
> current ARMv8 ARM ARM. This does not match my understanding, nor does it
> match the description in the ARMv7 ARM. I believe this may be a
> documentation error, and I'm chasing that up internally.
>
> Either the currently logic in the driver which attempts to read
> CNT{,EL0}BaseN.CNTFRQ is flawed, or the description in the ARM ARM is
> erroneous.

Yes, those description did confuse me. :-(

But according to another document(ARMv8-A Foundation Platform User
Guide  ARM DUI0677K),
Table 3-2 ARMv8-A Foundation Platform memory map (continued)

AP_REFCLK CNTBase0, Generic Timer 64KB   S
AP_REFCLK CNTBase1, Generic Timer 64KB   S/NS

Dose it means the timer frame 0 can be accessed in SECURE status  only,
and the timer frame 1 can be accessed in both status?

And because Linux kernel is running on Non-secure EL1, so should we
skip "SECURE" timer in Linux?

>
>> That means we still need to get the frequency of the system counter
>> from CNTFRQ_EL0 in MMIO timer code.
>> This have been proved when I tested this driver on foundation model, I
>> got "0" when I access CNTFRQ from Linux kernel (Non-secure EL1)
>
> As mentioned in I3.5.7, the CNTBase{,EL0}N.CNTFRQ values are UNKNOWN out
> of reset, and require configuration by FW.
>
>> So I guess the logic of the original code is
>>  static u32 arch_timer_rate keeps the frequency of the system counter,
>>  no matter where the value comes from.
>> Because  they should be the same value. if we have got the frequency
>> of the system counter(arch_timer_rate != 0), then we don't need to get
>> it again, even in anther way.
>
> Unfortunately, in practice this is not the case. :(
>
> Thanks,
> Mark.



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1569971 — Re: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.

FromMark Rutland <mark.rutland@arm.com>
Date2017-01-30 19:00 +0100
SubjectRe: [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
Message-ID<t5opd-6Tg-43@gated-at.bofh.it>
In reply to#1567121
On Thu, Jan 26, 2017 at 01:49:03PM +0800, Fu Wei wrote:
> On 26 January 2017 at 01:25, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Wed, Jan 25, 2017 at 02:46:12PM +0800, Fu Wei wrote:
> >> On 25 January 2017 at 01:24, Mark Rutland <mark.rutland@arm.com> wrote:
> >> > On Wed, Jan 18, 2017 at 09:25:32PM +0800, fu.wei@linaro.org wrote:
> >> >> From: Fu Wei <fu.wei@linaro.org>

> > For CNT{,EL0}BaseN.CNTFRQ, I am very concerned by the wording in the
> > current ARMv8 ARM ARM. This does not match my understanding, nor does it
> > match the description in the ARMv7 ARM. I believe this may be a
> > documentation error, and I'm chasing that up internally.
> >
> > Either the currently logic in the driver which attempts to read
> > CNT{,EL0}BaseN.CNTFRQ is flawed, or the description in the ARM ARM is
> > erroneous.
> 
> Yes, those description did confuse me. :-(
> 
> But according to another document(ARMv8-A Foundation Platform User
> Guide  ARM DUI0677K),
> Table 3-2 ARMv8-A Foundation Platform memory map (continued)
> 
> AP_REFCLK CNTBase0, Generic Timer 64KB   S
> AP_REFCLK CNTBase1, Generic Timer 64KB   S/NS
> 
> Dose it means the timer frame 0 can be accessed in SECURE status  only,
> and the timer frame 1 can be accessed in both status?

That does appear to be what it says.

I assume in this case CNTCTLBase.CNTSAR<0> is RES0.

> And because Linux kernel is running on Non-secure EL1, so should we
> skip "SECURE" timer in Linux?

I guess you mean by checking the GTx Common flags, to see if the timer
is secure? Yes, we must skip those.

Looking further at this, the ACPI spec is sorely lacking any statement
as to the configuration of CNTCTLBase.{CNTSAR,CNTTIDR,CNTACR}, so it's
not clear if we can access anything in a frame, even if it is listed as
being a non-secure timer.

I think we need a stronger statement here. Otherwise, we will encounter
problems. Linux currently assumes that CNTCTLBase.CNTACR<N> is
writeable, given a non-secure frame N. This is only the case if
CNTCTLBase.CNTSAR.NS<N> == 1.

Thanks,
Mark.

[toc] | [prev] | [next] | [standalone]


#1561809 — [PATCH v20 10/17] clocksource/drivers/arm_arch_timer: Move arch_timer_needs_of_probing into DT init call

Fromfu.wei@linaro.org
Date2017-01-18 14:40 +0100
Subject[PATCH v20 10/17] clocksource/drivers/arm_arch_timer: Move arch_timer_needs_of_probing into DT init call
Message-ID<t0YD1-4Gk-35@gated-at.bofh.it>
In reply to#1561785
From: Fu Wei <fu.wei@linaro.org>

Because arch_timer_needs_of_probing is only for booting with device-tree,
but arch_timer_common_init is a generic init call which shouldn't include
the FW-specific code. It's better to put arch_timer_needs_of_probing into
DT init function.

But for per-cpu timer, the arch_timer_common_init is called from
arch_timer_init. For reaching the goal above, this patch disassemble
arch_timer_init and use arch_timer_register and arch_timer_common_init
directly, just like arch_timer_mem init code is doing.
By this way, all the DT relevant code are only called from DT init call.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 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 d10c2f7..9db5fb9 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -825,9 +825,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();
@@ -865,26 +862,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");
@@ -895,6 +875,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];
+
 	/*
 	 * Try to determine the frequency from the device tree,
 	 * if fail, get the frequency from the sysreg CNTFRQ.
@@ -933,7 +915,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);
@@ -1021,7 +1010,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);
@@ -1050,6 +1040,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) {
@@ -1077,6 +1068,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_detect_rate();
 
@@ -1089,8 +1082,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

[toc] | [prev] | [next] | [standalone]


#1561812 — [PATCH v20 14/17] clocksource/drivers/arm_arch_timer: Simplify ACPI support code.

Fromfu.wei@linaro.org
Date2017-01-18 14:40 +0100
Subject[PATCH v20 14/17] clocksource/drivers/arm_arch_timer: Simplify ACPI support code.
Message-ID<t0YD1-4Gk-39@gated-at.bofh.it>
In reply to#1561785
From: Fu Wei <fu.wei@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.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
---
 drivers/clocksource/arm_arch_timer.c | 46 ++++++++++--------------------------
 1 file changed, 13 insertions(+), 33 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 6e8a20c..79dc004 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1076,59 +1076,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_detect_rate();
-
 	arch_timer_uses_ppi = arch_timer_select_ppi();
 	if (!arch_timer_ppi[arch_timer_uses_ppi]) {
 		pr_err("No interrupt available, giving up\n");
@@ -1136,7 +1113,10 @@ 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_detect_rate();
 
 	ret = arch_timer_register();
 	if (ret)
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1561813 — [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver

Fromfu.wei@linaro.org
Date2017-01-18 14:40 +0100
Subject[PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver
Message-ID<t0YD1-4Gk-47@gated-at.bofh.it>
In reply to#1561785
From: Fu Wei <fu.wei@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.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 drivers/acpi/arm64/gtdt.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/acpi.h      |   1 +
 2 files changed, 125 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index d93a790..91ea6cb 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,105 @@ 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 *data)
+{
+	int i;
+	struct acpi_gtdt_timer_entry *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;
+	}
+
+	data->cntctlbase = (phys_addr_t)block->block_address;
+	/*
+	 * According to "Table * CNTCTLBase memory map" of
+	 * <ARM Architecture Reference Manual> for ARMv8,
+	 * The size of the CNTCTLBase frame is 4KB(Offset 0x000 – 0xFFC).
+	 */
+	data->size = SZ_4K;
+	data->num_frames = block->timer_count;
+
+	frame = (void *)block + block->timer_offset;
+	if (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++, frame++) {
+		if (!frame->base_address || !frame->timer_interrupt)
+			return -EINVAL;
+
+		data->frame[i].phys_irq = map_gt_gsi(frame->timer_interrupt,
+						     frame->timer_flags);
+		if (data->frame[i].phys_irq <= 0) {
+			pr_warn("failed to map physical timer irq in frame %d.\n",
+				i);
+			return -EINVAL;
+		}
+
+		data->frame[i].virt_irq =
+			map_gt_gsi(frame->virtual_timer_interrupt,
+				   frame->virtual_timer_flags);
+		if (data->frame[i].virt_irq <= 0) {
+			pr_warn("failed to map virtual timer irq in frame %d.\n",
+				i);
+			acpi_unregister_gsi(frame->timer_interrupt);
+			return -EINVAL;
+		}
+
+		data->frame[i].frame_nr = frame->frame_number;
+		data->frame[i].cntbase = frame->base_address;
+		/*
+		 * According to "Table * CNTBaseN memory map" of
+		 * <ARM Architecture Reference Manual> for ARMv8,
+		 * The size of the CNTBaseN frame is 4KB(Offset 0x000 – 0xFFC).
+		 */
+		data->frame[i].size = SZ_4K;
+	}
+
+	return 0;
+}
+
+/**
+ * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT table.
+ * @data:	the pointer to the array of struct arch_timer_mem for returning
+ *		the result of parsing. The element number of this array should
+ *		be platform_timer_count(the total number of platform timers).
+ * @count:	The pointer of int variate for returning the number of GT
+ *		blocks we have parsed.
+ *
+ * Return: 0 if success, -EINVAL/-ENODEV if error.
+ */
+int __init acpi_arch_timer_mem_init(struct arch_timer_mem *data,
+				    int *timer_count)
+{
+	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, data);
+			if (ret)
+				return ret;
+			data++;
+			(*timer_count)++;
+		}
+	}
+
+	if (*timer_count)
+		pr_info("found %d memory-mapped timer block(s).\n",
+			*timer_count);
+
+	return 0;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d0b271e..51e85b9 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -601,6 +601,7 @@ int acpi_reconfig_notifier_unregister(struct notifier_block *nb);
 int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count);
 int acpi_gtdt_map_ppi(int type);
 bool acpi_gtdt_c3stop(int type);
+int acpi_arch_timer_mem_init(struct arch_timer_mem *data, int *timer_count);
 #endif
 
 #else	/* !CONFIG_ACPI */
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1561814 — [PATCH v20 17/17] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver

Fromfu.wei@linaro.org
Date2017-01-18 14:50 +0100
Subject[PATCH v20 17/17] acpi/arm64: Add SBSA Generic Watchdog support in GTDT driver
Message-ID<t0YMG-4JP-5@gated-at.bofh.it>
In reply to#1561785
From: Fu Wei <fu.wei@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.wei@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
---
 drivers/acpi/arm64/gtdt.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/watchdog/Kconfig  |  1 +
 2 files changed, 94 insertions(+)

diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
index 91ea6cb..22d3659 100644
--- a/drivers/acpi/arm64/gtdt.c
+++ b/drivers/acpi/arm64/gtdt.c
@@ -14,6 +14,7 @@
 #include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
 
 #include <clocksource/arm_arch_timer.h>
 
@@ -59,6 +60,13 @@ static inline bool is_timer_block(void *platform_timer)
 	return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK;
 }
 
+static inline bool is_watchdog(void *platform_timer)
+{
+	struct acpi_gtdt_header *gh = platform_timer;
+
+	return gh->type == ACPI_GTDT_TYPE_WATCHDOG;
+}
+
 static int __init map_gt_gsi(u32 interrupt, u32 flags)
 {
 	int trigger, polarity;
@@ -279,3 +287,88 @@ int __init acpi_arch_timer_mem_init(struct arch_timer_mem *data,
 
 	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);
+	int no_irq = 1;
+
+	/*
+	 * 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),
+	};
+
+	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 (!wd->timer_interrupt)
+		pr_warn(FW_BUG "failed to get the Watchdog interrupt.\n");
+	else if (irq <= 0)
+		pr_warn("failed to map the Watchdog interrupt.\n");
+	else
+		no_irq = 0;
+
+	/*
+	 * 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,
+					       ARRAY_SIZE(res) - no_irq);
+	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, &table)))
+		return -EINVAL;
+
+	ret = acpi_gtdt_init(table, NULL);
+	if (ret)
+		return ret;
+
+	for_each_platform_timer(platform_timer) {
+		if (is_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);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index acb00b5..c899df1 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -219,6 +219,7 @@ config ARM_SBSA_WATCHDOG
 	tristate "ARM SBSA Generic Watchdog"
 	depends on ARM64
 	depends on ARM_ARCH_TIMER
+	depends on ACPI_GTDT || !ACPI
 	select WATCHDOG_CORE
 	help
 	  ARM SBSA Generic Watchdog has two stage timeouts:
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1562513 — Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

FromHanjun Guo <hanjun.guo@linaro.org>
Date2017-01-19 10:30 +0100
SubjectRe: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer
Message-ID<t1hcB-86Q-17@gated-at.bofh.it>
In reply to#1561785
Hi Fuwei,

On 2017/1/18 21:25, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This patchset:
>     (1)Preparation for adding GTDT support in arm_arch_timer:
>         1. Clean up printk() usage
>         2. Rename the type macros
>         3. Rename the PPI enum & enum values
>         4. Move the type macro and PPI enum into the header file
>         5. Add new enum for SPIs
>         6. Rework PPI determination;
>         7. Rework counter frequency detection;
>         8. Refactor arch_timer_needs_probing, move it into DT init call
>         9. 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:
> v20: https://lkml.org/lkml/2017/1/18/
>      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

Other than some minor comments I raised, the patch set
looks fine to me, and I tested this patch set on D03,
the percpu arch timer works fine as before.

With the comments fixed,
Reviewed-by: Hanjun Guo <hanjun.gu@linaro.org>
Tested-by: Hanjun Guo <hanjun.gu@linaro.org>

Thanks
Hanjun

[toc] | [prev] | [next] | [standalone]


#1562618 — Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

FromFu Wei <fu.wei@linaro.org>
Date2017-01-19 12:20 +0100
SubjectRe: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer
Message-ID<t1iV4-Qv-3@gated-at.bofh.it>
In reply to#1562513
Hi Hanjun,

On 19 January 2017 at 17:20, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> Hi Fuwei,
>
>
> On 2017/1/18 21:25, fu.wei@linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patchset:
>>     (1)Preparation for adding GTDT support in arm_arch_timer:
>>         1. Clean up printk() usage
>>         2. Rename the type macros
>>         3. Rename the PPI enum & enum values
>>         4. Move the type macro and PPI enum into the header file
>>         5. Add new enum for SPIs
>>         6. Rework PPI determination;
>>         7. Rework counter frequency detection;
>>         8. Refactor arch_timer_needs_probing, move it into DT init call
>>         9. 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:
>> v20: https://lkml.org/lkml/2017/1/18/
>>      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
>
>
> Other than some minor comments I raised, the patch set
> looks fine to me, and I tested this patch set on D03,
> the percpu arch timer works fine as before.
>
> With the comments fixed,
> Reviewed-by: Hanjun Guo <hanjun.gu@linaro.org>
> Tested-by: Hanjun Guo <hanjun.gu@linaro.org>

Great thanks for your testing. :-)

will apply Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org> on all patches,
and Tested-by: Hanjun Guo <hanjun.guo@linaro.org> on arch_timer patches.

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

[toc] | [prev] | [next] | [standalone]


#1565247 — Re: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer

FromMark Rutland <mark.rutland@arm.com>
Date2017-01-23 20:00 +0100
SubjectRe: [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer
Message-ID<t2S0q-1AD-25@gated-at.bofh.it>
In reply to#1561785
Hi,

On Wed, Jan 18, 2017 at 09:25:24PM +0800, fu.wei@linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
> 
> This patchset:
>     (1)Preparation for adding GTDT support in arm_arch_timer:
>         1. Clean up printk() usage
>         2. Rename the type macros
>         3. Rename the PPI enum & enum values
>         4. Move the type macro and PPI enum into the header file
>         5. Add new enum for SPIs
>         6. Rework PPI determination;

I've taken these few patches onto a preliminary/unstable branch [1].

I haven't had the time to take a look at the rest of the series yet. I
intend to go over that tomorrow, picking what I can, and leaving
feedback for anything that will need rework.

Thanks,
Mark.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git arch-timer/updates

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | linux.kernel


csiph-web