Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/18] FSI device driver introduction
From: Greg KH @ 2017-01-19  9:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAA0LjjVAJiF8yF8prE22Uz18A+EWnNAPis+4LydGRK2BVp6NSg@mail.gmail.com>

On Tue, Jan 17, 2017 at 04:00:41PM -0600, Christopher Bostic wrote:
> On Tue, Jan 17, 2017 at 1:42 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> > On Mon, Jan 16, 2017 at 03:22:48PM -0600, christopher.lee.bostic at gmail.com wrote:
> >> From: Chris Bostic <cbostic@us.ibm.com>
> >
> > <snip>
> >
> > Only this, and patch 02/18 came through, did something get stuck on your
> > end?
> >
> 
> Hi Greg,
> 
> Yes had an issue with the server blocking send, investigating why.

It's still failing, I keep getting only the 00 email :(

^ permalink raw reply

* [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver
From: Hanjun Guo @ 2017-01-19  9:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170118132541.8989-14-fu.wei@linaro.org>

On 2017/1/18 21:25, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This patch adds support for parsing arch timer info in GTDT,
> provides some kernel APIs to parse all the PPIs and
> always-on info in GTDT and export them.
>
> By this driver, we can simplify arm_arch_timer drivers, and
> separate the ACPI GTDT knowledge from it.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
> ---
>  arch/arm64/Kconfig          |   1 +
>  drivers/acpi/arm64/Kconfig  |   3 +
>  drivers/acpi/arm64/Makefile |   1 +
>  drivers/acpi/arm64/gtdt.c   | 157 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/acpi.h        |   6 ++
>  5 files changed, 168 insertions(+)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1117421..ab1ee10 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -2,6 +2,7 @@ config ARM64
>  	def_bool y
>  	select ACPI_CCA_REQUIRED if ACPI
>  	select ACPI_GENERIC_GSI if ACPI
> +	select ACPI_GTDT if ACPI
>  	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>  	select ACPI_MCFG if ACPI
>  	select ACPI_SPCR_TABLE if ACPI
> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
> index 4616da4..5a6f80f 100644
> --- a/drivers/acpi/arm64/Kconfig
> +++ b/drivers/acpi/arm64/Kconfig
> @@ -4,3 +4,6 @@
>
>  config ACPI_IORT
>  	bool
> +
> +config ACPI_GTDT
> +	bool
> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
> index 72331f2..1017def 100644
> --- a/drivers/acpi/arm64/Makefile
> +++ b/drivers/acpi/arm64/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_ACPI_IORT) 	+= iort.o
> +obj-$(CONFIG_ACPI_GTDT) 	+= gtdt.o
> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
> new file mode 100644
> index 0000000..d93a790
> --- /dev/null
> +++ b/drivers/acpi/arm64/gtdt.c
> @@ -0,0 +1,157 @@
[...]
> +
> +/**
> + * acpi_gtdt_init() - Get the info of GTDT table to prepare for further init.
> + * @table:	The pointer to GTDT table.
> + * @platform_timer_count:	The pointer of int variate for returning the
> + *				number of platform timers. It can be NULL, if
> + *				driver don't need this info.
> + *
> + * Return: 0 if success, -EINVAL if error.
> + */
> +int __init acpi_gtdt_init(struct acpi_table_header *table,
> +			  int *platform_timer_count)
> +{
> +	int ret = 0;
> +	int timer_count = 0;
> +	void *platform_timer = NULL;
> +	struct acpi_table_gtdt *gtdt;
> +
> +	gtdt = container_of(table, struct acpi_table_gtdt, header);
> +	acpi_gtdt_desc.gtdt = gtdt;
> +	acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
> +
> +	if (table->revision < 2)
> +		pr_debug("Revision:%d doesn't support Platform Timers.\n",
> +			 table->revision);

GTDT table revision is updated to 2 in ACPI 5.1, we will
not support ACPI version under 5.1 and disable ACPI in FADT
parse before this code is called, so if we get revision
<2 here, I think we need to print warning (we need to keep
the firmware stick to the spec on ARM64).

> +	else if (!gtdt->platform_timer_count)
> +		pr_debug("No Platform Timer.\n");
> +	else
> +		timer_count = gtdt->platform_timer_count;
> +
> +	if (timer_count) {
> +		platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
> +		if (platform_timer < (void *)table +
> +				     sizeof(struct acpi_table_gtdt)) {
> +			pr_err(FW_BUG "invalid timer data.\n");

It's ok but I didn't see other ACPI tables parsing did this check,
maybe we can just remove it :)

> +			timer_count = 0;
> +			platform_timer = NULL;
> +			ret = -EINVAL;
> +		}
> +	}
> +
> +	acpi_gtdt_desc.platform_timer = platform_timer;
> +	if (platform_timer_count)
> +		*platform_timer_count = timer_count;

Then the code will much simple:

if (gtdt->platform_timer_count) {
	acpi_gtdt_desc.platform_timer = (void *)gtdt + gtdt->platform_timer_offset;
	if (platform_timer_count)
		*platform_timer_count = gtdt->platform_timer_count;
}

return 0;

and remove ret, timer_count and platform_timer.

Thanks
Hanjun

^ permalink raw reply

* [PATCH v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT support for memory-mapped timer
From: Hanjun Guo @ 2017-01-19  9:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170118132541.8989-17-fu.wei@linaro.org>

On 2017/1/18 21:25, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> The patch add memory-mapped timer register support by using the
> information provided by the new GTDT driver of ACPI.
>
> Signed-off-by: Fu Wei <fu.wei@linaro.org>
> ---
>  drivers/clocksource/arm_arch_timer.c | 35 ++++++++++++++++++++++++++++++++---
>  1 file changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 79dc004..7ca2da7 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -1077,10 +1077,36 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
>  		       arch_timer_mem_of_init);
>
>  #ifdef CONFIG_ACPI_GTDT
> -/* Initialize per-processor generic timer */
> +static int __init arch_timer_mem_acpi_init(int platform_timer_count)
> +{
> +	struct arch_timer_mem *timer_mem;
> +	int timer_count, i, ret;
> +

if (!platform_timer_count)
	return 0;

Did I miss something?

Thanks
Hanjun

> +	timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
> +			    GFP_KERNEL);
> +	if (!timer_mem)
> +		return -ENOMEM;
> +
> +	ret = acpi_arch_timer_mem_init(timer_mem, &timer_count);
> +	if (ret || !timer_count)
> +		goto error;
> +
> +	for (i = 0; i < timer_count; i++) {
> +		ret = arch_timer_mem_init(timer_mem);
> +		if (!ret)
> +			break;
> +		timer_mem++;
> +	}
> +
> +error:
> +	kfree(timer_mem);
> +	return ret;
> +}
> +
> +/* Initialize per-processor generic timer and memory-mapped timer(if present) */
>  static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>  {
> -	int ret;
> +	int ret, platform_timer_count;
>
>  	if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
>  		pr_warn("already initialized, skipping\n");
> @@ -1089,7 +1115,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>
>  	arch_timers_present |= ARCH_TIMER_TYPE_CP15;
>
> -	ret = acpi_gtdt_init(table, NULL);
> +	ret = acpi_gtdt_init(table, &platform_timer_count);
>  	if (ret) {
>  		pr_err("Failed to init GTDT table.\n");
>  		return ret;
> @@ -1122,6 +1148,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>  	if (ret)
>  		return ret;
>
> +	if (arch_timer_mem_acpi_init(platform_timer_count))
> +		pr_err("Failed to initialize memory-mapped timer.\n");
> +
>  	return arch_timer_common_init();
>  }
>  CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
>

^ permalink raw reply

* [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer
From: Hanjun Guo @ 2017-01-19  9:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170118132541.8989-1-fu.wei@linaro.org>

Hi Fuwei,

On 2017/1/18 21:25, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei@linaro.org>
>
> This patchset:
>     (1)Preparation for adding GTDT support in arm_arch_timer:
>         1. Clean up printk() usage
>         2. Rename the type macros
>         3. Rename the PPI enum & enum values
>         4. Move the type macro and PPI enum into the header file
>         5. Add new enum for SPIs
>         6. Rework PPI determination;
>         7. Rework counter frequency detection;
>         8. Refactor arch_timer_needs_probing, move it into DT init call
>         9. Introduce some new structs and refactor the MMIO timer init code
>         for reusing some common code.
>
>     (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>     Parse all kinds of timer in GTDT table of ACPI:arch timer,
>     memory-mapped timer and SBSA Generic Watchdog timer.
>     This driver can help to simplify all the relevant timer drivers,
>     and separate all the ACPI GTDT knowledge from them.
>
>     (3)Simplify ACPI code for arm_arch_timer
>
>     (4)Add GTDT support for ARM memory-mapped timer.
>
> This patchset has been tested on the following platforms with ACPI enabled:
>     (1)ARM Foundation v8 model
>
> Changelog:
> v20: https://lkml.org/lkml/2017/1/18/
>      Reorder the first 4 patches and split the 4th patches.
>      Leave CNTHCTL_* as they originally were.
>      Fix the bug in arch_timer_select_ppi.
>      Split "Rework counter frequency detection" patch.
>      Rework the arch_timer_detect_rate function.
>      Improve the commit message of "Refactor MMIO timer probing".
>      Rebase to 4.10.0-rc4

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

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

Thanks
Hanjun

^ permalink raw reply

* [linux-sunxi] [PATCH 1/2] drivers: pinctrl: add driver for Allwinner H5 SoC
From: Linus Walleij @ 2017-01-19  9:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87a535d3-1170-c388-ce7d-4921e69f4cab@arm.com>

On Wed, Jan 18, 2017 at 10:44 AM, Andre Przywara <andre.przywara@arm.com> wrote:

> Any future SoCs could then just use that compatible and would describe
> the SoC details in the DT, like it's meant to be and like we do already,
> but extended by putting the mux value in there as well.
> So the only kernel contribution would then be the DT, really, (...)

Your different positions have existed since the inception of the
pinctrl subsystem:

- One camp (myself included) wanted to describe the hardware mostly
  in the driver: functions, groups etc are tables in the driver file.

- Another camp (OMAP included) think that the device tree should take
  store most things: groups functions, etc.

What we know for sure should be described in DT is how different
IP blocks are connected in an SoC (e.g. interrupts, clocks, DMA
channels, regulators) and on the of course outside of the SoC, on
the board.

The question here is whether the way a hardware has instantiated
a certain IP block when doing physical compilation in their
Verilog, VHDL or SystemC files, is something that should be
described in DT.

Many companies have developed tools to
extract this data from their hardware design files and provide
it to developers as a blob och incomprehensible data, such was
the situation for OMAP for example. So to them it made most
sense to implement pinctrl-single, just parsing that data into
DTS(I) files.

Other companies (such as STMicroelectronics) instead put a
team of people to write a datasheet with a special chapter
on how pins etc are connected, and programmers are given
this datasheet and need to again type in the data and define
groups etc.

Whether parametrization of a HW block should be done in the
driver file from the compatible string or with custom attributes
in the node is not a simple answer to the question. OF is vague
on this kind of things: both solutions exist.

Allwinner and Qualcomm authors faced a situation such as that
they were given a code dump and no datasheet and no data
tables either. That creates an especially complicated situation
where none of the above scenarios apply.

What we/you need to ask: what is most helpful for the Allwinner
community? What makes the barrier low for new contributions,
and makes it easiest to cooperate?

I try to live by this motto from IETF:

   "rough consensus and running code"

Please do the same.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH V7 1/4] Documentation/devicetree/bindings: b850v3_lvds_dp
From: Peter Senna Tschudin @ 2017-01-19  9:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2338437.Vj2otdygnZ@avalon>

On Thu, Jan 19, 2017 at 10:17:45AM +0200, Laurent Pinchart wrote:
> Hi Peter,
> 
> On Thursday 19 Jan 2017 09:12:14 Peter Senna Tschudin wrote:
> > On Wed, Jan 18, 2017 at 11:10:58PM +0200, Laurent Pinchart wrote:
> > > On Monday 16 Jan 2017 09:37:11 Peter Senna Tschudin wrote:
> > >> On Tue, Jan 10, 2017 at 11:04:58PM +0200, Laurent Pinchart wrote:
> > >>> On Saturday 07 Jan 2017 01:29:52 Peter Senna Tschudin wrote:
> > >>>> On 04 January, 2017 21:39 CET, Rob Herring wrote:
> > >>>>> On Tue, Jan 3, 2017 at 5:34 PM, Peter Senna Tschudin wrote:
> > >>>>>> On 03 January, 2017 23:51 CET, Rob Herring <robh@kernel.org> wrote:
> > >>>>>>> On Sun, Jan 01, 2017 at 09:24:29PM +0100, Peter Senna Tschudin 
> wrote:
> > >>>>>>>> Devicetree bindings documentation for the GE B850v3 LVDS/DP++
> > >>>>>>>> display bridge.
> > >>>>>>>> 
> > >>>>>>>> Cc: Martyn Welch <martyn.welch@collabora.co.uk>
> > >>>>>>>> Cc: Martin Donnelly <martin.donnelly@ge.com>
> > >>>>>>>> Cc: Javier Martinez Canillas <javier@dowhile0.org>
> > >>>>>>>> Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> > >>>>>>>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> > >>>>>>>> Cc: Rob Herring <robh@kernel.org>
> > >>>>>>>> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > >>>>>>>> Signed-off-by: Peter Senna Tschudin <peter.senna@collabora.com>
> > >>>>>>>> ---
> > >>>>>>>> There was an Acked-by from Rob Herring <robh@kernel.org> for V6,
> > >>>>>>>> but I changed the bindings to use i2c_new_secondary_device() so I
> > >>>>>>>> removed it from the commit message.
> > 
> > [...]
> > 
> > >>>>>>>>  .../devicetree/bindings/ge/b850v3-lvds-dp.txt      | 39 +++++++++
> > >>>>>>> 
> > >>>>>>> Isn't '-lvds-dp' redundant? The part# should be enough.
> > >>>>>> 
> > >>>>>> b850v3 is the name of the product, this is why the proposed name.
> > >>>>>> What about, b850v3-dp2 dp2 indicating the second DP output?
> > >>>>> 
> > >>>>> Humm, b850v3 is the board name? This node should be the name of the
> > >>>>> bridge chip.
> > >>>> 
> > >>>> From the cover letter:
> > >>>> 
> > >>>> -- // --
> > >>>> There are two physical bridges on the video signal pipeline: a
> > >>>> STDP4028(LVDS to DP) and a STDP2690(DP to DP++).  The hardware and
> > >>>> firmware made it complicated for this binding to comprise two device
> > >>>> tree nodes, as the design goal is to configure both bridges based on
> > >>>> the LVDS signal, which leave the driver powerless to control the
> > >>>> video processing pipeline. The two bridges behaves as a single bridge,
> > >>>> and the driver is only needed for telling the host about EDID / HPD,
> > >>>> and for giving the host powers to ack interrupts. The video signal
> > >>>> pipeline
> > >>>> 
> > >>>> is as follows:
> > >>>>   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video
> > >>>>   output
> > >>>> 
> > >>>> -- // --
> > >>> 
> > >>> You forgot to prefix your patch series with [HACK] ;-)
> > >>> 
> > >>> How about fixing the issues that make the two DT nodes solution
> > >>> difficult ? What are they ?
> > >> 
> > >> The Firmware and the hardware design. Both bridges, with stock firmware,
> > >> are fully capable of providig EDID information and handling interrupts.
> > >> But on this specific design, with this specific firmware, I need to read
> > >> EDID from one bridge, and handle interrupts on the other.
> > > 
> > > Which firmware are you talking about ? Firmware running on the bridges, or
> > > somewhere else ?
> > 
> > Each bridge has it's own external flash containing a binary firmware.
> > The goal of the firmware is to configure the output end based on the
> > input end. This is part of what makes handling EDID and HPD challenging.
> > 
> > >> Back when I was starting the development I could not come up with a
> > >> proper way to split EDID and interrupts between two bridges in a way
> > >> that would result in a fully functional connector. Did I miss something?
> > > 
> > > You didn't, we did :-) I've been telling for quite some time now that we
> > > must decouple bridges from connectors, and this is another example of why
> > > we have such a need. Bridges should expose additional functions needed to
> > > implement connector operations, and the connector should be instantiated
> > > by the display driver with the help of bridge operations. You could then
> > > create a connector that relies on one bridge to read the EDID and on the
> > > other bridge to handle HPD.
> > 
> > Ah thanks. So for now the single DT node approach is acceptable, right?
> > The problem is that even if the driver is getting better on each
> > iteration, the single DT node for two chips issue comes back often and I
> > believe is _the_ issue preventing the driver from getting upstream. V1
> > was sent ~ 8 months ago...
> > 
> > Can I have some blessing on the single DT node approach for now?
> 
> With the "DT as an ABI" approach, I'm afraid not. Temporary hacks are 
> acceptable on the driver side, but you need two nodes in DT.

So can I make two node DT "in the right way" and work around current
connectors vs. bridge limitations on the driver side? This seems to be
doable.

Then I could fix bridge API, with my own driver and update API clients
affected by the change...

> 
> > I'm one of the 3 proposed maintainers for the driver, and I'm willing to
> > maintain the driver on the long run, as is the same with the other two
> > proposed maintainers. So when the time to split the node in two comes,
> > we will be around, and willing to do it ourselves.
> 
> How about putting that team of 3 maintainers to work on fixing the problem in 
> the bridge API ? :-)

Guess you would be a good lawyer! My point was not exactly that we could
work in parallel. Point was that there is redundancy in case one or two
of us loose interest. But nice try! :-)

Chances of having resources to fix bridge API and clients were better 6
months ago, but let me see what I can get.  Last blocking issue was the
migration to atomic, now this. I'm going to need to answer what the next
blocking issue is going to be.

Actually in these ~8 months one bit of the required changes was
accepted: dc80d7038883, but this was generic and not related to our
specific use case.

Thanks!

Peter

> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

^ permalink raw reply

* [PATCH 4/6] arm64: dts: mt8173: add reference clock for usb
From: Greg Kroah-Hartman @ 2017-01-19  9:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484719707-12107-4-git-send-email-chunfeng.yun@mediatek.com>

On Wed, Jan 18, 2017 at 02:08:25PM +0800, Chunfeng Yun wrote:
> add 26M reference clock for ssusb and xhci nodes
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi |    6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)

This patch doesn't apply to my tree :(

^ permalink raw reply

* [PATCH v20 08/17] clocksource/drivers/arm_arch_timer: Rework counter frequency detection.
From: Fu Wei @ 2017-01-19  9:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cafa8c7a-9c7c-51ba-5566-0cfe1fe6f764@linaro.org>

Hi Hanjun,

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

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

Here arch_timer_rate is not zero.

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

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

^ permalink raw reply

* [PATCH v20 11/17] clocksource/drivers/arm_arch_timer: Introduce some new structs to prepare for GTDT
From: Fu Wei @ 2017-01-19  9:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a47f2474-fb29-9217-3de1-6e2a6a36f21f@linaro.org>

Hi Hanjun,

On 19 January 2017 at 16:28, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> On 2017/1/18 21:25, fu.wei at linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The patch introduce two new structs: arch_timer_mem, arch_timer_mem_frame.
>> And also introduce a new define: ARCH_TIMER_MEM_MAX_FRAMES
>>
>> These will be used for refactoring the memory-mapped timer init code to
>> prepare for GTDT
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  include/clocksource/arm_arch_timer.h | 17 +++++++++++++++++
>>  1 file changed, 17 insertions(+)
>>
>> diff --git a/include/clocksource/arm_arch_timer.h
>> b/include/clocksource/arm_arch_timer.h
>> index 4a98c06..b7dd185 100644
>> --- a/include/clocksource/arm_arch_timer.h
>> +++ b/include/clocksource/arm_arch_timer.h
>> @@ -57,6 +57,8 @@ enum arch_timer_spi_nr {
>>  #define ARCH_TIMER_MEM_PHYS_ACCESS     2
>>  #define ARCH_TIMER_MEM_VIRT_ACCESS     3
>>
>> +#define ARCH_TIMER_MEM_MAX_FRAMES      8
>> +
>>  #define ARCH_TIMER_USR_PCT_ACCESS_EN   (1 << 0) /* physical counter */
>>  #define ARCH_TIMER_USR_VCT_ACCESS_EN   (1 << 1) /* virtual counter */
>>  #define ARCH_TIMER_VIRT_EVT_EN         (1 << 2)
>> @@ -72,6 +74,21 @@ struct arch_timer_kvm_info {
>>         int virtual_irq;
>>  };
>>
>> +struct arch_timer_mem_frame {
>> +       int frame_nr;
>> +       phys_addr_t cntbase;
>> +       size_t size;
>> +       int phys_irq;
>> +       int virt_irq;
>> +};
>> +
>> +struct arch_timer_mem {
>> +       phys_addr_t cntctlbase;
>> +       size_t size;
>> +       int num_frames;
>> +       struct arch_timer_mem_frame frame[ARCH_TIMER_MEM_MAX_FRAMES];
>> +};
>
>
> Since struct is introduced but not used in this patch, how about
> squash it with patch 12/17?

In the previous patchset, I have been suggested that I should split it out.

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

^ permalink raw reply

* [PATCH 0/5] meson-gx: reset RGMII PHYs and configure TX delay
From: Jerome Brunet @ 2017-01-19  9:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAFBinCACbeZPRXQO4OA5mJdGRvMkQoUmQEAKCi8KU2ZvrspF6A@mail.gmail.com>

On Wed, 2017-01-18 at 20:40 +0100, Martin Blumenstingl wrote:
> Kevin,
> 
> On Wed, Jan 18, 2017 at 8:28 PM, Kevin Hilman <khilman@baylibre.com>
> wrote:
> > 
> > Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
> > 
> > > 
> > > This partially fixes the 1000Mbit/s ethernet TX throughput issues
> > > (on
> > > networks which are not affected by the EEE problem, as reported
> > > here:
> > 
> > Based on the discussions with Jerome, I'm dropping this series from
> > the
> > v4.11/dt64 branch for now.
> what is you opinion on having the MDIO node in meson-gx (and keeping
> GXBB and GXL/GXM consistent) vs not having PHY autodetection for GXBB
> (= not having the MDIO in meson-gx)?
> I cannot send a v2 until we have a decision for this
> 
> > 
> > This series also had a small conflict with Jerome's fix[1] for the
> > odroid-c2, so please rebase any updates here on my v4.10/fixes
> > branch.
> will keep that in mind, noted.
Most this patch can go away with your patch.
Just make sure to keep "eee-broken-1000t;" in the odroidc2 dtsi and
it'll be OK.

> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply

* [PATCH] arm64: defconfig: disable CONFIG_DEVMEM
From: Will Deacon @ 2017-01-19  9:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAF7UmSxMqKodEZfqheRsJxsM_R1yZHJaXMnyLyJwqULRz1xH=A@mail.gmail.com>

On Wed, Jan 18, 2017 at 05:58:05PM +0000, Leif Lindholm wrote:
> On 15 January 2017 at 12:42, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> > On Fri, Jan 13, 2017 at 11:48:01AM +0000, Will Deacon wrote:
> >> On Fri, Jan 13, 2017 at 11:37:34AM +0000, Leif Lindholm wrote:
> >> > /dev/mem is the opposite of what an operating system is for.
> >> > Additionally, on arm* it opens up for denial-of-service attacks from
> >> > userspace. So leave it disabled by default, requiring people who need
> >> > it to enable it explicitly.
> >>
> >> I really like the idea, but are we sure that nothing common breaks without
> >> this? For example, does Debian still boot nicely with this patch applied?
> >
> > Getting distros to not have to shop around for config fragments in
> > order to be able to a stable system is one of my main purposes of this
> > patch.
> >
> > Since Debian just published a 4.9 kernel, I gave that a spin (both DT
> > and ACPI). No issues.
> 
> Will, any comments?

Nope; fine by me. arm-soc usually pick these up.

FWIW, I did do a Debian CodeSearch for /dev/mem and there were more hits
than I was hoping for. However, much of the code looked either:

 (a) Broken anyway
 (b) Not relevant to arm64
 (c) /dev/mem was just a string in a comment or something

There are a couple of crazy projects that appear to use /dev/mem to
implement a heap, but I really couldn't figure out how that worked.

Will

^ permalink raw reply

* [PATCH v29 3/9] arm64: kdump: reserve memory for crash dump kernel
From: AKASHI Takahiro @ 2017-01-19  9:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170117115441.GC11939@leverpostej>

On Tue, Jan 17, 2017 at 11:54:42AM +0000, Mark Rutland wrote:
> On Tue, Jan 17, 2017 at 05:20:44PM +0900, AKASHI Takahiro wrote:
> > On Fri, Jan 13, 2017 at 11:39:15AM +0000, Mark Rutland wrote:
> > > Great! I think it would be better to follow the approach of
> > > mark_rodata_ro(), rather than opening up set_memory_*(), but otherwise,
> > > it looks like it should work.
> > 
> > I'm not quite sure what the approach of mark_rodata_ro() means, but
> > I found that using create_mapping_late() may cause two problems:
> > 
> > 1) it fails when PTE_CONT bits mismatch between an old and new mmu entry.
> >    This can happen, say, if the memory range for crash dump kernel
> >    starts in the mid of _continuous_ pages.
> 
> That should only happen if we try to remap a segment different to what
> we originally mapped.
> 
> I was intending that we'd explicitly map the reserved region separately
> in the boot path, like we do for kernel segments in map_kernel(). We
> would allow sections and/or CONT entires. 
> 
> Then, in __map_memblock() we'd then skip that range as we do for the
> linear map alias of the kernel image.
> 
> That way, we can later use create_mapping_late for that same region, and
> it should handle sections and/or CONT entries in the exact same way as
> it does for the kernel image segments in mark_rodata_ro().

I see.
Which one do you prefer, yours above or my (second) solution?
Either way, they do almost the same thing in terms of mapping.

> > 2) The control code page, of one-page size, is still written out in
> >    machine_kexec() which is called at a crash, and this means that
> >    the range must be writable even after kexec_load(), but
> >    create_mapping_late() does not handle a case of changing attributes
> >    for a single page which is in _section_ mapping.
> >    We cannot make single-page mapping for the control page since the address
> >    of that page is not determined at the boot time.
> 
> That is a problem. I'm not sure I follow how set_memory_*() helps here
> though?
> 
> > As for (1), we need to call memblock_isolate_range() to make the region
> > an independent one.
> > 
> > > Either way, this still leaves us with an RO alias on crashed cores (and
> > > potential cache attribute mismatches in future). Do we need to read from
> > > the region later,
> > 
> > I believe not, but the region must be _writable_ as I mentioned in (2) above.
> > To avoid this issue, we have to move copying the control code page
> > to machine_kexec_prepare() which is called in kexec_load() and so
> > the region is writable anyway then.
> > I want Geoff to affirm that this change is safe.
> > 
> > (See my second solution below.)
> 
> From a quick scan that looks ok.
> 
> > > or could we unmap it entirely?
> > 
> > given the change above, I think we can.

I'm now asking Geoff ...

> 
> Great!
>
> > Is there any code to re-use especially for unmapping?
> 
> I don't think we have much code useful for unmapping. We could re-use 
> create_mapping_late for this, passing a set of prot bits that means the
> entries are invalid (e.g. have a PAGE_KERNEL_INVALID).

Do you really think that we should totally invalidate mmu entries?
I guess that, given proper cache & TLB flush operations, RO attribute is
good enough for memory consistency, no?
(None accesses the region, as I said, except in the case of re-loading
crash dump kernel though.)

> We'd have to perform the TLB invalidation ourselves, but that shouldn't
> be too painful.

Do we need to invalidate TLBs not only before but also after changing
permission attributes as make_rodata_ro() does?

-Takahiro AKASHI

> Thanks,
> Mark.
> 
> > ===8<===
> > diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
> > index c0fc3d458195..80a52e9aaf73 100644
> > --- a/arch/arm64/kernel/machine_kexec.c
> > +++ b/arch/arm64/kernel/machine_kexec.c
> > @@ -26,8 +26,6 @@
> >  extern const unsigned char arm64_relocate_new_kernel[];
> >  extern const unsigned long arm64_relocate_new_kernel_size;
> >  
> > -static unsigned long kimage_start;
> > -
> >  /**
> >   * kexec_image_info - For debugging output.
> >   */
> > @@ -68,7 +66,7 @@ void machine_kexec_cleanup(struct kimage *kimage)
> >   */
> >  int machine_kexec_prepare(struct kimage *kimage)
> >  {
> > -	kimage_start = kimage->start;
> > +	void *reboot_code_buffer;
> >  
> >  	kexec_image_info(kimage);
> >  
> > @@ -77,6 +75,21 @@ int machine_kexec_prepare(struct kimage *kimage)
> >  		return -EBUSY;
> >  	}
> >  
> > +	reboot_code_buffer =
> > +			phys_to_virt(page_to_phys(kimage->control_code_page));
> > +
> > +	/*
> > +	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
> > +	 * after the kernel is shut down.
> > +	 */
> > +	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
> > +		arm64_relocate_new_kernel_size);
> > +
> > +	/* Flush the reboot_code_buffer in preparation for its execution. */
> > +	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
> > +	flush_icache_range((uintptr_t)reboot_code_buffer,
> > +		arm64_relocate_new_kernel_size);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -147,7 +160,6 @@ static void kexec_segment_flush(const struct kimage *kimage)
> >  void machine_kexec(struct kimage *kimage)
> >  {
> >  	phys_addr_t reboot_code_buffer_phys;
> > -	void *reboot_code_buffer;
> >  
> >  	/*
> >  	 * New cpus may have become stuck_in_kernel after we loaded the image.
> > @@ -156,7 +168,6 @@ void machine_kexec(struct kimage *kimage)
> >  			!WARN_ON(kimage == kexec_crash_image));
> >  
> >  	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
> > -	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
> >  
> >  	kexec_image_info(kimage);
> >  
> > @@ -164,26 +175,12 @@ void machine_kexec(struct kimage *kimage)
> >  		kimage->control_code_page);
> >  	pr_debug("%s:%d: reboot_code_buffer_phys:  %pa\n", __func__, __LINE__,
> >  		&reboot_code_buffer_phys);
> > -	pr_debug("%s:%d: reboot_code_buffer:       %p\n", __func__, __LINE__,
> > -		reboot_code_buffer);
> >  	pr_debug("%s:%d: relocate_new_kernel:      %p\n", __func__, __LINE__,
> >  		arm64_relocate_new_kernel);
> >  	pr_debug("%s:%d: relocate_new_kernel_size: 0x%lx(%lu) bytes\n",
> >  		__func__, __LINE__, arm64_relocate_new_kernel_size,
> >  		arm64_relocate_new_kernel_size);
> >  
> > -	/*
> > -	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
> > -	 * after the kernel is shut down.
> > -	 */
> > -	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
> > -		arm64_relocate_new_kernel_size);
> > -
> > -	/* Flush the reboot_code_buffer in preparation for its execution. */
> > -	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
> > -	flush_icache_range((uintptr_t)reboot_code_buffer,
> > -		arm64_relocate_new_kernel_size);
> > -
> >  	/* Flush the kimage list and its buffers. */
> >  	kexec_list_flush(kimage);
> >  
> > @@ -206,7 +203,7 @@ void machine_kexec(struct kimage *kimage)
> >  	 */
> >  
> >  	cpu_soft_restart(kimage != kexec_crash_image,
> > -		reboot_code_buffer_phys, kimage->head, kimage_start, 0);
> > +		reboot_code_buffer_phys, kimage->head, kimage->start, 0);
> >  
> >  	BUG(); /* Should never get here. */
> >  }
> > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> > index 569ec3325bc8..e4cc170edc0c 100644
> > --- a/arch/arm64/mm/init.c
> > +++ b/arch/arm64/mm/init.c
> > @@ -90,6 +90,7 @@ early_param("initrd", early_initrd);
> >  static void __init reserve_crashkernel(void)
> >  {
> >  	unsigned long long crash_size, crash_base;
> > +	int start_rgn, end_rgn;
> >  	int ret;
> >  
> >  	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
> > @@ -120,6 +121,8 @@ static void __init reserve_crashkernel(void)
> >  			return;
> >  		}
> >  	}
> > +	memblock_isolate_range(&memblock.memory, crash_base, crash_size,
> > +			&start_rgn, &end_rgn);
> >  	memblock_reserve(crash_base, crash_size);
> >  
> >  	pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",
> > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> > index 17243e43184e..b7c75845407a 100644
> > --- a/arch/arm64/mm/mmu.c
> > +++ b/arch/arm64/mm/mmu.c
> > @@ -22,6 +22,8 @@
> >  #include <linux/kernel.h>
> >  #include <linux/errno.h>
> >  #include <linux/init.h>
> > +#include <linux/ioport.h>
> > +#include <linux/kexec.h>
> >  #include <linux/libfdt.h>
> >  #include <linux/mman.h>
> >  #include <linux/nodemask.h>
> > @@ -817,3 +819,27 @@ int pmd_clear_huge(pmd_t *pmd)
> >  	pmd_clear(pmd);
> >  	return 1;
> >  }
> > +
> > +#ifdef CONFIG_KEXEC_CORE
> > +void arch_kexec_protect_crashkres(void)
> > +{
> > +	flush_tlb_all();
> > +
> > +	create_mapping_late(crashk_res.start, __phys_to_virt(crashk_res.start),
> > +			    resource_size(&crashk_res), PAGE_KERNEL_RO);
> > +
> > +	/* flush the TLBs after updating live kernel mappings */
> > +	flush_tlb_all();
> > +}
> > +
> > +void arch_kexec_unprotect_crashkres(void)
> > +{
> > +	flush_tlb_all();
> > +
> > +	create_mapping_late(crashk_res.start, __phys_to_virt(crashk_res.start),
> > +			    resource_size(&crashk_res), PAGE_KERNEL);
> > +
> > +	/* flush the TLBs after updating live kernel mappings */
> > +	flush_tlb_all();
> > +}
> > +#endif
> > ===>8===

^ permalink raw reply

* [PATCH 2/2] ARM: dts: rockchip: add dts for RK3288-Tinker board
From: Heiko Stuebner @ 2017-01-19  9:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484791919-4665-3-git-send-email-eddie.cai@rock-chips.com>

Hi Eddie,

Am Donnerstag, 19. Januar 2017, 10:11:59 CET schrieb Eddie Cai:
> This patch add basic support for RK3288-Tinker board. We can boot in to
> rootfs with this patch.
> 
> Signed-off-by: Eddie Cai <eddie.cai@rock-chips.com>

looks good in general, just some small question down below.

[...]

> +	/*
> +	 * NOTE: vcc_sd isn't hooked up on v1.0 boards where power comes from
> +	 * vcc_io directly.  Those boards won't be able to power cycle SD cards
> +	 * but it shouldn't hurt to toggle this pin there anyway.
> +	 */

just to clarify, later board will have that pin connected, right?

> +	vcc_sd: sdmmc-regulator {
> +		compatible = "regulator-fixed";
> +		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sdmmc_pwr>;
> +		regulator-name = "vcc_sd";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <100000>;
> +		vin-supply = <&vcc_io>;
> +	};
> +};

[...]

> +&hdmi {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	#sound-dai-cells = <0>;
> +	ddc-i2c-bus = <&i2c5>;
> +	status = "okay";
> +	/* Don't use vopl for HDMI */
> +	ports {
> +		hdmi_in: port {
> +			/delete-node/ endpoint at 1;
> +		};

what is the reason for this? You enable both VOPs below and the linux display 
subsystem should be able to select an appropriate VOP for output just fine on 
its own. So there should be no reason for capping the hdmi's connection to one 
of the vops.

> +	};
> +};

[...]

> +&usb_host0_ehci {
> +	no-relinquish-port;

This seems like an unused/undocumented property

> +	status = "okay";
> +};

[...]

> +&vopl {
> +	status = "okay";
> +	/* Don't use vopl for HDMI */
> +	vopl_out: port {
> +		/delete-node/ endpoint at 0;
> +	};

see comment at the hdmi node

> +};


Thanks
Heiko

^ permalink raw reply

* [PATCH V10 3/3] irqchip: qcom: Add IRQ combiner driver
From: Marc Zyngier @ 2017-01-19 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484757988-23739-4-git-send-email-agustinv@codeaurora.org>

Hi Agustin,

On 18/01/17 16:46, Agustin Vega-Frias wrote:
> Driver for interrupt combiners in the Top-level Control and Status
> Registers (TCSR) hardware block in Qualcomm Technologies chips.
> 
> An interrupt combiner in this block combines a set of interrupts by
> OR'ing the individual interrupt signals into a summary interrupt
> signal routed to a parent interrupt controller, and provides read-
> only, 32-bit registers to query the status of individual interrupts.
> The status bit for IRQ n is bit (n % 32) within register (n / 32)
> of the given combiner. Thus, each combiner can be described as a set
> of register offsets and the number of IRQs managed.
> 
> Signed-off-by: Agustin Vega-Frias <agustinv@codeaurora.org>
> ---
>  drivers/irqchip/Kconfig             |   9 +
>  drivers/irqchip/Makefile            |   1 +
>  drivers/irqchip/qcom-irq-combiner.c | 319 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 329 insertions(+)
>  create mode 100644 drivers/irqchip/qcom-irq-combiner.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index ae96731..125528f 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -283,3 +283,12 @@ config EZNPS_GIC
>  config STM32_EXTI
>  	bool
>  	select IRQ_DOMAIN
> +
> +config QCOM_IRQ_COMBINER
> +	bool "QCOM IRQ combiner support"
> +	depends on ARCH_QCOM && ACPI
> +	select IRQ_DOMAIN
> +	select IRQ_DOMAIN_HIERARCHY
> +	help
> +	  Say yes here to add support for the IRQ combiner devices embedded
> +	  in Qualcomm Technologies chips.
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 0e55d94..5a531863 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -75,3 +75,4 @@ obj-$(CONFIG_LS_SCFG_MSI)		+= irq-ls-scfg-msi.o
>  obj-$(CONFIG_EZNPS_GIC)			+= irq-eznps.o
>  obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o
>  obj-$(CONFIG_STM32_EXTI) 		+= irq-stm32-exti.o
> +obj-$(CONFIG_QCOM_IRQ_COMBINER)		+= qcom-irq-combiner.o
> diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c
> new file mode 100644
> index 0000000..b7f0631
> --- /dev/null
> +++ b/drivers/irqchip/qcom-irq-combiner.c
> @@ -0,0 +1,319 @@
> +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * Driver for interrupt combiners in the Top-level Control and Status
> + * Registers (TCSR) hardware block in Qualcomm Technologies chips.
> + * An interrupt combiner in this block combines a set of interrupts by
> + * OR'ing the individual interrupt signals into a summary interrupt
> + * signal routed to a parent interrupt controller, and provides read-
> + * only, 32-bit registers to query the status of individual interrupts.
> + * The status bit for IRQ n is bit (n % 32) within register (n / 32)
> + * of the given combiner. Thus, each combiner can be described as a set
> + * of register offsets and the number of IRQs managed.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/platform_device.h>
> +
> +#define REG_SIZE 32
> +
> +struct combiner_reg {
> +	void __iomem *addr;
> +	unsigned long mask;
> +};
> +
> +struct combiner {
> +	struct irq_domain   *domain;
> +	int                 parent_irq;
> +	u32                 nirqs;
> +	u32                 nregs;
> +	struct combiner_reg regs[0];
> +};
> +
> +static inline u32 irq_register(int irq)
> +{
> +	return irq / REG_SIZE;
> +}
> +
> +static inline u32 irq_bit(int irq)
> +{
> +	return irq % REG_SIZE;
> +
> +}
> +
> +static inline int irq_nr(u32 reg, u32 bit)
> +{
> +	return reg * REG_SIZE + bit;
> +}
> +
> +/*
> + * Handler for the cascaded IRQ.
> + */
> +static void combiner_handle_irq(struct irq_desc *desc)
> +{
> +	struct combiner *combiner = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	u32 reg;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	for (reg = 0; reg < combiner->nregs; reg++) {
> +		int virq;
> +		int hwirq;
> +		u32 bit;
> +		u32 status;
> +
> +		if (combiner->regs[reg].mask == 0) {
> +			WARN_ON(readl_relaxed(combiner->regs[reg].addr) != 0);

Since we've now established that you couldn't really mask interrupts at 
all, screaming like this is just going to make the matter worse. Please 
drop this, or at the very least ratelimit it. Also, this is really 
tortuous since your 'mask' is actually an 'enable' (you only accept an 
interrupt if the bit is set).

But let's look at what you're testing here: If no interrupt is enabled, 
scream if something is pending. I really wonder what you get by doing 
so -- pending and masked interrupts are extremely common, and because 
you cannot handle them doesn't mean you should kill the machine (which 
your WARN_ON is guaranteed to do). Also, this should be consolidated 
with the code below...

> +			continue;
> +		}
> +
> +		status = readl_relaxed(combiner->regs[reg].addr);
> +		WARN_ON((status & ~combiner->regs[reg].mask) != 0);
> +		status &= combiner->regs[reg].mask;

Same thing: protesting against masked+pending interrupts is futile. If 
they happen, your CPU is wedged anyway. I'd suggest that you drop the 0 
test case (which doesn't save anything anyway):

		#define pr_fmt(fmt)     "QCOM80B1:" fmt

		bit = readl_relaxed(combiner->regs[reg].addr);
		status = bit & combiner->regs[reg].mask;
		if (!status)
			pr_warn_ratelimited("screaming interrupt (%08x %08x), CPU%d wedged\n", 
					    bit, combiner->regs[reg].mask, smp_processor_id());

and that's it, as the rest of the code already takes care of the status==0
case. Optionally, you could disable the parent interrupt and kill all the
other devices connected to the same combiner, since that's your only
alternative to loosing a CPU.

> +
> +		while (status) {
> +			bit = __ffs(status);
> +			status &= ~(1 << bit);
> +			hwirq = irq_nr(reg, bit);
> +			virq = irq_find_mapping(combiner->domain, hwirq);
> +			if (virq > 0)
> +				generic_handle_irq(virq);
> +
> +		}
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
> +/*
> + * irqchip callbacks
> + */
> +
> +static void combiner_irq_chip_mask_irq(struct irq_data *data)
> +{
> +	struct combiner *combiner = irq_data_get_irq_chip_data(data);
> +	struct combiner_reg *reg = combiner->regs + irq_register(data->hwirq);
> +
> +	clear_bit(irq_bit(data->hwirq), &reg->mask);
> +}
> +
> +static void combiner_irq_chip_unmask_irq(struct irq_data *data)
> +{
> +	struct combiner *combiner = irq_data_get_irq_chip_data(data);
> +	struct combiner_reg *reg = combiner->regs + irq_register(data->hwirq);
> +
> +	set_bit(irq_bit(data->hwirq), &reg->mask);
> +}

I'd still advocate for 'mask' to be renamed 'enabled', or to have the
bits flipped the other way around. Your call.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCHv4 3/5] pinctrl: mvebu: pinctrl driver for 98DX3236 SoC
From: Russell King - ARM Linux @ 2017-01-19 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170113091222.7132-4-chris.packham@alliedtelesis.co.nz>

On Fri, Jan 13, 2017 at 10:12:18PM +1300, Chris Packham wrote:
> +static struct mvebu_mpp_ctrl mv98dx3236_mpp_controls[] = {
> +	MPP_FUNC_CTRL(0, 32, NULL, armada_xp_mpp_ctrl),
> +};

As Linus has taken my mvebu pinctrl series, this will need to be
changed to "mvebu_mmio_mpp_ctrl" rather than "armada_xp_mpp_ctrl"
when it's merged.

-- 
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 v20 16/17] clocksource/drivers/arm_arch_timer: Add GTDT support for memory-mapped timer
From: Fu Wei @ 2017-01-19 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ed4efe25-1b40-66e2-ae3f-77a4e32715b6@linaro.org>

Hi Hanjun,

On 19 January 2017 at 17:16, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> On 2017/1/18 21:25, fu.wei at linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> The patch add memory-mapped timer register support by using the
>> information provided by the new GTDT driver of ACPI.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> ---
>>  drivers/clocksource/arm_arch_timer.c | 35
>> ++++++++++++++++++++++++++++++++---
>>  1 file changed, 32 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/clocksource/arm_arch_timer.c
>> b/drivers/clocksource/arm_arch_timer.c
>> index 79dc004..7ca2da7 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -1077,10 +1077,36 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem,
>> "arm,armv7-timer-mem",
>>                        arch_timer_mem_of_init);
>>
>>  #ifdef CONFIG_ACPI_GTDT
>> -/* Initialize per-processor generic timer */
>> +static int __init arch_timer_mem_acpi_init(int platform_timer_count)
>> +{
>> +       struct arch_timer_mem *timer_mem;
>> +       int timer_count, i, ret;
>> +
>
>
> if (!platform_timer_count)
>         return 0;
>
> Did I miss something?

Ah, thanks, I guess I miss this check below.

>
> Thanks
> Hanjun
>
>
>> +       timer_mem = kcalloc(platform_timer_count, sizeof(*timer_mem),
>> +                           GFP_KERNEL);
>> +       if (!timer_mem)
>> +               return -ENOMEM;
>> +
>> +       ret = acpi_arch_timer_mem_init(timer_mem, &timer_count);
>> +       if (ret || !timer_count)
>> +               goto error;
>> +
>> +       for (i = 0; i < timer_count; i++) {
>> +               ret = arch_timer_mem_init(timer_mem);
>> +               if (!ret)
>> +                       break;
>> +               timer_mem++;
>> +       }
>> +
>> +error:
>> +       kfree(timer_mem);
>> +       return ret;
>> +}
>> +
>> +/* Initialize per-processor generic timer and memory-mapped timer(if
>> present) */
>>  static int __init arch_timer_acpi_init(struct acpi_table_header *table)
>>  {
>> -       int ret;
>> +       int ret, platform_timer_count;
>>
>>         if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
>>                 pr_warn("already initialized, skipping\n");
>> @@ -1089,7 +1115,7 @@ static int __init arch_timer_acpi_init(struct
>> acpi_table_header *table)
>>
>>         arch_timers_present |= ARCH_TIMER_TYPE_CP15;
>>
>> -       ret = acpi_gtdt_init(table, NULL);
>> +       ret = acpi_gtdt_init(table, &platform_timer_count);
>>         if (ret) {
>>                 pr_err("Failed to init GTDT table.\n");
>>                 return ret;
>> @@ -1122,6 +1148,9 @@ static int __init arch_timer_acpi_init(struct
>> acpi_table_header *table)
>>         if (ret)
>>                 return ret;
>>
>> +       if (arch_timer_mem_acpi_init(platform_timer_count))

+       if (platform_timer_count &&
+           arch_timer_mem_acpi_init(platform_timer_count))


>> +               pr_err("Failed to initialize memory-mapped timer.\n");
>> +
>>         return arch_timer_common_init();
>>  }
>>  CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT,
>> arch_timer_acpi_init);
>>
>



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

^ permalink raw reply

* [PATCH net-next] macb: Common code to enable ptp support for SAMA5Dx platforms.
From: Andrei.Pistirica at microchip.com @ 2017-01-19 10:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1c534b5a-25cb-a5d6-f87c-db9ed958a606@atmel.com>

> Subject: Re: [PATCH net-next] macb: Common code to enable ptp support
> for SAMA5Dx platforms.
> 
> Le 18/01/2017 ? 09:57, Andrei Pistirica a ?crit :
> > This patch does the following:
> > - add GEM-PTP interface
> > - registers and bitfields for TSU are named according to SAMA5Dx data
> > sheet
> > - PTP support based on platform capability
> 
> The $subject will certainly never match reality, sadly "enable ptp support
> for SAMA5Dx platforms". So, you'd better change it.
> (no "." at the end BTW).

I will change it to: " Common code to enable ptp support for MACB/GEM"

> > +2518,7 @@ static void macb_configure_caps(struct macb *bp,
> >  		dcfg = gem_readl(bp, DCFG2);
> >  		if ((dcfg & (GEM_BIT(RX_PKT_BUFF) |
> GEM_BIT(TX_PKT_BUFF))) == 0)
> >  			bp->caps |= MACB_CAPS_FIFO_MODE;
> > +
> 
> Nitpicking, just because other issue exists: this white line doesn't belong to
> the patch.

Ok I'll remove it. I missed it because checkpatch didn't report any warning.

[...]

> >  #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
> >  #define MACB_CAPS_SG_DISABLED			0x40000000
> >  #define MACB_CAPS_MACB_IS_GEM			0x80000000
> > +#define MACB_CAPS_GEM_HAS_PTP			0x00000020
> 
> No, this mask already exists a couple of lines above:
> #define MACB_CAPS_JUMBO        0x00000020
> 
> That leads to a NACK, sorry (I didn't spotted earlier, BTW).

Yes... you are right... sorry.

[...] 

> Otherwise, I'm okay with the rest.
> 
> I suggest to people that will keep the ball rolling on this topic to take
> advantage of the chunks of code that Andrei developed with the help of
> Richard and the best practices discussed. I think particularly, if it makes
> sense with HW, about:
> - gem_ptp_do_[rt]xstamp(bp, skb) dereference scheme
> - gem_ptp_adjfine() rationale
> - gem_get_ptp_peer() if needed

Just mind that in case of an implementation with buffer rings and irqs
a different mechanism have to be used.

Regards,
Andrei

> 
> Regards,
> --
> Nicolas Ferre

^ permalink raw reply

* [PATCH v20 13/17] acpi/arm64: Add GTDT table parse driver
From: Fu Wei @ 2017-01-19 10:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e69d80d1-0954-b1be-817e-c0be6fc24b77@linaro.org>

Hi Hanjun,

On 19 January 2017 at 17:11, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> On 2017/1/18 21:25, fu.wei at linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patch adds support for parsing arch timer info in GTDT,
>> provides some kernel APIs to parse all the PPIs and
>> always-on info in GTDT and export them.
>>
>> By this driver, we can simplify arm_arch_timer drivers, and
>> separate the ACPI GTDT knowledge from it.
>>
>> Signed-off-by: Fu Wei <fu.wei@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
>> ---
>>  arch/arm64/Kconfig          |   1 +
>>  drivers/acpi/arm64/Kconfig  |   3 +
>>  drivers/acpi/arm64/Makefile |   1 +
>>  drivers/acpi/arm64/gtdt.c   | 157
>> ++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/acpi.h        |   6 ++
>>  5 files changed, 168 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 1117421..ab1ee10 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -2,6 +2,7 @@ config ARM64
>>         def_bool y
>>         select ACPI_CCA_REQUIRED if ACPI
>>         select ACPI_GENERIC_GSI if ACPI
>> +       select ACPI_GTDT if ACPI
>>         select ACPI_REDUCED_HARDWARE_ONLY if ACPI
>>         select ACPI_MCFG if ACPI
>>         select ACPI_SPCR_TABLE if ACPI
>> diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
>> index 4616da4..5a6f80f 100644
>> --- a/drivers/acpi/arm64/Kconfig
>> +++ b/drivers/acpi/arm64/Kconfig
>> @@ -4,3 +4,6 @@
>>
>>  config ACPI_IORT
>>         bool
>> +
>> +config ACPI_GTDT
>> +       bool
>> diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
>> index 72331f2..1017def 100644
>> --- a/drivers/acpi/arm64/Makefile
>> +++ b/drivers/acpi/arm64/Makefile
>> @@ -1 +1,2 @@
>>  obj-$(CONFIG_ACPI_IORT)        += iort.o
>> +obj-$(CONFIG_ACPI_GTDT)        += gtdt.o
>> diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
>> new file mode 100644
>> index 0000000..d93a790
>> --- /dev/null
>> +++ b/drivers/acpi/arm64/gtdt.c
>> @@ -0,0 +1,157 @@
>
> [...]
>
>> +
>> +/**
>> + * acpi_gtdt_init() - Get the info of GTDT table to prepare for further
>> init.
>> + * @table:     The pointer to GTDT table.
>> + * @platform_timer_count:      The pointer of int variate for returning
>> the
>> + *                             number of platform timers. It can be NULL,
>> if
>> + *                             driver don't need this info.
>> + *
>> + * Return: 0 if success, -EINVAL if error.
>> + */
>> +int __init acpi_gtdt_init(struct acpi_table_header *table,
>> +                         int *platform_timer_count)
>> +{
>> +       int ret = 0;
>> +       int timer_count = 0;
>> +       void *platform_timer = NULL;
>> +       struct acpi_table_gtdt *gtdt;
>> +
>> +       gtdt = container_of(table, struct acpi_table_gtdt, header);
>> +       acpi_gtdt_desc.gtdt = gtdt;
>> +       acpi_gtdt_desc.gtdt_end = (void *)table + table->length;
>> +
>> +       if (table->revision < 2)
>> +               pr_debug("Revision:%d doesn't support Platform Timers.\n",
>> +                        table->revision);
>
>
> GTDT table revision is updated to 2 in ACPI 5.1, we will
> not support ACPI version under 5.1 and disable ACPI in FADT
> parse before this code is called, so if we get revision
> <2 here, I think we need to print warning (we need to keep
> the firmware stick to the spec on ARM64).

agree, will change pr_debug to pr_warn.

Thanks :-)

>
>> +       else if (!gtdt->platform_timer_count)
>> +               pr_debug("No Platform Timer.\n");
>> +       else
>> +               timer_count = gtdt->platform_timer_count;
>> +
>> +       if (timer_count) {
>> +               platform_timer = (void *)gtdt +
>> gtdt->platform_timer_offset;
>> +               if (platform_timer < (void *)table +
>> +                                    sizeof(struct acpi_table_gtdt)) {
>> +                       pr_err(FW_BUG "invalid timer data.\n");
>
>
> It's ok but I didn't see other ACPI tables parsing did this check,
> maybe we can just remove it :)

here, I want to make sure the FW is valid.
Once there is a FW bug, we could just return with error.  :-)

>
>> +                       timer_count = 0;
>> +                       platform_timer = NULL;
>> +                       ret = -EINVAL;
>> +               }
>> +       }
>> +
>> +       acpi_gtdt_desc.platform_timer = platform_timer;
>> +       if (platform_timer_count)
>> +               *platform_timer_count = timer_count;
>
>
> Then the code will much simple:
>
> if (gtdt->platform_timer_count) {
>         acpi_gtdt_desc.platform_timer = (void *)gtdt +
> gtdt->platform_timer_offset;
>         if (platform_timer_count)
>                 *platform_timer_count = gtdt->platform_timer_count;
> }
>
> return 0;
>
> and remove ret, timer_count and platform_timer.

yes, this may can simplify the function, but this will be released at
the end of init because of "__init" :-)
So how about let's just keep this check to make sure the FW is OK.  :-)

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

^ permalink raw reply

* [PATCH v1 0/7] DRM: add LTDC support for STM32F4
From: Yannick FERTRE @ 2017-01-19 10:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cf29809f-f951-eeed-5886-02d0a7a1e56f@baylibre.com>

Hi Neil,
ST may use this hardware IP also in other SoC, even that is not true 
now, I hope that "st" is a more futur proof name.

Best regards

Yannick Fertr?


On 01/16/2017 05:02 PM, Neil Armstrong wrote:
> On 01/16/2017 02:28 PM, Yannick Fertre wrote:
>> The purpose of this set of patches is to add a new driver for stm32f429.
>> This driver was developed and tested on evaluation board stm32429i.
>>
>> Stm32f4 is a MCU platform which don't have MMU so the last patches developed
>> by Benjamin Gaignard regarding "DRM: allow to use mmuless devices"
>> are necessary.
>>
>> The board stm429i embeds a Ampire AM-480272H3TMQW-T01H screen.
>> A new simple panel am-480272h3tmqw-t01h have been added to support it.
>>
>> Yannick Fertre (7):
>>   dt-bindings: display: add STM32 LTDC driver
>>   drm/st: Add STM32 LTDC driver
>>   dt-bindings: Add Ampire AM-480272H3TMQW-T01H panel
>>   drm/panel: simple: Add support for Ampire AM-480272H3TMQW-T01H
>>   ARM: dts: stm32f429: Add ltdc support
>>   ARM: dts: stm32429i-eval: Enable ltdc & simple panel on Eval board
>>   ARM: configs: Add STM32 LTDC support in STM32 defconfig
>>
>>  .../display/panel/ampire,am-480272h3tmqw-t01h.txt  |    7 +
>>  .../devicetree/bindings/display/st,ltdc.txt        |   57 +
>>  arch/arm/boot/dts/stm32429i-eval.dts               |   58 +
>>  arch/arm/boot/dts/stm32f429.dtsi                   |   25 +-
>>  arch/arm/configs/stm32_defconfig                   |    5 +
>>  drivers/gpu/drm/Kconfig                            |    2 +
>>  drivers/gpu/drm/Makefile                           |    1 +
>>  drivers/gpu/drm/panel/panel-simple.c               |   29 +
>>  drivers/gpu/drm/st/Kconfig                         |   14 +
>>  drivers/gpu/drm/st/Makefile                        |    7 +
>>  drivers/gpu/drm/st/drv.c                           |  279 ++++
>>  drivers/gpu/drm/st/drv.h                           |   25 +
>>  drivers/gpu/drm/st/ltdc.c                          | 1438 ++++++++++++++++++++
>>  drivers/gpu/drm/st/ltdc.h                          |   20 +
>>  14 files changed, 1966 insertions(+), 1 deletion(-)
>>  create mode 100644 Documentation/devicetree/bindings/display/panel/ampire,am-480272h3tmqw-t01h.txt
>>  create mode 100644 Documentation/devicetree/bindings/display/st,ltdc.txt
>>  create mode 100644 drivers/gpu/drm/st/Kconfig
>>  create mode 100644 drivers/gpu/drm/st/Makefile
>>  create mode 100644 drivers/gpu/drm/st/drv.c
>>  create mode 100644 drivers/gpu/drm/st/drv.h
>>  create mode 100644 drivers/gpu/drm/st/ltdc.c
>>  create mode 100644 drivers/gpu/drm/st/ltdc.h
>>
>
> Hi Yannick,
>
> Shouldn't be more logical to use stm32 for the driver instead of st ?
> It would eventually collude with the other STMicroelectronics SoCs and
> will be aligned with other drivers like stm32-rtc, stm32-i2c, ...
>
> Neil
>

^ permalink raw reply

* [PATCH v3 09/13] sata: ahci: export ahci_do_hardreset() locally
From: Bartosz Golaszewski @ 2017-01-19 10:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170118182826.GA1451@mtj.duckdns.org>

2017-01-18 19:28 GMT+01:00 Tejun Heo <tj@kernel.org>:
> Hello, Bartosz.
>
> On Wed, Jan 18, 2017 at 02:19:57PM +0100, Bartosz Golaszewski wrote:
>> We need a way to retrieve the information about the online state of
>> the link in the ahci-da850 driver.
>>
>> Create a new function: ahci_do_hardreset() which is called from
>> ahci_hardreset() for backwards compatibility, but has an additional
>> argument: 'online' - which can be used to check if the link is online
>> after this function returns.
>
> Please just add @online to ahci_hardreset() and update the callers.
> Other than that, the sata changes look good to me.
>

Are you sure? There are 23 places in drivers/ata/ where the .hardreset
callback is assigned. I'd prefer not to change the drivers I can't
test. Besides all other **reset callbacks take three arguments -
should we really only change one of them for a single driver's needs?

Thanks,
Bartosz

^ permalink raw reply

* [PATCH 1/2] security: Change name of CONFIG_DEBUG_RODATA
From: Mark Rutland @ 2017-01-19 10:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484789346-21012-2-git-send-email-labbott@redhat.com>

Hi Laura,

On Wed, Jan 18, 2017 at 05:29:05PM -0800, Laura Abbott wrote:
> 
> Despite the word 'debug' in CONFIG_DEBUG_RODATA, this kernel option
> provides key security features that are to be expected on a modern
> system. Change the name to CONFIG_HARDENED_PAGE_MAPPINGS which more
> accurately describes what this option is intended to do.

This generally sounds good. Thanks for attacking this!

On the bikeshedding front, *maybe* it would be nice to mention
permissions in the name, something like STRICT_KERNEL_RWX. That might
also prevent the reading of 'hardened' as 'optional overhead'.

That said, the proposed name is fine by me -- I'm happy so long as
'DEBUG' goes.

> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1117421..06fed56 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -11,6 +11,7 @@ config ARM64
>  	select ARCH_HAS_ELF_RANDOMIZE
>  	select ARCH_HAS_GCOV_PROFILE_ALL
>  	select ARCH_HAS_GIGANTIC_PAGE
> +	select ARCH_HAS_HARDENED_MAPPINGS
>  	select ARCH_HAS_KCOV
>  	select ARCH_HAS_SG_CHAIN
>  	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
> @@ -123,9 +124,6 @@ config ARCH_PHYS_ADDR_T_64BIT
>  config MMU
>  	def_bool y
>  
> -config DEBUG_RODATA
> -	def_bool y
> -

> diff --git a/security/Kconfig b/security/Kconfig
> index 118f454..ad6ce82 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -158,6 +158,22 @@ config HARDENED_USERCOPY_PAGESPAN
>  	  been removed. This config is intended to be used only while
>  	  trying to find such users.
>  
> +config ARCH_HAS_HARDENED_MAPPINGS
> +	def_bool n
> +
> +config HARDENED_PAGE_MAPPINGS
> +	bool "Mark kernel mappings with stricter permissions (RO/W^X)"
> +	default y
> +	depends on ARCH_HAS_HARDENED_MAPPINGS
> +	help
> +          If this is set, kernel text and rodata memory will be made read-only,
> +	  and non-text memory will be made non-executable. This provides
> +	  protection against certain security attacks (e.g. executing the heap
> +	  or modifying text).
> +
> +	  Unless your system has known restrictions or performance issues, it
> +	  is recommended to say Y here.

It's somewhat unfortunate that this means the feature is no longer
mandatory on arm64 (and s390+x86). We have a boot-time switch to turn
the protections off, so I was hoping we could make this mandatory on all
architectures with support.

It would be good to see if we could make this mandatory for arm and
parisc, or if it really needs to be optional for either of those.

Thanks,
Mark.

^ permalink raw reply

* [PATCH v3] IOMMU: SMMUv2: Support for Extended Stream ID (16 bit)
From: Aleksey Makarov @ 2017-01-19 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bc9eb7ab-5cc7-411b-60f3-b8c369753f9b@caviumnetworks.com>

Hi Tomasz,

On 01/19/2017 11:55 AM, Tomasz Nowicki wrote:
> Hi Aleksey,
> 
> On 17.01.2017 16:14, Aleksey Makarov wrote:
>> Enable the Extended Stream ID feature when available.
>>
>> This patch on top of series "KVM PCIe/MSI passthrough on ARM/ARM64
>> and IOVA reserved regions" by Eric Auger [1] allows to passthrough
>> an external PCIe network card on a ThunderX server successfully.
>>
>> Without this patch that card caused a warning like
>>
>>     pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff)
>>
>> during boot.
>>
>> [1] https://lkml.kernel.org/r/1484127714-3263-1-git-send-email-eric.auger at redhat.com
>>
>> Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
> 
> I do not thing this is related to PCIe network card. It is rather common to all devices which bus number > 127
> 
> ----
> 
> iommu/arm-smmu: Support for Extended Stream ID (16 bit)
> 
> It is the time we have the real 16-bit Stream ID user, which is the ThunderX. Its IO topology uses 1:1 map for requester to stream ID translation:
> 
> RC no. | Requester ID | Stream ID
>        |              |
> RC_0   | 0-FFFF --->  | 0-FFFF
> 
> which allows to get full 16-bit stream ID. Currently all devices with bus number >= 128 (0x80) get non-zero 16th bit of BDF and stream ID (due to 1:1 map). Eventually SMMU drops such device because the stream ID is out of range. This is the case for all devices connected as external endpoints on ThunderX.

Technically the last sentence it is not correct as far as I can see.  There exists a device connected to PEM (external entpoint?) with BDF (== Stream ID) <= 0x7fff:

	0004:21:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 30)

> 
> ----

Thank you for review.  May I change the commit message this way and keep your 'Reviewed-by'?:

---
iommu/arm-smmu: Support for Extended Stream ID (16 bit)

It is the time we have the real 16-bit Stream ID user, which is the
ThunderX. Its IO topology uses 1:1 map for requester ID to stream ID
translation for each root complex which allows to get full 16-bit
stream ID.  Firmware assigns bus IDs that are greater than 128 (0x80)
to some buses under PEM (external PCIe interface).  Eventually SMMU
drops devices on that buses because their stream ID is out of range:

  pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff)

To fix above issue enable the Extended Stream ID optional feature when available.
---

Thank you
Aleksey Makarov

> 
> Please add my:
> Reviewed-by: Tomasz Nowicki <tomasz.nowicki@caviumnetworks.com>
> Tested-by: Tomasz Nowicki <tomasz.nowicki@caviumnetworks.com>
> 
> Thanks,
> Tomasz
> 
> 
>> ---
>> v3:
>> - keep formatting of the comment
>> - fix printk message after the deleted chunk.  "[Do] not print a mask
>>   here, since it's not overly interesting in itself, and add_device will
>>   still show the offending mask in full if it ever actually matters (as in
>>   the commit message)." (Robin Murphy)
>>
>> v2:
>> https://lkml.kernel.org/r/20170116141111.29444-1-aleksey.makarov at linaro.org
>> - remove unnecessary parentheses (Robin Murphy)
>> - refactor testing SMR fields to after setting sCR0 as theirs width
>>   depends on sCR0_EXIDENABLE (Robin Murphy)
>>
>> v1 (rfc):
>> https://lkml.kernel.org/r/20170110115755.19102-1-aleksey.makarov at linaro.org
>>
>>  drivers/iommu/arm-smmu.c | 69 +++++++++++++++++++++++++++++++++---------------
>>  1 file changed, 48 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>> index 13d26009b8e0..861cc135722f 100644
>> --- a/drivers/iommu/arm-smmu.c
>> +++ b/drivers/iommu/arm-smmu.c
>> @@ -24,6 +24,7 @@
>>   *    - v7/v8 long-descriptor format
>>   *    - Non-secure access to the SMMU
>>   *    - Context fault reporting
>> + *    - Extended Stream ID (16 bit)
>>   */
>>
>>  #define pr_fmt(fmt) "arm-smmu: " fmt
>> @@ -87,6 +88,7 @@
>>  #define sCR0_CLIENTPD            (1 << 0)
>>  #define sCR0_GFRE            (1 << 1)
>>  #define sCR0_GFIE            (1 << 2)
>> +#define sCR0_EXIDENABLE            (1 << 3)
>>  #define sCR0_GCFGFRE            (1 << 4)
>>  #define sCR0_GCFGFIE            (1 << 5)
>>  #define sCR0_USFCFG            (1 << 10)
>> @@ -126,6 +128,7 @@
>>  #define ID0_NUMIRPT_MASK        0xff
>>  #define ID0_NUMSIDB_SHIFT        9
>>  #define ID0_NUMSIDB_MASK        0xf
>> +#define ID0_EXIDS            (1 << 8)
>>  #define ID0_NUMSMRG_SHIFT        0
>>  #define ID0_NUMSMRG_MASK        0xff
>>
>> @@ -169,6 +172,7 @@
>>  #define ARM_SMMU_GR0_S2CR(n)        (0xc00 + ((n) << 2))
>>  #define S2CR_CBNDX_SHIFT        0
>>  #define S2CR_CBNDX_MASK            0xff
>> +#define S2CR_EXIDVALID            (1 << 10)
>>  #define S2CR_TYPE_SHIFT            16
>>  #define S2CR_TYPE_MASK            0x3
>>  enum arm_smmu_s2cr_type {
>> @@ -354,6 +358,7 @@ struct arm_smmu_device {
>>  #define ARM_SMMU_FEAT_FMT_AARCH64_64K    (1 << 9)
>>  #define ARM_SMMU_FEAT_FMT_AARCH32_L    (1 << 10)
>>  #define ARM_SMMU_FEAT_FMT_AARCH32_S    (1 << 11)
>> +#define ARM_SMMU_FEAT_EXIDS        (1 << 12)
>>      u32                features;
>>
>>  #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
>> @@ -1051,7 +1056,7 @@ static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
>>      struct arm_smmu_smr *smr = smmu->smrs + idx;
>>      u32 reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
>>
>> -    if (smr->valid)
>> +    if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
>>          reg |= SMR_VALID;
>>      writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
>>  }
>> @@ -1063,6 +1068,9 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
>>            (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
>>            (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
>>
>> +    if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs &&
>> +        smmu->smrs[idx].valid)
>> +        reg |= S2CR_EXIDVALID;
>>      writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_S2CR(idx));
>>  }
>>
>> @@ -1073,6 +1081,34 @@ static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
>>          arm_smmu_write_smr(smmu, idx);
>>  }
>>
>> +/*
>> + * The width of SMR's mask field depends on sCR0_EXIDENABLE, so this function
>> + * should be called after sCR0 is written.
>> + */
>> +static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
>> +{
>> +    void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
>> +    u32 smr;
>> +
>> +    if (!smmu->smrs)
>> +        return;
>> +
>> +    /*
>> +     * SMR.ID bits may not be preserved if the corresponding MASK
>> +     * bits are set, so check each one separately. We can reject
>> +     * masters later if they try to claim IDs outside these masks.
>> +     */
>> +    smr = smmu->streamid_mask << SMR_ID_SHIFT;
>> +    writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
>> +    smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
>> +    smmu->streamid_mask = smr >> SMR_ID_SHIFT;
>> +
>> +    smr = smmu->streamid_mask << SMR_MASK_SHIFT;
>> +    writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
>> +    smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
>> +    smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
>> +}
>> +
>>  static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
>>  {
>>      struct arm_smmu_smr *smrs = smmu->smrs;
>> @@ -1674,6 +1710,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
>>      if (smmu->features & ARM_SMMU_FEAT_VMID16)
>>          reg |= sCR0_VMID16EN;
>>
>> +    if (smmu->features & ARM_SMMU_FEAT_EXIDS)
>> +        reg |= sCR0_EXIDENABLE;
>> +
>>      /* Push the button */
>>      __arm_smmu_tlb_sync(smmu);
>>      writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
>> @@ -1761,11 +1800,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
>>                 "\t(IDR0.CTTW overridden by FW configuration)\n");
>>
>>      /* Max. number of entries we have for stream matching/indexing */
>> -    size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
>> +    if (smmu->version == ARM_SMMU_V2 && id & ID0_EXIDS) {
>> +        smmu->features |= ARM_SMMU_FEAT_EXIDS;
>> +        size = 1 << 16;
>> +    } else {
>> +        size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
>> +    }
>>      smmu->streamid_mask = size - 1;
>>      if (id & ID0_SMS) {
>> -        u32 smr;
>> -
>>          smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH;
>>          size = (id >> ID0_NUMSMRG_SHIFT) & ID0_NUMSMRG_MASK;
>>          if (size == 0) {
>> @@ -1774,21 +1816,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
>>              return -ENODEV;
>>          }
>>
>> -        /*
>> -         * SMR.ID bits may not be preserved if the corresponding MASK
>> -         * bits are set, so check each one separately. We can reject
>> -         * masters later if they try to claim IDs outside these masks.
>> -         */
>> -        smr = smmu->streamid_mask << SMR_ID_SHIFT;
>> -        writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
>> -        smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
>> -        smmu->streamid_mask = smr >> SMR_ID_SHIFT;
>> -
>> -        smr = smmu->streamid_mask << SMR_MASK_SHIFT;
>> -        writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
>> -        smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
>> -        smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
>> -
>>          /* Zero-initialised to mark as invalid */
>>          smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs),
>>                        GFP_KERNEL);
>> @@ -1796,8 +1823,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
>>              return -ENOMEM;
>>
>>          dev_notice(smmu->dev,
>> -               "\tstream matching with %lu register groups, mask 0x%x",
>> -               size, smmu->smr_mask_mask);
>> +               "\tstream matching with %lu register groups", size);
>>      }
>>      /* s2cr->type == 0 means translation, so initialise explicitly */
>>      smmu->s2crs = devm_kmalloc_array(smmu->dev, size, sizeof(*smmu->s2crs),
>> @@ -2120,6 +2146,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>      iommu_register_instance(dev->fwnode, &arm_smmu_ops);
>>      platform_set_drvdata(pdev, smmu);
>>      arm_smmu_device_reset(smmu);
>> +    arm_smmu_test_smr_masks(smmu);
>>
>>      /* Oh, for a proper bus abstraction */
>>      if (!iommu_present(&platform_bus_type))
>>

-- 
All the best
Alekse?y Maka?rov

^ permalink raw reply

* [PATCH v20 00/17] acpi, clocksource: add GTDT driver and GTDT support in arm_arch_timer
From: Fu Wei @ 2017-01-19 11:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bddc52ed-d1c9-c3c9-cb79-2c15d97450cc@linaro.org>

Hi Hanjun,

On 19 January 2017 at 17:20, Hanjun Guo <hanjun.guo@linaro.org> wrote:
> Hi Fuwei,
>
>
> On 2017/1/18 21:25, fu.wei at linaro.org wrote:
>>
>> From: Fu Wei <fu.wei@linaro.org>
>>
>> This patchset:
>>     (1)Preparation for adding GTDT support in arm_arch_timer:
>>         1. Clean up printk() usage
>>         2. Rename the type macros
>>         3. Rename the PPI enum & enum values
>>         4. Move the type macro and PPI enum into the header file
>>         5. Add new enum for SPIs
>>         6. Rework PPI determination;
>>         7. Rework counter frequency detection;
>>         8. Refactor arch_timer_needs_probing, move it into DT init call
>>         9. Introduce some new structs and refactor the MMIO timer init
>> code
>>         for reusing some common code.
>>
>>     (2)Introduce ACPI GTDT parser: drivers/acpi/arm64/acpi_gtdt.c
>>     Parse all kinds of timer in GTDT table of ACPI:arch timer,
>>     memory-mapped timer and SBSA Generic Watchdog timer.
>>     This driver can help to simplify all the relevant timer drivers,
>>     and separate all the ACPI GTDT knowledge from them.
>>
>>     (3)Simplify ACPI code for arm_arch_timer
>>
>>     (4)Add GTDT support for ARM memory-mapped timer.
>>
>> This patchset has been tested on the following platforms with ACPI
>> enabled:
>>     (1)ARM Foundation v8 model
>>
>> Changelog:
>> v20: https://lkml.org/lkml/2017/1/18/
>>      Reorder the first 4 patches and split the 4th patches.
>>      Leave CNTHCTL_* as they originally were.
>>      Fix the bug in arch_timer_select_ppi.
>>      Split "Rework counter frequency detection" patch.
>>      Rework the arch_timer_detect_rate function.
>>      Improve the commit message of "Refactor MMIO timer probing".
>>      Rebase to 4.10.0-rc4
>
>
> Other than some minor comments I raised, the patch set
> looks fine to me, and I tested this patch set on D03,
> the percpu arch timer works fine as before.
>
> With the comments fixed,
> Reviewed-by: Hanjun Guo <hanjun.gu@linaro.org>
> Tested-by: Hanjun Guo <hanjun.gu@linaro.org>

Great thanks for your testing. :-)

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

>
> Thanks
> Hanjun



-- 
Best regards,

Fu Wei
Software Engineer
Red Hat

^ permalink raw reply

* [PATCH v3] IOMMU: SMMUv2: Support for Extended Stream ID (16 bit)
From: Tomasz Nowicki @ 2017-01-19 11:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <67d2c502-43c4-8479-6abf-481a334f8047@linaro.org>

On 19.01.2017 11:57, Aleksey Makarov wrote:
> Hi Tomasz,
>
> On 01/19/2017 11:55 AM, Tomasz Nowicki wrote:
>> Hi Aleksey,
>>
>> On 17.01.2017 16:14, Aleksey Makarov wrote:
>>> Enable the Extended Stream ID feature when available.
>>>
>>> This patch on top of series "KVM PCIe/MSI passthrough on ARM/ARM64
>>> and IOVA reserved regions" by Eric Auger [1] allows to passthrough
>>> an external PCIe network card on a ThunderX server successfully.
>>>
>>> Without this patch that card caused a warning like
>>>
>>>     pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff)
>>>
>>> during boot.
>>>
>>> [1] https://lkml.kernel.org/r/1484127714-3263-1-git-send-email-eric.auger at redhat.com
>>>
>>> Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
>>
>> I do not thing this is related to PCIe network card. It is rather common to all devices which bus number > 127
>>
>> ----
>>
>> iommu/arm-smmu: Support for Extended Stream ID (16 bit)
>>
>> It is the time we have the real 16-bit Stream ID user, which is the ThunderX. Its IO topology uses 1:1 map for requester to stream ID translation:
>>
>> RC no. | Requester ID | Stream ID
>>        |              |
>> RC_0   | 0-FFFF --->  | 0-FFFF
>>
>> which allows to get full 16-bit stream ID. Currently all devices with bus number >= 128 (0x80) get non-zero 16th bit of BDF and stream ID (due to 1:1 map). Eventually SMMU drops such device because the stream ID is out of range. This is the case for all devices connected as external endpoints on ThunderX.
>
> Technically the last sentence it is not correct as far as I can see.  There exists a device connected to PEM (external entpoint?) with BDF (== Stream ID) <= 0x7fff:
>
> 	0004:21:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 30)

Right. You?ve got a point.

>
>>
>> ----
>
> Thank you for review.  May I change the commit message this way and keep your 'Reviewed-by'?:

Yes, the commit message is accurate now. Add my R-b please.

>
> ---
> iommu/arm-smmu: Support for Extended Stream ID (16 bit)
>
> It is the time we have the real 16-bit Stream ID user, which is the
> ThunderX. Its IO topology uses 1:1 map for requester ID to stream ID
> translation for each root complex which allows to get full 16-bit
> stream ID.  Firmware assigns bus IDs that are greater than 128 (0x80)
> to some buses under PEM (external PCIe interface).  Eventually SMMU
> drops devices on that buses because their stream ID is out of range:
>
>   pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff)
>
> To fix above issue enable the Extended Stream ID optional feature when available.
> ---
>

Thanks,
Tomasz

^ permalink raw reply

* [PATCH v3 2/2] mmc: host: s3cmci: allow probing from device tree
From: Ulf Hansson @ 2017-01-19 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1484319953-6479-3-git-send-email-sergio.prado@e-labworks.com>

On 13 January 2017 at 16:05, Sergio Prado <sergio.prado@e-labworks.com> wrote:
> Allows configuring Samsung S3C24XX MMC/SD/SDIO controller using a device
> tree.
>
> Signed-off-by: Sergio Prado <sergio.prado@e-labworks.com>

Looks good to me. Waiting for Rob's ack for the DT changes in patch1
(needed a re-spin) before I queue it.

Kind regards
Uffe

> ---
>  drivers/mmc/host/s3cmci.c | 298 ++++++++++++++++++++++++----------------------
>  drivers/mmc/host/s3cmci.h |   3 +-
>  2 files changed, 158 insertions(+), 143 deletions(-)
>
> diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
> index 932a4b1fed33..55535b65e0b3 100644
> --- a/drivers/mmc/host/s3cmci.c
> +++ b/drivers/mmc/host/s3cmci.c
> @@ -23,6 +23,10 @@
>  #include <linux/gpio.h>
>  #include <linux/irq.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>
> +#include <linux/mmc/slot-gpio.h>
>
>  #include <plat/gpio-cfg.h>
>  #include <mach/dma.h>
> @@ -127,6 +131,22 @@ enum dbg_channels {
>         dbg_conf  = (1 << 8),
>  };
>
> +struct s3cmci_variant_data {
> +       int s3c2440_compatible;
> +};
> +
> +static const struct s3cmci_variant_data s3c2410_s3cmci_variant_data = {
> +       .s3c2440_compatible = 0,
> +};
> +
> +static const struct s3cmci_variant_data s3c2412_s3cmci_variant_data = {
> +       .s3c2440_compatible = 1,
> +};
> +
> +static const struct s3cmci_variant_data s3c2440_s3cmci_variant_data = {
> +       .s3c2440_compatible = 1,
> +};
> +
>  static const int dbgmap_err   = dbg_fail;
>  static const int dbgmap_info  = dbg_info | dbg_conf;
>  static const int dbgmap_debug = dbg_err | dbg_debug;
> @@ -730,7 +750,7 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id)
>                 goto clear_status_bits;
>
>         /* Check for FIFO failure */
> -       if (host->is2440) {
> +       if (host->variant->s3c2440_compatible) {
>                 if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {
>                         dbg(host, dbg_err, "FIFO failure\n");
>                         host->mrq->data->error = -EILSEQ;
> @@ -806,21 +826,6 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id)
>
>  }
>
> -/*
> - * ISR for the CardDetect Pin
> -*/
> -
> -static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
> -{
> -       struct s3cmci_host *host = (struct s3cmci_host *)dev_id;
> -
> -       dbg(host, dbg_irq, "card detect\n");
> -
> -       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
> -
> -       return IRQ_HANDLED;
> -}
> -
>  static void s3cmci_dma_done_callback(void *arg)
>  {
>         struct s3cmci_host *host = arg;
> @@ -912,7 +917,7 @@ static void finalize_request(struct s3cmci_host *host)
>                 if (s3cmci_host_usedma(host))
>                         dmaengine_terminate_all(host->dma);
>
> -               if (host->is2440) {
> +               if (host->variant->s3c2440_compatible) {
>                         /* Clear failure register and reset fifo. */
>                         writel(S3C2440_SDIFSTA_FIFORESET |
>                                S3C2440_SDIFSTA_FIFOFAIL,
> @@ -1025,7 +1030,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
>                 dcon |= S3C2410_SDIDCON_XFER_RXSTART;
>         }
>
> -       if (host->is2440) {
> +       if (host->variant->s3c2440_compatible) {
>                 dcon |= S3C2440_SDIDCON_DS_WORD;
>                 dcon |= S3C2440_SDIDCON_DATSTART;
>         }
> @@ -1044,7 +1049,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
>
>         /* write TIMER register */
>
> -       if (host->is2440) {
> +       if (host->variant->s3c2440_compatible) {
>                 writel(0x007FFFFF, host->base + S3C2410_SDITIMER);
>         } else {
>                 writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
> @@ -1176,19 +1181,6 @@ static void s3cmci_send_request(struct mmc_host *mmc)
>         s3cmci_enable_irq(host, true);
>  }
>
> -static int s3cmci_card_present(struct mmc_host *mmc)
> -{
> -       struct s3cmci_host *host = mmc_priv(mmc);
> -       struct s3c24xx_mci_pdata *pdata = host->pdata;
> -       int ret;
> -
> -       if (pdata->no_detect)
> -               return -ENOSYS;
> -
> -       ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
> -       return ret ^ pdata->detect_invert;
> -}
> -
>  static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>  {
>         struct s3cmci_host *host = mmc_priv(mmc);
> @@ -1197,7 +1189,7 @@ static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>         host->cmd_is_stop = 0;
>         host->mrq = mrq;
>
> -       if (s3cmci_card_present(mmc) == 0) {
> +       if (mmc_gpio_get_cd(mmc) == 0) {
>                 dbg(host, dbg_err, "%s: no medium present\n", __func__);
>                 host->mrq->cmd->error = -ENOMEDIUM;
>                 mmc_request_done(mmc, mrq);
> @@ -1241,22 +1233,24 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>         case MMC_POWER_ON:
>         case MMC_POWER_UP:
>                 /* Configure GPE5...GPE10 pins in SD mode */
> -               s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
> -                                     S3C_GPIO_PULL_NONE);
> +               if (!host->pdev->dev.of_node)
> +                       s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
> +                                             S3C_GPIO_PULL_NONE);
>
>                 if (host->pdata->set_power)
>                         host->pdata->set_power(ios->power_mode, ios->vdd);
>
> -               if (!host->is2440)
> +               if (!host->variant->s3c2440_compatible)
>                         mci_con |= S3C2410_SDICON_FIFORESET;
>
>                 break;
>
>         case MMC_POWER_OFF:
>         default:
> -               gpio_direction_output(S3C2410_GPE(5), 0);
> +               if (!host->pdev->dev.of_node)
> +                       gpio_direction_output(S3C2410_GPE(5), 0);
>
> -               if (host->is2440)
> +               if (host->variant->s3c2440_compatible)
>                         mci_con |= S3C2440_SDICON_SDRESET;
>
>                 if (host->pdata->set_power)
> @@ -1294,21 +1288,6 @@ static void s3cmci_reset(struct s3cmci_host *host)
>         writel(con, host->base + S3C2410_SDICON);
>  }
>
> -static int s3cmci_get_ro(struct mmc_host *mmc)
> -{
> -       struct s3cmci_host *host = mmc_priv(mmc);
> -       struct s3c24xx_mci_pdata *pdata = host->pdata;
> -       int ret;
> -
> -       if (pdata->no_wprotect)
> -               return 0;
> -
> -       ret = gpio_get_value(pdata->gpio_wprotect) ? 1 : 0;
> -       ret ^= pdata->wprotect_invert;
> -
> -       return ret;
> -}
> -
>  static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>  {
>         struct s3cmci_host *host = mmc_priv(mmc);
> @@ -1352,8 +1331,8 @@ static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>  static struct mmc_host_ops s3cmci_ops = {
>         .request        = s3cmci_request,
>         .set_ios        = s3cmci_set_ios,
> -       .get_ro         = s3cmci_get_ro,
> -       .get_cd         = s3cmci_card_present,
> +       .get_ro         = mmc_gpio_get_ro,
> +       .get_cd         = mmc_gpio_get_cd,
>         .enable_sdio_irq = s3cmci_enable_sdio_irq,
>  };
>
> @@ -1429,7 +1408,7 @@ static int s3cmci_state_show(struct seq_file *seq, void *v)
>         seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
>         seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
>         seq_printf(seq, "Prescale = %d\n", host->prescaler);
> -       seq_printf(seq, "is2440 = %d\n", host->is2440);
> +       seq_printf(seq, "S3C2440 compatible = %d\n", host->variant->s3c2440_compatible);
>         seq_printf(seq, "IRQ = %d\n", host->irq);
>         seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
>         seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
> @@ -1544,21 +1523,15 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
>
>  #endif /* CONFIG_DEBUG_FS */
>
> -static int s3cmci_probe(struct platform_device *pdev)
> +static int s3cmci_probe_pdata(struct s3cmci_host *host)
>  {
> -       struct s3cmci_host *host;
> -       struct mmc_host *mmc;
> -       int ret;
> -       int is2440;
> -       int i;
> +       struct platform_device *pdev = host->pdev;
> +       struct mmc_host *mmc = host->mmc;
> +       struct s3c24xx_mci_pdata *pdata;
> +       int i, ret;
>
> -       is2440 = platform_get_device_id(pdev)->driver_data;
> -
> -       mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
> -       if (!mmc) {
> -               ret = -ENOMEM;
> -               goto probe_out;
> -       }
> +       host->variant = (const struct s3cmci_variant_data *)
> +               platform_get_device_id(pdev)->driver_data;
>
>         for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
>                 ret = gpio_request(i, dev_name(&pdev->dev));
> @@ -1568,25 +1541,103 @@ static int s3cmci_probe(struct platform_device *pdev)
>                         for (i--; i >= S3C2410_GPE(5); i--)
>                                 gpio_free(i);
>
> -                       goto probe_free_host;
> +                       return ret;
>                 }
>         }
>
> +       if (!pdev->dev.platform_data)
> +               pdev->dev.platform_data = &s3cmci_def_pdata;
> +
> +       pdata = pdev->dev.platform_data;
> +
> +       if (pdata->no_wprotect)
> +               mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
> +
> +       if (pdata->no_detect)
> +               mmc->caps |= MMC_CAP_NEEDS_POLL;
> +
> +       if (pdata->wprotect_invert);
> +               mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
> +
> +       if (pdata->detect_invert)
> +                mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> +
> +       if (gpio_is_valid(pdata->gpio_detect)) {
> +               ret = mmc_gpio_request_cd(mmc, pdata->gpio_detect, 0);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "error requesting GPIO for CD %d\n",
> +                               ret);
> +                       return ret;
> +               }
> +       }
> +
> +       if (gpio_is_valid(pdata->gpio_wprotect)) {
> +               ret = mmc_gpio_request_ro(mmc, pdata->gpio_wprotect);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "error requesting GPIO for WP %d\n",
> +                               ret);
> +                       return ret;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int s3cmci_probe_dt(struct s3cmci_host *host)
> +{
> +       struct platform_device *pdev = host->pdev;
> +       struct s3c24xx_mci_pdata *pdata;
> +       struct mmc_host *mmc = host->mmc;
> +       int ret;
> +
> +       host->variant = of_device_get_match_data(&pdev->dev);
> +       if (!host->variant)
> +               return -ENODEV;
> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret)
> +               return ret;
> +
> +       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +       if (!pdata)
> +               return -ENOMEM;
> +
> +       pdev->dev.platform_data = pdata;
> +
> +       return 0;
> +}
> +
> +static int s3cmci_probe(struct platform_device *pdev)
> +{
> +       struct s3cmci_host *host;
> +       struct mmc_host *mmc;
> +       int ret;
> +       int i;
> +
> +       mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
> +       if (!mmc) {
> +               ret = -ENOMEM;
> +               goto probe_out;
> +       }
> +
>         host = mmc_priv(mmc);
>         host->mmc       = mmc;
>         host->pdev      = pdev;
> -       host->is2440    = is2440;
> +
> +       if (pdev->dev.of_node)
> +               ret = s3cmci_probe_dt(host);
> +       else
> +               ret = s3cmci_probe_pdata(host);
> +
> +       if (ret)
> +               goto probe_free_host;
>
>         host->pdata = pdev->dev.platform_data;
> -       if (!host->pdata) {
> -               pdev->dev.platform_data = &s3cmci_def_pdata;
> -               host->pdata = &s3cmci_def_pdata;
> -       }
>
>         spin_lock_init(&host->complete_lock);
>         tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
>
> -       if (is2440) {
> +       if (host->variant->s3c2440_compatible) {
>                 host->sdiimsk   = S3C2440_SDIIMSK;
>                 host->sdidata   = S3C2440_SDIDATA;
>                 host->clk_div   = 1;
> @@ -1644,43 +1695,6 @@ static int s3cmci_probe(struct platform_device *pdev)
>         disable_irq(host->irq);
>         host->irq_state = false;
>
> -       if (!host->pdata->no_detect) {
> -               ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
> -               if (ret) {
> -                       dev_err(&pdev->dev, "failed to get detect gpio\n");
> -                       goto probe_free_irq;
> -               }
> -
> -               host->irq_cd = gpio_to_irq(host->pdata->gpio_detect);
> -
> -               if (host->irq_cd >= 0) {
> -                       if (request_irq(host->irq_cd, s3cmci_irq_cd,
> -                                       IRQF_TRIGGER_RISING |
> -                                       IRQF_TRIGGER_FALLING,
> -                                       DRIVER_NAME, host)) {
> -                               dev_err(&pdev->dev,
> -                                       "can't get card detect irq.\n");
> -                               ret = -ENOENT;
> -                               goto probe_free_gpio_cd;
> -                       }
> -               } else {
> -                       dev_warn(&pdev->dev,
> -                                "host detect has no irq available\n");
> -                       gpio_direction_input(host->pdata->gpio_detect);
> -               }
> -       } else
> -               host->irq_cd = -1;
> -
> -       if (!host->pdata->no_wprotect) {
> -               ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
> -               if (ret) {
> -                       dev_err(&pdev->dev, "failed to get writeprotect\n");
> -                       goto probe_free_irq_cd;
> -               }
> -
> -               gpio_direction_input(host->pdata->gpio_wprotect);
> -       }
> -
>         /* Depending on the dma state, get a DMA channel to use. */
>
>         if (s3cmci_host_usedma(host)) {
> @@ -1688,7 +1702,7 @@ static int s3cmci_probe(struct platform_device *pdev)
>                 ret = PTR_ERR_OR_ZERO(host->dma);
>                 if (ret) {
>                         dev_err(&pdev->dev, "cannot get DMA channel.\n");
> -                       goto probe_free_gpio_wp;
> +                       goto probe_free_irq;
>                 }
>         }
>
> @@ -1730,7 +1744,7 @@ static int s3cmci_probe(struct platform_device *pdev)
>
>         dbg(host, dbg_debug,
>             "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
> -           (host->is2440?"2440":""),
> +           (host->variant->s3c2440_compatible?"2440":""),
>             host->base, host->irq, host->irq_cd, host->dma);
>
>         ret = s3cmci_cpufreq_register(host);
> @@ -1767,18 +1781,6 @@ static int s3cmci_probe(struct platform_device *pdev)
>         if (s3cmci_host_usedma(host))
>                 dma_release_channel(host->dma);
>
> - probe_free_gpio_wp:
> -       if (!host->pdata->no_wprotect)
> -               gpio_free(host->pdata->gpio_wprotect);
> -
> - probe_free_gpio_cd:
> -       if (!host->pdata->no_detect)
> -               gpio_free(host->pdata->gpio_detect);
> -
> - probe_free_irq_cd:
> -       if (host->irq_cd >= 0)
> -               free_irq(host->irq_cd, host);
> -
>   probe_free_irq:
>         free_irq(host->irq, host);
>
> @@ -1789,8 +1791,9 @@ static int s3cmci_probe(struct platform_device *pdev)
>         release_mem_region(host->mem->start, resource_size(host->mem));
>
>   probe_free_gpio:
> -       for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
> -               gpio_free(i);
> +       if (!pdev->dev.of_node)
> +               for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
> +                       gpio_free(i);
>
>   probe_free_host:
>         mmc_free_host(mmc);
> @@ -1817,7 +1820,6 @@ static int s3cmci_remove(struct platform_device *pdev)
>  {
>         struct mmc_host         *mmc  = platform_get_drvdata(pdev);
>         struct s3cmci_host      *host = mmc_priv(mmc);
> -       struct s3c24xx_mci_pdata *pd = host->pdata;
>         int i;
>
>         s3cmci_shutdown(pdev);
> @@ -1831,15 +1833,9 @@ static int s3cmci_remove(struct platform_device *pdev)
>
>         free_irq(host->irq, host);
>
> -       if (!pd->no_wprotect)
> -               gpio_free(pd->gpio_wprotect);
> -
> -       if (!pd->no_detect)
> -               gpio_free(pd->gpio_detect);
> -
> -       for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
> -               gpio_free(i);
> -
> +       if (!pdev->dev.of_node)
> +               for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
> +                       gpio_free(i);
>
>         iounmap(host->base);
>         release_mem_region(host->mem->start, resource_size(host->mem));
> @@ -1848,16 +1844,33 @@ static int s3cmci_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct of_device_id s3cmci_dt_match[] = {
> +       {
> +               .compatible = "samsung,s3c2410-sdi",
> +               .data = &s3c2410_s3cmci_variant_data,
> +       },
> +       {
> +               .compatible = "samsung,s3c2412-sdi",
> +               .data = &s3c2412_s3cmci_variant_data,
> +       },
> +       {
> +               .compatible = "samsung,s3c2440-sdi",
> +               .data = &s3c2440_s3cmci_variant_data,
> +       },
> +       { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
> +
>  static const struct platform_device_id s3cmci_driver_ids[] = {
>         {
>                 .name   = "s3c2410-sdi",
> -               .driver_data    = 0,
> +               .driver_data    = (kernel_ulong_t) &s3c2410_s3cmci_variant_data,
>         }, {
>                 .name   = "s3c2412-sdi",
> -               .driver_data    = 1,
> +               .driver_data    = (kernel_ulong_t) &s3c2412_s3cmci_variant_data,
>         }, {
>                 .name   = "s3c2440-sdi",
> -               .driver_data    = 1,
> +               .driver_data    = (kernel_ulong_t) &s3c2440_s3cmci_variant_data,
>         },
>         { }
>  };
> @@ -1867,6 +1880,7 @@ static int s3cmci_remove(struct platform_device *pdev)
>  static struct platform_driver s3cmci_driver = {
>         .driver = {
>                 .name   = "s3c-sdi",
> +               .of_match_table = s3cmci_dt_match,
>         },
>         .id_table       = s3cmci_driver_ids,
>         .probe          = s3cmci_probe,
> diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
> index 30c2c0dd1bc8..e9fe48915a2e 100644
> --- a/drivers/mmc/host/s3cmci.h
> +++ b/drivers/mmc/host/s3cmci.h
> @@ -33,7 +33,8 @@ struct s3cmci_host {
>         unsigned long           real_rate;
>         u8                      prescaler;
>
> -       int                     is2440;
> +       const struct s3cmci_variant_data *variant;
> +
>         unsigned                sdiimsk;
>         unsigned                sdidata;
>
> --
> 1.9.1
>

^ 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