Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM64: perf: support dwarf unwinding in compat mode
From: Will Deacon @ 2014-01-16 11:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389869123-5884-1-git-send-email-jean.pihet@linaro.org>

Hi Jean,

On Thu, Jan 16, 2014 at 10:45:23AM +0000, Jean Pihet wrote:
> Add support for unwinding using the dwarf information in compat
> mode. Using the correct user stack pointer allows perf to record
> the frames correctly in the native and compat modes.
> 
> Note that although the dwarf frame unwinding works ok using
> libunwind in native mode (on ARMv7 & ARMv8), some changes are
> required to the libunwind code for the compat mode. Those changes
> are posted separately on the libunwind mailing list.
> 
> Tested on ARMv8 platform with v8 and compat v7 binaries, the latter
> are statically built.

I guess it makes sense to include this with your earlier series adding
support for compat backtracing?

> Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
> ---
>  arch/arm64/include/asm/ptrace.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
> index fbb0020..86d5b54 100644
> --- a/arch/arm64/include/asm/ptrace.h
> +++ b/arch/arm64/include/asm/ptrace.h
> @@ -133,7 +133,7 @@ struct pt_regs {
>  	(!((regs)->pstate & PSR_F_BIT))
>  
>  #define user_stack_pointer(regs) \
> -	((regs)->sp)
> +	(!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)

In your previous series, compat backtracing is actually split out into a
separate function (compat_user_backtrace), so it would be more consistent to
have a compat_user_stack_pointer macro, rather than add this check here.

Will

^ permalink raw reply

* [PATCH 4/5] arm: omap3: twl: use the new lookup method with usb phy
From: Heikki Krogerus @ 2014-01-16 11:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52D6972B.2030704@ti.com>

On Wed, Jan 15, 2014 at 07:41:55PM +0530, Kishon Vijay Abraham I wrote:
> The point I'm trying to make is that we won't 'always' know the device names in
> advance.

In which cases do we not know the device names, and please note, cases
where we would need to use the lookup? The normal cases we would use
it are..

1) A driver creating a child device, like dwc3 when it creates the
xhci. There the parent just delivers the phys it has to the child, so
both the device name and the phys are known.

2) Platform code. Hopefully we can get rid of the platform code one
day, but in any case, when we use it, we always know at least how many
users a phy has, and if there is only a singe user, we can rely con_id
to do the matching. Though I still don't really see much risk in using
the controller device name also there. The lookup table should in any
case be made in the place where the phy devices are created, so the
phy name is definitely always known.

3) Phys part of something like mfd. This is in practice the same as
the platform code case. For example, with twl we always know there is
only one user for the phy, which is musb. So we can just use musb's
con_id if it's to scary to use "musb-hdrc.0".

In any other case, you get the phy from DT, and there is no need to
use the lookup when linking the phys and the users.

> Btw how are you planning to differentiate between multiple controllers of the
> same type with con_id?

You don't rely on the con_id alone in those cases. You then use the
device name. The con_id is just one parameter you can use to do the
matching.

> Maybe I'm missing the actual intention of this patch. Do you face problem if
> the PHY's have to know about it's consumers in ACPI?

<snip>

> >> I would rather leave the way it is modelled now.
> > 
> > Do you mean, leave it in the platform code? Why? We would reduce the
> > platform code by moving it to the mfd driver. Or did I misunderstood
> > something?
> 
> In this case, the lookup table will be used only for non-dt boot so don't see
> much use in moving to mfd driver.
> I meant if the new method is not solving any problem then I would prefer the
> way it is modelled now where the PHY's know about it's consumers.

OK, so that's what you meant. Things like that init_data promotes use
of platform data in the drivers, something that we really should get
rid of. Is that not a problem to you?

The phy drivers simply should not need to care about the consumers.
They should not need to care about anything DT, ACPI, platform
specific if it's possible, and here there is nothing preventing it.
Let me clarify..

The plan is that ultimately the drivers (meaning all the drivers, not
just phy) don't need to care about things like DT properties, ACPI
properties or anything DT, ACPI, platform specific. We will have
generic driver properties and capabilities and the upper layers will
take care of delivering the correct values from the source at hand.
The drivers can be made truly platform agnostic.

That is the goal, and we should make everything new by keeping that in
mind. Many existing frameworks are being converted to that direction,
like the gpio framework and DMA Engine API. The way you force the phy
drivers the deliver the consumers is taking a step backwards.

> Btw where does device gets created in ACPI boot?

drivers/acpi/acpi_platform.c

Thanks,

-- 
heikki

^ permalink raw reply

* device-tree: at91: irq and gpios: problem while requesting a gpio used as an interrupt source.
From: Jean-Jacques Hiblot @ 2014-01-16 12:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52D7BCAA.30706@atmel.com>

2014/1/16 Nicolas Ferre <nicolas.ferre@atmel.com>:
> On 16/01/2014 09:54, boris brezillon :
>> On 15/01/2014 19:06, Jean-Christophe PLAGNIOL-VILLARD wrote:
>>> On 11:35 Mon 13 Jan     , boris brezillon wrote:
>>>> On 13/01/2014 11:29, Jean-Jacques Hiblot wrote:
>>>>> Hello Nicolas, Jean-Christophe,
>>>>>
>>>>> As I was trying to enable the touchscreen on the at91sam9261ek with
>>>>> device-tree support, I ran into an issue. The touchscreen driver needs
>>>>> to know the state of the pendown gpio and also needs it as an
>>>>> interrupt source.
>>>>>
>>>>> The problem is that when a gpio is used as an interrupt, it's
>>>>> requested by the pinctrl driver during the xlate stage, marking it
>>>>> unavaliable for the other driver.
>>>>> It looks like the at91 pinctrl driver is the only one to use
>>>>> gpio_request() in the xlate stage. Maybe we should remove this:
>>>> You should only request it as a GPIO and then use gpio_to_irq to get the
>>>> related IRQ.
>>> This here a HUGE issue in the hole kernel
>>>
>>> You should NEVER known ti's a gpio in the driver at all gpio_to_irq should never
>>> exist you need to only see the irq
>>>
>>>> Because what is done here, is to solve the case where only the irq
>>>> is request, and in this specific case we need to request the pin as a
>>>> GPIO.
>>> this need to be handled at irq level not drivers
>>
>> Then propose something (or at least give us a deadline for this new
>> interrupt
>> model to come out), because the ADS7843E touchscreen is not working anymore
>> (at least on at91 platforms).
>>
>> What this driver needs is a level IRQ (not an edge IRQ). The code in
>> ads7846_hard_irq<http://lxr.free-electrons.com/ident?i=ads7846_hard_irq>
>> interrupt handler is here to transform an edge IRQ into a level IRQ.
>>
>> Is there a way to provide a generic framework to transform edge IRQs
>> into level IRQs
>> (because some GPIO controllers do not support level IRQs, and this is
>> the case for the
>> at91sam9261 one) ?
>>
>>
>> Of cource the gpio_to_irq approach is not perfect, but at least it as
>> the benefit to quickly
>> fix the bug, and we will still be able to improve this later, when we
>> have enough tools
>> (or mechanisms) to do it.
>
> Moreover, I do not see the rationale behind the concept of "interrupt
> with an electrical value". An interrupt signals an event and this event
> can be a transition or a state but an electrical value is the
> responsibility of a GPIO line, not the other way around.
>
> I see a code that could give the value of an electrical line related to
> an interrupt as a twisted interpretation of the notion of "interrupt".
> It surprises me that it could be thought as an enhancement that an IRQ
> coming from a GPIO could give a value!
>
> Isn't it why other people are also using this simple distinction to use
> their GPIO/IRQ mechanism? Maybe this is why we are the only ones to
> completely forbid this possibility.
>
> So, let's fix the bug, submit the modification to mainline, make
> platform work and see if somebody can convince me that retrieving an
> electrical line status from a GPIO is a "bad" thing...
>

I share your view on this.

Linus,
 the root of the issue is the fact that a GPIO can't be requested
twice. But IMO it's safe for a single device to request it more than
once and use it for different purposes (irq and electrical signal
value). Maybe we can rework the GPIO request to include this ownership
information. I can post a draft implementation for this if you think
it's worthwhile.

Jean-Jacques

> Bye,
> --
> Nicolas Ferre

^ permalink raw reply

* Huge lockdep warning from sdhci/imx esdhc code
From: Fabio Estevam @ 2014-01-16 12:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140116114654.GU15937@n2100.arm.linux.org.uk>

Hi Russell,

On Thu, Jan 16, 2014 at 9:46 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> ======================================================
> [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ]
> 3.13.0-rc7+ #401 Not tainted
> ------------------------------------------------------
> kworker/u8:1/44 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
>  (prepare_lock){+.+.+.}, at: [<c04d10d4>] clk_prepare_lock+0x80/0xf4
>
> and this task is already holding:
>  (&(&host->lock)->rlock){-.-...}, at: [<c04b0528>] sdhci_do_set_ios+0x20/0x740
> which would create a new lock dependency:
>  (&(&host->lock)->rlock){-.-...} -> (prepare_lock){+.+.+.}

Please apply this patch:
https://git.kernel.org/cgit/linux/kernel/git/cjb/mmc.git/commit/?h=mmc-next&id=a974862faee199cba3ff36b5a148df5fd34bd1e7

Regards,

Fabio Estevam

^ permalink raw reply

* [PATCH] arch_timer: Move delay timer to drivers clocksource
From: Will Deacon @ 2014-01-16 12:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52D76BC8.6080405@nvidia.com>

On Thu, Jan 16, 2014 at 05:19:04AM +0000, Prashant Gaikwad wrote:
> On Wednesday 15 January 2014 09:15 PM, Will Deacon wrote:
> > On Wed, Jan 15, 2014 at 01:07:07PM +0000, Prashant Gaikwad wrote:
> >> Now arch timer is registerd using generic sched timer, delay
> >> timer registration is the only part remaining in arch ports.
> >> Move this part to drivers clocksource and remove arch timer
> >> from arch ports.
> > What's the advantage in doing this? I'd have thought consolidation, but...
> 
> Primary objective of doing this to use other timers on SoC instead of 
> arch timers. It is observed that on ARM implementations of ARMv8 
> architecture context of per CPU logic of arch timer is not preserved 
> when CPU is powered down and reset is held during powerdown.
> 
> This makes arch timers unusable as wake events for some CPU idle states 
> where CPU core is powered down.
> 
> So we have two options:
> 1. Use system timers as broadcast timers and save/restore arch timers 
> context actross these CPU idle states.
> 2. Disable arch timer and use system timers.

Why can't you use the C3STOP feature so that the arch-timer isn't used when
you go idle?

There are several good reasons to use the architected timers when you can:

  - KVM requires them, as they have hardware support for virtualisation
  - The VDSO can make use of them to implement efficient gtod in userspace
  - They are per-cpu, so no need to broadcasting in software
  - They can generate events and allow userspace to implement efficient
    polling loops

> > What happens if I call udelay on arm64 before the counter has registered?
> 
> I will fix this in next patch. Do you have plan to add busy-loop for 
> arm64? Or I will have to initialize read counter function early.

Well, I assume the virtual counter (cntvct) still ticks on your system? If
so, I would suggest having that as the default delay implementation and
allowing it to be over-ridden later on.

The part I don't understand is why being `unusable as wake events' affects
the delay loop. All we need for that is the counter, the timers are irrelevant.

Will

^ permalink raw reply

* linux-next: manual merge of the libata tree with the arm-soc tree
From: Jason Cooper @ 2014-01-16 12:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140116114831.50261e22b6fb25aac2004b43@canb.auug.org.au>

Stephen,

Thanks, this looks good.

Arnd, Olof, Kevin,

This patch is in Tejun's tree because it is part of a patch series
fixing SATA hotplug.  That series is marked for stable.

thx,

Jason.

On Thu, Jan 16, 2014 at 11:48:31AM +1100, Stephen Rothwell wrote:
> Hi Tejun,
> 
> Today's linux-next merge of the libata tree got a conflict in
> arch/arm/boot/dts/armada-370-xp.dtsi between commit a095b1c78a35 ("ARM:
> mvebu: sort DT nodes by address") from the arm-soc tree and commit
> a96cc303e42a ("ARM: mvebu: update the SATA compatible string for Armada
> 370/XP") from the libata tree.
> 
> I fixed it up (see below) and can carry the fix as necessary (no action
> is required).
> 
> -- 
> Cheers,
> Stephen Rothwell                    sfr at canb.auug.org.au
> 
> diff --cc arch/arm/boot/dts/armada-370-xp.dtsi
> index b6b253924893,df141a1d6448..000000000000
> --- a/arch/arm/boot/dts/armada-370-xp.dtsi
> +++ b/arch/arm/boot/dts/armada-370-xp.dtsi
> @@@ -236,12 -183,13 +236,12 @@@
>   				status = "disabled";
>   			};
>   
>  -			i2c0: i2c at 11000 {
>  -				compatible = "marvell,mv64xxx-i2c";
>  -				#address-cells = <1>;
>  -				#size-cells = <0>;
>  -				interrupts = <31>;
>  -				timeout-ms = <1000>;
>  -				clocks = <&coreclk 0>;
>  +			sata at a0000 {
> - 				compatible = "marvell,orion-sata";
> ++				compatible = "marvell,armada-370-sata";
>  +				reg = <0xa0000 0x5000>;
>  +				interrupts = <55>;
>  +				clocks = <&gateclk 15>, <&gateclk 30>;
>  +				clock-names = "0", "1";
>   				status = "disabled";
>   			};
>   

^ permalink raw reply

* [PATCH] ARM64: perf: support dwarf unwinding in compat mode
From: Jean Pihet @ 2014-01-16 12:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140116115634.GE30257@mudshark.cambridge.arm.com>

On 16 January 2014 12:56, Will Deacon <will.deacon@arm.com> wrote:
> Hi Jean,
>
> On Thu, Jan 16, 2014 at 10:45:23AM +0000, Jean Pihet wrote:
>> Add support for unwinding using the dwarf information in compat
>> mode. Using the correct user stack pointer allows perf to record
>> the frames correctly in the native and compat modes.
>>
>> Note that although the dwarf frame unwinding works ok using
>> libunwind in native mode (on ARMv7 & ARMv8), some changes are
>> required to the libunwind code for the compat mode. Those changes
>> are posted separately on the libunwind mailing list.
>>
>> Tested on ARMv8 platform with v8 and compat v7 binaries, the latter
>> are statically built.
>
> I guess it makes sense to include this with your earlier series adding
> support for compat backtracing?
>
>> Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
>> ---
>>  arch/arm64/include/asm/ptrace.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
>> index fbb0020..86d5b54 100644
>> --- a/arch/arm64/include/asm/ptrace.h
>> +++ b/arch/arm64/include/asm/ptrace.h
>> @@ -133,7 +133,7 @@ struct pt_regs {
>>       (!((regs)->pstate & PSR_F_BIT))
>>
>>  #define user_stack_pointer(regs) \
>> -     ((regs)->sp)
>> +     (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
>
> In your previous series, compat backtracing is actually split out into a
> separate function (compat_user_backtrace), so it would be more consistent to
> have a compat_user_stack_pointer macro, rather than add this check here.

Do you mean this change instead?

diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 569b2187..9b88d2e 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -185,7 +185,8 @@ static inline bool arch_perf_have_user_stack_dump(void)
        return true;
 }

-#define perf_user_stack_pointer(regs) user_stack_pointer(regs)
+#define perf_user_stack_pointer(regs) \
+       (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
 #else
 static inline bool arch_perf_have_user_stack_dump(void)
 {

If so let me prepare/test and re-submit this.

Thx!
Jean

>
> Will

^ permalink raw reply related

* [PATCH v2] mmc: dw_mmc: fix dw_mci_get_cd
From: zhangfei @ 2014-01-16 12:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401161150.34258.arnd@arndb.de>



On 01/16/2014 06:50 PM, Arnd Bergmann wrote:
> On Thursday 16 January 2014, Zhangfei Gao wrote:
>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>> @@ -73,6 +73,8 @@ Optional properties:
>>
>>   * caps2-mmc-hs200-1_2v: Supports mmc HS200 SDR 1.2V mode
>>
>> +* caps2-mmc-cd-active-high: cd pin is high when card present
>> +
>>   * broken-cd: as documented in mmc core bindings.
>>
>>   * vmmc-supply: The phandle to the regulator to use for vmmc.  If this is
>
> No, don't introduce a new flag when there is already one defined
> in the generic mmc binding.

Got it.

Update with "cd-inverted".

      if (of_get_property(np, "cd-inverted", NULL))
                 pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;


Thanks

^ permalink raw reply

* [PATCH v3 1/3] ARM: sun7i/sun6i: irqchip: Add irqchip driver for NMI controller
From: Maxime Ripard @ 2014-01-16 12:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389453548-10665-2-git-send-email-carlo.caione@gmail.com>

Hi Carlo,

On Sat, Jan 11, 2014 at 04:19:06PM +0100, Carlo Caione wrote:
> Allwinner A20/A31 SoCs have special registers to control / (un)mask /
> acknowledge NMI. This NMI controller is separated and independent from GIC.
> This patch adds a new irqchip to manage NMI.
> 
> Signed-off-by: Carlo Caione <carlo.caione@gmail.com>
> ---
>  drivers/irqchip/Makefile        |   1 +
>  drivers/irqchip/irq-sunxi-nmi.c | 228 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 229 insertions(+)
>  create mode 100644 drivers/irqchip/irq-sunxi-nmi.c
> 
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index c60b901..e31d4d6 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)	+= irq-metag.o
>  obj-$(CONFIG_ARCH_MOXART)		+= irq-moxart.o
>  obj-$(CONFIG_ORION_IRQCHIP)		+= irq-orion.o
>  obj-$(CONFIG_ARCH_SUNXI)		+= irq-sun4i.o
> +obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi-nmi.o
>  obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
>  obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
>  obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
> diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
> new file mode 100644
> index 0000000..a2b7373
> --- /dev/null
> +++ b/drivers/irqchip/irq-sunxi-nmi.c
> @@ -0,0 +1,228 @@
> +/*
> + * Allwinner A20/A31 SoCs NMI IRQ chip driver.
> + *
> + * Carlo Caione <carlo.caione@gmail.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include "irqchip.h"
> +
> +#define SUNXI_NMI_SRC_TYPE_MASK	0x00000003
> +
> +enum {
> +	SUNXI_SRC_TYPE_LEVEL_LOW = 0,
> +	SUNXI_SRC_TYPE_EDGE_FALLING,
> +	SUNXI_SRC_TYPE_LEVEL_HIGH,
> +	SUNXI_SRC_TYPE_EDGE_RISING,
> +};
> +
> +struct sunxi_sc_nmi_reg_offs {
> +	u32 ctrl;
> +	u32 pend;
> +	u32 enable;
> +};
> +
> +static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = {
> +	.ctrl	= 0x00,
> +	.pend	= 0x04,
> +	.enable	= 0x08,
> +};
> +
> +static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
> +	.ctrl	= 0x00,
> +	.pend	= 0x04,
> +	.enable	= 0x34,
> +};
> +
> +/*
> + * Ack level interrupts right before unmask
> + *
> + * In case of level-triggered interrupt, IRQ line must be acked before it
> + * is unmasked or else a double-interrupt is triggered
> + */
> +
> +static void sunxi_sc_nmi_ack_and_unmask(struct irq_data *d)
> +{
> +	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> +	struct irq_chip_type *ct = irq_data_get_chip_type(d);
> +	u32 mask = d->mask;
> +
> +	if (irqd_get_trigger_type(d) & IRQ_TYPE_LEVEL_MASK)
> +		ct->chip.irq_ack(d);
> +
> +	irq_gc_lock(gc);
> +	irq_reg_writel(mask, gc->reg_base + ct->regs.mask);
> +	irq_gc_unlock(gc);
> +}

Hmmm, handle_level_irq seems to be doing exactly that already. It
first masks and acks the interrupts, and then unmask it, so we should
be fine, don't we?

> +static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
> +				      u32 val)
> +{
> +	irq_reg_writel(val, gc->reg_base + off);
> +}
> +
> +static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off)
> +{
> +	return irq_reg_readl(gc->reg_base + off);
> +}
> +
> +static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc)
> +{
> +	struct irq_domain *domain = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_get_chip(irq);
> +	unsigned int virq = irq_find_mapping(domain, 0);
> +
> +	chained_irq_enter(chip, desc);
> +	generic_handle_irq(virq);
> +	chained_irq_exit(chip, desc);
> +}
> +
> +static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
> +{
> +	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
> +	struct irq_chip_type *ct = gc->chip_types;
> +	u32 src_type_reg;
> +	u32 ctrl_off = ct->regs.type;
> +	unsigned int src_type;
> +	unsigned int i;
> +
> +	irq_gc_lock(gc);
> +
> +	switch (flow_type & IRQF_TRIGGER_MASK) {
> +	case IRQ_TYPE_EDGE_FALLING:
> +		src_type = SUNXI_SRC_TYPE_EDGE_FALLING;
> +		break;
> +	case IRQ_TYPE_EDGE_RISING:
> +		src_type = SUNXI_SRC_TYPE_EDGE_RISING;
> +		break;
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		src_type = SUNXI_SRC_TYPE_LEVEL_HIGH;
> +		break;
> +	case IRQ_TYPE_NONE:
> +	case IRQ_TYPE_LEVEL_LOW:
> +		src_type = SUNXI_SRC_TYPE_LEVEL_LOW;
> +		break;
> +	default:
> +		irq_gc_unlock(gc);
> +		pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n",
> +			__func__, data->irq);
> +		return -EBADR;
> +	}
> +
> +	irqd_set_trigger_type(data, flow_type);
> +	irq_setup_alt_chip(data, flow_type);
> +
> +	for (i = 0; i <= gc->num_ct; i++, ct++)
> +		if (ct->type & flow_type)
> +			ctrl_off = ct->regs.type;
> +
> +	src_type_reg = sunxi_sc_nmi_read(gc, ctrl_off);
> +	src_type_reg &= ~SUNXI_NMI_SRC_TYPE_MASK;
> +	src_type_reg |= src_type;
> +	sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg);
> +
> +	irq_gc_unlock(gc);
> +
> +	return IRQ_SET_MASK_OK;
> +}
> +
> +static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
> +					struct sunxi_sc_nmi_reg_offs *reg_offs)
> +{
> +	struct irq_domain *domain;
> +	struct irq_chip_generic *gc;
> +	unsigned int irq;
> +	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
> +	int ret;
> +
> +
> +	domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL);
> +	if (!domain) {
> +		pr_err("%s: Could not register interrupt domain.\n", node->name);
> +		return -ENOMEM;
> +	}
> +
> +	ret = irq_alloc_domain_generic_chips(domain, 1, 2, node->name,
> +					     handle_level_irq, clr, 0,
> +					     IRQ_GC_INIT_MASK_CACHE);
> +	if (ret) {
> +		 pr_err("%s: Could not allocate generic interrupt chip.\n",
> +			 node->name);
> +		 goto fail_irqd_remove;
> +	}
> +
> +	irq = irq_of_parse_and_map(node, 0);
> +	if (irq <= 0) {
> +		pr_err("%s: unable to parse irq\n", node->name);
> +		ret = -EINVAL;
> +		goto fail_irqd_remove;
> +	}
> +
> +	gc = irq_get_domain_generic_chip(domain, 0);
> +	gc->reg_base = of_iomap(node, 0);
> +	if (!gc->reg_base) {
> +		pr_err("%s: unable to map resource\n", node->name);
> +		ret = -ENOMEM;
> +		goto fail_irqd_remove;
> +	}
> +
> +	gc->chip_types[0].type			= IRQ_TYPE_LEVEL_MASK;
> +	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_set_bit;
> +	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_clr_bit;
> +	gc->chip_types[0].chip.irq_unmask	= sunxi_sc_nmi_ack_and_unmask;
> +	gc->chip_types[0].chip.irq_set_type	= sunxi_sc_nmi_set_type;
> +	gc->chip_types[0].regs.ack		= reg_offs->pend;
> +	gc->chip_types[0].regs.mask		= reg_offs->enable;
> +	gc->chip_types[0].regs.type		= reg_offs->ctrl;
> +
> +	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;
> +	gc->chip_types[1].chip.name		= gc->chip_types[0].chip.name;
> +	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_set_bit;
> +	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
> +	gc->chip_types[1].chip.irq_unmask	= sunxi_sc_nmi_ack_and_unmask;
> +	gc->chip_types[1].chip.irq_set_type	= sunxi_sc_nmi_set_type;
> +	gc->chip_types[1].regs.ack		= reg_offs->pend;
> +	gc->chip_types[1].regs.mask		= reg_offs->enable;
> +	gc->chip_types[1].regs.type		= reg_offs->ctrl;
> +	gc->chip_types[1].handler		= handle_edge_irq;
> +
> +	irq_set_handler_data(irq, domain);
> +	irq_set_chained_handler(irq, sunxi_sc_nmi_handle_irq);
> +
> +	sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
> +	sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1);

I really wonder whether it makes sense to have a generic chip here. It
seems to be much more complicated than it should. It's only about a
single interrupt interrupt chip here.

> +
> +	return 0;
> +
> +fail_irqd_remove:
> +	irq_domain_remove(domain);
> +
> +	return ret;
> +}
> +
> +static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
> +					struct device_node *parent)
> +{
> +	return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
> +}
> +IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-sc-nmi", sun6i_sc_nmi_irq_init);

I'm curious, where did you get these infos on the A31? :)


> +static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
> +					struct device_node *parent)
> +{
> +	return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
> +}
> +IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-sc-nmi", sun7i_sc_nmi_irq_init);

The compatibles should be sun6i-a31-* and sun7i-a20-*.

Thanks for your work!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140116/0150fad3/attachment.sig>

^ permalink raw reply

* [PATCH v4 0/11] iommu/arm-smmu: Misc modifications to support SMMUs on Calxeda ECX-2000
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is v4 of arm-smmu changes to support SMMUs on Calxeda ECX-2000.

Patches are based on v3.13-rc8.

Major change to previous version is new code that allows to extend an
existing IOMMU address mapping. (last two patches)

Changelog:
v4:
 - added support to extend the size of an IOMMU address mapping
 - check for duplicate stream IDs
 - Increase MAX_PHANDLE_ARGS
 - misc minor changes of patch
   "iommu/arm-smmu: Introduce automatic stream-id-masking"
v3:
  http://marc.info/?l=linux-arm-kernel&m=138212725606348
v2:
  http://marc.info/?l=linux-arm-kernel&m=138135834704855
v1:
   http://marc.info/?l=linux-arm-kernel&m=138122450023564


Regards,
Andreas

^ permalink raw reply

* [PATCH 01/11] iommu/arm-smmu: Introduce driver option handling
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

Introduce handling of driver options. Options are set based on DT
information when probing an SMMU device. The first option introduced
is "arm,smmu-isolate-devices". (It will be used in the bus notifier
block.)

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |   29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index e46a887..0b97d03 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -47,6 +47,9 @@
 
 #include <asm/pgalloc.h>
 
+/* Driver options */
+#define ARM_SMMU_OPT_ISOLATE_DEVICES		(1 << 0)
+
 /* Maximum number of stream IDs assigned to a single device */
 #define MAX_MASTER_STREAMIDS		8
 
@@ -348,6 +351,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_TRANS_S2		(1 << 3)
 #define ARM_SMMU_FEAT_TRANS_NESTED	(1 << 4)
 	u32				features;
+	u32				options;
 	int				version;
 
 	u32				num_context_banks;
@@ -398,6 +402,29 @@ struct arm_smmu_domain {
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
 static LIST_HEAD(arm_smmu_devices);
 
+struct arm_smmu_option_prop {
+	u32 opt;
+	const char *prop;
+};
+
+static struct arm_smmu_option_prop arm_smmu_options [] = {
+	{ ARM_SMMU_OPT_ISOLATE_DEVICES, "arm,smmu-isolate-devices" },
+	{ 0, NULL},
+};
+
+static void check_driver_options(struct arm_smmu_device *smmu)
+{
+	int i = 0;
+	do {
+		if (of_property_read_bool(smmu->dev->of_node,
+						arm_smmu_options[i].prop)) {
+			smmu->options |= arm_smmu_options[i].opt;
+			dev_dbg(smmu->dev, "option %s\n",
+				arm_smmu_options[i].prop);
+		}
+	} while (arm_smmu_options[++i].opt);
+}
+
 static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
 						struct device_node *dev_node)
 {
@@ -1783,6 +1810,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	}
 	smmu->dev = dev;
 
+	check_driver_options(smmu);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	smmu->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(smmu->base))
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 02/11] iommu/arm-smmu: Introduce bus notifier block
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

At the moment just handle BUS_NOTIFY_BIND_DRIVER to conditionally
isolate all master devices for an SMMU.

Depending on DT information each device is put into its own protection
domain (if possible).  For configuration with one or just a few
masters per SMMU that is easy to achieve.

In case of many devices per SMMU (e.g. MMU-500 with it's distributed
translation support) isolation of each device might not be possible --
depending on number of available SMR groups and/or context banks.

Default is that device isolation is contolled per SMMU with SMMU node
property "arm,smmu-isolate-devices" in a DT. If this property is set
for an SMMU node, device isolation is performed.

W/o device isolation the driver detects SMMUs but no translation is
configured (transactions just bypass translation process).

Note that for device isolation dma_base and size are fixed as 0 and
SZ_128M at the moment. Additional patches will address this
restriction and allow automatic growth of mapping size.

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 0b97d03..bc81dd0 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -46,6 +46,7 @@
 #include <linux/amba/bus.h>
 
 #include <asm/pgalloc.h>
+#include <asm/dma-iommu.h>
 
 /* Driver options */
 #define ARM_SMMU_OPT_ISOLATE_DEVICES		(1 << 0)
@@ -1964,6 +1965,48 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int arm_smmu_device_notifier(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct device *dev = data;
+	struct dma_iommu_mapping *mapping;
+	struct arm_smmu_device *smmu;
+	int ret;
+
+	switch (action) {
+	case BUS_NOTIFY_BIND_DRIVER:
+
+		arm_smmu_add_device(dev);
+		smmu = dev->archdata.iommu;
+		if (!smmu || !(smmu->options & ARM_SMMU_OPT_ISOLATE_DEVICES))
+			break;
+
+		mapping = arm_iommu_create_mapping(&platform_bus_type,
+						0, SZ_128M, 0);
+		if (IS_ERR(mapping)) {
+			ret = PTR_ERR(mapping);
+			dev_info(dev, "arm_iommu_create_mapping failed\n");
+			break;
+		}
+
+		ret = arm_iommu_attach_device(dev, mapping);
+		if (ret < 0) {
+			dev_info(dev, "arm_iommu_attach_device failed\n");
+			arm_iommu_release_mapping(mapping);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct notifier_block device_nb = {
+	.notifier_call = arm_smmu_device_notifier,
+};
+
 #ifdef CONFIG_OF
 static struct of_device_id arm_smmu_of_match[] = {
 	{ .compatible = "arm,smmu-v1", },
@@ -2000,6 +2043,8 @@ static int __init arm_smmu_init(void)
 	if (!iommu_present(&amba_bustype))
 		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
 
+	bus_register_notifier(&platform_bus_type, &device_nb);
+
 	return 0;
 }
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 03/11] iommu/arm-smmu: Support buggy implementation where all config accesses are secure
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

In such a case we have to use secure aliases of some non-secure
registers.

This handling is switched on by DT property
"calxeda,smmu-secure-config-access" for an SMMU node.

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |   31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index bc81dd0..823699e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -50,6 +50,7 @@
 
 /* Driver options */
 #define ARM_SMMU_OPT_ISOLATE_DEVICES		(1 << 0)
+#define ARM_SMMU_OPT_SECURE_CONFIG_ACCESS	(1 << 1)
 
 /* Maximum number of stream IDs assigned to a single device */
 #define MAX_MASTER_STREAMIDS		8
@@ -64,6 +65,15 @@
 #define ARM_SMMU_GR0(smmu)		((smmu)->base)
 #define ARM_SMMU_GR1(smmu)		((smmu)->base + (smmu)->pagesize)
 
+/*
+ * SMMU global address space with conditional offset to access secure aliases of
+ * non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448, nsGFSYNR0: 0x450)
+ */
+#define ARM_SMMU_GR0_NS(smmu)						\
+	((smmu)->base +							\
+		((smmu->options & ARM_SMMU_OPT_SECURE_CONFIG_ACCESS)	\
+			? 0x400 : 0))
+
 /* Page table bits */
 #define ARM_SMMU_PTE_PAGE		(((pteval_t)3) << 0)
 #define ARM_SMMU_PTE_CONT		(((pteval_t)1) << 52)
@@ -410,6 +420,7 @@ struct arm_smmu_option_prop {
 
 static struct arm_smmu_option_prop arm_smmu_options [] = {
 	{ ARM_SMMU_OPT_ISOLATE_DEVICES, "arm,smmu-isolate-devices" },
+	{ ARM_SMMU_OPT_SECURE_CONFIG_ACCESS, "calxeda,smmu-secure-config-access" },
 	{ 0, NULL},
 };
 
@@ -639,16 +650,16 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
 {
 	u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
 	struct arm_smmu_device *smmu = dev;
-	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
+	void __iomem *gr0_base = ARM_SMMU_GR0_NS(smmu);
 
 	gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
-	if (!gfsr)
-		return IRQ_NONE;
-
 	gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0);
 	gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1);
 	gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2);
 
+	if (!gfsr)
+		return IRQ_NONE;
+
 	dev_err_ratelimited(smmu->dev,
 		"Unexpected global fault, this could be serious\n");
 	dev_err_ratelimited(smmu->dev,
@@ -1586,9 +1597,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	int i = 0;
 	u32 reg;
 
-	/* Clear Global FSR */
-	reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR);
-	writel(reg, gr0_base + ARM_SMMU_GR0_sGFSR);
+	/* clear global FSR */
+	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
+	writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
 
 	/* Mark all SMRn as invalid and all S2CRn as bypass */
 	for (i = 0; i < smmu->num_mapping_groups; ++i) {
@@ -1608,7 +1619,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH);
 	writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH);
 
-	reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
+	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 
 	/* Enable fault reporting */
 	reg |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE);
@@ -1627,7 +1638,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 
 	/* Push the button */
 	arm_smmu_tlb_sync(smmu);
-	writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sCR0);
+	writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 }
 
 static int arm_smmu_id_size_to_bits(int size)
@@ -1961,7 +1972,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
 		free_irq(smmu->irqs[i], smmu);
 
 	/* Turn the thing off */
-	writel_relaxed(sCR0_CLIENTPD, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_sCR0);
+	writel(sCR0_CLIENTPD,ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 	return 0;
 }
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 04/11] iommu/arm-smmu: Introduce automatic stream-id-masking
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

Try to determine a mask that can be used for all StreamIDs of a master
device. This allows to use just one SMR group instead of
number-of-streamids SMR groups for a master device.

Changelog:
* dropped "#define DEBUG"
* removed  "BUG_ON(!is_power_of_2(nr))" from determine_smr_mask
  by passing an order instead of the actual number of streamids
  to this function.
* added check for master->num_used_smrs being 0 to
  determine_smr_mapping
* renamed num_used_smrs to num_s2crs
* added validation of calculated SMR mask and id field (against number
  of implemented bits of SMR

Notes:

* Check for duplicate stream IDs
  - not implemented with this patch but in a separate patch
  - If the same stream ID is specified for 2 masters further behaviour
    is implementation defined (we'll end with more than one matching
    entry in the stream mapping table).
  - If one stream ID is specified twice for a master device, the
    determination of how many S2CR/SMR groups are required for stream
    mapping will fail. Esp. it can happen that more than one matching
    entry is created in the stream mapping table.

* Sorting of stream IDs (to make usage of S2CR independend of sequence of
  stream IDs in DT)
  - intentionally not implemented
  - code does not rely on sorting
  - in fact sorting might make things worse with this simple
    implementation
    + Example: master with stream IDs 4, 5, 6, 0xe, 0xf requires 3
      SMRs when IDs are specified in this sorted order (one to map 4,
      5, one to map 6, one to map 0xe, 0xf) but just 2 SMRs when
      specified as 4, 5, 0xe, 0xf, 6 (one to map 4, 5, 0xe, 0xf and
      one SMR to map 6)
  - thus by modifying the DT information you can affect the number of
    S2CRs required for stream matching
  => I'd say "use common sense" when specifying stream IDs for a master
   device in DT.

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |  142 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 127 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 823699e..02a871e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -42,6 +42,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/bitops.h>
 
 #include <linux/amba/bus.h>
 
@@ -338,8 +339,9 @@ struct arm_smmu_master {
 	 * SMMU chain.
 	 */
 	struct rb_node			node;
-	int				num_streamids;
+	u32				num_streamids;
 	u16				streamids[MAX_MASTER_STREAMIDS];
+	int				num_s2crs;
 
 	/*
 	 * We only need to allocate these on the root SMMU, as we
@@ -381,6 +383,9 @@ struct arm_smmu_device {
 	u32				num_context_irqs;
 	unsigned int			*irqs;
 
+	u32				smr_mask_mask;
+	u32				smr_id_mask;
+
 	struct list_head		list;
 	struct rb_root			masters;
 };
@@ -1025,10 +1030,109 @@ static void arm_smmu_domain_destroy(struct iommu_domain *domain)
 	kfree(smmu_domain);
 }
 
+static int determine_smr_mask(struct arm_smmu_device *smmu,
+			struct arm_smmu_master *master,
+			struct arm_smmu_smr *smr, int start, int order)
+{
+	u16 i, zero_bits_mask, one_bits_mask, const_mask;
+	int nr;
+
+	nr = 1 << order;
+
+	if (nr == 1) {
+		/* no mask, use streamid to match and be done with it */
+		smr->mask = 0;
+		smr->id = master->streamids[start];
+		return 0;
+	}
+
+	zero_bits_mask = 0;
+	one_bits_mask = 0xffff;
+	for (i = start; i < start + nr; i++) {
+		zero_bits_mask |= master->streamids[i];   /* const 0 bits */
+		one_bits_mask &= master->streamids[i]; /* const 1 bits */
+	}
+	zero_bits_mask = ~zero_bits_mask;
+
+	/* bits having constant values (either 0 or 1) */
+	const_mask = zero_bits_mask | one_bits_mask;
+
+	i = hweight16(~const_mask);
+	if ((1 << i) == nr) {
+		smr->mask = ~const_mask;
+		smr->id = one_bits_mask;
+	} else {
+		/* no usable mask for this set of streamids */
+		return 1;
+	}
+
+	if (((smr->mask & smmu->smr_mask_mask) != smr->mask) ||
+		((smr->id & smmu->smr_id_mask) != smr->id))
+		/* insufficient number of mask/id bits */
+		return 1;
+
+	return 0;
+}
+
+static int determine_smr_mapping(struct arm_smmu_device *smmu,
+				struct arm_smmu_master *master,
+				struct arm_smmu_smr *smrs, int max_smrs)
+{
+	int nr_sid, nr, i, bit, start;
+
+	/*
+	 * This function is called only once -- when a master is added
+	 * to a domain. If master->num_s2crs != 0 then this master
+	 * was already added to a domain.
+	 */
+	BUG_ON(master->num_s2crs);
+
+	start = nr = 0;
+	nr_sid = master->num_streamids;
+	do {
+		/*
+		 * largest power-of-2 number of streamids for which to
+		 * determine a usable mask/id pair for stream matching
+		 */
+		bit = fls(nr_sid);
+		if (!bit)
+			return 0;
+
+		/*
+		 * iterate over power-of-2 numbers to determine
+		 * largest possible mask/id pair for stream matching
+		 * of next 2**i streamids
+		 */
+		for (i = bit - 1; i >= 0; i--) {
+			if(!determine_smr_mask(smmu, master,
+						&smrs[master->num_s2crs],
+						start, i))
+				break;
+		}
+
+		if (i < 0)
+			goto out;
+
+		nr = 1 << i;
+		nr_sid -= nr;
+		start += nr;
+		master->num_s2crs++;
+	} while (master->num_s2crs <= max_smrs);
+
+out:
+	if (nr_sid) {
+		/* not enough mapping groups available */
+		master->num_s2crs = 0;
+		return -ENOSPC;
+	}
+
+	return 0;
+}
+
 static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
 					  struct arm_smmu_master *master)
 {
-	int i;
+	int i, max_smrs, ret;
 	struct arm_smmu_smr *smrs;
 	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 
@@ -1038,42 +1142,45 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
 	if (master->smrs)
 		return -EEXIST;
 
-	smrs = kmalloc(sizeof(*smrs) * master->num_streamids, GFP_KERNEL);
+	max_smrs = min(smmu->num_mapping_groups, master->num_streamids);
+	smrs = kmalloc(sizeof(*smrs) * max_smrs, GFP_KERNEL);
 	if (!smrs) {
 		dev_err(smmu->dev, "failed to allocate %d SMRs for master %s\n",
-			master->num_streamids, master->of_node->name);
+			max_smrs, master->of_node->name);
 		return -ENOMEM;
 	}
 
+	ret = determine_smr_mapping(smmu, master, smrs, max_smrs);
+	if (ret)
+		goto err_free_smrs;
+
 	/* Allocate the SMRs on the root SMMU */
-	for (i = 0; i < master->num_streamids; ++i) {
+	for (i = 0; i < master->num_s2crs; ++i) {
 		int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
 						  smmu->num_mapping_groups);
 		if (IS_ERR_VALUE(idx)) {
 			dev_err(smmu->dev, "failed to allocate free SMR\n");
-			goto err_free_smrs;
+			goto err_free_bitmap;
 		}
-
-		smrs[i] = (struct arm_smmu_smr) {
-			.idx	= idx,
-			.mask	= 0, /* We don't currently share SMRs */
-			.id	= master->streamids[i],
-		};
+		smrs[i].idx = idx;
 	}
 
 	/* It worked! Now, poke the actual hardware */
-	for (i = 0; i < master->num_streamids; ++i) {
+	for (i = 0; i < master->num_s2crs; ++i) {
 		u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
 			  smrs[i].mask << SMR_MASK_SHIFT;
+		dev_dbg(smmu->dev, "SMR%d: 0x%x\n", smrs[i].idx, reg);
 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
 	}
 
 	master->smrs = smrs;
 	return 0;
 
-err_free_smrs:
+err_free_bitmap:
 	while (--i >= 0)
 		__arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx);
+	master->num_s2crs = 0;
+err_free_smrs:
 	kfree(smrs);
 	return -ENOSPC;
 }
@@ -1136,11 +1243,14 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
 	}
 
 	/* Now we're at the root, time to point at our context bank */
-	for (i = 0; i < master->num_streamids; ++i) {
+	if (!master->num_s2crs)
+		master->num_s2crs = master->num_streamids;
+	for (i = 0; i < master->num_s2crs; ++i) {
 		u32 idx, s2cr;
 		idx = master->smrs ? master->smrs[i].idx : master->streamids[i];
 		s2cr = (S2CR_TYPE_TRANS << S2CR_TYPE_SHIFT) |
 		       (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT);
+		dev_dbg(smmu->dev, "S2CR%d: 0x%x\n", idx, s2cr);
 		writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
 	}
 
@@ -1733,6 +1843,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 				mask, sid);
 			return -ENODEV;
 		}
+		smmu->smr_mask_mask = mask;
+		smmu->smr_id_mask = sid;
 
 		dev_notice(smmu->dev,
 			   "\tstream matching with %u register groups, mask 0x%x",
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] dts: i.MX: Add aliases
From: Sascha Hauer @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel

This adds some aliases to the i.MX5/6 dts files.

Sascha

----------------------------------------------------------------
Sascha Hauer (4):
      ARM: dts: imx53: Add mmc aliases
      ARM: dts: imx6q: Add spi4 alias
      ARM: dts: imx6qdl: Add mmc aliases
      ARM: dts: imx51: Add mmc aliases

 arch/arm/boot/dts/imx51.dtsi   | 4 ++++
 arch/arm/boot/dts/imx53.dtsi   | 4 ++++
 arch/arm/boot/dts/imx6q.dtsi   | 4 ++++
 arch/arm/boot/dts/imx6qdl.dtsi | 4 ++++
 4 files changed, 16 insertions(+)

^ permalink raw reply

* [PATCH 05/11] iommu/arm-smmu: Check for duplicate stream IDs when registering master devices
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |   25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 02a871e..a4e0c93 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -56,6 +56,9 @@
 /* Maximum number of stream IDs assigned to a single device */
 #define MAX_MASTER_STREAMIDS		8
 
+/* Maximum stream ID */
+#define ARM_SMMU_MAX_STREAMID		(SZ_64K - 1)
+
 /* Maximum number of context banks per SMMU */
 #define ARM_SMMU_MAX_CBS		128
 
@@ -386,6 +389,8 @@ struct arm_smmu_device {
 	u32				smr_mask_mask;
 	u32				smr_id_mask;
 
+	unsigned long			*sids;
+
 	struct list_head		list;
 	struct rb_root			masters;
 };
@@ -491,7 +496,7 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
 				struct device *dev,
 				struct of_phandle_args *masterspec)
 {
-	int i;
+	int i, sid;
 	struct arm_smmu_master *master;
 
 	master = find_smmu_master(smmu, masterspec->np);
@@ -516,8 +521,14 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
 	master->of_node		= masterspec->np;
 	master->num_streamids	= masterspec->args_count;
 
-	for (i = 0; i < master->num_streamids; ++i)
-		master->streamids[i] = masterspec->args[i];
+	for (i = 0; i < master->num_streamids; ++i) {
+		sid = masterspec->args[i];
+		if (test_and_set_bit(sid, smmu->sids)) {
+			dev_err(dev, "duplicate stream ID (%d)\n", sid);
+			return -EEXIST;
+		}
+		master->streamids[i] = sid;
+	}
 
 	return insert_smmu_master(smmu, master);
 }
@@ -1934,6 +1945,14 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	}
 	smmu->dev = dev;
 
+	smmu->sids = devm_kzalloc(dev, BITS_TO_LONGS(ARM_SMMU_MAX_STREAMID) *
+				sizeof(long), GFP_KERNEL);
+	if (!smmu->sids) {
+		dev_err(dev,
+			"failed to allocate bitmap for stream ID tracking\n");
+		return -ENOMEM;
+	}
+
 	check_driver_options(smmu);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/4] ARM: dts: imx53: Add mmc aliases
From: Sascha Hauer @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876261-29087-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boot/dts/imx53.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 4dbde25..84828b2 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -28,6 +28,10 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		mmc0 = &esdhc1;
+		mmc1 = &esdhc2;
+		mmc2 = &esdhc3;
+		mmc3 = &esdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH 06/11] documentation/iommu: Update description of ARM System MMU binding
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

This patch adds descriptions fore new properties of device tree
binding for the ARM SMMU architecture. These properties control
arm-smmu driver options.

Cc: Rob Herring <robherring2@gmail.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 .../devicetree/bindings/iommu/arm,smmu.txt         |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index e34c6cd..7ad8ff0 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -48,6 +48,16 @@ conditions.
                   from the mmu-masters towards memory) node for this
                   SMMU.
 
+- arm,smmu-isolate-devices : Enable device isolation for all masters
+                   of this SMMU. Ie. each master will be attached to
+                   its own iommu domain.
+
+- calxeda,smmu-secure-config-access : Enable proper handling of buggy
+                   implementations that always use secure access to
+                   SMMU configuration registers. In this case
+                   non-secure aliases of secure registers have to be
+                   used during SMMU configuration.
+
 Example:
 
         smmu {
@@ -67,4 +77,5 @@ Example:
                  */
                 mmu-masters = <&dma0 0xd01d 0xd01e>,
                               <&dma1 0xd11c>;
+                arm,smmu-isolate-devices;
         };
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 2/4] ARM: dts: imx6q: Add spi4 alias
From: Sascha Hauer @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876261-29087-1-git-send-email-s.hauer@pengutronix.de>

The quad version has a SPI controller more than the other
versions. Add an alias for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boot/dts/imx6q.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 021e0cb..52a9a2b 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -14,6 +14,10 @@
 #include "imx6qdl.dtsi"
 
 / {
+	aliases {
+		spi4 = &ecspi5;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH 07/11] iommu/arm-smmu: Set MAX_MASTER_STREAMIDS to MAX_PHANDLE_ARGS
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

The DT parsing code that determines stream IDs uses
of_parse_phandle_with_args and thus MAX_MASTER_STREAMIDS
is always bound by MAX_PHANDLE_ARGS.

Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 drivers/iommu/arm-smmu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a4e0c93..68bbe45 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -54,7 +54,7 @@
 #define ARM_SMMU_OPT_SECURE_CONFIG_ACCESS	(1 << 1)
 
 /* Maximum number of stream IDs assigned to a single device */
-#define MAX_MASTER_STREAMIDS		8
+#define MAX_MASTER_STREAMIDS		MAX_PHANDLE_ARGS
 
 /* Maximum stream ID */
 #define ARM_SMMU_MAX_STREAMID		(SZ_64K - 1)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 3/4] ARM: dts: imx6qdl: Add mmc aliases
From: Sascha Hauer @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876261-29087-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boot/dts/imx6qdl.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 8a86502..2dd30ec 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -26,6 +26,10 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		mmc2 = &usdhc3;
+		mmc3 = &usdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH 08/11] of: Increase MAX_PHANDLE_ARGS
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

arm-smmu driver uses of_parse_phandle_with_args when parsing DT
information to determine stream IDs for a master device.
Thus the number of stream IDs per master device is bound by
MAX_PHANDLE_ARGS.

To support Calxeda ECX-2000 hardware arm-smmu driver requires a
slightly higher value for MAX_PHANDLE_ARGS as this hardware has 10
stream IDs for one master device.

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree at vger.kernel.org
Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 include/linux/of.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/of.h b/include/linux/of.h
index 276c546..0807af8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -67,7 +67,7 @@ struct device_node {
 #endif
 };
 
-#define MAX_PHANDLE_ARGS 8
+#define MAX_PHANDLE_ARGS 10
 struct of_phandle_args {
 	struct device_node *np;
 	int args_count;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 4/4] ARM: dts: imx51: Add mmc aliases
From: Sascha Hauer @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876261-29087-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boot/dts/imx51.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index a462163..54e9063 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -25,6 +25,10 @@
 		gpio3 = &gpio4;
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
+		mmc0 = &esdhc1;
+		mmc1 = &esdhc2;
+		mmc2 = &esdhc3;
+		mmc3 = &esdhc4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH 09/11] ARM: dts: Add nodes for SMMUs on Calxeda ECX-2000
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 arch/arm/boot/dts/ecx-2000.dts    |   44 +++++++++++++++++++++++++++++++++++--
 arch/arm/boot/dts/ecx-common.dtsi |    9 +++++---
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/ecx-2000.dts b/arch/arm/boot/dts/ecx-2000.dts
index 2ccbb57f..722de49 100644
--- a/arch/arm/boot/dts/ecx-2000.dts
+++ b/arch/arm/boot/dts/ecx-2000.dts
@@ -76,10 +76,11 @@
 	};
 
 	soc {
-		ranges = <0x00000000 0x00000000 0x00000000 0xffffffff>;
+		ranges = <0x0 0x0 0x0 0xffffffff>;
 
 		timer {
-			compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; 			interrupts = <1 13 0xf08>,
+			compatible = "arm,cortex-a15-timer", "arm,armv7-timer";
+			interrupts = <1 13 0xf08>,
 				<1 14 0xf08>,
 				<1 11 0xf08>,
 				<1 10 0xf08>;
@@ -109,6 +110,45 @@
 			interrupts = <0 76 4  0 75 4  0 74 4  0 73 4>;
 		};
 	};
+
+	soc at 920000000 {
+		ranges = <0x9 0x20000000 0x9 0x20000000 0x290000>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+
+		smmu_mac0: smmu at 920000000 {
+			compatible = "arm,mmu-400";
+			reg = <0x9 0x20000000 0x10000>;
+			#global-interrupts = <1>;
+			interrupts = <0 106 4 0 106 4>;
+			mmu-masters = <&mac0 0 1>;
+			calxeda,smmu-secure-config-access;
+			arm,smmu-isolate-devices;
+		};
+
+		smmu_mac1: smmu at 920080000 {
+			compatible = "arm,mmu-400";
+			reg = <0x9 0x20080000 0x10000>;
+			#global-interrupts = <1>;
+			interrupts = <0 108 4 0 108 4>;
+			mmu-masters = <&mac1 0 1>;
+			calxeda,smmu-secure-config-access;
+			arm,smmu-isolate-devices;
+		};
+
+		smmu_sata: smmu at 920180000 {
+			compatible = "arm,mmu-400";
+			reg = <0x00000009 0x20180000 0x10000>;
+			mmu-masters = <&sata 0 1 2 3 4 5 6 7 8 9>;
+			#global-interrupts = <1>;
+			interrupts = <0 114 4 0 114 4>;
+			calxeda,smmu-secure-config-access;
+			arm,smmu-isolate-devices;
+		};
+	};
+
 };
 
 /include/ "ecx-common.dtsi"
diff --git a/arch/arm/boot/dts/ecx-common.dtsi b/arch/arm/boot/dts/ecx-common.dtsi
index b90045a..ad9b2fd 100644
--- a/arch/arm/boot/dts/ecx-common.dtsi
+++ b/arch/arm/boot/dts/ecx-common.dtsi
@@ -33,7 +33,7 @@
 		compatible = "simple-bus";
 		interrupt-parent = <&intc>;
 
-		sata at ffe08000 {
+		sata: sata at ffe08000 {
 			compatible = "calxeda,hb-ahci";
 			reg = <0xffe08000 0x10000>;
 			interrupts = <0 83 4>;
@@ -43,6 +43,7 @@
 					     &combophy0 3>;
 			calxeda,sgpio-gpio =<&gpioh 5 1 &gpioh 6 1 &gpioh 7 1>;
 			calxeda,led-order = <4 0 1 2 3>;
+			#stream-id-cells = <10>;
 		};
 
 		sdhci at ffe0e000 {
@@ -210,18 +211,20 @@
 			clock-names = "apb_pclk";
 		};
 
-		ethernet at fff50000 {
+		mac0: ethernet at fff50000 {
 			compatible = "calxeda,hb-xgmac";
 			reg = <0xfff50000 0x1000>;
 			interrupts = <0 77 4  0 78 4  0 79 4>;
 			dma-coherent;
+			#stream-id-cells = <2>;
 		};
 
-		ethernet at fff51000 {
+		mac1: ethernet at fff51000 {
 			compatible = "calxeda,hb-xgmac";
 			reg = <0xfff51000 0x1000>;
 			interrupts = <0 80 4  0 81 4  0 82 4>;
 			dma-coherent;
+			#stream-id-cells = <2>;
 		};
 
 		combophy0: combo-phy at fff58000 {
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 10/11] arm: dma-mapping: Add additional parameters to arm_iommu_create_mapping
From: Andreas Herrmann @ 2014-01-16 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389876263-25759-1-git-send-email-andreas.herrmann@calxeda.com>

The new parameters are

  dma_addr_t grow_size

         Specifies the size by which the mapping will be extended in
         case that no sufficient space is left in the mapping to
         handle an iova allocation request. If a grow_size of 0 is
         specified the mapping is not extended.

  dma_addr_t max_size

         Specifies the maximum size for the entire mapping --
         including all extensions made over time. The mapping can only
         be extended if the entire size is less than or equal to
         max_size.

Adapt existing calls to arm_iommu_create_mapping in exynos_drm_iommu.c
and shmobile-iommu.c such that they do not make use of the extension
feature.

Adapt existing call to arm_iommu_create_mapping in arm-smmu.c such
that the extension feature will be used.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Hiroshi Doyu <hdoyu@nvidia.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Inki Dae <inki.dae@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
---
 arch/arm/include/asm/dma-iommu.h          |    4 ++--
 arch/arm/mm/dma-mapping.c                 |    2 +-
 drivers/gpu/drm/exynos/exynos_drm_iommu.c |    4 ++--
 drivers/iommu/arm-smmu.c                  |    2 +-
 drivers/iommu/shmobile-iommu.c            |    2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index a8c56ac..50edacd 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -23,8 +23,8 @@ struct dma_iommu_mapping {
 };
 
 struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-			 int order);
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base,  size_t size,
+			int order, dma_addr_t grow_size, dma_addr_t max_size);
 
 void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
 
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f61a570..ccea46a 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1887,7 +1887,7 @@ struct dma_map_ops iommu_coherent_ops = {
  */
 struct dma_iommu_mapping *
 arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
-			 int order)
+			int order, dma_addr_t grow_size, dma_addr_t max_size)
 {
 	unsigned int count = size >> (PAGE_SHIFT + order);
 	unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index fb8db03..c1cd18b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -40,8 +40,8 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
 		priv->da_space_order = EXYNOS_DEV_ADDR_ORDER;
 
 	mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
-						priv->da_space_size,
-						priv->da_space_order);
+					priv->da_space_size,
+					priv->da_space_order, 0, 0);
 	if (IS_ERR(mapping))
 		return PTR_ERR(mapping);
 
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 68bbe45..31414e5 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2124,7 +2124,7 @@ static int arm_smmu_device_notifier(struct notifier_block *nb,
 			break;
 
 		mapping = arm_iommu_create_mapping(&platform_bus_type,
-						0, SZ_128M, 0);
+						0, SZ_128M, 0, SZ_128M, SZ_2G);
 		if (IS_ERR(mapping)) {
 			ret = PTR_ERR(mapping);
 			dev_info(dev, "arm_iommu_create_mapping failed\n");
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c
index d572863..1ba3a01 100644
--- a/drivers/iommu/shmobile-iommu.c
+++ b/drivers/iommu/shmobile-iommu.c
@@ -343,7 +343,7 @@ static int shmobile_iommu_add_device(struct device *dev)
 	mapping = archdata->iommu_mapping;
 	if (!mapping) {
 		mapping = arm_iommu_create_mapping(&platform_bus_type, 0,
-						   L1_LEN << 20, 0);
+						L1_LEN << 20, 0, 0, 0);
 		if (IS_ERR(mapping))
 			return PTR_ERR(mapping);
 		archdata->iommu_mapping = mapping;
-- 
1.7.9.5

^ permalink raw reply related


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