Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 01/11] arm64: use RET instruction for exiting the trampoline
From: Will Deacon @ 2018-01-08 14:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_F_hWvF7CghnDCQGCaxeViTZjvT=zqdFdD5rqdORCceQ@mail.gmail.com>

On Mon, Jan 08, 2018 at 02:38:00PM +0000, Ard Biesheuvel wrote:
> On 8 January 2018 at 14:33, Will Deacon <will.deacon@arm.com> wrote:
> > On Sat, Jan 06, 2018 at 01:13:23PM +0000, Ard Biesheuvel wrote:
> >> On 5 January 2018 at 13:12, Will Deacon <will.deacon@arm.com> wrote:
> >> > Speculation attacks against the entry trampoline can potentially resteer
> >> > the speculative instruction stream through the indirect branch and into
> >> > arbitrary gadgets within the kernel.
> >> >
> >> > This patch defends against these attacks by forcing a misprediction
> >> > through the return stack: a dummy BL instruction loads an entry into
> >> > the stack, so that the predicted program flow of the subsequent RET
> >> > instruction is to a branch-to-self instruction which is finally resolved
> >> > as a branch to the kernel vectors with speculation suppressed.
> >> >
> >>
> >> How safe is it to assume that every microarchitecture will behave as
> >> expected here? Wouldn't it be safer in general not to rely on a memory
> >> load for x30 in the first place? (see below) Or may the speculative
> >> execution still branch anywhere even if the branch target is
> >> guaranteed to be known by that time?
> >
> > The main problem with this approach is that EL0 can read out the text and
> > find the kaslr offset.
> 
> Not really - the CONFIG_RANDOMIZE_BASE path puts the movz/movk
> sequence in the next page, but that does involve an unconditional
> branch.

Ah sorry, I had missed that. The unconditional branch may still be attacked,
however.

> > The memory load is fine, because the data page is
> > unmapped along with the kernel text. I'm not aware of any
> > micro-architectures where this patch doesn't do what we need.
> >
> 
> Well, the memory load is what may incur the delay, creating the window
> for speculative execution of the indirect branch. What I don't have
> enough of a handle on is whether this speculative execution may still
> branch to wherever the branch predictor is pointing even if the
> register containing the branch target is already available.

For the micro-architectures I'm aware of, the return stack predictor will
always safely mispredict the jump into the kernel vectors with this patch
applied.

Will

^ permalink raw reply

* [PATCH v6 08/10] pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops
From: Neil Armstrong @ 2018-01-08 14:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <fd544471-63d0-dbf1-cee5-53f05c837cdd@ti.com>

On 08/01/2018 15:33, Keerthy wrote:
> 
> 
> On Monday 08 January 2018 02:14 PM, Claudiu Beznea wrote:
>>
>>
>> On 02.01.2018 12:09, Keerthy wrote:
>>> Adapt driver to utilize dmtimer pdata ops instead of pdata-quirks.
>>>
>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>> Tested-by: Ladislav Michl <ladis@linux-mips.org>
>>> ---
>>>  drivers/pwm/pwm-omap-dmtimer.c | 39 ++++++++++++++++++++++-----------------
>>>  1 file changed, 22 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
>>> index 5ad42f3..3b27aff 100644
>>> --- a/drivers/pwm/pwm-omap-dmtimer.c
>>> +++ b/drivers/pwm/pwm-omap-dmtimer.c
>>> @@ -23,6 +23,7 @@
>>>  #include <linux/mutex.h>
>>>  #include <linux/of.h>
>>>  #include <linux/of_platform.h>
>>> +#include <linux/platform_data/dmtimer-omap.h>
>>>  #include <linux/platform_data/pwm_omap_dmtimer.h>
>>>  #include <linux/platform_device.h>
>>>  #include <linux/pm_runtime.h>
>>> @@ -37,7 +38,7 @@ struct pwm_omap_dmtimer_chip {
>>>  	struct pwm_chip chip;
>>>  	struct mutex mutex;
>>>  	pwm_omap_dmtimer *dm_timer;
>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>> +	struct omap_dm_timer_ops *pdata;
>>>  	struct platform_device *dm_timer_pdev;
>>>  };
>>>  
>>> @@ -242,19 +243,33 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>  {
>>>  	struct device_node *np = pdev->dev.of_node;
>>>  	struct device_node *timer;
>>> +	struct platform_device *timer_pdev;
>>>  	struct pwm_omap_dmtimer_chip *omap;
>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>> +	struct dmtimer_platform_data *timer_pdata;
>>> +	struct omap_dm_timer_ops *pdata;
>>>  	pwm_omap_dmtimer *dm_timer;
>>>  	u32 v;
>>>  	int status;
>>>  
>>> -	pdata = dev_get_platdata(&pdev->dev);
>>> -	if (!pdata) {
>>> -		dev_err(&pdev->dev, "Missing dmtimer platform data\n");
>>> +	timer = of_parse_phandle(np, "ti,timers", 0);
>> of_node_put() should be called when done with device_node pointer returned
>> by of_parse_phandle() (you may want to check the return ERROR cases below
>> regarding this statement):
>>> +	if (!timer)
>>> +		return -ENODEV;
>>> +
>>> +	timer_pdev = of_find_device_by_node(timer);
>>> +	if (!timer_pdev) {
>>> +		dev_err(&pdev->dev, "Unable to find Timer pdev\n");
>> here
>>> +		return -ENODEV;
>>> +	}
>>> +
>>> +	timer_pdata = dev_get_platdata(&timer_pdev->dev);
>>> +	if (!timer_pdata) {
>>> +		dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
>> here
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> -	if (!pdata->request_by_node ||
>>> +	pdata = timer_pdata->timer_ops;
>>> +
>>> +	if (!pdata || !pdata->request_by_node ||
>>>  	    !pdata->free ||
>>>  	    !pdata->enable ||
>>>  	    !pdata->disable ||
>>> @@ -270,10 +285,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> -	timer = of_parse_phandle(np, "ti,timers", 0);
>>> -	if (!timer)
>>> -		return -ENODEV;
>>> -
>>>  	if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
>> here
>>>  		dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
>>>  		return -ENODEV;
>>> @@ -291,13 +302,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>  
>>>  	omap->pdata = pdata;
>>>  	omap->dm_timer = dm_timer;
>>> -
>>> -	omap->dm_timer_pdev = of_find_device_by_node(timer);
>>> -	if (!omap->dm_timer_pdev) {
>>> -		dev_err(&pdev->dev, "Unable to find timer pdev\n");
>>> -		omap->pdata->free(dm_timer);
>>> -		return -EINVAL;
>>> -	}
>>> +	omap->dm_timer_pdev = timer_pdev;
>>>  
>>>  	/*
>>>  	 * Ensure that the timer is stopped before we allow PWM core to call
>>>
>> And all the other return instructions from probe function not listed by git diff
> 
> Thanks for reviewing. I will add the of_node_put call for all the error
> paths.
> 
>>
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

Apart the missing of_node_put() :

Acked-by: Neil Armstrong <narmstrong@baylibre.com>

^ permalink raw reply

* [PATCH v2 01/11] arm64: use RET instruction for exiting the trampoline
From: Ard Biesheuvel @ 2018-01-08 14:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108143345.GH25869@arm.com>

On 8 January 2018 at 14:33, Will Deacon <will.deacon@arm.com> wrote:
> On Sat, Jan 06, 2018 at 01:13:23PM +0000, Ard Biesheuvel wrote:
>> On 5 January 2018 at 13:12, Will Deacon <will.deacon@arm.com> wrote:
>> > Speculation attacks against the entry trampoline can potentially resteer
>> > the speculative instruction stream through the indirect branch and into
>> > arbitrary gadgets within the kernel.
>> >
>> > This patch defends against these attacks by forcing a misprediction
>> > through the return stack: a dummy BL instruction loads an entry into
>> > the stack, so that the predicted program flow of the subsequent RET
>> > instruction is to a branch-to-self instruction which is finally resolved
>> > as a branch to the kernel vectors with speculation suppressed.
>> >
>>
>> How safe is it to assume that every microarchitecture will behave as
>> expected here? Wouldn't it be safer in general not to rely on a memory
>> load for x30 in the first place? (see below) Or may the speculative
>> execution still branch anywhere even if the branch target is
>> guaranteed to be known by that time?
>
> The main problem with this approach is that EL0 can read out the text and
> find the kaslr offset.

Not really - the CONFIG_RANDOMIZE_BASE path puts the movz/movk
sequence in the next page, but that does involve an unconditional
branch.

> The memory load is fine, because the data page is
> unmapped along with the kernel text. I'm not aware of any
> micro-architectures where this patch doesn't do what we need.
>

Well, the memory load is what may incur the delay, creating the window
for speculative execution of the indirect branch. What I don't have
enough of a handle on is whether this speculative execution may still
branch to wherever the branch predictor is pointing even if the
register containing the branch target is already available.

^ permalink raw reply

* [PATCH v6 08/10] pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops
From: Keerthy @ 2018-01-08 14:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e9f73341-5262-0d9c-ecb8-f04f18d0bb05@microchip.com>



On Monday 08 January 2018 02:14 PM, Claudiu Beznea wrote:
> 
> 
> On 02.01.2018 12:09, Keerthy wrote:
>> Adapt driver to utilize dmtimer pdata ops instead of pdata-quirks.
>>
>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>> Tested-by: Ladislav Michl <ladis@linux-mips.org>
>> ---
>>  drivers/pwm/pwm-omap-dmtimer.c | 39 ++++++++++++++++++++++-----------------
>>  1 file changed, 22 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
>> index 5ad42f3..3b27aff 100644
>> --- a/drivers/pwm/pwm-omap-dmtimer.c
>> +++ b/drivers/pwm/pwm-omap-dmtimer.c
>> @@ -23,6 +23,7 @@
>>  #include <linux/mutex.h>
>>  #include <linux/of.h>
>>  #include <linux/of_platform.h>
>> +#include <linux/platform_data/dmtimer-omap.h>
>>  #include <linux/platform_data/pwm_omap_dmtimer.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/pm_runtime.h>
>> @@ -37,7 +38,7 @@ struct pwm_omap_dmtimer_chip {
>>  	struct pwm_chip chip;
>>  	struct mutex mutex;
>>  	pwm_omap_dmtimer *dm_timer;
>> -	struct pwm_omap_dmtimer_pdata *pdata;
>> +	struct omap_dm_timer_ops *pdata;
>>  	struct platform_device *dm_timer_pdev;
>>  };
>>  
>> @@ -242,19 +243,33 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>  {
>>  	struct device_node *np = pdev->dev.of_node;
>>  	struct device_node *timer;
>> +	struct platform_device *timer_pdev;
>>  	struct pwm_omap_dmtimer_chip *omap;
>> -	struct pwm_omap_dmtimer_pdata *pdata;
>> +	struct dmtimer_platform_data *timer_pdata;
>> +	struct omap_dm_timer_ops *pdata;
>>  	pwm_omap_dmtimer *dm_timer;
>>  	u32 v;
>>  	int status;
>>  
>> -	pdata = dev_get_platdata(&pdev->dev);
>> -	if (!pdata) {
>> -		dev_err(&pdev->dev, "Missing dmtimer platform data\n");
>> +	timer = of_parse_phandle(np, "ti,timers", 0);
> of_node_put() should be called when done with device_node pointer returned
> by of_parse_phandle() (you may want to check the return ERROR cases below
> regarding this statement):
>> +	if (!timer)
>> +		return -ENODEV;
>> +
>> +	timer_pdev = of_find_device_by_node(timer);
>> +	if (!timer_pdev) {
>> +		dev_err(&pdev->dev, "Unable to find Timer pdev\n");
> here
>> +		return -ENODEV;
>> +	}
>> +
>> +	timer_pdata = dev_get_platdata(&timer_pdev->dev);
>> +	if (!timer_pdata) {
>> +		dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
> here
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (!pdata->request_by_node ||
>> +	pdata = timer_pdata->timer_ops;
>> +
>> +	if (!pdata || !pdata->request_by_node ||
>>  	    !pdata->free ||
>>  	    !pdata->enable ||
>>  	    !pdata->disable ||
>> @@ -270,10 +285,6 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>  		return -EINVAL;
>>  	}
>>  
>> -	timer = of_parse_phandle(np, "ti,timers", 0);
>> -	if (!timer)
>> -		return -ENODEV;
>> -
>>  	if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
> here
>>  		dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
>>  		return -ENODEV;
>> @@ -291,13 +302,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>  
>>  	omap->pdata = pdata;
>>  	omap->dm_timer = dm_timer;
>> -
>> -	omap->dm_timer_pdev = of_find_device_by_node(timer);
>> -	if (!omap->dm_timer_pdev) {
>> -		dev_err(&pdev->dev, "Unable to find timer pdev\n");
>> -		omap->pdata->free(dm_timer);
>> -		return -EINVAL;
>> -	}
>> +	omap->dm_timer_pdev = timer_pdev;
>>  
>>  	/*
>>  	 * Ensure that the timer is stopped before we allow PWM core to call
>>
> And all the other return instructions from probe function not listed by git diff

Thanks for reviewing. I will add the of_node_put call for all the error
paths.

> 

^ permalink raw reply

* [PATCH v2 01/11] arm64: use RET instruction for exiting the trampoline
From: Will Deacon @ 2018-01-08 14:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-efng1k+QbeKmd2pGz1p4vhoFE4fZ8rZ7bihGvsb-e+w@mail.gmail.com>

On Sat, Jan 06, 2018 at 01:13:23PM +0000, Ard Biesheuvel wrote:
> On 5 January 2018 at 13:12, Will Deacon <will.deacon@arm.com> wrote:
> > Speculation attacks against the entry trampoline can potentially resteer
> > the speculative instruction stream through the indirect branch and into
> > arbitrary gadgets within the kernel.
> >
> > This patch defends against these attacks by forcing a misprediction
> > through the return stack: a dummy BL instruction loads an entry into
> > the stack, so that the predicted program flow of the subsequent RET
> > instruction is to a branch-to-self instruction which is finally resolved
> > as a branch to the kernel vectors with speculation suppressed.
> >
> 
> How safe is it to assume that every microarchitecture will behave as
> expected here? Wouldn't it be safer in general not to rely on a memory
> load for x30 in the first place? (see below) Or may the speculative
> execution still branch anywhere even if the branch target is
> guaranteed to be known by that time?

The main problem with this approach is that EL0 can read out the text and
find the kaslr offset. The memory load is fine, because the data page is
unmapped along with the kernel text. I'm not aware of any
micro-architectures where this patch doesn't do what we need.

Will

^ permalink raw reply

* [PATCH v4 6/6] ARM: imx_v6_v7_defconfig: Enable Dialog Semiconductor DA9062 driver
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

The phyCORE-i.MX 6 uses the DA9062/63 PMIC, RTC and Watchdog driver.

Enable these options by default.

Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/configs/imx_v6_v7_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 6726c83..e3c4163 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -216,8 +216,10 @@ CONFIG_THERMAL_WRITABLE_TRIPS=y
 CONFIG_CPU_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_WATCHDOG=y
+CONFIG_DA9062_WATCHDOG=y
 CONFIG_IMX2_WDT=y
 CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_DA9062=y
 CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_MFD_STMPE=y
@@ -225,6 +227,7 @@ CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_ANATOP=y
 CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_DA9062=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
@@ -348,6 +351,7 @@ CONFIG_RTC_DRV_ISL1208=y
 CONFIG_RTC_DRV_PCF8523=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_DA9063=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_RTC_DRV_SNVS=y
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/3] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12, A15 and A17
From: Andre Przywara @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106120907.26701-2-marc.zyngier@arm.com>

Hi,

On 06/01/18 12:09, Marc Zyngier wrote:
> In order to avoid aliasing attacks against the branch predictor,
> some implementations require to invalidate the BTB when switching
> from one user context to another.
> 
> For this, we reuse the existing implementation for Cortex-A8, and
> apply it to A9, A12, A15, and A17.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mm/proc-v7-2level.S |  4 ++--
>  arch/arm/mm/proc-v7-3level.S |  6 ++++++
>  arch/arm/mm/proc-v7.S        | 32 ++++++++++++++++----------------
>  3 files changed, 24 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
> index c6141a5435c3..0422e58b74e8 100644
> --- a/arch/arm/mm/proc-v7-2level.S
> +++ b/arch/arm/mm/proc-v7-2level.S
> @@ -41,7 +41,7 @@
>   *	even on Cortex-A8 revisions not affected by 430973.
>   *	If IBE is not set, the flush BTAC/BTB won't do anything.
>   */
> -ENTRY(cpu_ca8_switch_mm)
> +ENTRY(cpu_v7_btbinv_switch_mm)
>  #ifdef CONFIG_MMU
>  	mov	r2, #0
>  	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
> @@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
>  #endif
>  	bx	lr
>  ENDPROC(cpu_v7_switch_mm)
> -ENDPROC(cpu_ca8_switch_mm)
> +ENDPROC(cpu_v7_btbinv_switch_mm)
>  
>  /*
>   *	cpu_v7_set_pte_ext(ptep, pte)
> diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
> index 7d16bbc4102b..934272e1fa08 100644
> --- a/arch/arm/mm/proc-v7-3level.S
> +++ b/arch/arm/mm/proc-v7-3level.S
> @@ -54,6 +54,11 @@
>   * Set the translation table base pointer to be pgd_phys (physical address of
>   * the new TTB).
>   */
> +ENTRY(cpu_v7_btbinv_switch_mm)
> +#ifdef CONFIG_MMU
> +	mov	r2, #0
> +	mcr	p15, 0, r2, c7, c5, 6			@ flush BTAC/BTB

r2 is already used below: this is the second argument to the function.
The first argument is a phys_addr_t, so it takes both r0 and r1 already.
That's why we need to use r3 above.
This fixes a crash on the Midway for me.

Cheers,
Andre.

> +#endif
>  ENTRY(cpu_v7_switch_mm)
>  #ifdef CONFIG_MMU
>  	mmid	r2, r2
> @@ -64,6 +69,7 @@ ENTRY(cpu_v7_switch_mm)
>  #endif
>  	ret	lr
>  ENDPROC(cpu_v7_switch_mm)
> +ENDPROC(cpu_v7_btbinv_switch_mm)
>  
>  #ifdef __ARMEB__
>  #define rl r3
> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index 01d64c0b2563..23fa537101ab 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> @@ -159,18 +159,18 @@ ENDPROC(cpu_v7_do_resume)
>  #endif
>  
>  /*
> - * Cortex-A8
> + * Cortex-A8/A12/A15/A17 that require a BTB invalidation on switch_mm
>   */
> -	globl_equ	cpu_ca8_proc_init,	cpu_v7_proc_init
> -	globl_equ	cpu_ca8_proc_fin,	cpu_v7_proc_fin
> -	globl_equ	cpu_ca8_reset,		cpu_v7_reset
> -	globl_equ	cpu_ca8_do_idle,	cpu_v7_do_idle
> -	globl_equ	cpu_ca8_dcache_clean_area, cpu_v7_dcache_clean_area
> -	globl_equ	cpu_ca8_set_pte_ext,	cpu_v7_set_pte_ext
> -	globl_equ	cpu_ca8_suspend_size,	cpu_v7_suspend_size
> +	globl_equ	cpu_v7_btbinv_proc_init,	cpu_v7_proc_init
> +	globl_equ	cpu_v7_btbinv_proc_fin,		cpu_v7_proc_fin
> +	globl_equ	cpu_v7_btbinv_reset,		cpu_v7_reset
> +	globl_equ	cpu_v7_btbinv_do_idle,		cpu_v7_do_idle
> +	globl_equ	cpu_v7_btbinv_dcache_clean_area, cpu_v7_dcache_clean_area
> +	globl_equ	cpu_v7_btbinv_set_pte_ext,	cpu_v7_set_pte_ext
> +	globl_equ	cpu_v7_btbinv_suspend_size,	cpu_v7_suspend_size
>  #ifdef CONFIG_ARM_CPU_SUSPEND
> -	globl_equ	cpu_ca8_do_suspend,	cpu_v7_do_suspend
> -	globl_equ	cpu_ca8_do_resume,	cpu_v7_do_resume
> +	globl_equ	cpu_v7_btbinv_do_suspend,	cpu_v7_do_suspend
> +	globl_equ	cpu_v7_btbinv_do_resume,	cpu_v7_do_resume
>  #endif
>  
>  /*
> @@ -181,7 +181,7 @@ ENDPROC(cpu_v7_do_resume)
>  	globl_equ	cpu_ca9mp_reset,	cpu_v7_reset
>  	globl_equ	cpu_ca9mp_do_idle,	cpu_v7_do_idle
>  	globl_equ	cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area
> -	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_switch_mm
> +	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_btbinv_switch_mm
>  	globl_equ	cpu_ca9mp_set_pte_ext,	cpu_v7_set_pte_ext
>  .globl	cpu_ca9mp_suspend_size
>  .equ	cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2
> @@ -548,8 +548,8 @@ __v7_setup_stack:
>  
>  	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
>  	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
> +	define_processor_functions v7_btbinv, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  #ifndef CONFIG_ARM_LPAE
> -	define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
>  #endif
>  #ifdef CONFIG_CPU_PJ4B
> @@ -614,7 +614,7 @@ __v7_ca9mp_proc_info:
>  __v7_ca8_proc_info:
>  	.long	0x410fc080
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = ca8_processor_functions
> +	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca8_proc_info, . - __v7_ca8_proc_info
>  
>  #endif	/* CONFIG_ARM_LPAE */
> @@ -658,7 +658,7 @@ __v7_ca7mp_proc_info:
>  __v7_ca12mp_proc_info:
>  	.long	0x410fc0d0
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup
> +	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info
>  
>  	/*
> @@ -668,7 +668,7 @@ __v7_ca12mp_proc_info:
>  __v7_ca15mp_proc_info:
>  	.long	0x410fc0f0
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup
> +	__v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
>  
>  	/*
> @@ -688,7 +688,7 @@ __v7_b15mp_proc_info:
>  __v7_ca17mp_proc_info:
>  	.long	0x410fc0e0
>  	.long	0xff0ffff0
> -	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup
> +	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup, proc_fns = v7_btbinv_processor_functions
>  	.size	__v7_ca17mp_proc_info, . - __v7_ca17mp_proc_info
>  
>  	/*
> 

^ permalink raw reply

* [PATCH v4 5/6] ARM: dts: imx6: Add support for phyBOARD-Mira with i.MX 6QuadPlus
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

From: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>

Add support for the PHYTEC phyBOARD-Mira with i.MX 6QuadPlus with NAND.
It is based on the phyBOARD-Mira with i.MX 6Quad/Dual and supports the
same interfaces.

Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
Signed-off-by: Stefan Lengfeld <s.lengfeld@phytec.de>
Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/Makefile                        |  1 +
 arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts | 72 +++++++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 07d99a1..d42b522 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -479,6 +479,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-zii-rdu2.dtb \
 	imx6qp-nitrogen6_max.dtb \
 	imx6qp-nitrogen6_som2.dtb \
+	imx6qp-phytec-mira-rdk-nand.dtb \
 	imx6qp-sabreauto.dtb \
 	imx6qp-sabresd.dtb \
 	imx6qp-tx6qp-8037.dtb \
diff --git a/arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts
new file mode 100644
index 0000000..8b73d1c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
+ */
+
+/dts-v1/;
+#include "imx6qp.dtsi"
+#include "imx6qdl-phytec-phycore-som.dtsi"
+#include "imx6qdl-phytec-mira.dtsi"
+
+/ {
+	model = "PHYTEC phyBOARD-Mira QuadPlus Carrier-Board with NAND";
+	compatible = "phytec,imx6qp-pbac06-nand", "phytec,imx6qp-pbac06",
+		     "phytec,imx6qdl-pcm058", "fsl,imx6qp";
+
+	chosen {
+		linux,stdout-path = &uart2;
+	};
+};
+
+&can1 {
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
+
+&m25p80 {
+	status = "okay";
+};
+
+&gpmi {
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c_rtc {
+	status = "okay";
+};
+
+&pcie {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 4/6] ARM: dts: imx6: Add support for phyBOARD-Mira i.MX 6 DualLight/Solo RDK
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

From: Christian Hemp <c.hemp@phytec.de>

Add support for the PHYTEC phyBOARD-Mira Low-Cost Rapid Development Kit
with i.MX 6DualLight/Solo with NAND.

Following interfaces are supported:
- 100 MBit Ethernet
- USB Host
- RS232
- HDMI

Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Signed-off-by: Stefan Christ <s.christ@phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/Makefile                        |  1 +
 arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts | 64 +++++++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b793617..07d99a1 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -388,6 +388,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-icore-rqs.dtb \
 	imx6dl-nit6xlite.dtb \
 	imx6dl-nitrogen6x.dtb \
+	imx6dl-phytec-mira-rdk-nand.dtb \
 	imx6dl-phytec-pbab01.dtb \
 	imx6dl-rex-basic.dtb \
 	imx6dl-riotboard.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts
new file mode 100644
index 0000000..a8adcb2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-phytec-phycore-som.dtsi"
+#include "imx6qdl-phytec-mira.dtsi"
+
+/ {
+	model = "PHYTEC phyBOARD-Mira DualLite/Solo Carrier-Board with NAND";
+	compatible = "phytec,imx6dl-pbac06-nand", "phytec,imx6dl-pbac06",
+		     "phytec,imx6qdl-pcm058", "fsl,imx6dl";
+
+	chosen {
+		linux,stdout-path = &uart2;
+	};
+};
+
+&ethphy {
+	max-speed = <100>;
+};
+
+&fec {
+	status = "okay";
+};
+
+&gpmi {
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c_rtc {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 3/6] ARM: dts: imx6: Add support for phyBOARD-Mira i.MX 6Quad/Dual RDK
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

From: Christian Hemp <c.hemp@phytec.de>

Add support for the PHYTEC phyBOARD-Mira Rapid Development Kit with
i.MX 6Quad/Dual with eMMC or NAND.

Following interfaces are supported:
- Gigabit Ethernet
- USB Host
- CAN
- RS232
- PCIe
- LVDS
- HDMI

Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Signed-off-by: Stefan Christ <s.christ@phytec.de>
Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/Makefile                       |  2 +
 arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts | 72 ++++++++++++++++++++++++
 arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts | 72 ++++++++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts
 create mode 100644 arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d0381e9..b793617 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -449,6 +449,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-nitrogen6_max.dtb \
 	imx6q-nitrogen6_som2.dtb \
 	imx6q-novena.dtb \
+	imx6q-phytec-mira-rdk-emmc.dtb \
+	imx6q-phytec-mira-rdk-nand.dtb \
 	imx6q-phytec-pbab01.dtb \
 	imx6q-pistachio.dtb \
 	imx6q-rex-pro.dtb \
diff --git a/arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts b/arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts
new file mode 100644
index 0000000..8132d73
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-phytec-phycore-som.dtsi"
+#include "imx6qdl-phytec-mira.dtsi"
+
+/ {
+	model = "PHYTEC phyBOARD-Mira Quad Carrier-Board with eMMC";
+	compatible = "phytec,imx6q-pbac06-emmc", "phytec,imx6q-pbac06",
+		     "phytec,imx6qdl-pcm058", "fsl,imx6q";
+
+	chosen {
+		linux,stdout-path = &uart2;
+	};
+};
+
+&can1 {
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
+
+&m25p80 {
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c_rtc {
+	status = "okay";
+};
+
+&pcie {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+};
+
+&usdhc4 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts b/arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts
new file mode 100644
index 0000000..974b269
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-phytec-phycore-som.dtsi"
+#include "imx6qdl-phytec-mira.dtsi"
+
+/ {
+	model = "PHYTEC phyBOARD-Mira Quad Carrier-Board with NAND";
+	compatible = "phytec,imx6q-pbac06-nand", "phytec,imx6q-pbac06",
+		     "phytec,imx6qdl-pcm058", "fsl,imx6q";
+
+	chosen {
+		linux,stdout-path = &uart2;
+	};
+};
+
+&can1 {
+	status = "okay";
+};
+
+&fec {
+	status = "okay";
+};
+
+&m25p80 {
+	status = "okay";
+};
+
+&gpmi {
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c_rtc {
+	status = "okay";
+};
+
+&pcie {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usdhc1 {
+	status = "okay";
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 2/6] ARM: dts: imx6: Add initial support for phyBOARD-Mira
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

This patch adds basic support for PHYTEC phyBOARD-Mira as carrier board
for PHYTEC phyCORE-i.MX 6.

Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Signed-off-by: Stefan Christ <s.christ@phytec.de>
Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi | 388 +++++++++++++++++++++++++++++
 1 file changed, 388 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi

diff --git a/arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi
new file mode 100644
index 0000000..89458d0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+
+/ {
+	aliases {
+		rtc0 = &i2c_rtc;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_backlight>;
+		pwms = <&pwm1 0 5000000>;
+		status = "okay";
+	};
+
+	gpio_leds: leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioleds>;
+		status = "disabled";
+
+		red {
+			label = "phyboard-mira:red";
+			gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>;
+		};
+
+		green {
+			label = "phyboard-mira:green";
+			gpios = <&gpio5 23 GPIO_ACTIVE_HIGH>;
+		};
+
+		blue {
+			label = "phyboard-mira:blue";
+			gpios = <&gpio5 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+		};
+	};
+
+	reg_backlight: regulator-backlight {
+		compatible = "regulator-fixed";
+		regulator-name = "backlight_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_en_switch: regulator-en-switch {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_en_switch>;
+		regulator-name = "Enable Switch";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpio = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+		regulator-always-on;
+	};
+
+	reg_flexcan1: regulator-flexcan1 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flexcan1_en>;
+		regulator-name = "flexcan1-reg";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_panel: regulator-panel {
+		compatible = "regulator-fixed";
+		regulator-name = "panel-power-supply";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+	};
+
+	reg_pcie: regulator-pcie {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pcie_reg>;
+		regulator-name = "mPCIe_1V5";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		gpio = <&gpio3 0 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usb_h1_vbus: usb-h1-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1_vbus>;
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usbotg_vbus: usbotg-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbotg_vbus>;
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	panel {
+		compatible = "auo,g104sn02";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_panel_en>;
+		power-supply = <&reg_panel>;
+		enable-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+		backlight = <&backlight>;
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	xceiver-supply = <&reg_flexcan1>;
+	status = "disabled";
+};
+
+&hdmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hdmicec>;
+	ddc-i2c-bus = <&i2c2>;
+	status = "disabled";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	clock-frequency = <400000>;
+	status = "disabled";
+
+	stmpe: touchctrl at 44 {
+		compatible = "st,stmpe811";
+		reg = <0x44>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <12 IRQ_TYPE_NONE>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_stmpe>;
+		status = "disabled";
+
+		stmpe_touchscreen {
+			compatible = "st,stmpe-ts";
+			st,sample-time = <4>;
+			st,mod-12b = <1>;
+			st,ref-sel = <0>;
+			st,adc-freq = <1>;
+			st,ave-ctrl = <1>;
+			st,touch-det-delay = <2>;
+			st,settling = <2>;
+			st,fraction-z = <7>;
+			st,i-drive = <1>;
+		};
+	};
+
+	i2c_rtc: rtc at 68 {
+		compatible = "microcrystal,rv4162";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_rtc_int>;
+		reg = <0x68>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <100000>;
+	status = "disabled";
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel at 0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <24>;
+		status = "disabled";
+
+		port at 4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio2 25 GPIO_ACTIVE_LOW>;
+	vpcie-supply = <&reg_pcie>;
+	status = "disabled";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
+	status = "disabled";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	disable-over-current;
+	status = "disabled";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	vbus-supply = <&reg_usbotg_vbus>;
+	disable-over-current;
+	status = "disabled";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	cd-gpios = <&gpio6 31 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_panel_en: panelen1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB0__GPIO2_IO28		0xb0b1
+		>;
+	};
+
+	pinctrl_en_switch: enswitchgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_DA4__GPIO3_IO04		0xb0b1
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__FLEXCAN1_TX		0x1b0b0
+			MX6QDL_PAD_GPIO_8__FLEXCAN1_RX		0x1b0b0
+		>;
+	};
+
+	pinctrl_flexcan1_en: flexcan1engrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A18__GPIO2_IO20		0xb0b1
+		>;
+	};
+
+	pinctrl_gpioleds: gpioledsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT5__GPIO5_IO23	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT6__GPIO5_IO24	0x1b0b0
+		>;
+	};
+
+	pinctrl_hdmicec: hdmicecgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE	0x1f8b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_OE__GPIO2_IO25		0xb0b1
+		>;
+	};
+
+	pinctrl_pcie_reg: pciereggrp {
+		fsl,pins = <MX6QDL_PAD_EIM_DA0__GPIO3_IO00	0xb0b1>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_rtc_int: rtcintgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_RST__GPIO7_IO08		0x1b0b0
+		>;
+	};
+
+	pinctrl_stmpe: stmpegrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x1b0b0
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB3__UART3_CTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_D23__UART3_RTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbh1_vbus: usbh1vbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A20__GPIO2_IO18		0xb0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+		>;
+	};
+
+	pinctrl_usbotg_vbus: usbotgvbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A19__GPIO2_IO19		0xb0b1
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__SD1_CMD		0x170f9
+			MX6QDL_PAD_SD1_CLK__SD1_CLK		0x100f9
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x170f9
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x170f9
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x170f9
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x170f9
+			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0xb0b1  /* CD */
+		>;
+	};
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 1/6] ARM: dts: imx6: Add initial support for phyCORE-i.MX 6 SOM
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515421758-4240-1-git-send-email-s.riedmueller@phytec.de>

This patch adds basic support for PHYTEC phyCORE-i.MX 6 SOM with i.MX
6Quad/Dual or i.MX 6DualLight/Solo.

Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Signed-off-by: Stefan Christ <s.christ@phytec.de>
Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
Signed-off-by: Stefan Riedmueller <s.riedmueller@phytec.de>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi | 279 ++++++++++++++++++++++
 1 file changed, 279 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi

diff --git a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
new file mode 100644
index 0000000..6486df3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		rtc1 = &da9062_rtc;
+		rtc2 = &snvs_rtc;
+	};
+
+	/*
+	 * Set the minimum memory size here and
+	 * let the bootloader set the real size.
+	 */
+	memory at 10000000 {
+		device_type = "memory";
+		reg = <0x10000000 0x8000000>;
+	};
+
+	gpio_leds_som: somleds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpioleds_som>;
+
+		som-led-green {
+			label = "phycore:green";
+			gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	m25p80: flash at 0 {
+		compatible = "jedec,spi-nor";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+		status = "disabled";
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-handle = <&ethphy>;
+	phy-mode = "rgmii";
+	phy-supply = <&vdd_eth_io>;
+	phy-reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+	status = "disabled";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy: ethernet-phy at 3 {
+			reg = <3>;
+			txc-skew-ps = <1680>;
+			rxc-skew-ps = <1860>;
+		};
+	};
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	status = "disabled";
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	eeprom at 50 {
+		compatible = "atmel,24c32";
+		reg = <0x50>;
+	};
+
+	pmic at 58 {
+		compatible = "dlg,da9062";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		reg = <0x58>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+
+		da9062_rtc: rtc {
+			compatible = "dlg,da9062-rtc";
+		};
+
+		watchdog {
+			compatible = "dlg,da9062-watchdog";
+		};
+
+		regulators {
+			vdd_arm: buck1 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <730000>;
+				regulator-max-microvolt = <1380000>;
+				regulator-always-on;
+			};
+
+			vdd_soc: buck2 {
+				regulator-name = "vdd_soc";
+				regulator-min-microvolt = <730000>;
+				regulator-max-microvolt = <1380000>;
+				regulator-always-on;
+			};
+
+			vdd_ddr3_1p5: buck3 {
+				regulator-name = "vdd_ddr3";
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+			};
+
+			vdd_eth_1p2: buck4 {
+				regulator-name = "vdd_eth";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			vdd_snvs: ldo1 {
+				regulator-name = "vdd_snvs";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			vdd_high: ldo2 {
+				regulator-name = "vdd_high";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			vdd_eth_io: ldo3 {
+				regulator-name = "vdd_eth_io";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+			};
+
+			vdd_emmc_1p8: ldo4 {
+				regulator-name = "vdd_emmc";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+		};
+	};
+};
+
+&reg_arm {
+	vin-supply = <&vdd_arm>;
+};
+
+&reg_pu {
+	vin-supply = <&vdd_soc>;
+};
+
+&reg_soc {
+	vin-supply = <&vdd_soc>;
+};
+
+&snvs_poweroff {
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	vmmc-supply = <&vdd_emmc_1p8>;
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
+			MX6QDL_PAD_SD2_DAT1__GPIO1_IO14		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpioleds_som: gpioledssomgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS2__NAND_CE2_B	0xb0b1
+			MX6QDL_PAD_NANDF_CS3__NAND_CE3_B	0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+			MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x1b0b0
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1b0b0
+		>;
+	};
+
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+			MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+			MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+			MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+			MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+		>;
+	};
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 0/6] ARM: dts: Add PHYTEC phyCORE-i.MX 6 and phyBOARD-Mira carrier board support
From: Stefan Riedmueller @ 2018-01-08 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds support for the PHYTEC phyCORE-i.MX 6 and phyBOARD-Mira.

Following boards are included:
phyBOARD-Mira with phyCORE-i.MX 6 Quad/Dual with:
- i.MX 6Quad/Dual SOC
- NAND or eMMC
- HDMI interface
- LVDS display interface
- Gigabit Ethernet
- USB Host
- CAN
- RS232
- PCIe
This board also contains an LVDS camera interface and parallel display
interface which are not yet supported.

phyBAORD-Mira with phyCORE-i.MX 6 DualLight/Solo with:
- i.MX 6DualLight/Solo
- NAND
- HDMI interface
- 100 MBit/s Ethernet
- USB Host
- RS232

phyBOARD-Mira with phyCORE-i.MX 6 QuadPlus with:
- i.MX 6QuadPlus SOC
- NAND
- HDMI interface
- LVDS display interface
- Gigabit Ethernet
- USB Host
- CAN
- RS232
- PCIe
This board also contains an LVDS camera interface and parallel display
interface which are not yet supported.

The entire series is based on v4.15-rc4.

Changes since v1:
- Removed unnecessary ipu aliases
- Added unit-address to memory node name
- Fixed eeprom compatible to correct vendor name (atmel instead of cat)
- Fixed rtc compatible to correct vendor name (microcrystal instead of mc)
- Changed pcie regulator to be used with vpcie-supply in &pcie node and
  removed regulator-always-on
- Changed pcie reset-gpio polarity to GPIO_ACTIVE_LOW
- Replaced fsl,uart-has-rtscts by uart-has-rtscts
- Fixed typos in defconfig patch

Changes since v2:
- Fixed typo in patch subject PATCH 4/6
- Added reviewed by tags on PATCH 4/6 and PATCH 6/6

Changes since v3:
- Removed model and compatible from phycore dtsi
- Changed flash compatible to jedec,spi-nor
- Renamed some_green node to som-led-green
- Dropped labels for eeprom, pmic, da9062_wdt and da9062_reg
- Renamed flash label to m25p80
- Put compatible at beginning of property lists
- Changed copyright year to 2018
- Added reviewed by tags on PATCH 1/6, 2/6, 3/6 and 5/6

Christian Hemp (2):
  ARM: dts: imx6: Add support for phyBOARD-Mira i.MX 6Quad/Dual RDK
  ARM: dts: imx6: Add support for phyBOARD-Mira i.MX 6 DualLight/Solo
    RDK

Enrico Scholz (1):
  ARM: dts: imx6: Add support for phyBOARD-Mira with i.MX 6QuadPlus

Stefan Riedmueller (3):
  ARM: dts: imx6: Add initial support for phyCORE-i.MX 6 SOM
  ARM: dts: imx6: Add initial support for phyBOARD-Mira
  ARM: imx_v6_v7_defconfig: Enable Dialog Semiconductor DA9062 driver

 arch/arm/boot/dts/Makefile                        |   4 +
 arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts |  64 ++++
 arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts  |  72 ++++
 arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts  |  72 ++++
 arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi        | 388 ++++++++++++++++++++++
 arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi | 279 ++++++++++++++++
 arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts |  72 ++++
 arch/arm/configs/imx_v6_v7_defconfig              |   4 +
 8 files changed, 955 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6dl-phytec-mira-rdk-nand.dts
 create mode 100644 arch/arm/boot/dts/imx6q-phytec-mira-rdk-emmc.dts
 create mode 100644 arch/arm/boot/dts/imx6q-phytec-mira-rdk-nand.dts
 create mode 100644 arch/arm/boot/dts/imx6qdl-phytec-mira.dtsi
 create mode 100644 arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
 create mode 100644 arch/arm/boot/dts/imx6qp-phytec-mira-rdk-nand.dts

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 07/11] arm64: Add skeleton to harden the branch predictor against aliasing attacks
From: Will Deacon @ 2018-01-08 14:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5A53611C.5030003@arm.com>

Hi James,

Thanks for having a look.

On Mon, Jan 08, 2018 at 12:16:28PM +0000, James Morse wrote:
> On 05/01/18 13:12, Will Deacon wrote:
> > diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> > index 22168cd0dde7..5203b6040cb6 100644
> > --- a/arch/arm64/mm/fault.c
> > +++ b/arch/arm64/mm/fault.c
> > @@ -318,6 +318,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
> >  		lsb = PAGE_SHIFT;
> >  	si.si_addr_lsb = lsb;
> >  
> > +	arm64_apply_bp_hardening();
> 
> Due to the this_cpu_ptr() call:
> 
> | BUG: using smp_processor_id() in preemptible [00000000] code: print_my_pa/2093
> | caller is debug_smp_processor_id+0x1c/0x24
> | CPU: 0 PID: 2093 Comm: print_my_pa Tainted: G        W
> 4.15.0-rc3-00044-g7f0aaec94f27-dirty #8950
> | Call trace:
> |  dump_backtrace+0x0/0x164
> |  show_stack+0x14/0x1c
> |  dump_stack+0xa4/0xdc
> |  check_preemption_disabled+0xfc/0x100
> |  debug_smp_processor_id+0x1c/0x24
> |  __do_user_fault+0xcc/0x180
> |  do_page_fault+0x14c/0x364
> |  do_translation_fault+0x40/0x48
> |  do_mem_abort+0x40/0xb8
> |  el0_da+0x20/0x24

Ah bugger, yes, we re-enabled interrupts in the entry code when we took the
fault initially.

> Make it a TIF flag?
> 
> (Seen with arm64's kpti-base tag and this series)

A TIF flag is still a bit fiddly, because we need to track that the
predictor could be dirty on this CPU. Instead, I'll postpone the re-enabling
of IRQs on el0_ia until we're in C code -- we can quickly a check on the
address before doing that. See below.

Will

--->8

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 80b539845da6..07a7d4db8ec4 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -721,12 +721,15 @@ el0_ia:
 	 * Instruction abort handling
 	 */
 	mrs	x26, far_el1
-	enable_daif
+	enable_da_f
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
 	ct_user_exit
 	mov	x0, x26
 	mov	x1, x25
 	mov	x2, sp
-	bl	do_mem_abort
+	bl	do_el0_ia_bp_hardening
 	b	ret_to_user
 el0_fpsimd_acc:
 	/*
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5203b6040cb6..0e671ddf4855 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -318,7 +318,6 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
 		lsb = PAGE_SHIFT;
 	si.si_addr_lsb = lsb;
 
-	arm64_apply_bp_hardening();
 	force_sig_info(sig, &si, tsk);
 }
 
@@ -709,6 +708,23 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
 	arm64_notify_die("", regs, &info, esr);
 }
 
+asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
+						   unsigned int esr,
+						   struct pt_regs *regs)
+{
+	/*
+	 * We've taken an instruction abort from userspace and not yet
+	 * re-enabled IRQs. If the address is a kernel address, apply
+	 * BP hardening prior to enabling IRQs and pre-emption.
+	 */
+	if (addr > TASK_SIZE)
+		arm64_apply_bp_hardening();
+
+	local_irq_enable();
+	do_mem_abort(addr, esr, regs);
+}
+
+
 asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
 					   unsigned int esr,
 					   struct pt_regs *regs)

^ permalink raw reply related

* [PATCH 12/14] iio: adc: at91-sama5d2_adc: support for position and pressure channels
From: Ludovic Desroches @ 2018-01-08 14:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106150537.684345f3@archlinux>

Hi Jonathan, Eugen,

On Sat, Jan 06, 2018 at 03:05:37PM +0000, Jonathan Cameron wrote:
> On Thu, 4 Jan 2018 17:17:54 +0200
> Eugen Hristev <eugen.hristev@microchip.com> wrote:
> 
> > On 29.12.2017 19:02, Jonathan Cameron wrote:
> > > On Fri, 22 Dec 2017 17:07:19 +0200
> > > Eugen Hristev <eugen.hristev@microchip.com> wrote:
> > >   
> > >> The ADC IP supports position and pressure measurements for a touchpad
> > >> connected on channels 0,1,2,3 for a 4-wire touchscreen with pressure
> > >> measurement support.
> > >> Using the inkern API, a driver can request a trigger and read the
> > >> channel values from the ADC.
> > >> The implementation provides a trigger named "touch" which can be
> > >> connected to a consumer driver.
> > >> Once a driver connects and attaches a pollfunc to this trigger, the
> > >> configure trigger callback is called, and then the ADC driver will
> > >> initialize pad measurement.
> > >> First step is to enable touchscreen 4wire support and enable
> > >> pen detect IRQ.
> > >> Once a pen is detected, a periodic trigger is setup to trigger every
> > >> 2 ms (e.g.) and sample the resistive touchscreen values. The trigger poll
> > >> is called, and the consumer driver is then woke up, and it can read the
> > >> respective channels for the values : X, and Y for position and pressure
> > >> channel.
> > >> Because only one trigger can be active in hardware in the same time,
> > >> while touching the pad, the ADC will block any attempt to use the
> > >> triggered buffer. Same, conversions using the software trigger are also
> > >> impossible (since the periodic trigger is setup).
> > >> If some driver wants to attach while the trigger is in use, it will
> > >> also fail.
> > >> Once the pen is not detected anymore, the trigger is free for use (hardware
> > >> or software trigger, with or without DMA).
> > >> Channels 0,1,2 and 3 are unavailable if a touchscreen is enabled.
> > >>
> > >> Some parts of this patch are based on initial original work by
> > >> Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
> > >>  
> > > OK, so comments inline.
> > > 
> > > What I'm missing currently though is an explanation of why the slightly
> > > more standard arrangement of using a callback buffer doesn't work here.
> > > The only addition I think you need to do that is to allow a consumer to
> > > request a particular trigger.  I also think some of the other provisions
> > > could be handled using standard features and slightly reducing the flexibility.
> > > I don't know for example if it's useful to allow other channels to be
> > > read when touch is not in progress or not.
> > > 
> > > So restrictions:
> > > 
> > > 1. Touch screen channels can only be read when touch is enabled.
> > >   - use the available_scan_masks to control this. Or the callback that lets
> > >     you do the same dynamically.
> > > 2. You need to push these channels to your consumer driver.
> > >   - register a callback buffer rather than jumping through the hoops to
> > >     insert your own pollfunc.  That will call a function in your
> > >     consumer, providing the data from the 3 channels directly.
> > > 3. You need to make sure it is using the right driver.  For that you
> > >     will I think need a new interface.
> > > 
> > > Various other comments inline. I may well be missing something as this is
> > > a fair bit of complex code to read - if so then next version should have
> > > a clear cover letter describing why this more standard approach can't be
> > > used.  
> > 
> > Hello Jonathan and thanks for the review of my patch series,
> > 
> > before starting and working over the required modifications and 
> > suggestions that you sent me, I want to be a little more explicit about 
> > the design of my implementation.
> > Hope this will clarify some things, and maybe I can as well understand 
> > better what you have in mind to support this feature set.
> > 
> > Why have I picked a pollfunction: We discussed a while back on the 
> > mailing list that you do not have an inkern mechanism to expose the 
> > triggers to other drivers, and that it may be a good idea to have it for 
> > such kind of actually multi function device, instead of having a MFD 
> > driver, an ADC driver, and an Input driver, all sharing the same 
> > register map, the same IRQ , etc, with some kind of synchronization to 
> > avoid stepping on each other for the hardware resource.
> 
> No disagreement with that principle.
> 
> > So I considered to expose the trigger by attaching and detaching 
> > pollfunctions to it. Which is the main thing what we use a trigger for.
> 
> Hmm. It's definitely one approach. But we do already have other drivers
> where the trigger is controlled by a consumer and to my mind that
> is a cleaner approach as it doesn't short cut the equivalent of
> doing it from userspace.
> 
> drivers/iio/potentiostat/lmp91000.c does something similar though
> for a rather different use. You need your consumer interface
> to get the handle to the trigger in this case
> (the lmp91000 is actually providing the trigger rather than
> consuming it).
> 
> 
> > 
> > So, what I had in mind, was to create a consumer driver that will 
> > request triggers from the IIO device just like other drivers request 
> > channels (part which is already done in IIO).
> > In order to do this I had to somehow wake up the consumer driver when 
> > new data was available from the touchscreen. So, having the IRQ only in 
> > the ADC device, and then on Pen detect and No pen detect just start or 
> > stop the periodic trigger, which needs to be polled. The magic part is 
> > that the consumer driver has a poll function already attached to this 
> > trigger, so the poll function is just called every time we have new 
> > data. The poll function is attached as an irq handler, and then we can 
> > reuse all the read_raw data by using a scheduled work from the consumer 
> > driver, to read the channels.
> 
> If you had done this via a callback buffer the only difference is that
> the pollfunc would have been a standard one pulling the relevant channels
> and passing them on down to the buffer interface which could then decide
> what to do with them.
> 
> > To do this, the ADC registers a special trigger named "touch trigger" 
> > which is never enabled by the ADC driver. Instead, when a pollfunc is 
> > attached to it, the attach function will also configure it with enabled 
> > state.
> 
> Whilst it might not make sense to enable it in the touch screen driver
> I'm not sure there is strictly any reason to prevent it being so used.
> 
> > In the ADC, this means to start the touchscreen functionality. If 
> > the touch is requested, it will standby and wait for pen detect IRQ.
> > Once we have pen detect, we can use a periodic trigger to sample the 
> > touch data, and poll the "touch" trigger. The consumer driver will wake 
> > up and schedule a work , that will use the standard read raw interface 
> > (inkern) that will read three virtual channels (position + pressure). 
> > They are not actual hardware channels, as the touch information is being 
> > received on channels 0,1,2,3, but reading these virtual channels will 
> > read from different registers inside the ADC IP ( x position, y 
> > position, pressure), do some computations on the data, and feed the 
> > consumer with the values , hiding the behind the scenes hardware 
> > specific calculations.
> 
> I wouldn't worry about whether they are real channels or not. This
> is really similar to a differential ADC (some of those do the differential
> digitally). Light sensors often have a number of 'real' channels used
> to derive (via hideous non linear calculations) the illuminance as
> it's hard to build a light sensor with the same sensitivity as the human
> eye.  We have worse 'non real' channels as well such as activity channels
> on some the accelerometers that report if it thinks you are walking /
> running etc.
>  
> > After trigger is polled , the ADC will resume normal functionality, and 
> > the consumer driver will continue to sleep.
> 
> So this is where I'm unsure.  Do you actually have a usecase where it
> makes the sense to read from the ADC only when there is no touch?  Any
> system doing that has an obvious denial of service attack - touch the
> screen.
> 

You're right. We have an issue in this case due to the hardware. Using
touchscreen has side effects on other channels. We can use only one
trigger for all the channels. The situation would have been better with
a trigger dedicated to the touchscreen.

At the moment, we have not really stated about the exclusive use or not
of the touchscreen. We suppose we can get some customers wanting to use
both touchscreen and ADC. Eugen tried to deal with this case but, as you
noticed, it can lead to DoS.

> > We need to have a periodic trigger to sample the data because the actual 
> > analog to digital conversion inside the IP block needs to be triggered. 
> > The touchscreen data measurements cannot happen in hardware without 
> > being triggered. If I try with a hrtimer to get a periodic IRQ to just 
> > read the data, it will never be ready. The datasheet states that the 
> > touchscreen measurements "will be attached to the conversion sequence". 
> > So the periodic trigger is forcing a conversion sequence. This could be 
> > done with a software trigger as well, but why the hassle to start it 
> > every 2 milliseconds (or other time interval), if we can do it by 
> > periodic trigger ?
> 
> Ah, one reason here would be to allow separate consumers to use the
> device. In that case you'd run with a periodic trigger all the time
> and have two buffers attached, the buffer_cb that is feeding your
> touchscreen and another buffer to deal with the other channels
> (presumably the standard one an IIO device has when using buffered
> interfaces).

The issue is that we are sharing the periodic trigger so we have to use
the same period for both usage.

Regards

Ludovic

> 
> The buffer demux would ensure the data from the right channels
> ends up in the right place.  It makes it look to the buffer
> consumer like it is the only thing using / controlling the data
> flow.
> 
> > Once we get the No pen IRQ, we stop the periodic trigger and it can be 
> > used in another purpose (software or external as of now in the driver, 
> > in the future we can add PWM trigger and Timer trigger)
> 
> This case isn't really useful though as any other use is denied
> access when touch occurs.
> 
> I'll summarise what I think would work for this below.
> 
> > 
> > In short, the ADC in Sama5D2 also supports touchscreen, and in 
> > touchscreen mode , 4 of the channels are being used for this purpose. 
> > This however, doesn't stop the ADC to use the other channels . The 
> > hardware has 12 total single channels and they can be paired to have 6 
> > more differential channels. The only thing that is blocked is the 
> > trigger, but only if the pen is touching (when we start the periodic 
> > trigger to sample the touchscreen). If the pen is not touching, an 
> > external trigger or software trigger can be used without any issues (so 
> > why limit the functionality, if this is available from hardware ?). 
> > Because of the reason I discussed above (touchscreen sequence must be 
> > triggered), we cannot use another trigger in the same time.
> > 
> > 
> > I see your idea with the callback buffer and it's worth exploring. 
> > Mainly this series was to actually show you what I had in mind about 
> > supporting the resistive touchscreen, and to give you some actually 
> > working code/patch, so we can discuss based on real implementation, not 
> > just suppositions.
> 
> That side of things is fine.
> 
> > 
> > You are right in many of the other comments that you said, and I will 
> > come up with a v2 to this series. For now, I need to know if this is a 
> > good or right direction in which I am going, or I should try to change 
> > all the mechanism to callback buffer ? Or maybe I am totally in a bad 
> > direction ?
> > The requirements are that the consumer driver needs to be somehow woke 
> > up for every new touch data available, and report to the input 
> > subsystem. As it was done before, the at91 old driver, just creates and 
> > registers an input device by itself, and then reports the position and 
> > touches. I was thinking that with this trigger consumer implementation, 
> > things can be better in terms of subsystem separation and support.
> > 
> > Thanks again and let me know of your thoughts,
> > 
> > Eugen
> 
> So a couple of things come to mind on how I'd structure this.
> So what we have (very briefly)
> 
> No touch screen case:
> * Generic ADC using all sorts of different triggers
> 
> Touch screen only case:
> * Interrupt to indicate pen on / off
> * A need to do a periodic trigger of the device but only
> useful when touch is in progress.
> 
> Touch screen and other users:
> * Interrupt to indicate pen on / off
> * Periodic trigger needed for touchscreen when touch in progress.
> * Do not have denial of service on other channels.
> 
> First two cases are easy enough by having a magic trigger, third
> case is harder.
> If we have the touchscreen then I would drop support for direct access to
> to ADC channels whilst it's in use (so no sysfs - or emulate it if you
> really want it by stashing results from scans done when touch is in
> progress).
> 
> Have your touch screen channels just as normal additional channels,
> but only via the buffered interface (no _RAW attribute).
> If someone sets up to read them via buffered interface with
> a different trigger I think they'll get values - whether they
> are right is dependent (if I understand correctly) on whether
> there is a touch in progress.  So no harm done and it'll make
> the logic simpler.
> 
> The moment touch is opened and acquires the IIO channels
> fix the trigger (may need new interface) to the periodic one
> that you were enabling and disabling on touch.
> Things get dicey if there is an existing user so you may
> have to do it on driver probe rather than open of the input
> device if we effectively want touch to have the highest
> priority use of the ADC.
> 
> If other channels are enabled for buffered mode then note
> this in the driver and have the periodic trigger on all the
> time (to ensure they keep getting read)  This will pass
> garbage to your touch screen driver, but it'll remove it due
> to the pressure value being too low so no harm there.
> 
> Normal path will work for non touch channels (and in theory
> the touch ones if they are turned on) via IIO buffer
> interface.  It'll be restricted in form due to the needs of
> the touch driver, but better than nothing and should cover
> most usecases.
> 
> Now the interrupt on / off on touch bit becomes an optimization
> in the case of only the buffer_cb being attached.
> 
> I think that fits cleanly in the current IIO framework and
> looks more similar to our existing provider consumer approaches.
> 
> Still needs the hooks to get hold of the trigger though so
> as to be able to tell the ADC which one to use. So rather
> than being a trigger consumer interface, it's more of a trigger
> configuration interface..  Exact term doesn't matter though.
> 
> Jonathan
> 
> > 
> > 
> > 
> > [...]
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: Jiri Olsa @ 2018-01-08 14:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <850a0774-9442-c836-f457-69e1e0d72fb2@huawei.com>

On Thu, Jan 04, 2018 at 05:17:56PM +0000, John Garry wrote:

SNIP

> 
> 
> Hi Jirka,
> 
> Sorry for the slow reply.

np, just got back from holidays anyway ;-)

> 
> > > > Won't this all potentially have a big maintainence cost?
> > as Andi said it's mostly just the disk space,
> > which is not big deal
> > 
> > I'm not doing JSON file updates, but I think having
> > simple single dir for platform/cpu could save us some
> > confusion in future
> 
> Understood. But for ARM, which has very standardised architecture events, it
> is good to reduce this event duplication between platforms.
> 
> > 
> > however I won't oppose if you want to add this logic,
> > but please:
> >   - use the list_head ;-)
> 
> Of course
> 
> >   - leave the process_one_file function simple
> >     and separate the level0 processing
> 
> ok, this is how it should look already, albeit a couple of
> process_one_file() modifications. I'll re-check this.
> 
> >   - you are using 'EventCode' as an unique ID to find
> >     the base, but it's not unique for x86, you'll need
> >     to add some other ID scheme that fits to all archs
> 
> Right, so you mentioned earlier using a new keyword token to identify
> whether we use the standard event, so we can go his way - ok?

yes, something like that

> I would also like to mention at this point why I did the event
> pre-processing in jevents, and not a separate script:
> - current build does not transverse the arch tree
> 	- tree transversal for JSON processing is done in jevents
> - a script would mean derived objects, which means:
> 	- makefile changes for derived objects
> 	- jevents would have to deal with derived objects
> - jevents already has support for JSON processing
> 
> The advantage of using a script is that we keep the JSON processing in
> jevents simple.

I don't mind the extra functionality in jevents as long as the current
one keeps on working and the new one works for all archs ;-)

thanks,
jirka

^ permalink raw reply

* [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks
From: Sekhar Nori @ 2018-01-08 14:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515377863-20358-2-git-send-email-david@lechnology.com>

On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new binding for the PLL IP blocks in the mach-davinci family
> of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
> but in the future additional child nodes could be added for OBSCLK and
> BPDIV.
> 
> Note: Although these PLL controllers are very similar to the TI Keystone
> SoCs, we are not re-using those bindings. The Keystone bindings use a
> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs

Not sure what is meant by "legacy one-node-per-clock binding"

> have a slightly different PLL register layout and a number of quirks that
> can't be handled by the existing bindings, so the keystone bindings could
> not be used as-is anyway.

Right, I think different register layout between the processors is the
main reason for a new driver. This should be sufficient reason IMO.

> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  .../devicetree/bindings/clock/ti/davinci/pll.txt   | 47 ++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> new file mode 100644
> index 0000000..99bf5da
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> @@ -0,0 +1,47 @@
> +Binding for TI DaVinci PLL Controllers
> +
> +The PLL provides clocks to most of the components on the SoC. In addition
> +to the PLL itself, this controller also contains bypasses, gates, dividers,
> +an multiplexers for various clock signals.
> +
> +Required properties:
> +- compatible: shall be one of:
> +	- "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
> +	- "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX

These PLLs are same IP so they should use the same compatible. You can
initialize both PLLs for DA850 based on the same compatible.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH 20/20] clocksource/drivers/stm32: Start the timer's counter sooner
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

As we have a lot of timers on this platform, we can have potentially all the
timers enabled in the DT, so we don't want to start the timer for every probe
otherwise they will be running for nothing as only one will be used.

Start the timer only when setting the mode or when the clocksource is
enabled.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index dcf8445..4ce2345 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -101,7 +101,15 @@ static void stm32_clock_event_disable(struct timer_of *to)
 	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
 }
 
-static void stm32_clock_event_enable(struct timer_of *to)
+/**
+ * stm32_timer_start - Start the counter without event
+ * @to: a timer_of structure pointer
+ *
+ * Start the timer in order to have the counter reset and start
+ * incrementing but disable interrupt event when there is a counter
+ * overflow. By default, the counter direction is used as upcounter.
+ */
+static void stm32_timer_start(struct timer_of *to)
 {
 	writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
 }
@@ -137,7 +145,7 @@ static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	stm32_clock_event_enable(to);
+	stm32_timer_start(to);
 
 	return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
 }
@@ -146,7 +154,7 @@ static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	stm32_clock_event_enable(to);
+	stm32_timer_start(to);
 
 	return 0;
 }
@@ -235,6 +243,13 @@ static int __init stm32_clocksource_init(struct timer_of *to)
 	 * sched_clock.
 	 */
 	if (bits == 32 && !stm32_timer_cnt) {
+
+		/*
+		 * Start immediately the counter as we will be using
+		 * it right after.
+		 */
+		stm32_timer_start(to);
+
 		stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
 		sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
 		pr_info("%s: STM32 sched_clock registered\n", name);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 19/20] clocksource/drivers/stm32: Add the timer delay
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

Add the timer delay, that saves us ~90ms of boot time.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4634f4d..dcf8445 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
@@ -88,6 +89,13 @@ static u64 notrace stm32_read_sched_clock(void)
 	return readl_relaxed(stm32_timer_cnt);
 }
 
+static struct delay_timer stm32_timer_delay;
+
+static unsigned long stm32_read_delay(void)
+{
+	return readl_relaxed(stm32_timer_cnt);
+}
+
 static void stm32_clock_event_disable(struct timer_of *to)
 {
 	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -230,6 +238,11 @@ static int __init stm32_clocksource_init(struct timer_of *to)
 		stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
 		sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
 		pr_info("%s: STM32 sched_clock registered\n", name);
+
+		stm32_timer_delay.read_current_timer = stm32_read_delay;
+		stm32_timer_delay.freq = timer_of_rate(to);
+		register_current_timer_delay(&stm32_timer_delay);
+		pr_info("%s: STM32 delay timer registered\n", name);
 	}
 
 	return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 18/20] clocksource/drivers/stm32: Add the clocksource
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

From: Benjamin Gaignard <benjamin.gaignard@st.com>

The scene is set for the clocksource, let's add it for this driver.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1891924..4634f4d 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,7 @@
 #include <linux/of_irq.h>
 #include <linux/clk.h>
 #include <linux/reset.h>
+#include <linux/sched_clock.h>
 #include <linux/slab.h>
 
 #include "timer-of.h"
@@ -80,6 +81,13 @@ static int stm32_timer_of_bits_get(struct timer_of *to)
 	return pd->bits;
 }
 
+static void __iomem *stm32_timer_cnt __read_mostly;
+
+static u64 notrace stm32_read_sched_clock(void)
+{
+	return readl_relaxed(stm32_timer_cnt);
+}
+
 static void stm32_clock_event_disable(struct timer_of *to)
 {
 	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -204,6 +212,31 @@ static void __init stm32_timer_set_prescaler(struct timer_of *to)
 	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
 }
 
+static int __init stm32_clocksource_init(struct timer_of *to)
+{
+        u32 bits = stm32_timer_of_bits_get(to);
+	const char *name = to->np->full_name;
+
+	/*
+	 * This driver allows to register several timers and relies on
+	 * the generic time framework to select the right one.
+	 * However, nothing allows to do the same for the
+	 * sched_clock. We are not interested in a sched_clock for the
+	 * 16bits timers but only for the 32bits, so if no 32bits
+	 * timer registered yet, we select this 32bits timer as a
+	 * sched_clock.
+	 */
+	if (bits == 32 && !stm32_timer_cnt) {
+		stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
+		sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
+		pr_info("%s: STM32 sched_clock registered\n", name);
+	}
+
+	return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
+				     timer_of_rate(to), bits == 32 ? 250 : 100,
+				     bits, clocksource_mmio_readl_up);
+}
+
 static void __init stm32_clockevent_init(struct timer_of *to)
 {
 	u32 bits = stm32_timer_of_bits_get(to);
@@ -256,6 +289,10 @@ static int __init stm32_timer_init(struct device_node *node)
 
 	stm32_timer_set_prescaler(to);
 
+	ret = stm32_clocksource_init(to);
+	if (ret)
+		goto deinit;
+
 	stm32_clockevent_init(to);
 	return 0;
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 17/20] clocksource/drivers/stm32: Encapsulate more the clockevent code
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

In order to prepare the clocksource code, let's encapsulate the clockevent
code, split the prescaler and timer width code into separate functions.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 107 +++++++++++++++++++++++++++++---------
 1 file changed, 82 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index baca42c..1891924 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -44,6 +44,42 @@
 #define TIM_PSC_MAX	USHRT_MAX
 #define TIM_PSC_CLKRATE	10000
 
+struct stm32_timer_private {
+	int bits;
+};
+
+/**
+ * stm32_timer_of_bits_set - set accessor helper
+ * @to: a timer_of structure pointer
+ * @bits: the number of bits (16 or 32)
+ *
+ * Accessor helper to set the number of bits in the timer-of private
+ * structure.
+ *
+ */
+static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
+{
+	struct stm32_timer_private *pd = to->private_data;
+
+	pd->bits = bits;
+}
+
+/**
+ * stm32_timer_of_bits_get - get accessor helper
+ * @to: a timer_of structure pointer
+ *
+ * Accessor helper to get the number of bits in the timer-of private
+ * structure.
+ *
+ * Returns an integer corresponding to the number of bits.
+ */
+static int stm32_timer_of_bits_get(struct timer_of *to)
+{
+	struct stm32_timer_private *pd = to->private_data;
+
+	return pd->bits;
+}
+
 static void stm32_clock_event_disable(struct timer_of *to)
 {
 	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -124,35 +160,31 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
  * is a 32bits width, the result will be UINT_MAX, otherwise it will
  * be truncated by the 16bits register to USHRT_MAX.
  *
- * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
- * 16bits width.
  */
-static u32 __init stm32_timer_width(struct timer_of *to)
+static void __init stm32_timer_set_width(struct timer_of *to)
 {
+	u32 width;
+
 	writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
 
-	return readl_relaxed(timer_of_base(to) + TIM_ARR);
+	width = readl_relaxed(timer_of_base(to) + TIM_ARR);
+
+	stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
 }
 
-static void __init stm32_clockevent_init(struct timer_of *to)
+/**
+ * stm32_timer_set_prescaler - Compute and set the prescaler register
+ * @to: a pointer to a timer-of structure
+ *
+ * Depending on the timer width, compute the prescaler to always
+ * target a 10MHz timer rate for the 16bits. 32bits timers are
+ * considered precise and long enough to not use the prescaler.
+ */
+static void __init stm32_timer_set_prescaler(struct timer_of *to)
 {
-	u32 width = 0;
-	int prescaler;
+	int prescaler = 1;
 
-	to->clkevt.name = to->np->full_name;
-	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
-	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
-	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
-	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
-	to->clkevt.tick_resume = stm32_clock_event_shutdown;
-	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
-
-	width = stm32_timer_width(to);
-	if (width == UINT_MAX) {
-		prescaler = 1;
-		to->clkevt.rating = 250;
-	} else {
+	if (stm32_timer_of_bits_get(to) != 32) {
 		prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
 					      TIM_PSC_CLKRATE);
 		/*
@@ -161,7 +193,6 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 		 * this case.
 		 */
 		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
-		to->clkevt.rating = 100;
 	}
 
 	writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
@@ -171,12 +202,26 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 	/* Adjust rate and period given the prescaler value */
 	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
 	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
+}
+
+static void __init stm32_clockevent_init(struct timer_of *to)
+{
+	u32 bits = stm32_timer_of_bits_get(to);
 
-	clockevents_config_and_register(&to->clkevt,
-					timer_of_rate(to), 0x1, width);
+	to->clkevt.name = to->np->full_name;
+	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
+	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
+	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
+	to->clkevt.tick_resume = stm32_clock_event_shutdown;
+	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
+	to->clkevt.rating = bits == 32 ? 250 : 100;
+
+	clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
+					(1 <<  bits) - 1);
 
 	pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
-		to->np, width == UINT_MAX ? 32 : 16);
+		to->np, bits);
 }
 
 static int __init stm32_timer_init(struct device_node *node)
@@ -196,14 +241,26 @@ static int __init stm32_timer_init(struct device_node *node)
 	if (ret)
 		goto err;
 
+	to->private_data = kzalloc(sizeof(struct stm32_timer_private),
+				   GFP_KERNEL);
+	if (!to->private_data)
+		goto deinit;
+
 	rstc = of_reset_control_get(node, NULL);
 	if (!IS_ERR(rstc)) {
 		reset_control_assert(rstc);
 		reset_control_deassert(rstc);
 	}
 
+	stm32_timer_set_width(to);
+
+	stm32_timer_set_prescaler(to);
+
 	stm32_clockevent_init(to);
 	return 0;
+
+deinit:
+	timer_of_cleanup(to);
 err:
 	kfree(to);
 	return ret;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 16/20] clocksource/drivers/stm32: Add the oneshot mode
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

From: Benjamin Gaignard <benjamin.gaignard@st.com>

The stm32 timer block is able to have a counter and a comparator.

Instead of using the auto-reload register for periodic event, we switch
to the oneshot mode by using the comparator register.

The timer is able to generate an interrupt when the counter overflows but
we don't want that as this counter will be use as a clocksource in the next
patches. So it is disabled by the UDIS bit of the control register.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 56 ++++++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index ac55896..baca42c 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -24,14 +24,18 @@
 #define TIM_DIER	0x0c
 #define TIM_SR		0x10
 #define TIM_EGR		0x14
+#define TIM_CNT		0x24
 #define TIM_PSC		0x28
 #define TIM_ARR		0x2c
+#define TIM_CCR1	0x34
 
 #define TIM_CR1_CEN	BIT(0)
+#define TIM_CR1_UDIS	BIT(1)
 #define TIM_CR1_OPM	BIT(3)
 #define TIM_CR1_ARPE	BIT(7)
 
 #define TIM_DIER_UIE	BIT(0)
+#define TIM_DIER_CC1IE	BIT(1)
 
 #define TIM_SR_UIF	BIT(0)
 
@@ -40,33 +44,57 @@
 #define TIM_PSC_MAX	USHRT_MAX
 #define TIM_PSC_CLKRATE	10000
 
+static void stm32_clock_event_disable(struct timer_of *to)
+{
+	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
+}
+
+static void stm32_clock_event_enable(struct timer_of *to)
+{
+	writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+}
+
 static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(0, timer_of_base(to) + TIM_CR1);
+	stm32_clock_event_disable(to);
 
 	return 0;
 }
 
-static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+static int stm32_clock_event_set_next_event(unsigned long evt,
+					    struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
+	unsigned long now, next;
+
+	next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
+	writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
+	now = readl_relaxed(timer_of_base(to) + TIM_CNT);
+
+	if ((next - now) > evt)
+		return -ETIME;
 
-	writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
-	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+	writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
 
 	return 0;
 }
 
-static int stm32_clock_event_set_next_event(unsigned long evt,
-					    struct clock_event_device *clkevt)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+{
+	struct timer_of *to = to_timer_of(clkevt);
+
+	stm32_clock_event_enable(to);
+
+	return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
+}
+
+static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
-	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
-		       timer_of_base(to) + TIM_CR1);
+	stm32_clock_event_enable(to);
 
 	return 0;
 }
@@ -78,6 +106,11 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 
 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
 
+	if (clockevent_state_periodic(clkevt))
+		stm32_clock_event_set_periodic(clkevt);
+	else
+		stm32_clock_event_shutdown(clkevt);
+
 	clkevt->event_handler(clkevt);
 
 	return IRQ_HANDLED;
@@ -108,9 +141,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 
 	to->clkevt.name = to->np->full_name;
 	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
 	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
-	to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
 	to->clkevt.tick_resume = stm32_clock_event_shutdown;
 	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
 
@@ -129,12 +163,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
 		to->clkevt.rating = 100;
 	}
-	writel_relaxed(0, timer_of_base(to) + TIM_ARR);
 
 	writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
 	writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
-	writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
 
 	/* Adjust rate and period given the prescaler value */
 	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 15/20] clocksource/drivers/stm32: Compute a prescaler value with a targeted rate
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

From: Benjamin Gaignard <benjamin.gaignard@st.com>

The prescaler value is arbitrarily set to 1024 without any regard to the
timer frequency. For 32bits timers, there is no need to set a prescaler
value as they wrap in an acceptable interval and give the opportunity to
have precise timers on this platform. However, for 16bits timers a prescaler
value is needed if we don't want to wrap too often per second which is
unefficient and adds more and more error margin. With a targeted clock
of 10MHz, the 16bits are precise enough whatever the timer frequency is
as we will compute the prescaler.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 862134e..ac55896 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -37,6 +37,9 @@
 
 #define TIM_EGR_UG	BIT(0)
 
+#define TIM_PSC_MAX	USHRT_MAX
+#define TIM_PSC_CLKRATE	10000
+
 static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
@@ -116,7 +119,14 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 		prescaler = 1;
 		to->clkevt.rating = 250;
 	} else {
-		prescaler = 1024;
+		prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
+					      TIM_PSC_CLKRATE);
+		/*
+		 * The prescaler register is an u16, the variable
+		 * can't be greater than TIM_PSC_MAX, let's cap it in
+		 * this case.
+		 */
+		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
 		to->clkevt.rating = 100;
 	}
 	writel_relaxed(0, timer_of_base(to) + TIM_ARR);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 14/20] clocksource/drivers/stm32: Encapsulate the timer width sorting out function
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

In order to clarify and encapsulate the code for the next changes move the
timer width check into a function and add some documentation.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 14b7a2b..862134e 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -80,9 +80,27 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+/**
+ * stm32_timer_width - Sort out the timer width (32/16)
+ * @to: a pointer to a timer-of structure
+ *
+ * Write the 32bits max value and read/return the result. If the timer
+ * is a 32bits width, the result will be UINT_MAX, otherwise it will
+ * be truncated by the 16bits register to USHRT_MAX.
+ *
+ * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
+ * 16bits width.
+ */
+static u32 __init stm32_timer_width(struct timer_of *to)
+{
+	writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
+
+	return readl_relaxed(timer_of_base(to) + TIM_ARR);
+}
+
 static void __init stm32_clockevent_init(struct timer_of *to)
 {
-	unsigned long max_delta;
+	u32 width = 0;
 	int prescaler;
 
 	to->clkevt.name = to->np->full_name;
@@ -93,10 +111,8 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 	to->clkevt.tick_resume = stm32_clock_event_shutdown;
 	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
 
-	/* Detect whether the timer is 16 or 32 bits */
-	writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
-	max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
-	if (max_delta == ~0U) {
+	width = stm32_timer_width(to);
+	if (width == UINT_MAX) {
 		prescaler = 1;
 		to->clkevt.rating = 250;
 	} else {
@@ -115,10 +131,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
 
 	clockevents_config_and_register(&to->clkevt,
-					timer_of_rate(to), 0x1, max_delta);
+					timer_of_rate(to), 0x1, width);
 
 	pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
-		to->np, max_delta == UINT_MAX ? 32 : 16);
+		to->np, width == UINT_MAX ? 32 : 16);
 }
 
 static int __init stm32_timer_init(struct device_node *node)
-- 
2.7.4

^ permalink raw reply related

* [PATCH 13/20] clocksource/drivers/stm32: Use the node name as timer name
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>

As there are different timers on the stm32, use the node name for the timer
name in order to give the indication of which timer the kernel is using.

The /proc/timer_list gives all the information with the right name, otherwise
we end up digging in the kernel log and /proc/interrupt to do the connection
between the used timer.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
 drivers/clocksource/timer-stm32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 3e4ab07..14b7a2b 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -85,7 +85,7 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 	unsigned long max_delta;
 	int prescaler;
 
-	to->clkevt.name = "stm32_clockevent";
+	to->clkevt.name = to->np->full_name;
 	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
 	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
 	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
-- 
2.7.4

^ permalink raw reply related


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