Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] PCI/MSI: pci-xgene-msi: Fix CPU hotplug registration handling
From: Sebastian Andrzej Siewior @ 2017-01-11 10:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484130407-24707-1-git-send-email-marc.zyngier@arm.com>

On 2017-01-11 10:26:47 [+0000], Marc Zyngier wrote:
> The conversion to the new hotplug state machine introduced a regression
> where a successful hotplug registration would be treated as an error,
> effectively disabling the MSI driver forever.
> 
> Fix it by doing the proper check on the return value.
> 
> Fixes: 9c248f8896e6 ("PCI/xgene-msi: Convert to hotplug state machine")
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Sebastian

^ permalink raw reply

* [PATCHv3 3/8] rtc: add STM32 RTC driver
From: Amelie DELAUNAY @ 2017-01-11 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170111101708.ujcgo7kpyywymyzp@piout.net>


On 01/11/2017 11:17 AM, Alexandre Belloni wrote:
> On 11/01/2017 at 11:07:16 +0100, Amelie DELAUNAY wrote :
>>> This will never happen, tm is already checked multiple times (up to
>>> three) in the core before this function can be called.
>>>
>> You're right. I'll remove all rtc_valid_tm calls.
>
> You can keep the one in read_time
>
Even if rtc_valid_tm is called just after rtc->ops->read_time() in 
__rtc_read_time ?

^ permalink raw reply

* [PATCH v2 5/5] ARM: dts: Add LEGO MINDSTORMS EV3 dts
From: Sekhar Nori @ 2017-01-11 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483677228-2325-6-git-send-email-david@lechnology.com>

On Friday 06 January 2017 10:03 AM, David Lechner wrote:

> +	beeper {
> +		compatible = "pwm-beeper";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&ehrpwm0b_pins>, <&amp_pins>;
> +		pwms = <&ehrpwm0 1 0 0>;
> +		enable-gpios = <&gpio 111 GPIO_ACTIVE_HIGH>;

Since the enable-gpios binding for pwm beeper is still not accepted, can
you drop the property or the node itself (if that makes more sense)?

> +&spi0 {
> +	status = "okay";
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>, <&spi0_cs3_pin>;
> +
> +	flash at 0 {
> +		compatible = "n25q128a13", "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <50000000>;
> +		ti,spi-wdelay = <8>;
> +
> +		/* Partitions are based on the official firmware from LEGO */
> +		partitions {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			partition at 0 {
> +				label = "U-Boot";
> +				reg = <0 0x40000>;
> +			};
> +
> +			partition at 40000 {
> +				label = "U-Boot Env";
> +				reg = <0x40000 0x10000>;
> +			};
> +
> +			partition at 50000 {
> +				label = "Kernel";
> +				reg = <0x50000 0x200000>;
> +			};
> +
> +			partition at 250000 {
> +				label = "Filesystem";
> +				reg = <0x250000 0xa50000>;
> +			};
> +
> +			partition at cb0000 {
> +				label = "Storage";
> +				reg = <0xcb0000 0x2f0000>;
> +			};
> +		};
> +	};
> +
> +	adc at 3 {
> +		compatible = "ti-ads7957";

So looks like this works because of_register_spi_device() sets up
modalias of spi device from compatible string. I am fine with it, just
highlighting it here to make sure this is acceptable practice. I did not
really find any precedence for using SPI device name as compatible
property in existing DTS files.

> +		reg = <3>;
> +		spi-max-frequency = <10000000>;
> +		refin-supply = <&adc_ref>;
> +	};

Rest of the patch looks good to me.

Thanks,
Sekhar

^ permalink raw reply

* [PATCHv3 3/8] rtc: add STM32 RTC driver
From: Alexandre Belloni @ 2017-01-11 10:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ff7a532e-a2a7-920a-29d9-e8a82d6ed915@st.com>

On 11/01/2017 at 11:42:50 +0100, Amelie DELAUNAY wrote :
> 
> On 01/11/2017 11:17 AM, Alexandre Belloni wrote:
> > On 11/01/2017 at 11:07:16 +0100, Amelie DELAUNAY wrote :
> > > > This will never happen, tm is already checked multiple times (up to
> > > > three) in the core before this function can be called.
> > > > 
> > > You're right. I'll remove all rtc_valid_tm calls.
> > 
> > You can keep the one in read_time
> > 
> Even if rtc_valid_tm is called just after rtc->ops->read_time() in
> __rtc_read_time ?

Ah yes, I forgot it was added, you can remove all of them.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH] rtc: armada38x: make struct rtc_class_ops const
From: Alexandre Belloni @ 2017-01-11 10:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <E1cRFxi-00083n-FY@rmk-PC.armlinux.org.uk>

On 11/01/2017 at 10:16:58 +0000, Russell King wrote :
> Armada38x wants to modify its rtc_class_ops to remove the interrupt
> handling when there is no usable interrupt, but this means we leave
> function pointers in writable memory.
> 
> Since rtc_class_ops is small, arrange to have two instances, one for
> when we have interrupts, and one for when we have none, both marked
> const.  This allows the compiler to place them in read-only memory,
> which is better than placing them in __ro_after_init.
> 
> Thanks to Bhumika Goyal <bhumirks@gmail.com> for pointing out that
> the structure was writable and submitting a patch to add
> __ro_after_init.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
> As the thread has gone quiet, I'm submitting the patch I sent within that
> thread.  No one appears to have raised an objection to it (other than what
> appears to be a misunderstanding.)
> 
>  drivers/rtc/rtc-armada38x.c | 24 +++++++++++++++++-------
>  1 file changed, 17 insertions(+), 7 deletions(-)
> 
Applied, thanks.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 56/62] watchdog: tangox_wdt: Convert to use device managed functions
From: Guenter Roeck @ 2017-01-11 10:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bd56e90c-5cb8-02d8-3518-c8f5483a6df4@sigmadesigns.com>

On 01/11/2017 01:07 AM, Marc Gonzalez wrote:

>> @@ -134,12 +134,15 @@ static int tangox_wdt_probe(struct platform_device *pdev)
>>  	err = clk_prepare_enable(dev->clk);
>>  	if (err)
>>  		return err;
>> +	err = devm_add_action_or_reset(&pdev->dev,
>> +				       (void(*)(void *))clk_disable_unprepare,
>> +				       dev->clk);
>> +	if (err)
>> +		return err;
>
> Hello Guenter,
>
> I would rather avoid the function pointer cast.
> How about defining an auxiliary function for the cleanup action?
>
> clk_disable_unprepare() is static inline, so gcc will have to
> define an auxiliary function either way. What do you think?
>

Not really. It would just make it more complicated to replace the
call with devm_clk_prepare_enable(), should it ever find its way
into the light of day.

Guenter

^ permalink raw reply

* [PATCH v29 4/9] arm64: kdump: implement machine_crash_shutdown()
From: Will Deacon @ 2017-01-11 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170111063626.GE20972@linaro.org>

On Wed, Jan 11, 2017 at 03:36:28PM +0900, AKASHI Takahiro wrote:
> On Tue, Jan 10, 2017 at 11:32:48AM +0000, Will Deacon wrote:
> > On Wed, Dec 28, 2016 at 01:36:01PM +0900, AKASHI Takahiro wrote:
> > > @@ -22,6 +25,7 @@
> > >  extern const unsigned char arm64_relocate_new_kernel[];
> > >  extern const unsigned long arm64_relocate_new_kernel_size;
> > >  
> > > +static bool in_crash_kexec;
> > 
> > Do you actually need this bool? Why not call kexec_crash_loaded() instead?
> 
> The two have different meanings:
> "in_crash_kexec" indicates that kdump is taking place, while
> kexec_crash_loaded() tells us only whether crash dump kernel has been
> loaded or not.
> 
> It is crucial to distinguish them especially for machine_kexec()
> which can be called on normal kexec even if kdump has been set up.

Ah, I see. So how about just doing:

  if (kimage == kexec_crash_image)

in machine_kexec?

Will

^ permalink raw reply

* [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
From: Jean-Jacques Hiblot @ 2017-01-11 11:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <F9F4555C4E01D7469D37975B62D0EFBB496BE4@CHN-SV-EXMX07.mchp-main.com>

2017-01-11 9:15 GMT+01:00  <Wenyou.Yang@microchip.com>:
> Hi Jean-Jacques,
>
>> -----Original Message-----
>> From: Jean-Jacques Hiblot [mailto:jjhiblot at gmail.com]
>> Sent: 2017?1?11? 0:51
>> To: Alexandre Belloni <alexandre.belloni@free-electrons.com>
>> Cc: Wenyou Yang - A41535 <Wenyou.Yang@microchip.com>; Mark Rutland
>> <mark.rutland@arm.com>; devicetree <devicetree@vger.kernel.org>; Russell
>> King <linux@arm.linux.org.uk>; Wenyou Yang - A41535
>> <Wenyou.Yang@microchip.com>; Nicolas Ferre <nicolas.ferre@atmel.com>;
>> Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; Rob Herring
>> <robh+dt@kernel.org>; linux-arm-kernel at lists.infradead.org
>> Subject: Re: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
>>
>> 2017-01-10 17:18 GMT+01:00 Alexandre Belloni
>> <alexandre.belloni@free-electrons.com>:
>> > I though a bit more about it, and I don't really like the new
>> > compatible string. I don't feel this should be necessary.
>> >
>> > What about the following:
>> >
>> > diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
>> > b4332b727e9c..0333aca63e44 100644
>> > --- a/arch/arm/mach-at91/pm.c
>> > +++ b/arch/arm/mach-at91/pm.c
>> > @@ -53,6 +53,7 @@ extern void at91_pinctrl_gpio_resume(void);  static
>> > struct {
>> >         unsigned long uhp_udp_mask;
>> >         int memctrl;
>> > +       bool has_l2_cache;
>> >  } at91_pm_data;
>> >
>> >  void __iomem *at91_ramc_base[2];
>> > @@ -267,6 +268,11 @@ static void at91_ddr_standby(void)
>> >         u32 lpr0, lpr1 = 0;
>> >         u32 saved_lpr0, saved_lpr1 = 0;
>> >
>>
>> > +       if (at91_pm_data.has_l2_cache) {
>> > +               flush_cache_all();
>> what is the point of calling flush_cache_all() here ? Do we really care that dirty
>> data in L1 is written to DDR ? I may be missing something but to me it's just extra
>> latency.
>
> Are you mean use outer_flush_all() to flush all cache lines in the outer cache only?

Yes that's what I meant. You see, you don't flush the cache for
sama5d3 so it shouldn't be required either for sam5d4. You should be
able to test it quickly and see if L1 flush is indeed required by
replacing  flush_cache_all() with outer_flush_all(). BTW is highly
probable that L2 cache flush is done in outer_disable() so calling
outer_flush_all() is probably no required.

However the more I think on it, the more I wonder about the reason why
L2 flushing is required or to put it differently: is flusing the L2
cache the correct thing to do or just a workaround ?
Could it be that L2 is doing some maintenance operation when DDR
enters self refresh? In that case maybe a simple cache sync could be
used.

>
>> > +               outer_disable();
>> It seems to me that if there's no L2 cache, then outer_disable()  is a no-op. It
>> could be called unconditionally.
>> > +       }
>> > +
>> >         if (at91_ramc_base[1]) {
>> >                 saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
>> >                 lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB; @@ -287,6
>> > +293,9 @@ static void at91_ddr_standby(void)
>> >         at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
>> >         if (at91_ramc_base[1])
>> >                 at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
>> > +
>> > +       if (at91_pm_data.has_l2_cache)
>> > +               outer_resume();
>>
>> same remark as for outer_disable()
>>
>> Jean-Jacques
>>
>> >  }
>> >
>> >  /* We manage both DDRAM/SDRAM controllers, we need more than one
>> > value
>> >  * to
>> > @@ -353,6 +362,11 @@ static __init void at91_dt_ramc(void)
>> >                 return;
>> >         }
>> >
>> > +       np = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
>> > +       if (np)
>> > +               at91_pm_data.has_l2_cache = true;
>> > +       of_node_put(np);
>> > +
>> >         at91_pm_set_standby(standby);
>> >  }
>> >
>> >
>> > This has the following benefits:
>> >  - everybody will have the fix, regardless of whether the dtb is
>> > updated
>> >  - has_l2_cache can be used later in at91_pm_suspend instead of calling
>> >    it unconditionnaly (I'll send a patch)
>> >
>> >
>> > On 06/01/2017 at 14:59:45 +0800, Wenyou Yang wrote :
>> >> For the SoCs such as SAMA5D2 and SAMA5D4 which have L2 cache, flush
>> >> the L2 cache first before entering the cpu idle.
>> >>
>> >> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
>> >> ---
>> >>
>> >>  arch/arm/mach-at91/pm.c       | 19 +++++++++++++++++++
>> >>  drivers/memory/atmel-sdramc.c |  1 +
>> >>  2 files changed, 20 insertions(+)
>> >>
>> >> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
>> >> b4332b727e9c..1a60dede1a01 100644
>> >> --- a/arch/arm/mach-at91/pm.c
>> >> +++ b/arch/arm/mach-at91/pm.c
>> >> @@ -289,6 +289,24 @@ static void at91_ddr_standby(void)
>> >>               at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);  }
>> >>
>> >> +static void at91_ddr_cache_standby(void) {
>> >> +     u32 saved_lpr;
>> >> +
>> >> +     flush_cache_all();
>> >> +     outer_disable();
>> >> +
>> >> +     saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
>> >> +     at91_ramc_write(0, AT91_DDRSDRC_LPR, (saved_lpr &
>> >> +                     (~AT91_DDRSDRC_LPCB)) |
>> >> + AT91_DDRSDRC_LPCB_SELF_REFRESH);
>> >> +
>> >> +     cpu_do_idle();
>> >> +
>> >> +     at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr);
>> >> +
>> >> +     outer_resume();
>> >> +}
>> >> +
>> >>  /* We manage both DDRAM/SDRAM controllers, we need more than one
>> value to
>> >>   * remember.
>> >>   */
>> >> @@ -324,6 +342,7 @@ static const struct of_device_id const ramc_ids[]
>> __initconst = {
>> >>       { .compatible = "atmel,at91sam9260-sdramc", .data =
>> at91sam9_sdram_standby },
>> >>       { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
>> >>       { .compatible = "atmel,sama5d3-ddramc", .data =
>> >> at91_ddr_standby },
>> >> +     { .compatible = "atmel,sama5d4-ddramc", .data =
>> >> + at91_ddr_cache_standby },
>> >>       { /*sentinel*/ }
>> >>  };
>> >>
>> >> diff --git a/drivers/memory/atmel-sdramc.c
>> >> b/drivers/memory/atmel-sdramc.c index b418b39af180..7e5c5c6c1348
>> >> 100644
>> >> --- a/drivers/memory/atmel-sdramc.c
>> >> +++ b/drivers/memory/atmel-sdramc.c
>> >> @@ -48,6 +48,7 @@ static const struct of_device_id atmel_ramc_of_match[]
>> = {
>> >>       { .compatible = "atmel,at91sam9260-sdramc", .data =
>> &at91rm9200_caps, },
>> >>       { .compatible = "atmel,at91sam9g45-ddramc", .data =
>> &at91sam9g45_caps, },
>> >>       { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps,
>> >> },
>> >> +     { .compatible = "atmel,sama5d4-ddramc", .data = &sama5d3_caps,
>> >> + },
>> >>       {},
>> >>  };
>> >>
>> >> --
>> >> 2.11.0
>> >>
>> >
>> > --
>> > Alexandre Belloni, Free Electrons
>> > Embedded Linux and Kernel engineering
>> > http://free-electrons.com
>> >
>> > _______________________________________________
>> > linux-arm-kernel mailing list
>> > linux-arm-kernel at lists.infradead.org
>> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
From: Russell King - ARM Linux @ 2017-01-11 11:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACh+v5M3tU4WHMqAX0zm2H=zzwc0+XChyG1tnH2aHxaacm6C=A@mail.gmail.com>

On Wed, Jan 11, 2017 at 12:05:05PM +0100, Jean-Jacques Hiblot wrote:
> 2017-01-11 9:15 GMT+01:00  <Wenyou.Yang@microchip.com>:
> > Hi Jean-Jacques,
> >
> >> -----Original Message-----
> >> From: Jean-Jacques Hiblot [mailto:jjhiblot at gmail.com]
> >> Sent: 2017?1?11? 0:51
> >> To: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> >> Cc: Wenyou Yang - A41535 <Wenyou.Yang@microchip.com>; Mark Rutland
> >> <mark.rutland@arm.com>; devicetree <devicetree@vger.kernel.org>; Russell
> >> King <linux@arm.linux.org.uk>; Wenyou Yang - A41535
> >> <Wenyou.Yang@microchip.com>; Nicolas Ferre <nicolas.ferre@atmel.com>;
> >> Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; Rob Herring
> >> <robh+dt@kernel.org>; linux-arm-kernel at lists.infradead.org
> >> Subject: Re: [PATCH 1/3] ARM: at91: flush the L2 cache before entering cpu idle
> >>
> >> 2017-01-10 17:18 GMT+01:00 Alexandre Belloni
> >> <alexandre.belloni@free-electrons.com>:
> >> > I though a bit more about it, and I don't really like the new
> >> > compatible string. I don't feel this should be necessary.
> >> >
> >> > What about the following:
> >> >
> >> > diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index
> >> > b4332b727e9c..0333aca63e44 100644
> >> > --- a/arch/arm/mach-at91/pm.c
> >> > +++ b/arch/arm/mach-at91/pm.c
> >> > @@ -53,6 +53,7 @@ extern void at91_pinctrl_gpio_resume(void);  static
> >> > struct {
> >> >         unsigned long uhp_udp_mask;
> >> >         int memctrl;
> >> > +       bool has_l2_cache;
> >> >  } at91_pm_data;
> >> >
> >> >  void __iomem *at91_ramc_base[2];
> >> > @@ -267,6 +268,11 @@ static void at91_ddr_standby(void)
> >> >         u32 lpr0, lpr1 = 0;
> >> >         u32 saved_lpr0, saved_lpr1 = 0;
> >> >
> >>
> >> > +       if (at91_pm_data.has_l2_cache) {
> >> > +               flush_cache_all();
> >> what is the point of calling flush_cache_all() here ? Do we really care that dirty
> >> data in L1 is written to DDR ? I may be missing something but to me it's just extra
> >> latency.
> >
> > Are you mean use outer_flush_all() to flush all cache lines in the outer cache only?
> 
> Yes that's what I meant. You see, you don't flush the cache for
> sama5d3 so it shouldn't be required either for sam5d4. You should be
> able to test it quickly and see if L1 flush is indeed required by
> replacing  flush_cache_all() with outer_flush_all(). BTW is highly
> probable that L2 cache flush is done in outer_disable() so calling
> outer_flush_all() is probably no required.

Please don't.  Read the comments in the code, and understand the APIs
that you're suggesting people use _before_ making the suggestion:

/**
 * outer_flush_all - clean and invalidate all cache lines in the outer cache
 *
 * Note: depending on implementation, this may not be atomic - it must
 * only be called with interrupts disabled and no other active outer
 * cache masters.
 *
 * It is intended that this function is only used by implementations
 * needing to override the outer_cache.disable() method due to security.
 * (Some implementations perform this as a clean followed by an invalidate.)
 */

So, outer_flush_all() should not be called except from L2 cache code
implementing the outer_disable() function - it's not intended for
platforms to use.

There are, however, sadly three users of outer_flush_all() which have
crept in through arm-soc, that should be outer_disable() instead.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

^ permalink raw reply

* [PATCH] coresight: STM: Balance enable/disable
From: Chunyan Zhang @ 2017-01-11 11:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170110173637.GA12100@linaro.org>

On 11 January 2017 at 01:36, Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
> On Tue, Jan 10, 2017 at 11:21:55AM +0000, Suzuki K Poulose wrote:
>> The stm is automatically enabled when an application sets the policy
>> via ->link() call back by using coresight_enable(), which keeps the
>> refcount of the current users of the STM. However, the unlink() callback
>> issues stm_disable() directly, which leaves the STM turned off, without
>> the coresight layer knowing about it. This prevents any further uses
>> of the STM hardware as the coresight layer still thinks the STM is
>> turned on and doesn't issue an stm_enable(). Even manually enabling
>> the STM via sysfs can't really enable the hw.
>>
>> e.g,
>>
>> $ echo 1 > $CS_DEVS/$ETR/enable_sink
>> $ mkdir -p $CONFIG_FS/stp-policy/$source.0/stm_test/
>> $ echo 32768 65535 > $CONFIG_FS/stp-policy/$source.0/stm_test/channels
>> $ echo 64 > $CS_DEVS/$source/traceid
>> $ ./stm_app
>> Sending 64000 byte blocks of pattern 0 at 0us intervals
>> Success to map channel(32768~32783) to 0xffffa95fa000
>> Sending on channel 32768
>> $ dd if=/dev/$ETR of=~/trace.bin.1
>> 597+1 records in
>> 597+1 records out
>> 305920 bytes (306 kB) copied, 0.399952 s, 765 kB/s
>> $ ./stm_app
>> Sending 64000 byte blocks of pattern 0 at 0us intervals
>> Success to map channel(32768~32783) to 0xffff7e9e2000
>> Sending on channel 32768
>> $ dd if=/dev/$ETR of=~/trace.bin.2
>> 0+0 records in
>> 0+0 records out
>> 0 bytes (0 B) copied, 0.0232083 s, 0.0 kB/s
>>
>> Note that we don't get any data from the ETR for the second session.
>>
>> Also dmesg shows :
>>
>> [   77.520458] coresight-tmc 20800000.etr: TMC-ETR enabled
>> [   77.537097] coresight-replicator etr_replicator at 20890000: REPLICATOR enabled
>> [   77.558828] coresight-replicator main_replicator at 208a0000: REPLICATOR enabled
>> [   77.581068] coresight-funnel 208c0000.main_funnel: FUNNEL inport 0 enabled
>> [   77.602217] coresight-tmc 20840000.etf: TMC-ETF enabled
>> [   77.618422] coresight-stm 20860000.stm: STM tracing enabled
>> [  139.554252] coresight-stm 20860000.stm: STM tracing disabled
>>  # End of first tracing session
>> [  146.351135] coresight-tmc 20800000.etr: TMC read start
>> [  146.514486] coresight-tmc 20800000.etr: TMC read end
>>  # Note that the STM is not turned on via stm_generic_link()->coresight_enable()
>>  # and hence none of the components are turned on.
>> [  152.479080] coresight-tmc 20800000.etr: TMC read start
>> [  152.542632] coresight-tmc 20800000.etr: TMC read end
>>
>> This patch balances the unlink operation by using the coresight_disable(),
>> keeping the coresight layer in sync with the hardware state.
>>
>> Fixes: commit 237483aa5cf43 ("coresight: stm: adding driver for CoreSight STM component")
>> Cc: Pratik Patel <pratikp@codeaurora.org>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Cc: Chunyan Zhang <zhang.chunyan@linaro.org>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: stable at vger.kernel.org # 4.7+
>> Reported-by: Robert Walker <robert.walker@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>>  drivers/hwtracing/coresight/coresight-stm.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
>> index 3524452..57b7330 100644
>> --- a/drivers/hwtracing/coresight/coresight-stm.c
>> +++ b/drivers/hwtracing/coresight/coresight-stm.c
>> @@ -356,7 +356,7 @@ static void stm_generic_unlink(struct stm_data *stm_data,
>>       if (!drvdata || !drvdata->csdev)
>>               return;
>>
>> -     stm_disable(drvdata->csdev, NULL);
>> +     coresight_disable(drvdata->csdev);
>
> This looks valid to me.
>
> Chunyan, any reason to use stm_disable() directly rather than calling it as part
> of the device OPS in coresight_disable()?

I don't think there's some special reason for this. I simply hadn't
noticed that these two operations didn't use two balanced functions.

Thanks,
Chunyan

>
> Thanks,
> Mathieu
>
>>  }
>>
>>  static phys_addr_t
>> --
>> 2.7.4
>>

^ permalink raw reply

* imx: RS-485 problems during TX, maybe DMA related
From: Fabio Estevam @ 2017-01-11 11:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170111003319.GA25265@archie.localdomain>

Hi Clemens,

On Tue, Jan 10, 2017 at 10:33 PM, Clemens Gruber
<clemens.gruber@pqgruber.com> wrote:
> Hi Fabio,
>
> On Sun, Jan 08, 2017 at 07:46:29PM -0200, Fabio Estevam wrote:
>> > What's the revision of the i.MX6Q on your board? Mine is 1.5 (TO 1.3)
>>
>> Mine is a mx6solo rev1.1.
>
> Could it be dependent upon SMP? Do you have an i.MX6Q board around to
> try?

Unfortunately the only hardware I can test RS485 is based on mx6solo.

Adding Tim Harvey, who could probably test RS485 on MX6Q.

Regards,

Fabio Estevam

^ permalink raw reply

* [PATCH 1/1] iommu/arm-smmu: Fix for ThunderX erratum #27704
From: Tomasz Nowicki @ 2017-01-11 11:51 UTC (permalink / raw)
  To: linux-arm-kernel

The goal of erratum #27704 workaround was to make sure that ASIDs and VMIDs
are unique across all SMMU instances on affected Cavium systems.

Currently, the workaround code partitions ASIDs and VMIDs by increasing
global cavium_smmu_context_count which in turn becomes the base ASID and VMID
value for the given SMMU instance upon the context bank initialization.

For systems with multiple SMMU instances this approach implies the risk
of crossing 8-bit ASID, like for CN88xx capable of 4 SMMUv2, 128 context bank each:
SMMU_0 (0-127 ASID RANGE)
SMMU_1 (127-255 ASID RANGE)
SMMU_2 (256-383 ASID RANGE) <--- crossing 8-bit ASID
SMMU_3 (384-511 ASID RANGE) <--- crossing 8-bit ASID

Since we use 8-bit ASID now we effectively misconfigure ASID[15:8] bits for
SMMU_CBn_TTBRm register. Also, we still use non-zero ASID[15:8] bits
upon context invalidation. This patch adds 16-bit ASID support for stage-1
AArch64 contexts for Cavium SMMUv2 model so that we use ASIDs consistently.

Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
---
 drivers/iommu/arm-smmu.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a60cded..ae8f059 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -260,6 +260,7 @@ enum arm_smmu_s2cr_privcfg {
 
 #define TTBCR2_SEP_SHIFT		15
 #define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS			(1 << 4)
 
 #define TTBRn_ASID_SHIFT		48
 
@@ -778,6 +779,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
 			reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
 			reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
 			reg2 |= TTBCR2_SEP_UPSTREAM;
+			if (smmu->model == CAVIUM_SMMUV2 &&
+			    cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
+				reg2 |= TTBCR2_AS;
 		}
 		if (smmu->version > ARM_SMMU_V1)
 			writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
-- 
2.7.4

^ permalink raw reply related

* [PATCH] arm64: avoid increasing DMA masks above what hardware supports
From: Robin Murphy @ 2017-01-11 11:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <67314806-361d-e0ac-9292-37542160ead5@cogentembedded.com>

On 11/01/17 07:59, Nikita Yushchenko wrote:
>>> +	/*
>>> +	 * we don't yet support buses that have a non-zero mapping.
>>> +	 *  Let's hope we won't need it
>>> +	 */
>>> +	WARN_ON(dma_base != 0);
>>
>> I believe we now accomodate the bus remap bits on BCM2837 as a DMA
>> offset, so unfortunately I think this is no longer true.
> 
> Arnd, this check is from you. Any updates? Perhaps this check can be
> just dropped?
> 
> In swiotlb code, dma address (i.e. with offset already applied) is
> checked against mask.  Not sure what 'dma_base' means in iommu case.
> 
>>> +	/*
>>> +	 * Whatever the parent bus can set. A device must not set
>>> +	 * a DMA mask larger than this.
>>> +	 */
>>> +	dev->archdata.parent_dma_mask = size - 1;
>>
>> This will effectively constrain *all* DMA masks to be 32-bit, since for
>> 99% of devices we're going to see a size derived from the default mask
>> passed in here. I worry that that's liable to lead to performance and
>> stability regressions
> 
> That was exactly my concern when I first tried to address this issue. My
> first attempt was to alter very locally exact configuration where
> problem shows, while ensuring that everything else stays as is. See
> https://lkml.org/lkml/2016/12/29/218
> 
> But looks like people want a generic solution.
> 
>> I reckon the easiest way forward would be to pass in some flag to
>> arch_setup_dma_ops to indicate whether it's an explicitly-configured
>> range or not - then simply initialising parent_dma_mask to ~0 for the
>> default case *should* keep things working as before.
> 
> Currently only arm, arm64 and mips define arch_setup_dma_ops().
> Mips version only checks 'coherent' argument, 'size' is used only by arm
> and arm64.
> 
> Maybe move setting the default from caller to callee?
> I.e. pass size=0 if no explicit information exists, and let architecture
> handle that?

Yes, I think that ought to work, although the __iommu_setup_dma_ops()
call will still want a real size reflecting the default mask, so
something like:

if (size == 0) {
	dev->archdata.parent_dma_mask = ~0;
	size = 1ULL << 32;
} else {
	dev->archdata.parent_dma_mask = size - 1;
}

should probably do the trick.

Robin.

^ permalink raw reply

* [PATCH] usb: gadget: udc: atmel: remove memory leak
From: Alexandre Belloni @ 2017-01-11 12:11 UTC (permalink / raw)
  To: linux-arm-kernel

Commit bbe097f092b0 ("usb: gadget: udc: atmel: fix endpoint name")
introduced a memory leak when unbinding the driver. The endpoint names
would not be freed. Solve that by including the name as a string in struct
usba_ep so it is freed when the endpoint is.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 3 ++-
 drivers/usb/gadget/udc/atmel_usba_udc.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index f3212db9bc37..12c7687216e6 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1978,7 +1978,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
 			dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
 			goto err;
 		}
-		ep->ep.name = kasprintf(GFP_KERNEL, "ep%d", ep->index);
+		sprintf(ep->name, "ep%d", ep->index);
+		ep->ep.name = ep->name;
 
 		ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
 		ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
index 3e1c9d589dfa..b03b2ebfc53a 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -280,6 +280,7 @@ struct usba_ep {
 	void __iomem				*ep_regs;
 	void __iomem				*dma_regs;
 	void __iomem				*fifo;
+	char					name[8];
 	struct usb_ep				ep;
 	struct usba_udc				*udc;
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH] arm64: errata: Provide macro for major and minor cpu revisions
From: Robert Richter @ 2017-01-11 12:11 UTC (permalink / raw)
  To: linux-arm-kernel

Definition of cpu ranges are hard to read if the cpu variant is not
zero. Provide MIDR_CPU_FULL_REV() macro to describe the full hardware
revision of a cpu including variant and (minor) revision.

Signed-off-by: Robert Richter <rrichter@cavium.com>
---
 arch/arm64/include/asm/cputype.h |  3 +++
 arch/arm64/kernel/cpu_errata.c   | 15 +++++++++------
 arch/arm64/kernel/cpufeature.c   |  8 +++-----
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 26a68ddb11c1..983e59cbdd54 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -56,6 +56,9 @@
 	(0xf			<< MIDR_ARCHITECTURE_SHIFT) | \
 	((partnum)		<< MIDR_PARTNUM_SHIFT))
 
+#define MIDR_CPU_FULL_REV(var, rev) \
+	(((var)	<< MIDR_VARIANT_SHIFT) | (rev))
+
 #define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
 			     MIDR_ARCHITECTURE_MASK)
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index b75e917aac46..63b61e981e2f 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -79,8 +79,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 832075",
 		.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
-		MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
-			   (1 << MIDR_VARIANT_SHIFT) | 2),
+		MIDR_RANGE(MIDR_CORTEX_A57,
+			   MIDR_CPU_FULL_REV(0, 0),
+			   MIDR_CPU_FULL_REV(1, 2)),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_834220
@@ -88,8 +89,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cortex-A57 r0p0 - r1p2 */
 		.desc = "ARM erratum 834220",
 		.capability = ARM64_WORKAROUND_834220,
-		MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
-			   (1 << MIDR_VARIANT_SHIFT) | 2),
+		MIDR_RANGE(MIDR_CORTEX_A57,
+			   MIDR_CPU_FULL_REV(0, 0),
+			   MIDR_CPU_FULL_REV(1, 2)),
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -113,8 +115,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	/* Cavium ThunderX, T88 pass 1.x - 2.1 */
 		.desc = "Cavium erratum 27456",
 		.capability = ARM64_WORKAROUND_CAVIUM_27456,
-		MIDR_RANGE(MIDR_THUNDERX, 0x00,
-			   (1 << MIDR_VARIANT_SHIFT) | 1),
+		MIDR_RANGE(MIDR_THUNDERX,
+			   MIDR_CPU_FULL_REV(0, 0),
+			   MIDR_CPU_FULL_REV(1, 1)),
 	},
 	{
 	/* Cavium ThunderX, T81 pass 1.0 */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fdf8f045929f..f12b13de24f4 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -720,13 +720,11 @@ static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry,
 static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused)
 {
 	u32 midr = read_cpuid_id();
-	u32 rv_min, rv_max;
 
 	/* Cavium ThunderX pass 1.x and 2.x */
-	rv_min = 0;
-	rv_max = (1 << MIDR_VARIANT_SHIFT) | MIDR_REVISION_MASK;
-
-	return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, rv_min, rv_max);
+	return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX,
+		MIDR_CPU_FULL_REV(0, 0),
+		MIDR_CPU_FULL_REV(1, MIDR_REVISION_MASK));
 }
 
 static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused)
-- 
2.11.0

^ permalink raw reply related

* [PATCH 55/62] watchdog: sunxi_wdt: Convert to use device managed functions and other improvements
From: Maxime Ripard @ 2017-01-11 12:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484100561-17638-4-git-send-email-linux@roeck-us.net>

On Tue, Jan 10, 2017 at 06:09:09PM -0800, Guenter Roeck wrote:
> Use device managed functions to simplify error handling, reduce
> source code size, improve readability, and reduce the likelyhood of bugs.
> Other improvements as listed below.
> 
> The conversion was done automatically with coccinelle using the
> following semantic patches. The semantic patches and the scripts used
> to generate this commit log are available at
> https://github.com/groeck/coccinelle-patches
> 
> - Drop assignments to otherwise unused variables
> - Drop remove function
> - Drop platform_set_drvdata()
> - Use devm_watchdog_register_driver() to register watchdog device
> - Replace shutdown function with call to watchdog_stop_on_reboot()
> 
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170111/51fbbf9a/attachment-0001.sig>

^ permalink raw reply

* [PATCH 1/1] iommu/arm-smmu: Fix for ThunderX erratum #27704
From: Robin Murphy @ 2017-01-11 12:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484135507-24872-1-git-send-email-tn@semihalf.com>

On 11/01/17 11:51, Tomasz Nowicki wrote:
> The goal of erratum #27704 workaround was to make sure that ASIDs and VMIDs
> are unique across all SMMU instances on affected Cavium systems.
> 
> Currently, the workaround code partitions ASIDs and VMIDs by increasing
> global cavium_smmu_context_count which in turn becomes the base ASID and VMID
> value for the given SMMU instance upon the context bank initialization.
> 
> For systems with multiple SMMU instances this approach implies the risk
> of crossing 8-bit ASID, like for CN88xx capable of 4 SMMUv2, 128 context bank each:
> SMMU_0 (0-127 ASID RANGE)
> SMMU_1 (127-255 ASID RANGE)
> SMMU_2 (256-383 ASID RANGE) <--- crossing 8-bit ASID
> SMMU_3 (384-511 ASID RANGE) <--- crossing 8-bit ASID

I could swear that@some point in the original discussion it was said
that the TLBs were only shared between pairs of SMMUs, so in fact 0/1
and 2/3 are independent of each other - out of interest, have you
managed to hit an actual problem in practice or is this patch just by
inspection?

Of course, depending on the SMMUs to probe in the right order isn't
particularly robust, so it's still probably a worthwhile change.

> Since we use 8-bit ASID now we effectively misconfigure ASID[15:8] bits for
> SMMU_CBn_TTBRm register. Also, we still use non-zero ASID[15:8] bits
> upon context invalidation. This patch adds 16-bit ASID support for stage-1
> AArch64 contexts for Cavium SMMUv2 model so that we use ASIDs consistently.
> 
> Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
> ---
>  drivers/iommu/arm-smmu.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index a60cded..ae8f059 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -260,6 +260,7 @@ enum arm_smmu_s2cr_privcfg {
>  
>  #define TTBCR2_SEP_SHIFT		15
>  #define TTBCR2_SEP_UPSTREAM		(0x7 << TTBCR2_SEP_SHIFT)
> +#define TTBCR2_AS			(1 << 4)
>  
>  #define TTBRn_ASID_SHIFT		48
>  
> @@ -778,6 +779,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>  			reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
>  			reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
>  			reg2 |= TTBCR2_SEP_UPSTREAM;
> +			if (smmu->model == CAVIUM_SMMUV2 &&

I'd be inclined to say "smmu->version == ARM_SMMU_V2" there, rather than
make it Cavium-specific - we enable 16-bit VMID unconditionally where
supported, so I don't see any reason not to handle 16-bit ASIDs in the
same manner.

> +			    cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
> +				reg2 |= TTBCR2_AS;
>  		}
>  		if (smmu->version > ARM_SMMU_V1)
>  			writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
> 

Either way:

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

^ permalink raw reply

* [PATCH 56/62] watchdog: tangox_wdt: Convert to use device managed functions
From: Marc Gonzalez @ 2017-01-11 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <94c4d5c0-f639-eab1-6706-335977690e88@roeck-us.net>

On 11/01/2017 11:52, Guenter Roeck wrote:

> On 01/11/2017 01:07 AM, Marc Gonzalez wrote:
> 
>>> @@ -134,12 +134,15 @@ static int tangox_wdt_probe(struct platform_device *pdev)
>>>  	err = clk_prepare_enable(dev->clk);
>>>  	if (err)
>>>  		return err;
>>> +	err = devm_add_action_or_reset(&pdev->dev,
>>> +				       (void(*)(void *))clk_disable_unprepare,
>>> +				       dev->clk);
>>> +	if (err)
>>> +		return err;
>>
>> Hello Guenter,
>>
>> I would rather avoid the function pointer cast.
>> How about defining an auxiliary function for the cleanup action?
>>
>> clk_disable_unprepare() is static inline, so gcc will have to
>> define an auxiliary function either way. What do you think?
> 
> Not really. It would just make it more complicated to replace the
> call with devm_clk_prepare_enable(), should it ever find its way
> into the light of day.

More complicated, because the cleanup function will have to be deleted later?
The compiler will warn if someone forgets to do that.

In my opinion, it's not a good idea to rely on the fact that casting
void(*)(struct clk *clk) to void(*)(void *) is likely to work as expected
on most platforms. (It has undefined behavior, strictly speaking.)

Do you really dislike the portable solution I suggested? :-(

Regards.

^ permalink raw reply

* [RFC PATCH 09/10] drivers/perf: Add support for ARMv8.2 Statistical Profiling Extension
From: Will Deacon @ 2017-01-11 12:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170110160419.4cc3d61c9d652e5d5da13f15@arm.com>

Hi Kim,

On Tue, Jan 10, 2017 at 04:04:19PM -0600, Kim Phillips wrote:
> On Tue, 3 Jan 2017 18:10:26 +0000
> Will Deacon <will.deacon@arm.com> wrote:
> 
> > +#define DRVNAME				"arm_spe_pmu"
> 
> Based on Intel naming "intel_pt" and "intel_bts', I had expected
> "arm-spe" as the universal basename for SPE.  I don't really care about
> whether '_pmu' is included, but it's yet another naming inconsistency we
> have with coresight's "cs_etm" (the other being prefixed with "arm_").

It's consistent with the other PMUs under drivers/perf.

> Also, nit, since I don't know why perf userspace tools can't handle
> dashes in PMU names (commit 3d1ff755e367 "arm: perf: clean up PMU
> names" doesn't say), can we at least start to use dashes in our
> filenames?  arm-spe-pmu.c is easier to type than arm_spe_pmu.c.

I'd rather go for consistency both with the other PMU drivers under
drivers/perf, but also with the PMU name itself.

> > +static int arm_spe_pmu_event_init(struct perf_event *event)
> > +{
> > +	u64 reg;
> > +	struct perf_event_attr *attr = &event->attr;
> > +	struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu);
> > +
> > +	/* This is, of course, deeply driver-specific */
> > +	if (attr->type != event->pmu->type)
> > +		return -ENOENT;
> > +
> > +	if (event->cpu >= 0 &&
> > +	    !cpumask_test_cpu(event->cpu, &spe_pmu->supported_cpus))
> > +		return -ENOENT;
> > +
> > +	if (arm_spe_event_to_pmsevfr(event) & PMSEVFR_EL1_RES0)
> > +		return -EOPNOTSUPP;
> > +
> > +	if (event->hw.sample_period < spe_pmu->min_period ||
> > +	    event->hw.sample_period & PMSIRR_EL1_IVAL_MASK)
> > +		return -EOPNOTSUPP;
> > +
> > +	if (attr->exclude_idle)
> > +		return -EOPNOTSUPP;
> > +
> > +	/*
> > +	 * Feedback-directed frequency throttling doesn't work when we
> > +	 * have a buffer of samples. We'd need to manually count the
> > +	 * samples in the buffer when it fills up and adjust the event
> > +	 * count to reflect that. Instead, force the user to specify a
> > +	 * sample period instead.
> > +	 */
> > +	if (attr->freq)
> > +		return -EINVAL;
> > +
> > +	if (is_kernel_in_hyp_mode()) {
> > +		if (attr->exclude_kernel != attr->exclude_hv)
> > +			return -EOPNOTSUPP;
> > +	} else if (!attr->exclude_hv) {
> > +		return -EOPNOTSUPP;
> > +	}
> > +
> > +	reg = arm_spe_event_to_pmsfcr(event);
> > +	if ((reg & BIT(PMSFCR_EL1_FE_SHIFT)) &&
> > +	    !(spe_pmu->features & SPE_PMU_FEAT_FILT_EVT))
> > +		return -EOPNOTSUPP;
> > +
> > +	if ((reg & BIT(PMSFCR_EL1_FT_SHIFT)) &&
> > +	    !(spe_pmu->features & SPE_PMU_FEAT_FILT_TYP))
> > +		return -EOPNOTSUPP;
> > +
> > +	if ((reg & BIT(PMSFCR_EL1_FL_SHIFT)) &&
> > +	    !(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
> > +		return -EOPNOTSUPP;
> > +
> > +	return 0;
> > +}
> 
> Without being provided instructions on how to use, I had to add
> debug printks here to find out e.g., an event period *must* be specified
> with record -c, and then again to find out that only a certain set of
> numbers is allowed by the h/w (256, 512, etc.). Is it possible to
> report why the driver is returning an error before it does?  Otherwise,
> all the user sees is, e.g.:
> 
> Error:
> The sys_perf_event_open() syscall returned with 19 (No such device) for event (arm_spe_pmu_0).
> /bin/dmesg may provide additional information.
> No CONFIG_PERF_EVENTS=y kernel support configured?
> 
> ...and, in this case, with nothing in dmesg.  And, IIRC, the above text
> is emitted only if perf is run with -v and/or built with DEBUG set.
> Granted, *that* problem is not explicitly relevant to this patch, but
> new drivers should nevertheless express their usage details better.

I don't disagree that the error reporting from the driver up to userspace
leaves much to be desired, but there currently isn't a sensible way to
communicate the exact reason for failure back from event_init and I
don't think we're different to other PMU drivers in this respect. Yes,
you can paper around the problem using pr_debug, but that really only
helps the developer writing the perf tool support, and much of the
constraints can also be inferred from the architecture spec.

There were patches to allow providing strings back via perf_err:

  https://lkml.org/lkml/2015/8/24/506

but I don't think it ended up getting merged. Other subsystems wanted to
use the same approach, and there are ABI considerations with all of this
(the thread is worth a read).

> Also, curiously, arm_spe_pmu doesn't appear in 'perf list' (even when
> SPE h/w is present).

Weird, it would be nice to understand why that is. The sysfs plumbing should
all be there, so I'd expect to see something. On my laptop, for example,
intel_pt appears as:

  intel_pt//                                         [Kernel PMU event]

and strace show perf doing the following:

stat("/sys/bus/event_source/devices/intel_pt/format", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
open("/sys/bus/event_source/devices/intel_pt/format", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 82
open("/sys/bus/event_source/devices/intel_pt/format/psb_period", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/noretcomp", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/tsc", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/cyc_thresh", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/mtc_period", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/cyc", O_RDONLY) = 83
open("/sys/bus/event_source/devices/intel_pt/format/mtc", O_RDONLY) = 83
stat("/sys/bus/event_source/devices/intel_pt/events", 0x7ffe54eebb40) = -1 ENOENT (No such file or directory)
stat("/sys/bus/event_source/devices/intel_pt/type", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0
open("/sys/bus/event_source/devices/intel_pt/type", O_RDONLY) = 82
stat("/sys/bus/event_source/devices/intel_pt/cpumask", 0x7ffe54eedd60) = -1 ENOENT (No such file or directory)
stat("/sys/bus/event_source/devices/intel_pt/cpus", 0x7ffe54eedd60) = -1 ENOENT (No such file or directory)
stat("/sys/bus/event_source/devices/intel_pt/caps/mtc", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0
open("/sys/bus/event_source/devices/intel_pt/caps/mtc", O_RDONLY) = 82
stat("/sys/bus/event_source/devices/intel_pt/caps/psb_cyc", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0
open("/sys/bus/event_source/devices/intel_pt/caps/psb_cyc", O_RDONLY) = 82

What do you see for SPE?

> Other than that, this gets my:
> 
> Tested-by: Kim Phillips <kim.phillips@arm.com>

Thanks!

Will

^ permalink raw reply

* [PATCH v2] arm64: do not set dma masks that device connection can't handle
From: Nikita Yushchenko @ 2017-01-11 12:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5c5cd4fd-4854-a2dd-10b6-9cc98e63a85c@arm.com>

> I actually have a third variation of this problem involving a PCI root
> complex which *could* drive full-width (40-bit) addresses, but won't,
> due to the way its PCI<->AXI interface is programmed. That would require
> even more complicated dma-ranges handling to describe the windows of
> valid physical addresses which it *will* pass, so I'm not pressing the
> issue - let's just get the basic DMA mask case fixed first.

R-Car + NVMe is actually not "basic case".

It has PCI<->AXI interface involved.
PCI addresses are 64-bit and controller does handle 64-bit addresses
there. Mapping between PCI addresses and AXI addresses is defined. But
AXI is 32-bit.

SoC has iommu that probably could be used between PCIe module and RAM.
Although AFAIK nobody made that working yet.

Board I work with has 4G of RAM, in 4 banks, located at different parts
of wide address space, and only one of them is below 4G. But if iommu is
capable of translating addresses such that 4 gigabyte banks map to first
4 gigabytes of address space, then all memory will become available for
DMA from PCIe device.

^ permalink raw reply

* [PATCH v2 0/7] uapi: export all headers under uapi directories
From: Jesper Nilsson @ 2017-01-11 12:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3131144.4Ej3KFWRbz@wuerfel>

On Mon, Jan 09, 2017 at 12:33:58PM +0100, Arnd Bergmann wrote:
> On Friday, January 6, 2017 10:43:52 AM CET Nicolas Dichtel wrote:
> > Here is the v2 of this series. The first 5 patches are just cleanup: some
> > exported headers were still under a non-uapi directory.
> 
> Since this is meant as a cleanup, I commented on this to point out a cleaner
> way to do the same.
> 
> > The patch 6 was spotted by code review: there is no in-tree user of this
> > functionality.
> > The last patch remove the use of header-y. Now all files under an uapi
> > directory are exported.
> 
> Very nice!
> 
> > asm is a bit special, most of architectures export asm/<arch>/include/uapi/asm
> > only, but there is two exceptions:
> >  - cris which exports arch/cris/include/uapi/arch-v[10|32];
> 
> This is interesting, though not your problem. Maybe someone who understands
> cris better can comment on this: How is the decision made about which of
> the arch/user.h headers gets used? I couldn't find that in the sources,
> but it appears to be based on kernel compile-time settings, which is
> wrong for user space header files that should be independent of the kernel
> config.

I believe it's since the CRISv10 and CRISv32 are very different beasts,
and that is selected via kernel config...

This part of the CRIS port has been transformed a couple of times from
the original layout without uapi, and there's still some legacy silliness,
where some files might have been exported but never used from userspace
except for some corner cases.

> >  - tile which exports arch/tile/include/uapi/arch.
> > Because I don't know if the output of 'make headers_install_all' can be changed,
> > I introduce subdir-y in Kbuild file. The headers_install_all target copies all
> > asm/<arch>/include/uapi/asm to usr/include/asm-<arch> but
> > arch/cris/include/uapi/arch-v[10|32] and arch/tile/include/uapi/arch are not
> > prefixed (they are put asis in usr/include/). If it's acceptable to modify the
> > output of 'make headers_install_all' to export asm headers in
> > usr/include/asm-<arch>/asm, then I could remove this new subdir-y and exports
> > everything under arch/<arch>/include/uapi/.
> 
> I don't know if anyone still uses "make headers_install_all", I suspect
> distros these days all use "make headers_install", so it probably
> doesn't matter much.
> 
> In case of cris, it should be easy enough to move all the contents of the
> uapi/arch-*/*.h headers into the respective uapi/asm/*.h headers, they
> only seem to be referenced from there.

This would seem to be a reasonable change.

> For tile, I suspect that would not work as the arch/*.h headers are
> apparently defined as interfaces for both user space and kernel.
> 
> > Note also that exported files for asm are a mix of files listed by:
> >  - include/uapi/asm-generic/Kbuild.asm;
> >  - arch/x86/include/uapi/asm/Kbuild;
> >  - arch/x86/include/asm/Kbuild.
> > This complicates a lot the processing (arch/x86/include/asm/Kbuild is also
> > used by scripts/Makefile.asm-generic).
> > 
> > This series has been tested with a 'make headers_install' on x86 and a
> > 'make headers_install_all'. I've checked the result of both commands.
> > 
> > This patch is built against linus tree. I don't know if it should be
> > made against antoher tree.
> 
> The series should probably get merged through the kbuild tree, but testing
> it on mainline is fine here.
> 
> 	Arnd

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson at axis.com

^ permalink raw reply

* [PATCHv4 3/8] rtc: add STM32 RTC driver
From: Amelie Delaunay @ 2017-01-11 12:48 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for the STM32 RTC.

Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
 drivers/rtc/Kconfig     |  11 +
 drivers/rtc/Makefile    |   1 +
 drivers/rtc/rtc-stm32.c | 727 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 739 insertions(+)
 create mode 100644 drivers/rtc/rtc-stm32.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e859d14..11eb28a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1706,6 +1706,17 @@ config RTC_DRV_PIC32
 	   This driver can also be built as a module. If so, the module
 	   will be called rtc-pic32
 
+config RTC_DRV_STM32
+	tristate "STM32 RTC"
+	select REGMAP_MMIO
+	depends on ARCH_STM32 || COMPILE_TEST
+	help
+	   If you say yes here you get support for the STM32 On-Chip
+	   Real Time Clock.
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-stm32".
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 1ac694a..87bd9cc 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_SNVS)	+= rtc-snvs.o
 obj-$(CONFIG_RTC_DRV_SPEAR)	+= rtc-spear.o
 obj-$(CONFIG_RTC_DRV_STARFIRE)	+= rtc-starfire.o
 obj-$(CONFIG_RTC_DRV_STK17TA8)	+= rtc-stk17ta8.o
+obj-$(CONFIG_RTC_DRV_STM32) 	+= rtc-stm32.o
 obj-$(CONFIG_RTC_DRV_STMP)	+= rtc-stmp3xxx.o
 obj-$(CONFIG_RTC_DRV_ST_LPC)	+= rtc-st-lpc.o
 obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
new file mode 100644
index 0000000..f49226e
--- /dev/null
+++ b/drivers/rtc/rtc-stm32.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (C) Amelie Delaunay 2016
+ * Author:  Amelie Delaunay <amelie.delaunay@st.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+
+#define DRIVER_NAME "stm32_rtc"
+
+/* STM32 RTC registers */
+#define STM32_RTC_TR		0x00
+#define STM32_RTC_DR		0x04
+#define STM32_RTC_CR		0x08
+#define STM32_RTC_ISR		0x0C
+#define STM32_RTC_PRER		0x10
+#define STM32_RTC_ALRMAR	0x1C
+#define STM32_RTC_WPR		0x24
+
+/* STM32_RTC_TR bit fields  */
+#define STM32_RTC_TR_SEC_SHIFT		0
+#define STM32_RTC_TR_SEC		GENMASK(6, 0)
+#define STM32_RTC_TR_MIN_SHIFT		8
+#define STM32_RTC_TR_MIN		GENMASK(14, 8)
+#define STM32_RTC_TR_HOUR_SHIFT		16
+#define STM32_RTC_TR_HOUR		GENMASK(21, 16)
+
+/* STM32_RTC_DR bit fields */
+#define STM32_RTC_DR_DATE_SHIFT		0
+#define STM32_RTC_DR_DATE		GENMASK(5, 0)
+#define STM32_RTC_DR_MONTH_SHIFT	8
+#define STM32_RTC_DR_MONTH		GENMASK(12, 8)
+#define STM32_RTC_DR_WDAY_SHIFT		13
+#define STM32_RTC_DR_WDAY		GENMASK(15, 13)
+#define STM32_RTC_DR_YEAR_SHIFT		16
+#define STM32_RTC_DR_YEAR		GENMASK(23, 16)
+
+/* STM32_RTC_CR bit fields */
+#define STM32_RTC_CR_FMT		BIT(6)
+#define STM32_RTC_CR_ALRAE		BIT(8)
+#define STM32_RTC_CR_ALRAIE		BIT(12)
+
+/* STM32_RTC_ISR bit fields */
+#define STM32_RTC_ISR_ALRAWF		BIT(0)
+#define STM32_RTC_ISR_INITS		BIT(4)
+#define STM32_RTC_ISR_RSF		BIT(5)
+#define STM32_RTC_ISR_INITF		BIT(6)
+#define STM32_RTC_ISR_INIT		BIT(7)
+#define STM32_RTC_ISR_ALRAF		BIT(8)
+
+/* STM32_RTC_PRER bit fields */
+#define STM32_RTC_PRER_PRED_S_SHIFT	0
+#define STM32_RTC_PRER_PRED_S		GENMASK(14, 0)
+#define STM32_RTC_PRER_PRED_A_SHIFT	16
+#define STM32_RTC_PRER_PRED_A		GENMASK(22, 16)
+
+/* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */
+#define STM32_RTC_ALRMXR_SEC_SHIFT	0
+#define STM32_RTC_ALRMXR_SEC		GENMASK(6, 0)
+#define STM32_RTC_ALRMXR_SEC_MASK	BIT(7)
+#define STM32_RTC_ALRMXR_MIN_SHIFT	8
+#define STM32_RTC_ALRMXR_MIN		GENMASK(14, 8)
+#define STM32_RTC_ALRMXR_MIN_MASK	BIT(15)
+#define STM32_RTC_ALRMXR_HOUR_SHIFT	16
+#define STM32_RTC_ALRMXR_HOUR		GENMASK(21, 16)
+#define STM32_RTC_ALRMXR_PM		BIT(22)
+#define STM32_RTC_ALRMXR_HOUR_MASK	BIT(23)
+#define STM32_RTC_ALRMXR_DATE_SHIFT	24
+#define STM32_RTC_ALRMXR_DATE		GENMASK(29, 24)
+#define STM32_RTC_ALRMXR_WDSEL		BIT(30)
+#define STM32_RTC_ALRMXR_WDAY_SHIFT	24
+#define STM32_RTC_ALRMXR_WDAY		GENMASK(27, 24)
+#define STM32_RTC_ALRMXR_DATE_MASK	BIT(31)
+
+/* STM32_RTC_WPR key constants */
+#define RTC_WPR_1ST_KEY			0xCA
+#define RTC_WPR_2ND_KEY			0x53
+#define RTC_WPR_WRONG_KEY		0xFF
+
+/*
+ * RTC registers are protected agains parasitic write access.
+ * PWR_CR_DBP bit must be set to enable write access to RTC registers.
+ */
+/* STM32_PWR_CR */
+#define PWR_CR				0x00
+/* STM32_PWR_CR bit field */
+#define PWR_CR_DBP			BIT(8)
+
+static struct regmap *dbp;
+
+struct stm32_rtc {
+	struct rtc_device *rtc_dev;
+	void __iomem *base;
+	struct clk *ck_rtc;
+	int irq_alarm;
+};
+
+static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
+{
+	writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR);
+	writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR);
+}
+
+static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
+{
+	writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR);
+}
+
+static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
+{
+	unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+	if (!(isr & STM32_RTC_ISR_INITF)) {
+		isr |= STM32_RTC_ISR_INIT;
+		writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+		/*
+		 * It takes around 2 ck_rtc clock cycles to enter in
+		 * initialization phase mode (and have INITF flag set). As
+		 * slowest ck_rtc frequency may be 32kHz and highest should be
+		 * 1MHz, we poll every 10 us with a timeout of 100ms.
+		 */
+		return readl_relaxed_poll_timeout_atomic(
+					rtc->base + STM32_RTC_ISR,
+					isr, (isr & STM32_RTC_ISR_INITF),
+					10, 100000);
+	}
+
+	return 0;
+}
+
+static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
+{
+	unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+	isr &= ~STM32_RTC_ISR_INIT;
+	writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+}
+
+static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
+{
+	unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+	isr &= ~STM32_RTC_ISR_RSF;
+	writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+	/*
+	 * Wait for RSF to be set to ensure the calendar registers are
+	 * synchronised, it takes around 2 ck_rtc clock cycles
+	 */
+	return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+						 isr,
+						 (isr & STM32_RTC_ISR_RSF),
+						 10, 100000);
+}
+
+static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
+{
+	struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
+	unsigned int isr, cr;
+
+	mutex_lock(&rtc->rtc_dev->ops_lock);
+
+	isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+
+	if ((isr & STM32_RTC_ISR_ALRAF) &&
+	    (cr & STM32_RTC_CR_ALRAIE)) {
+		/* Alarm A flag - Alarm interrupt */
+		dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n");
+
+		/* Pass event to the kernel */
+		rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+		/* Clear event flag, otherwise new events won't be received */
+		writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF,
+			       rtc->base + STM32_RTC_ISR);
+	}
+
+	mutex_unlock(&rtc->rtc_dev->ops_lock);
+
+	return IRQ_HANDLED;
+}
+
+/* Convert rtc_time structure from bin to bcd format */
+static void tm2bcd(struct rtc_time *tm)
+{
+	tm->tm_sec = bin2bcd(tm->tm_sec);
+	tm->tm_min = bin2bcd(tm->tm_min);
+	tm->tm_hour = bin2bcd(tm->tm_hour);
+
+	tm->tm_mday = bin2bcd(tm->tm_mday);
+	tm->tm_mon = bin2bcd(tm->tm_mon + 1);
+	tm->tm_year = bin2bcd(tm->tm_year - 100);
+	/*
+	 * Number of days since Sunday
+	 * - on kernel side, 0=Sunday...6=Saturday
+	 * - on rtc side, 0=invalid,1=Monday...7=Sunday
+	 */
+	tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday;
+}
+
+/* Convert rtc_time structure from bcd to bin format */
+static void bcd2tm(struct rtc_time *tm)
+{
+	tm->tm_sec = bcd2bin(tm->tm_sec);
+	tm->tm_min = bcd2bin(tm->tm_min);
+	tm->tm_hour = bcd2bin(tm->tm_hour);
+
+	tm->tm_mday = bcd2bin(tm->tm_mday);
+	tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
+	tm->tm_year = bcd2bin(tm->tm_year) + 100;
+	/*
+	 * Number of days since Sunday
+	 * - on kernel side, 0=Sunday...6=Saturday
+	 * - on rtc side, 0=invalid,1=Monday...7=Sunday
+	 */
+	tm->tm_wday %= 7;
+}
+
+static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int tr, dr;
+
+	/* Time and Date in BCD format */
+	tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+	dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+
+	tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
+	tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
+	tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
+
+	tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
+	tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
+	tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
+	tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT;
+
+	/* We don't report tm_yday and tm_isdst */
+
+	bcd2tm(tm);
+
+	return 0;
+}
+
+static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int tr, dr;
+	int ret = 0;
+
+	tm2bcd(tm);
+
+	/* Time in BCD format */
+	tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) |
+	     ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) |
+	     ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) & STM32_RTC_TR_HOUR);
+
+	/* Date in BCD format */
+	dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) & STM32_RTC_DR_DATE) |
+	     ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) & STM32_RTC_DR_MONTH) |
+	     ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) & STM32_RTC_DR_YEAR) |
+	     ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) & STM32_RTC_DR_WDAY);
+
+	stm32_rtc_wpr_unlock(rtc);
+
+	ret = stm32_rtc_enter_init_mode(rtc);
+	if (ret) {
+		dev_err(dev, "Can't enter in init mode. Set time aborted.\n");
+		goto end;
+	}
+
+	writel_relaxed(tr, rtc->base + STM32_RTC_TR);
+	writel_relaxed(dr, rtc->base + STM32_RTC_DR);
+
+	stm32_rtc_exit_init_mode(rtc);
+
+	ret = stm32_rtc_wait_sync(rtc);
+end:
+	stm32_rtc_wpr_lock(rtc);
+
+	return ret;
+}
+
+static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alrm->time;
+	unsigned int alrmar, cr, isr;
+
+	alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR);
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+	isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+
+	if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
+		/*
+		 * Date/day doesn't matter in Alarm comparison so alarm
+		 * triggers every day
+		 */
+		tm->tm_mday = -1;
+		tm->tm_wday = -1;
+	} else {
+		if (alrmar & STM32_RTC_ALRMXR_WDSEL) {
+			/* Alarm is set to a day of week */
+			tm->tm_mday = -1;
+			tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >>
+				      STM32_RTC_ALRMXR_WDAY_SHIFT;
+			tm->tm_wday %= 7;
+		} else {
+			/* Alarm is set to a day of month */
+			tm->tm_wday = -1;
+			tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >>
+				       STM32_RTC_ALRMXR_DATE_SHIFT;
+		}
+	}
+
+	if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) {
+		/* Hours don't matter in Alarm comparison */
+		tm->tm_hour = -1;
+	} else {
+		tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >>
+			       STM32_RTC_ALRMXR_HOUR_SHIFT;
+		if (alrmar & STM32_RTC_ALRMXR_PM)
+			tm->tm_hour += 12;
+	}
+
+	if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) {
+		/* Minutes don't matter in Alarm comparison */
+		tm->tm_min = -1;
+	} else {
+		tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >>
+			      STM32_RTC_ALRMXR_MIN_SHIFT;
+	}
+
+	if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) {
+		/* Seconds don't matter in Alarm comparison */
+		tm->tm_sec = -1;
+	} else {
+		tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >>
+			      STM32_RTC_ALRMXR_SEC_SHIFT;
+	}
+
+	bcd2tm(tm);
+
+	alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
+	alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
+
+	return 0;
+}
+
+static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int isr, cr;
+
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+
+	stm32_rtc_wpr_unlock(rtc);
+
+	/* We expose Alarm A to the kernel */
+	if (enabled)
+		cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
+	else
+		cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
+	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+	/* Clear event flag, otherwise new events won't be received */
+	isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+	isr &= ~STM32_RTC_ISR_ALRAF;
+	writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+
+	stm32_rtc_wpr_lock(rtc);
+
+	return 0;
+}
+
+static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
+{
+	unsigned int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
+	unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+	unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+
+	cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
+	cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
+	cur_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
+	cur_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
+	cur_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
+	cur_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
+
+	/*
+	 * Assuming current date is M-D-Y H:M:S.
+	 * RTC alarm can't be set on a specific month and year.
+	 * So the valid alarm range is:
+	 *	M-D-Y H:M:S < alarm <= (M+1)-D-Y H:M:S
+	 * with a specific case for December...
+	 */
+	if ((((tm->tm_year > cur_year) &&
+	      (tm->tm_mon == 0x1) && (cur_mon == 0x12)) ||
+	     ((tm->tm_year == cur_year) &&
+	      (tm->tm_mon <= cur_mon + 1))) &&
+	    ((tm->tm_mday > cur_day) ||
+	     ((tm->tm_mday == cur_day) &&
+	     ((tm->tm_hour > cur_hour) ||
+	      ((tm->tm_hour == cur_hour) && (tm->tm_min > cur_min)) ||
+	      ((tm->tm_hour == cur_hour) && (tm->tm_min == cur_min) &&
+	       (tm->tm_sec >= cur_sec))))))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alrm->time;
+	unsigned int cr, isr, alrmar;
+	int ret = 0;
+
+	tm2bcd(tm);
+
+	/*
+	 * RTC alarm can't be set on a specific date, unless this date is
+	 * up to the same day of month next month.
+	 */
+	if (stm32_rtc_valid_alrm(rtc, tm) < 0) {
+		dev_err(dev, "Alarm can be set only on upcoming month.\n");
+		return -EINVAL;
+	}
+
+	alrmar = 0;
+	/* tm_year and tm_mon are not used because not supported by RTC */
+	alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
+		  STM32_RTC_ALRMXR_DATE;
+	/* 24-hour format */
+	alrmar &= ~STM32_RTC_ALRMXR_PM;
+	alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) &
+		  STM32_RTC_ALRMXR_HOUR;
+	alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) &
+		  STM32_RTC_ALRMXR_MIN;
+	alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) &
+		  STM32_RTC_ALRMXR_SEC;
+
+	stm32_rtc_wpr_unlock(rtc);
+
+	/* Disable Alarm */
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+	cr &= ~STM32_RTC_CR_ALRAE;
+	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+	/*
+	 * Poll Alarm write flag to be sure that Alarm update is allowed: it
+	 * takes around 2 ck_rtc clock cycles
+	 */
+	ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+						isr,
+						(isr & STM32_RTC_ISR_ALRAWF),
+						10, 100000);
+
+	if (ret) {
+		dev_err(dev, "Alarm update not allowed\n");
+		goto end;
+	}
+
+	/* Write to Alarm register */
+	writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR);
+
+	if (alrm->enabled)
+		stm32_rtc_alarm_irq_enable(dev, 1);
+	else
+		stm32_rtc_alarm_irq_enable(dev, 0);
+
+end:
+	stm32_rtc_wpr_lock(rtc);
+
+	return ret;
+}
+
+static const struct rtc_class_ops stm32_rtc_ops = {
+	.read_time	= stm32_rtc_read_time,
+	.set_time	= stm32_rtc_set_time,
+	.read_alarm	= stm32_rtc_read_alarm,
+	.set_alarm	= stm32_rtc_set_alarm,
+	.alarm_irq_enable = stm32_rtc_alarm_irq_enable,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id stm32_rtc_of_match[] = {
+	{ .compatible = "st,stm32-rtc" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
+#endif
+
+static int stm32_rtc_init(struct platform_device *pdev,
+			  struct stm32_rtc *rtc)
+{
+	unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
+	unsigned int rate;
+	int ret = 0;
+
+	rate = clk_get_rate(rtc->ck_rtc);
+
+	/* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
+	pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
+	pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
+
+	for (pred_a = pred_a_max; pred_a >= 0; pred_a--) {
+		pred_s = (rate / (pred_a + 1)) - 1;
+
+		if (((pred_s + 1) * (pred_a + 1)) == rate)
+			break;
+	}
+
+	/*
+	 * Can't find a 1Hz, so give priority to RTC power consumption
+	 * by choosing the higher possible value for prediv_a
+	 */
+	if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
+		pred_a = pred_a_max;
+		pred_s = (rate / (pred_a + 1)) - 1;
+
+		dev_warn(&pdev->dev, "ck_rtc is %s\n",
+			 (rate - ((pred_a + 1) * (pred_s + 1)) < 0) ?
+			 "fast" : "slow");
+	}
+
+	stm32_rtc_wpr_unlock(rtc);
+
+	ret = stm32_rtc_enter_init_mode(rtc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Can't enter in init mode. Prescaler config failed.\n");
+		goto end;
+	}
+
+	prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
+	writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+	prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
+	writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+
+	/* Force 24h time format */
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+	cr &= ~STM32_RTC_CR_FMT;
+	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+
+	stm32_rtc_exit_init_mode(rtc);
+
+	ret = stm32_rtc_wait_sync(rtc);
+end:
+	stm32_rtc_wpr_lock(rtc);
+
+	return ret;
+}
+
+static int stm32_rtc_probe(struct platform_device *pdev)
+{
+	struct stm32_rtc *rtc;
+	struct resource *res;
+	int ret;
+
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rtc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rtc->base))
+		return PTR_ERR(rtc->base);
+
+	dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "st,syscfg");
+	if (IS_ERR(dbp)) {
+		dev_err(&pdev->dev, "no st,syscfg\n");
+		return PTR_ERR(dbp);
+	}
+
+	rtc->ck_rtc = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(rtc->ck_rtc)) {
+		dev_err(&pdev->dev, "no ck_rtc clock");
+		return PTR_ERR(rtc->ck_rtc);
+	}
+
+	ret = clk_prepare_enable(rtc->ck_rtc);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
+
+	/*
+	 * After a system reset, RTC_ISR.INITS flag can be read to check if
+	 * the calendar has been initalized or not. INITS flag is reset by a
+	 * power-on reset (no vbat, no power-supply). It is not reset if
+	 * ck_rtc parent clock has changed (so RTC prescalers need to be
+	 * changed). That's why we cannot rely on this flag to know if RTC
+	 * init has to be done.
+	 */
+	ret = stm32_rtc_init(pdev, rtc);
+	if (ret)
+		goto err;
+
+	rtc->irq_alarm = platform_get_irq(pdev, 0);
+	if (rtc->irq_alarm <= 0) {
+		dev_err(&pdev->dev, "no alarm irq\n");
+		ret = rtc->irq_alarm;
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	ret = device_init_wakeup(&pdev->dev, true);
+	if (ret)
+		dev_warn(&pdev->dev,
+			 "alarm won't be able to wake up the system");
+
+	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
+			&stm32_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc_dev)) {
+		ret = PTR_ERR(rtc->rtc_dev);
+		dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
+			ret);
+		goto err;
+	}
+
+	/* Handle RTC alarm interrupts */
+	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
+					stm32_rtc_alarm_irq,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					pdev->name, rtc);
+	if (ret) {
+		dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
+			rtc->irq_alarm);
+		goto err;
+	}
+
+	/*
+	 * If INITS flag is reset (calendar year field set to 0x00), calendar
+	 * must be initialized
+	 */
+	if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS))
+		dev_warn(&pdev->dev, "Date/Time must be initialized\n");
+
+	return 0;
+err:
+	clk_disable_unprepare(rtc->ck_rtc);
+
+	regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+
+	device_init_wakeup(&pdev->dev, false);
+
+	return ret;
+}
+
+static int __exit stm32_rtc_remove(struct platform_device *pdev)
+{
+	struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+	unsigned int cr;
+
+	/* Disable interrupts */
+	stm32_rtc_wpr_unlock(rtc);
+	cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+	cr &= ~STM32_RTC_CR_ALRAIE;
+	writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+	stm32_rtc_wpr_lock(rtc);
+
+	clk_disable_unprepare(rtc->ck_rtc);
+
+	/* Enable backup domain write protection */
+	regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
+
+	device_init_wakeup(&pdev->dev, false);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stm32_rtc_suspend(struct device *dev)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		return enable_irq_wake(rtc->irq_alarm);
+
+	return 0;
+}
+
+static int stm32_rtc_resume(struct device *dev)
+{
+	struct stm32_rtc *rtc = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = stm32_rtc_wait_sync(rtc);
+	if (ret < 0)
+		return ret;
+
+	if (device_may_wakeup(dev))
+		return disable_irq_wake(rtc->irq_alarm);
+
+	return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
+			 stm32_rtc_suspend, stm32_rtc_resume);
+
+static struct platform_driver stm32_rtc_driver = {
+	.probe		= stm32_rtc_probe,
+	.remove		= stm32_rtc_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.pm	= &stm32_rtc_pm_ops,
+		.of_match_table = stm32_rtc_of_match,
+	},
+};
+
+module_platform_driver(stm32_rtc_driver);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related

* [PATCHv4 3/8] rtc: add STM32 RTC driver
From: Corentin Labbe @ 2017-01-11 13:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484138905-5903-1-git-send-email-amelie.delaunay@st.com>

On Wed, Jan 11, 2017 at 01:48:25PM +0100, Amelie Delaunay wrote:
> This patch adds support for the STM32 RTC.
> 
> Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
> ---
>  drivers/rtc/Kconfig     |  11 +
>  drivers/rtc/Makefile    |   1 +
>  drivers/rtc/rtc-stm32.c | 727 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 739 insertions(+)
>  create mode 100644 drivers/rtc/rtc-stm32.c

[...]
> +/* STM32_PWR_CR */
> +#define PWR_CR				0x00
> +/* STM32_PWR_CR bit field */
> +#define PWR_CR_DBP			BIT(8)
> +
> +static struct regmap *dbp;

Hello

Why using a global static struct ?
You could alloc a private structure in probe for storing it and use platform_set_drvdata()

Regards

^ permalink raw reply

* [PATCH v2 2/5] arm64: Work around Falkor erratum 1003
From: Christopher Covington @ 2017-01-11 13:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170104103322.GA20461@cbox>

Hi Christoffer,

On 01/04/2017 05:33 AM, Christoffer Dall wrote:
> On Thu, Dec 29, 2016 at 05:43:32PM -0500, Christopher Covington wrote:
>> From: Shanker Donthineni <shankerd@codeaurora.org>
>>
>> On the Qualcomm Datacenter Technologies Falkor v1 CPU, memory accesses may
>> allocate TLB entries using an incorrect ASID when TTBRx_EL1 is being
>> updated. Changing the TTBRx_EL1[ASID] and TTBRx_EL1[BADDR] fields
>> separately using a reserved ASID will ensure that there are no TLB entries
>> with incorrect ASID after changing the the ASID.
> 
> When we restore guest state in KVM, we completely save and restore
> TTBRx_EL1 from EL2. Would that be affected by this erratum?

Good question, but apparently not. I'll add the following explanation to the
v3 commit message.

"EL2 and EL3 code changing the EL1&0 ASID is not subject to this erratum
because hardware is prohibited from performing translations from an
out-of-context translation regime."

Thanks,
Cov

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

^ permalink raw reply

* [RFC PATCH v4 0/5] ARM: Fix dma_alloc_coherent() and friends for NOMMU
From: Benjamin Gaignard @ 2017-01-11 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484057925-23586-1-git-send-email-vladimir.murzin@arm.com>

2017-01-10 15:18 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
> Hi,
>
> It seem that addition of cache support for M-class cpus uncovered
> latent bug in DMA usage. NOMMU memory model has been treated as being
> always consistent; however, for R/M classes of cpu memory can be
> covered by MPU which in turn might configure RAM as Normal
> i.e. bufferable and cacheable. It breaks dma_alloc_coherent() and
> friends, since data can stuck in caches now or be buffered.
>
> This patch set is trying to address the issue by providing region of
> memory suitable for consistent DMA operations. It is supposed that
> such region is marked by MPU as non-cacheable. Robin suggested to
> advertise such memory as reserved shared-dma-pool, rather then using
> homebrew command line option, and extend dma-coherent to provide
> default DMA area in the similar way as it is done for CMA (PATCH
> 2/5). It allows us to offload all bookkeeping on generic coherent DMA
> framework, and it is seems that it might be reused by other
> architectures like c6x and blackfin.
>
> Dedicated DMA region is required for cases other than:
>  - MMU/MPU is off
>  - cpu is v7m w/o cache support
>  - device is coherent
>
> In case one of the above conditions is true dma operations are forced
> to be coherent and wired with dma_noop_ops.
>
> To make life easier NOMMU dma operations are kept in separate
> compilation unit.
>
> Since the issue was reported in the same time as Benjamin sent his
> patch [1] to allow mmap for NOMMU, his case is also addressed in this
> series (PATCH 1/5 and PATCH 3/5).
>
> Thanks!

I have tested this v4 on my setup (stm32f4, no cache, no MPU) and unfortunately
it doesn't work with my drm/kms driver.
I haven't any errors but nothing is displayed unlike what I have when
using current dma-mapping
code.
I guess the issue is coming from dma-noop where __get_free_pages() is
used instead of alloc_pages()
in dma-mapping.

Since my hardware doesn't have cache or MPU (and so use dma-noop) I
haven't reserved specific memory region.
Buffer addresses and vma parameters look correct... What could I have
miss here ?

Benjamin

>
> [1] http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8633/1
>
> Vladimir Murzin (5):
>   dma: Add simple dma_noop_mmap
>   drivers: dma-coherent: Introduce default DMA pool
>   ARM: NOMMU: Introduce dma operations for noMMU
>   ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
>   ARM: dma-mapping: Remove traces of NOMMU code
>
>  .../bindings/reserved-memory/reserved-memory.txt   |   3 +
>  arch/arm/include/asm/dma-mapping.h                 |   3 +-
>  arch/arm/mm/Kconfig                                |   2 +-
>  arch/arm/mm/Makefile                               |   5 +-
>  arch/arm/mm/dma-mapping-nommu.c                    | 252 +++++++++++++++++++++
>  arch/arm/mm/dma-mapping.c                          |  26 +--
>  drivers/base/dma-coherent.c                        |  59 ++++-
>  lib/dma-noop.c                                     |  21 ++
>  8 files changed, 335 insertions(+), 36 deletions(-)
>  create mode 100644 arch/arm/mm/dma-mapping-nommu.c
>
> --
> 2.0.0
>



-- 
Benjamin Gaignard

Graphic Study Group

Linaro.org ? Open source software for ARM SoCs

Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply


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