This brings in the initial support for the Marvell Armada XP/370 SoCs.
Successfully tested on RD-A370-A1 and DB-MV784MP-GP boards the following
interfaces:
- Ethernet
- SDIO
- GPIOs
- SATA
Signed-off-by: Florian Fainelli <florian@openwrt.org>
SVN-Revision: 35058
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_CBUS_GPIO is not set
# CONFIG_I2C_CHARDEV is not set
# CONFIG_I2C_COMPAT is not set
# CONFIG_I2C_DEBUG_ALGO is not set
--- /dev/null
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=arm
+BOARD:=mvebu
+BOARDNAME:=Marvell Armada XP/370 boards
+FEATURES:=targz usb jffs2 pci pcie gpio
+CFLAGS:=-Os -pipe -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp
+MAINTAINER:=Florian Fainelli <florian@openwrt.org>
+
+LINUX_VERSION:=3.8-rc2
+
+include $(INCLUDE_DIR)/target.mk
+
+KERNELNAME:="zImage dtbs"
+
+DEFAULT_PACKAGES +=
+
+$(eval $(call BuildTarget))
--- /dev/null
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_AMBA_PL08X is not set
+# CONFIG_ARCH_BCM is not set
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MVEBU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SUNXI is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_VEXPRESS=y
+# CONFIG_ARCH_VEXPRESS_CA9X4 is not set
+CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
+# CONFIG_ARCH_VT8500_SINGLE is not set
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARM=y
+CONFIG_ARMADA_370_XP_TIMER=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_APPENDED_DTB=y
+# CONFIG_ARM_ATAG_DTB_COMPAT is not set
+# CONFIG_ARM_CHARLCD is not set
+# CONFIG_ARM_CPU_SUSPEND is not set
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_ERRATA_720789=y
+# CONFIG_ARM_ERRATA_743622 is not set
+CONFIG_ARM_ERRATA_751472=y
+# CONFIG_ARM_ERRATA_754322 is not set
+CONFIG_ARM_GIC=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_NR_BANKS=8
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_TIMER_SP804=y
+CONFIG_ASYNC_TX_DMA=y
+CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y
+CONFIG_ATAGS=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_BOUNCE=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_VERSATILE=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_PJ4B=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_INCLUDE="debug/mvebu.S"
+CONFIG_DEBUG_MVEBU_UART=y
+# CONFIG_DEBUG_PINCTRL is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_VEXPRESS_UART0_CA9 is not set
+# CONFIG_DEBUG_VEXPRESS_UART0_DETECT is not set
+# CONFIG_DEBUG_VEXPRESS_UART0_RS1 is not set
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DTC=y
+# CONFIG_DW_DMAC is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_FAT_FS=y
+CONFIG_FRAME_POINTER=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_MVEBU=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAVE_AOUT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_BPF_JIT=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PATA_PLATFORM=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_ICST=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_ISO9660_FS=y
+CONFIG_JBD=y
+CONFIG_JUMP_LABEL=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_MACH_ARMADA_XP=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MSDOS_FS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_PHYSMAP_OF is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MVEBU_CLK_CORE=y
+CONFIG_MVEBU_CLK_CPU=y
+CONFIG_MVEBU_CLK_GATING=y
+CONFIG_MVMDIO=y
+CONFIG_MVNETA=y
+CONFIG_MV_XOR=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_NEON is not set
+CONFIG_NET_DMA=y
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_NO_IOPORT=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+CONFIG_OF_NET=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PCI_SYSCALL is not set
+CONFIG_PERCPU_RWSEM=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PHYLIB=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_370=y
+CONFIG_PINCTRL_ARMADA_XP=y
+# CONFIG_PINCTRL_EXYNOS4 is not set
+CONFIG_PINCTRL_MVEBU=y
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_PINMUX=y
+# CONFIG_PL310_ERRATA_588369 is not set
+# CONFIG_PL310_ERRATA_727915 is not set
+CONFIG_PL310_ERRATA_753970=y
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_PL330_DMA is not set
+CONFIG_PLAT_ORION=y
+CONFIG_PLAT_VERSATILE=y
+CONFIG_PLAT_VERSATILE_CLCD=y
+CONFIG_PLAT_VERSATILE_SCHED_CLOCK=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_STATS=y
+CONFIG_UDF_FS=m
+CONFIG_UID16=y
+CONFIG_UIDGID_CONVERTED=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USE_OF=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VEXPRESS_CONFIG=y
+CONFIG_VFAT_FS=y
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_XEN is not set
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZONE_DMA_FLAG=0
--- /dev/null
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+TARGET_DTBS := armada-xp-db armada-370-db armada-xp-openblocks-ax3-4 armada-370-mirabox
+
+LOADADDR:=0x00008000
+
+JFFS2_BLOCKSIZE = 128k
+
+UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage
+ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y)
+ UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage-initramfs
+endif
+
+define Image/Build/MkuImage
+ mkimage -A arm -O linux -T kernel -a $(LOADADDR) -C none -e $(LOADADDR) \
+ -n 'ARM OpenWrt Linux-$(LINUX_VERSION)' -d $(1) $(2);
+endef
+
+define Image/Build/DTB
+ cp $(KDIR)/zImage $(KDIR)/zImage-$(1);
+ cat $(LINUX_DIR)/arch/$(ARCH)/boot/dts/$(1).dtb >> $(KDIR)/zImage-$(1);
+ $(call Image/Build/MkuImage,$(KDIR)/zImage-$(1),$(KDIR)/uImage-$(1))
+ cp $(KDIR)/uImage-$(1) $(UIMAGE)-$(1);
+endef
+
+define Image/Prepare
+ cp $(LINUX_DIR)/arch/$(ARCH)/boot/zImage $(KDIR)/zImage
+endef
+
+define Image/BuildKernel
+ $(foreach dtb,$(TARGET_DTBS),$(call Image/Build/DTB,$(dtb)))
+ $(call Image/Build/Initramfs)
+endef
+
+define Image/Build/squashfs
+ $(STAGING_DIR_HOST)/bin/padjffs2 $(KDIR)/root.squashfs 128
+endef
+
+define Image/Build
+ $(call Image/Build/$(1))
+ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync
+endef
+
+$(eval $(call BuildImage))
--- /dev/null
+From: Joshua Coombs <josh.coombs@gmail.com>
+
+If the Orion WDT driver is built as a module, an opps occurs during
+clk lookup when calling mvebu_clk_gating_get_src(). Remove the
+inappropriate __init tag so the function is available for modules
+after kernel init.
+
+Signed-off-by: Joshua Coombs <josh.coombs@gmail.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/clk/mvebu/clk-gating-ctrl.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
+index c6d3c26..8fa5408 100644
+--- a/drivers/clk/mvebu/clk-gating-ctrl.c
++++ b/drivers/clk/mvebu/clk-gating-ctrl.c
+@@ -32,7 +32,7 @@ struct mvebu_soc_descr {
+
+ #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+-static struct clk __init *mvebu_clk_gating_get_src(
++static struct clk *mvebu_clk_gating_get_src(
+ struct of_phandle_args *clkspec, void *data)
+ {
+ struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
+--
+1.7.10.4
--- /dev/null
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+When mv_xor_channel_add() fails for one XOR channel, we jump to the
+err_channel_add label to clean up all previous channels that had been
+initialized correctly. Unfortunately, while handling this error
+condition, we were disposing the IRQ mapping before calling
+mv_xor_channel_remove() (which does the free_irq()), which is
+incorrect.
+
+Instead, do things properly in the reverse order of the
+initialization: first remove the XOR channel (so that free_irq() is
+done), and then dispose the IRQ mapping.
+
+This avoids ugly warnings when for some reason one of the XOR channel
+fails to initialize.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/dma/mv_xor.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
+index ac71f55..cc5d23d 100644
+--- a/drivers/dma/mv_xor.c
++++ b/drivers/dma/mv_xor.c
+@@ -1361,9 +1361,9 @@ static int mv_xor_probe(struct platform_device *pdev)
+ err_channel_add:
+ for (i = 0; i < MV_XOR_MAX_CHANNELS; i++)
+ if (xordev->channels[i]) {
++ mv_xor_channel_remove(xordev->channels[i]);
+ if (pdev->dev.of_node)
+ irq_dispose_mapping(xordev->channels[i]->irq);
+- mv_xor_channel_remove(xordev->channels[i]);
+ }
+
+ clk_disable_unprepare(xordev->clk);
+--
+1.7.10.4
--- /dev/null
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+When a channel fails to initialize, we release all ressources,
+including clocks. However, a XOR unit is not necessarily associated to
+a clock (some variants of Marvell SoCs have a clock for XOR units,
+some don't), so we shouldn't unconditionally be releasing the clock.
+
+Instead, just like we do in the mv_xor_remove() function, we should
+check if one clock was found before releasing it.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/dma/mv_xor.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
+index cc5d23d..e17fad0 100644
+--- a/drivers/dma/mv_xor.c
++++ b/drivers/dma/mv_xor.c
+@@ -1366,8 +1366,11 @@ err_channel_add:
+ irq_dispose_mapping(xordev->channels[i]->irq);
+ }
+
+- clk_disable_unprepare(xordev->clk);
+- clk_put(xordev->clk);
++ if (!IS_ERR(xordev->clk)) {
++ clk_disable_unprepare(xordev->clk);
++ clk_put(xordev->clk);
++ }
++
+ return ret;
+ }
+
+--
+1.7.10.4
--- /dev/null
+From: Dmitri Epshtein <dima@marvell.com>
+
+In order for the driver to behave properly in a SMP context, the same
+transmit queue should be used by the kernel in dev_queue_xmit() and in
+the driver's mvneta_tx() function. To achieve that, the driver now
+implements the ->ndo_select_txq() operation.
+
+For now, it always returns the same transmit queue, txq_def, until the
+driver is expanded to properly take advantage of the multiqueue
+capabilities of the hardware.
+
+Without this patch, the network driver crashes the kernel almost
+immediately on Armada XP platforms, if the network load is at least a
+little bit parallel (i.e several threads).
+
+[Thomas Petazzoni: reword commit message]
+Signed-off-by: Dmitri Epshtein <dima@marvell.com>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+This is 3.8-rc material.
+---
+ drivers/net/ethernet/marvell/mvneta.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
+index b6025c3..af2c421 100644
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -1310,6 +1310,17 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
+ return MVNETA_TX_L4_CSUM_NOT;
+ }
+
++static u16 mvneta_tx_policy(struct mvneta_port *pp, struct sk_buff *skb)
++{
++ return (u16)txq_def;
++}
++
++static u16 mvneta_select_txq(struct net_device *dev, struct sk_buff *skb)
++{
++ struct mvneta_port *pp = netdev_priv(dev);
++ return mvneta_tx_policy(pp, skb);
++}
++
+ /* Returns rx queue pointer (find last set bit) according to causeRxTx
+ * value
+ */
+@@ -1476,7 +1487,8 @@ error:
+ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct mvneta_port *pp = netdev_priv(dev);
+- struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
++ u16 txq_id = mvneta_tx_policy(pp, skb);
++ struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
+ struct mvneta_tx_desc *tx_desc;
+ struct netdev_queue *nq;
+ int frags = 0;
+@@ -1486,7 +1498,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
+ goto out;
+
+ frags = skb_shinfo(skb)->nr_frags + 1;
+- nq = netdev_get_tx_queue(dev, txq_def);
++ nq = netdev_get_tx_queue(dev, txq_id);
+
+ /* Get a descriptor for the first part of the packet */
+ tx_desc = mvneta_txq_next_desc_get(txq);
+@@ -2550,6 +2562,7 @@ static const struct net_device_ops mvneta_netdev_ops = {
+ .ndo_change_mtu = mvneta_change_mtu,
+ .ndo_tx_timeout = mvneta_tx_timeout,
+ .ndo_get_stats64 = mvneta_get_stats64,
++ .ndo_select_queue = mvneta_select_txq,
+ };
+
+ const struct ethtool_ops mvneta_eth_tool_ops = {
+--
+1.7.9.5
--- /dev/null
+The Armada XP GPIO controller has two ways of notifying interrupts:
+using global interrupts or using per-CPU interrupts. In an attempt to
+use the best available features, the 'marvell,armadaxp-gpio'
+compatible string selects a variant of the gpio-mvebu driver that
+makes use of the per-CPU interrupts.
+
+Unfortunately, this doesn't work properly in a SMP context, because we
+fall into cases where the GPIO interrupt is enabled on CPU X at the
+GPIO controller level, but on CPU Y at the interrupt controller
+level. It is not yet clear how to fix that easily.
+
+So for 3.8, our approach is to switch to global interrupts for GPIOs,
+so that we do not fall into this per-CPU interrupts problem.
+
+This patch therefore fixes GPIO interrupts on Armada XP
+platforms. Without this patch, GPIO interrupts simply do not work
+reliably, because their proper operation depends on which CPU the code
+requesting the interrupt is running.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+This is 3.8-rc material.
+---
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi | 14 ++++++--------
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 21 +++++++++------------
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 21 +++++++++------------
+ 3 files changed, 24 insertions(+), 32 deletions(-)
+
+diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+index 271855a..e041f42 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+@@ -50,27 +50,25 @@
+ };
+
+ gpio0: gpio@d0018100 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018100 0x40>,
+- <0xd0018800 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018100 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <16>, <17>, <18>, <19>;
++ interrupts = <82>, <83>, <84>, <85>;
+ };
+
+ gpio1: gpio@d0018140 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018140 0x40>,
+- <0xd0018840 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018140 0x40>;
+ ngpios = <17>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <20>, <21>, <22>;
++ interrupts = <87>, <88>, <89>;
+ };
+ };
+ };
+diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+index 1c1937d..9e23bd8 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+@@ -51,39 +51,36 @@
+ };
+
+ gpio0: gpio@d0018100 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018100 0x40>,
+- <0xd0018800 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018100 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <16>, <17>, <18>, <19>;
++ interrupts = <82>, <83>, <84>, <85>;
+ };
+
+ gpio1: gpio@d0018140 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018140 0x40>,
+- <0xd0018840 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018140 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <20>, <21>, <22>, <23>;
++ interrupts = <87>, <88>, <89>, <90>;
+ };
+
+ gpio2: gpio@d0018180 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018180 0x40>,
+- <0xd0018870 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018180 0x40>;
+ ngpios = <3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <24>;
++ interrupts = <91>;
+ };
+
+ ethernet@d0034000 {
+diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+index 4905cf3..9659661 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+@@ -66,39 +66,36 @@
+ };
+
+ gpio0: gpio@d0018100 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018100 0x40>,
+- <0xd0018800 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018100 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <16>, <17>, <18>, <19>;
++ interrupts = <82>, <83>, <84>, <85>;
+ };
+
+ gpio1: gpio@d0018140 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018140 0x40>,
+- <0xd0018840 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018140 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <20>, <21>, <22>, <23>;
++ interrupts = <87>, <88>, <89>, <90>;
+ };
+
+ gpio2: gpio@d0018180 {
+- compatible = "marvell,armadaxp-gpio";
+- reg = <0xd0018180 0x40>,
+- <0xd0018870 0x30>;
++ compatible = "marvell,orion-gpio";
++ reg = <0xd0018180 0x40>;
+ ngpios = <3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupts-cells = <2>;
+- interrupts = <24>;
++ interrupts = <91>;
+ };
+
+ ethernet@d0034000 {
+--
+1.7.9.5
--- /dev/null
+The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice
+set of helper functions to simplify the management of the write
+protect GPIO in MMC host drivers. This patch migrates the mvsdio
+driver to using those helpers, which will make the ->probe() code
+simpler, and therefore ease the process of adding a Device Tree
+binding for this driver.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/mmc/host/mvsdio.c | 34 +++++-----------------------------
+ 1 file changed, 5 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+index de4c20b..a24a22f 100644
+--- a/drivers/mmc/host/mvsdio.c
++++ b/drivers/mmc/host/mvsdio.c
+@@ -22,6 +22,7 @@
+ #include <linux/clk.h>
+ #include <linux/gpio.h>
+ #include <linux/mmc/host.h>
++#include <linux/mmc/slot-gpio.h>
+
+ #include <asm/sizes.h>
+ #include <asm/unaligned.h>
+@@ -54,7 +55,6 @@ struct mvsd_host {
+ int irq;
+ struct clk *clk;
+ int gpio_card_detect;
+- int gpio_write_protect;
+ };
+
+ #define mvsd_write(offs, val) writel(val, iobase + (offs))
+@@ -566,20 +566,6 @@ static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable)
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+
+-static int mvsd_get_ro(struct mmc_host *mmc)
+-{
+- struct mvsd_host *host = mmc_priv(mmc);
+-
+- if (host->gpio_write_protect)
+- return gpio_get_value(host->gpio_write_protect);
+-
+- /*
+- * Board doesn't support read only detection; let the mmc core
+- * decide what to do.
+- */
+- return -ENOSYS;
+-}
+-
+ static void mvsd_power_up(struct mvsd_host *host)
+ {
+ void __iomem *iobase = host->base;
+@@ -676,7 +662,7 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+
+ static const struct mmc_host_ops mvsd_ops = {
+ .request = mvsd_request,
+- .get_ro = mvsd_get_ro,
++ .get_ro = mmc_gpio_get_ro,
+ .set_ios = mvsd_set_ios,
+ .enable_sdio_irq = mvsd_enable_sdio_irq,
+ };
+@@ -798,15 +784,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ if (!host->gpio_card_detect)
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+- if (mvsd_data->gpio_write_protect) {
+- ret = gpio_request(mvsd_data->gpio_write_protect,
+- DRIVER_NAME " wp");
+- if (ret == 0) {
+- gpio_direction_input(mvsd_data->gpio_write_protect);
+- host->gpio_write_protect =
+- mvsd_data->gpio_write_protect;
+- }
+- }
++ mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
+
+ setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
+ platform_set_drvdata(pdev, mmc);
+@@ -831,8 +809,7 @@ out:
+ free_irq(gpio_to_irq(host->gpio_card_detect), host);
+ gpio_free(host->gpio_card_detect);
+ }
+- if (host->gpio_write_protect)
+- gpio_free(host->gpio_write_protect);
++ mmc_gpio_free_ro(mmc);
+ if (host->base)
+ iounmap(host->base);
+ }
+@@ -861,8 +838,7 @@ static int __exit mvsd_remove(struct platform_device *pdev)
+ }
+ mmc_remove_host(mmc);
+ free_irq(host->irq, host);
+- if (host->gpio_write_protect)
+- gpio_free(host->gpio_write_protect);
++ mmc_gpio_free_ro(mmc);
+ del_timer_sync(&host->timer);
+ mvsd_power_down(host);
+ iounmap(host->base);
+--
+1.7.9.5
--- /dev/null
+The MMC core subsystem provides in drivers/mmc/core/slot-gpio.c a nice
+set of helper functions to simplify the management of the card detect
+GPIO in MMC host drivers. This patch migrates the mvsdio driver to
+using those helpers, which will make the ->probe() code simpler, and
+therefore ease the process of adding a Device Tree binding for this
+driver.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/mmc/host/mvsdio.c | 44 +++++++++-----------------------------------
+ 1 file changed, 9 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+index a24a22f..baf19fc 100644
+--- a/drivers/mmc/host/mvsdio.c
++++ b/drivers/mmc/host/mvsdio.c
+@@ -54,7 +54,6 @@ struct mvsd_host {
+ struct resource *res;
+ int irq;
+ struct clk *clk;
+- int gpio_card_detect;
+ };
+
+ #define mvsd_write(offs, val) writel(val, iobase + (offs))
+@@ -540,13 +539,6 @@ static void mvsd_timeout_timer(unsigned long data)
+ mmc_request_done(host->mmc, mrq);
+ }
+
+-static irqreturn_t mvsd_card_detect_irq(int irq, void *dev)
+-{
+- struct mvsd_host *host = dev;
+- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+- return IRQ_HANDLED;
+-}
+-
+ static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable)
+ {
+ struct mvsd_host *host = mmc_priv(mmc);
+@@ -765,23 +757,11 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ clk_prepare_enable(host->clk);
+ }
+
+- if (mvsd_data->gpio_card_detect) {
+- ret = gpio_request(mvsd_data->gpio_card_detect,
+- DRIVER_NAME " cd");
+- if (ret == 0) {
+- gpio_direction_input(mvsd_data->gpio_card_detect);
+- irq = gpio_to_irq(mvsd_data->gpio_card_detect);
+- ret = request_irq(irq, mvsd_card_detect_irq,
+- IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
+- DRIVER_NAME " cd", host);
+- if (ret == 0)
+- host->gpio_card_detect =
+- mvsd_data->gpio_card_detect;
+- else
+- gpio_free(mvsd_data->gpio_card_detect);
+- }
+- }
+- if (!host->gpio_card_detect)
++ if (gpio_is_valid(mvsd_data->gpio_card_detect)) {
++ ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect);
++ if (ret)
++ goto out;
++ } else
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+ mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
+@@ -794,9 +774,9 @@ static int __init mvsd_probe(struct platform_device *pdev)
+
+ pr_notice("%s: %s driver initialized, ",
+ mmc_hostname(mmc), DRIVER_NAME);
+- if (host->gpio_card_detect)
++ if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
+ printk("using GPIO %d for card detection\n",
+- host->gpio_card_detect);
++ mvsd_data->gpio_card_detect);
+ else
+ printk("lacking card detect (fall back to polling)\n");
+ return 0;
+@@ -805,10 +785,7 @@ out:
+ if (host) {
+ if (host->irq)
+ free_irq(host->irq, host);
+- if (host->gpio_card_detect) {
+- free_irq(gpio_to_irq(host->gpio_card_detect), host);
+- gpio_free(host->gpio_card_detect);
+- }
++ mmc_gpio_free_cd(mmc);
+ mmc_gpio_free_ro(mmc);
+ if (host->base)
+ iounmap(host->base);
+@@ -832,10 +809,7 @@ static int __exit mvsd_remove(struct platform_device *pdev)
+ if (mmc) {
+ struct mvsd_host *host = mmc_priv(mmc);
+
+- if (host->gpio_card_detect) {
+- free_irq(gpio_to_irq(host->gpio_card_detect), host);
+- gpio_free(host->gpio_card_detect);
+- }
++ mmc_gpio_free_cd(mmc);
+ mmc_remove_host(mmc);
+ free_irq(host->irq, host);
+ mmc_gpio_free_ro(mmc);
+--
+1.7.9.5
--- /dev/null
+This patch adds a simple Device Tree binding for the mvsdio driver, as
+well as the necessary documentation for it. Compatibility with non-DT
+platforms is preserved, by keeping the platform_data based
+initialization.
+
+We introduce a small difference between non-DT and DT platforms: DT
+platforms are required to provide a clocks = <...> property, which the
+driver uses to get the frequency of the clock that goes to the SDIO
+IP. The behaviour on non-DT platforms is kept unchanged: a clock
+reference is not mandatory, but the clock frequency must be passed in
+the "clock" field of the mvsdio_platform_data structure.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ .../devicetree/bindings/mmc/orion-sdio.txt | 17 ++++++
+ drivers/mmc/host/mvsdio.c | 60 +++++++++++++++-----
+ 2 files changed, 62 insertions(+), 15 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mmc/orion-sdio.txt
+
+diff --git a/Documentation/devicetree/bindings/mmc/orion-sdio.txt b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
+new file mode 100644
+index 0000000..84f0ebd
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
+@@ -0,0 +1,17 @@
++* Marvell orion-sdio controller
++
++This file documents differences between the core properties in mmc.txt
++and the properties used by the orion-sdio driver.
++
++- compatible: Should be "marvell,orion-sdio"
++- clocks: reference to the clock of the SDIO interface
++
++Example:
++
++ mvsdio@d00d4000 {
++ compatible = "marvell,orion-sdio";
++ reg = <0xd00d4000 0x200>;
++ interrupts = <54>;
++ clocks = <&gateclk 17>;
++ status = "disabled";
++ };
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+index baf19fc..56954bc 100644
+--- a/drivers/mmc/host/mvsdio.c
++++ b/drivers/mmc/host/mvsdio.c
+@@ -21,6 +21,8 @@
+ #include <linux/irq.h>
+ #include <linux/clk.h>
+ #include <linux/gpio.h>
++#include <linux/of_gpio.h>
++#include <linux/of_irq.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/slot-gpio.h>
+
+@@ -683,17 +685,17 @@ mv_conf_mbus_windows(struct mvsd_host *host,
+
+ static int __init mvsd_probe(struct platform_device *pdev)
+ {
++ struct device_node *np = pdev->dev.of_node;
+ struct mmc_host *mmc = NULL;
+ struct mvsd_host *host = NULL;
+- const struct mvsdio_platform_data *mvsd_data;
+ const struct mbus_dram_target_info *dram;
+ struct resource *r;
+ int ret, irq;
++ int gpio_card_detect, gpio_write_protect;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+- mvsd_data = pdev->dev.platform_data;
+- if (!r || irq < 0 || !mvsd_data)
++ if (!r || irq < 0)
+ return -ENXIO;
+
+ r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
+@@ -710,7 +712,35 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ host->mmc = mmc;
+ host->dev = &pdev->dev;
+ host->res = r;
+- host->base_clock = mvsd_data->clock / 2;
++
++ /* Some non-DT platforms do not pass a clock, and the clock
++ frequency is passed through platform_data. On DT platforms,
++ a clock must always be passed, even if there is no gatable
++ clock associated to the SDIO interface (it can simply be a
++ fixed rate clock). */
++ host->clk = clk_get(&pdev->dev, NULL);
++ if (!IS_ERR(host->clk))
++ clk_prepare_enable(host->clk);
++
++ if (np) {
++ if (IS_ERR(host->clk)) {
++ dev_err(&pdev->dev, "DT platforms must have a clock associated\n");
++ ret = -EINVAL;
++ goto out;
++ }
++
++ host->base_clock = clk_get_rate(host->clk) / 2;
++ gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0);
++ gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0);
++ } else {
++ const struct mvsdio_platform_data *mvsd_data;
++ mvsd_data = pdev->dev.platform_data;
++ if (!mvsd_data)
++ return -ENXIO;
++ host->base_clock = mvsd_data->clock / 2;
++ gpio_card_detect = mvsd_data->gpio_card_detect;
++ gpio_write_protect = mvsd_data->gpio_write_protect;
++ }
+
+ mmc->ops = &mvsd_ops;
+
+@@ -750,21 +780,14 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ } else
+ host->irq = irq;
+
+- /* Not all platforms can gate the clock, so it is not
+- an error if the clock does not exists. */
+- host->clk = clk_get(&pdev->dev, NULL);
+- if (!IS_ERR(host->clk)) {
+- clk_prepare_enable(host->clk);
+- }
+-
+- if (gpio_is_valid(mvsd_data->gpio_card_detect)) {
+- ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect);
++ if (gpio_is_valid(gpio_card_detect)) {
++ ret = mmc_gpio_request_cd(mmc, gpio_card_detect);
+ if (ret)
+ goto out;
+ } else
+ mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+- mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
++ mmc_gpio_request_ro(mmc, gpio_write_protect);
+
+ setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
+ platform_set_drvdata(pdev, mmc);
+@@ -776,7 +799,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ mmc_hostname(mmc), DRIVER_NAME);
+ if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
+ printk("using GPIO %d for card detection\n",
+- mvsd_data->gpio_card_detect);
++ gpio_card_detect);
+ else
+ printk("lacking card detect (fall back to polling)\n");
+ return 0;
+@@ -855,12 +878,19 @@ static int mvsd_resume(struct platform_device *dev)
+ #define mvsd_resume NULL
+ #endif
+
++static const struct of_device_id mvsdio_dt_ids[] = {
++ { .compatible = "marvell,orion-sdio" },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
++
+ static struct platform_driver mvsd_driver = {
+ .remove = __exit_p(mvsd_remove),
+ .suspend = mvsd_suspend,
+ .resume = mvsd_resume,
+ .driver = {
+ .name = DRIVER_NAME,
++ .of_match_table = mvsdio_dt_ids,
+ },
+ };
+
+--
+1.7.9.5
--- /dev/null
+On many Marvell SoCs, the pins used for the SDIO interface are part of
+the MPP pins, that are muxable pins. In order to get the muxing of
+those pins correct, this commit integrates the mvsdio driver with the
+pinctrl infrastructure by calling devm_pinctrl_get_select_default()
+during ->probe().
+
+Note that we permit this function to fail because not all Marvell
+platforms have yet been fully converted to using the pinctrl
+infrastructure.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/mmc/host/mvsdio.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+index 56954bc..feb16bd 100644
+--- a/drivers/mmc/host/mvsdio.c
++++ b/drivers/mmc/host/mvsdio.c
+@@ -25,6 +25,7 @@
+ #include <linux/of_irq.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/slot-gpio.h>
++#include <linux/pinctrl/consumer.h>
+
+ #include <asm/sizes.h>
+ #include <asm/unaligned.h>
+@@ -692,6 +693,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ struct resource *r;
+ int ret, irq;
+ int gpio_card_detect, gpio_write_protect;
++ struct pinctrl *pinctrl;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+@@ -713,6 +715,10 @@ static int __init mvsd_probe(struct platform_device *pdev)
+ host->dev = &pdev->dev;
+ host->res = r;
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "no pins associated\n");
++
+ /* Some non-DT platforms do not pass a clock, and the clock
+ frequency is passed through platform_data. On DT platforms,
+ a clock must always be passed, even if there is no gatable
+--
+1.7.9.5
--- /dev/null
+Now that the mvsdio MMC driver has a Device Tree binding, we add the
+Device Tree informations to describe the SDIO interface available in
+the Armada 370/XP SoCs.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370-xp.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
+index cf6c48a..41a5b11 100644
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -129,6 +129,14 @@
+ clocks = <&coreclk 0>;
+ status = "disabled";
+ };
++
++ mvsdio@d00d4000 {
++ compatible = "marvell,orion-sdio";
++ reg = <0xd00d4000 0x200>;
++ interrupts = <54>;
++ clocks = <&gateclk 17>;
++ status = "disabled";
++ };
+ };
+ };
+
+--
+1.7.9.5
--- /dev/null
+The SDIO interface is available either on pins MPP9/11/12/13/14/15 or
+MPP47/48/49/50/51/52 on the Armada 370. Even though all combinations
+are potentially possible, those two muxing options are the most
+probable ones, so we provide those at the SoC level .dtsi file.
+
+In practice, in turns out the Armada 370 DB board uses the former,
+while the Armada 370 Mirabox uses the latter.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370.dtsi | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
+index 636cf7d..88f9bab 100644
+--- a/arch/arm/boot/dts/armada-370.dtsi
++++ b/arch/arm/boot/dts/armada-370.dtsi
+@@ -47,6 +47,18 @@
+ pinctrl {
+ compatible = "marvell,mv88f6710-pinctrl";
+ reg = <0xd0018000 0x38>;
++
++ sdio_pins1: sdio-pins1 {
++ marvell,pins = "mpp9", "mpp11", "mpp12",
++ "mpp13", "mpp14", "mpp15";
++ marvell,function = "sd0";
++ };
++
++ sdio_pins2: sdio-pins2 {
++ marvell,pins = "mpp47", "mpp48", "mpp49",
++ "mpp50", "mpp51", "mpp52";
++ marvell,function = "sd0";
++ };
+ };
+
+ gpio0: gpio@d0018100 {
+--
+1.7.9.5
--- /dev/null
+The SDIO interface is only available on pins MPP30/31/32/33/34/35 on
+the various Armada XP variants, so we provide a pin muxing option for
+this in the Armada XP .dtsi files.
+
+Even though those muxing options are the same for MV78230, MV78260 and
+MV78460, we keep them in each .dtsi file, because the number of pins,
+and therefore the declaration of the pinctrl node, is different for
+each SoC variant.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi | 6 ++++++
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 6 ++++++
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 6 ++++++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+index c45c7b4..3fa9c84 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+@@ -40,6 +40,12 @@
+ pinctrl {
+ compatible = "marvell,mv78230-pinctrl";
+ reg = <0xd0018000 0x38>;
++
++ sdio_pins: sdio-pins {
++ marvell,pins = "mpp30", "mpp31", "mpp32",
++ "mpp33", "mpp34", "mpp35";
++ marvell,function = "sd0";
++ };
+ };
+
+ gpio0: gpio@d0018100 {
+diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+index a2aee57..5a907b3 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+@@ -48,6 +48,12 @@
+ pinctrl {
+ compatible = "marvell,mv78260-pinctrl";
+ reg = <0xd0018000 0x38>;
++
++ sdio_pins: sdio-pins {
++ marvell,pins = "mpp30", "mpp31", "mpp32",
++ "mpp33", "mpp34", "mpp35";
++ marvell,function = "sd0";
++ };
+ };
+
+ gpio0: gpio@d0018100 {
+diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+index da03a12..6dcdc50d 100644
+--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+@@ -63,6 +63,12 @@
+ pinctrl {
+ compatible = "marvell,mv78460-pinctrl";
+ reg = <0xd0018000 0x38>;
++
++ sdio_pins: sdio-pins {
++ marvell,pins = "mpp30", "mpp31", "mpp32",
++ "mpp33", "mpp34", "mpp35";
++ marvell,function = "sd0";
++ };
+ };
+
+ gpio0: gpio@d0018100 {
+--
+1.7.9.5
--- /dev/null
+The Armada XP DB evaluation board has one SD card slot, directly
+connected to the SDIO IP of the SoC, so we enable this
+IP. Unfortunately, there are no GPIOs for card-detect and
+write-protect.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp-db.dts | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
+index 8e53b25..c7035c5 100644
+--- a/arch/arm/boot/dts/armada-xp-db.dts
++++ b/arch/arm/boot/dts/armada-xp-db.dts
+@@ -90,5 +90,12 @@
+ phy = <&phy3>;
+ phy-mode = "sgmii";
+ };
++
++ mvsdio@d00d4000 {
++ pinctrl-0 = <&sdio_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++ /* No CD or WP GPIOs */
++ };
+ };
+ };
+--
+1.7.9.5
--- /dev/null
+The Armada XP DB evaluation board has one SD card slot, directly
+connected to the SDIO IP of the SoC, so we add a device tree
+description for it.
+
+However, in the default configuration of the board, the SD card slot
+is not usable: the connector plugged into CON40 must be changed
+against a different one, provided with the board by the
+manufacturer. Since such a manual modification of the hardware is
+needed, we did not enable the SDIO interface by default, and left it
+to the board user to modify the Device Tree if needed. Since this
+board is really only an evaluation board for developers and not a
+final product, it is not too bad.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+[florian: changed status to "okay" for RD-A370-A1]
+ arch/arm/boot/dts/armada-370-db.dts | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
+index 0004402..43ff156 100644
+--- a/arch/arm/boot/dts/armada-370-db.dts
++++ b/arch/arm/boot/dts/armada-370-db.dts
+@@ -59,5 +59,20 @@
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+ };
++
++ mvsdio@d00d4000 {
++ pinctrl-0 = <&sdio_pins1>;
++ pinctrl-names = "default";
++ /*
++ * This device is disabled by default, because
++ * using the SD card connector requires
++ * changing the default CON40 connector
++ * "DB-88F6710_MPP_2xRGMII_DEVICE_Jumper" to a
++ * different connector
++ * "DB-88F6710_MPP_RGMII_SD_Jumper".
++ */
++ status = "okay";
++ /* No CD or WP GPIOs */
++ };
+ };
+ };
+--
+1.7.9.5
--- /dev/null
+The Globalscale Mirabox uses the SDIO interface of the Armada 370 to
+connect to a Wifi/Bluetooth SD8787 chip, so we enable the SDIO
+interface of this board in its Device Tree file.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370-mirabox.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
+index 3b40713..1864820 100644
+--- a/arch/arm/boot/dts/armada-370-mirabox.dts
++++ b/arch/arm/boot/dts/armada-370-mirabox.dts
+@@ -52,5 +52,15 @@
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+ };
++
++ mvsdio@d00d4000 {
++ pinctrl-0 = <&sdio_pins2>;
++ pinctrl-names = "default";
++ status = "okay";
++ /*
++ * No CD or WP GPIOs: SDIO interface used for
++ * Wifi/Bluetooth chip
++ */
++ };
+ };
+ };
+--
+1.7.9.5
--- /dev/null
+From e84ed03e1c5d45305fdd9b872e0b7be97bcfda16 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 13 Dec 2012 15:03:27 +0100
+Subject: [PATCH] arm: cache-l2x0: aurora: Invalidate during clean operation
+ with WT enable
+
+This patch fixes a bug for Aurora L2 cache controller when the
+write-through mode is enable. For the clean operation even if we don't
+have to flush the lines we still need to invalidate them.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm/mm/cache-l2x0.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
+index 6911b8b..7ffe943 100644
+--- a/arch/arm/mm/cache-l2x0.c
++++ b/arch/arm/mm/cache-l2x0.c
+@@ -505,15 +505,21 @@ static void aurora_clean_range(unsigned long start, unsigned long end)
+
+ static void aurora_flush_range(unsigned long start, unsigned long end)
+ {
+- if (!l2_wt_override) {
+- start &= ~(CACHE_LINE_SIZE - 1);
+- end = ALIGN(end, CACHE_LINE_SIZE);
+- while (start != end) {
+- unsigned long range_end = calc_range_end(start, end);
++ start &= ~(CACHE_LINE_SIZE - 1);
++ end = ALIGN(end, CACHE_LINE_SIZE);
++ while (start != end) {
++ unsigned long range_end = calc_range_end(start, end);
++ /*
++ * If L2 is forced to WT, the L2 will always be clean and we
++ * just need to invalidate.
++ */
++ if (l2_wt_override)
+ aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+- AURORA_FLUSH_RANGE_REG);
+- start = range_end;
+- }
++ AURORA_INVAL_RANGE_REG);
++ else
++ aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
++ AURORA_FLUSH_RANGE_REG);
++ start = range_end;
+ }
+ }
+
+--
+1.7.10.4
+
--- /dev/null
+From 6c8928f877a1572f16cfc8a0c055d7e16320c741 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 13 Dec 2012 18:33:06 +0100
+Subject: [PATCH] arm: cache-l2x0: aurora: Use writel_relaxed instead of
+ writel
+
+The use of writel instead of writel_relaxed lead to deadlock in some
+situation (SMP on Armada 370 for instance). The use of writel_relaxed
+as it was done in the rest of this driver fixes this bug.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm/mm/cache-l2x0.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
+index 7ffe943..96a1ae4 100644
+--- a/arch/arm/mm/cache-l2x0.c
++++ b/arch/arm/mm/cache-l2x0.c
+@@ -459,8 +459,8 @@ static void aurora_pa_range(unsigned long start, unsigned long end,
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
+- writel(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
+- writel(end, l2x0_base + offset);
++ writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
++ writel_relaxed(end, l2x0_base + offset);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+
+ cache_sync();
+@@ -674,8 +674,9 @@ static void pl310_resume(void)
+ static void aurora_resume(void)
+ {
+ if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
+- writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
+- writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
++ writel_relaxed(l2x0_saved_regs.aux_ctrl,
++ l2x0_base + L2X0_AUX_CTRL);
++ writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
+ }
+ }
+
+--
+1.7.10.4
+
--- /dev/null
+From 3487b074a742bc3300683e91e3ade383b659fbe9 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Tue, 4 Dec 2012 18:04:59 +0100
+Subject: [PATCH] arm: mvebu: Use dw-apb-uart instead of ns16650 as UART
+ driver
+
+The UART controller used in the Armada 370 and Armada XP SoCs is the
+Synopsys DesignWare 8250 (aka Synopsys DesignWare ABP UART). The
+improper use of the ns16550 can lead to a kernel oops during boot if
+a character is sent to the UART before the initialization of the
+driver. The DW APB has an extra interrupt that gets raised when
+writing to the LCR when busy. This explains why we need to use
+dw-apb-uart driver to handle this.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370-xp.dtsi | 6 ++++--
+ arch/arm/boot/dts/armada-xp.dtsi | 6 ++++--
+ arch/arm/configs/mvebu_defconfig | 1 +
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
+index cf6c48a..4c0abe8 100644
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -50,17 +50,19 @@
+ ranges;
+
+ serial@d0012000 {
+- compatible = "ns16550";
++ compatible = "snps,dw-apb-uart";
+ reg = <0xd0012000 0x100>;
+ reg-shift = <2>;
+ interrupts = <41>;
++ reg-io-width = <4>;
+ status = "disabled";
+ };
+ serial@d0012100 {
+- compatible = "ns16550";
++ compatible = "snps,dw-apb-uart";
+ reg = <0xd0012100 0x100>;
+ reg-shift = <2>;
+ interrupts = <42>;
++ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
+index 367aa3f..8a85ffe 100644
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -42,17 +42,19 @@
+
+ soc {
+ serial@d0012200 {
+- compatible = "ns16550";
++ compatible = "snps,dw-apb-uart";
+ reg = <0xd0012200 0x100>;
+ reg-shift = <2>;
+ interrupts = <43>;
++ reg-io-width = <4>;
+ status = "disabled";
+ };
+ serial@d0012300 {
+- compatible = "ns16550";
++ compatible = "snps,dw-apb-uart";
+ reg = <0xd0012300 0x100>;
+ reg-shift = <2>;
+ interrupts = <44>;
++ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
+index a702fb3..3ba35f1 100644
+--- a/arch/arm/configs/mvebu_defconfig
++++ b/arch/arm/configs/mvebu_defconfig
+@@ -34,6 +34,7 @@ CONFIG_MARVELL_PHY=y
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_SERIAL_8250_DW=y
+ CONFIG_I2C=y
+ CONFIG_I2C_MV64XXX=y
+ CONFIG_GPIOLIB=y
+--
+1.7.10.4
+