summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwigyori <wigyori@3c298f89-4303-0410-b956-a3cf2f4a3e73>2014-03-06 00:09:30 +0000
committerwigyori <wigyori@3c298f89-4303-0410-b956-a3cf2f4a3e73>2014-03-06 00:09:30 +0000
commit59d180d755c4f79fa07354b8484a7f7b25538d4e (patch)
tree0a2be71f002d9dd9084a172a72bef22388f0ca0e
parenta43b11d49a2880582433e4fc1acb1a6679b0705b (diff)
sunxi: driver refresh for 3.13
- update gmac / mmc / usb / ahci drivers to follow mainline dev trees - add driver for spi - update clock support - update a31 support - move to new DT compats where appropriate - re-order patchqueue where needed - verified working a20 smp - move most DTSes off files/ - update defconfig Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@39782 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--target/linux/sunxi/config-3.1320
-rw-r--r--target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts168
-rw-r--r--target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts168
-rw-r--r--target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts75
-rw-r--r--target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c908
-rw-r--r--target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h246
-rw-r--r--target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch95
-rw-r--r--target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch (renamed from target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch (renamed from target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch60
-rw-r--r--target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch (renamed from target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch)21
-rw-r--r--target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch139
-rw-r--r--target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch261
-rw-r--r--target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch112
-rw-r--r--target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch132
-rw-r--r--target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch (renamed from target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch (renamed from target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch (renamed from target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch (renamed from target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch)9
-rw-r--r--target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch (renamed from target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch56
-rw-r--r--target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch39
-rw-r--r--target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch (renamed from target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch)35
-rw-r--r--target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch50
-rw-r--r--target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch77
-rw-r--r--target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch223
-rw-r--r--target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch214
-rw-r--r--target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch45
-rw-r--r--target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch57
-rw-r--r--target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch146
-rw-r--r--target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch50
-rw-r--r--target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch73
-rw-r--r--target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch38
-rw-r--r--target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch (renamed from target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch)31
-rw-r--r--target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch (renamed from target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch)34
-rw-r--r--target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch41
-rw-r--r--target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch97
-rw-r--r--target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch96
-rw-r--r--target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch158
-rw-r--r--target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch131
-rw-r--r--target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch124
-rw-r--r--target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch55
-rw-r--r--target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch123
-rw-r--r--target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch273
-rw-r--r--target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch22
-rw-r--r--target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch45
-rw-r--r--target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch40
-rw-r--r--target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch48
-rw-r--r--target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch222
-rw-r--r--target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch255
-rw-r--r--target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch141
-rw-r--r--target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch211
-rw-r--r--target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch344
-rw-r--r--target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch188
-rw-r--r--target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch46
-rw-r--r--target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch352
-rw-r--r--target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch436
-rw-r--r--target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch90
-rw-r--r--target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch142
-rw-r--r--target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch167
-rw-r--r--target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch85
-rw-r--r--target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch47
-rw-r--r--target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch122
-rw-r--r--target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch127
-rw-r--r--target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch1187
-rw-r--r--target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch56
-rw-r--r--target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch49
-rw-r--r--target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch32
-rw-r--r--target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch34
-rw-r--r--target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch45
-rw-r--r--target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch (renamed from target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch)8
-rw-r--r--target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch (renamed from target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch)9
-rw-r--r--target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch44
-rw-r--r--target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch (renamed from target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch)11
-rw-r--r--target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch49
-rw-r--r--target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch26
-rw-r--r--target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch46
-rw-r--r--target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch493
-rw-r--r--target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch129
-rw-r--r--target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch27
-rw-r--r--target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch58
-rw-r--r--target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch (renamed from target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch)101
-rw-r--r--target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch81
-rw-r--r--target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch160
-rw-r--r--target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch78
-rw-r--r--target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch64
-rw-r--r--target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch107
-rw-r--r--target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch73
-rw-r--r--target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch27
-rw-r--r--target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch58
-rw-r--r--target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch80
-rw-r--r--target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch86
-rw-r--r--target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch83
-rw-r--r--target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch27
-rw-r--r--target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch46
-rw-r--r--target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch58
-rw-r--r--target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch339
-rw-r--r--target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch59
-rw-r--r--target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch104
-rw-r--r--target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch98
-rw-r--r--target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch30
-rw-r--r--target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch22
-rw-r--r--target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch896
-rw-r--r--target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch322
-rw-r--r--target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch392
-rw-r--r--target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch80
-rw-r--r--target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch77
-rw-r--r--target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch69
-rw-r--r--target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch83
-rw-r--r--target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch83
-rw-r--r--target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch56
-rw-r--r--target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch127
-rw-r--r--target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch50
-rw-r--r--target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch79
-rw-r--r--target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch95
-rw-r--r--target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch420
-rw-r--r--target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch34
-rw-r--r--target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch86
-rw-r--r--target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch62
-rw-r--r--target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch61
-rw-r--r--target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch34
-rw-r--r--target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch86
-rw-r--r--target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch62
-rw-r--r--target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch61
-rw-r--r--target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch55
-rw-r--r--target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch103
-rw-r--r--target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch72
-rw-r--r--target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch66
-rw-r--r--target/linux/sunxi/patches-3.13/190-sunxi-select-PSCI.patch (renamed from target/linux/sunxi/patches-3.13/180-sunxi-select-PSCI.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch24
-rw-r--r--target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch68
-rw-r--r--target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch187
-rw-r--r--target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch33
-rw-r--r--target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch29
-rw-r--r--target/linux/sunxi/patches-3.13/211-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch (renamed from target/linux/sunxi/patches-3.13/212-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/212-dt-sun7i-add-pinmuxing-for-extclocks.patch (renamed from target/linux/sunxi/patches-3.13/213-dt-sun7i-add-external-clk-outputs.patch)0
-rw-r--r--target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch62
-rw-r--r--target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch10
-rw-r--r--target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch57
-rw-r--r--target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch10
-rw-r--r--target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch57
-rw-r--r--target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch14
-rw-r--r--target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch85
-rw-r--r--target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch14
-rw-r--r--target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch14
-rw-r--r--target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch33
-rw-r--r--target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch32
-rw-r--r--target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch37
-rw-r--r--target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch35
-rw-r--r--target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch45
-rw-r--r--target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch55
-rw-r--r--target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch83
-rw-r--r--target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch177
-rw-r--r--target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch36
-rw-r--r--target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch111
-rw-r--r--target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch599
-rw-r--r--target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch82
-rw-r--r--target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch571
-rw-r--r--target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch85
-rw-r--r--target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch84
-rw-r--r--target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch67
-rw-r--r--target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch67
-rw-r--r--target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch38
-rw-r--r--target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch46
-rw-r--r--target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch53
-rw-r--r--target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch31
-rw-r--r--target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch86
-rw-r--r--target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch354
-rw-r--r--target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch86
-rw-r--r--target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch73
-rw-r--r--target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch58
-rw-r--r--target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch150
179 files changed, 14841 insertions, 4719 deletions
diff --git a/target/linux/sunxi/config-3.13 b/target/linux/sunxi/config-3.13
index fc3de0147c..a7f42fbca9 100644
--- a/target/linux/sunxi/config-3.13
+++ b/target/linux/sunxi/config-3.13
@@ -1,4 +1,4 @@
-# CONFIG_AHCI_SUNXI is not set
+CONFIG_AHCI_SUNXI=y
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
@@ -47,6 +47,7 @@ CONFIG_AUDIT=y
CONFIG_AUDIT_GENERIC=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_AVERAGE=y
+CONFIG_BCH=y
CONFIG_BINFMT_MISC=y
CONFIG_BLK_CGROUP=y
CONFIG_BLK_DEV_SD=y
@@ -139,6 +140,7 @@ CONFIG_EXT4_FS=y
CONFIG_FRAME_POINTER=y
CONFIG_FRAME_WARN=2048
CONFIG_FREEZER=y
+CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_GARP=y
CONFIG_GENERIC_ACL=y
@@ -152,6 +154,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
@@ -225,6 +228,7 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_IOSCHED_CFQ=y
CONFIG_IPC_NS=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -236,7 +240,6 @@ CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
-# CONFIG_JFFS2_CMODE_PRIORITY is not set
CONFIG_KALLSYMS=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
@@ -260,7 +263,6 @@ CONFIG_MMC_BLOCK=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MODULES_USE_ELF_REL=y
-# CONFIG_MTD is not set
CONFIG_MULTI_IRQ_HANDLER=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
@@ -284,6 +286,7 @@ 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_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
@@ -294,6 +297,7 @@ CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
+CONFIG_PHY_SUN4I_USB=y
CONFIG_PID_NS=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_SINGLE is not set
@@ -340,7 +344,6 @@ CONFIG_RESOURCE_COUNTERS=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_SATA_AHCI_PLATFORM=y
-# CONFIG_SATA_RCAR is not set
CONFIG_SCHED_HRTICK=y
CONFIG_SCSI=y
CONFIG_SECURITYFS=y
@@ -360,6 +363,10 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_SUN4I=y
+# CONFIG_SPI_SUN6I is not set
# CONFIG_STAGING is not set
# CONFIG_STMMAC_DA is not set
# CONFIG_STMMAC_DEBUG_FS is not set
@@ -371,6 +378,7 @@ CONFIG_STRICT_DEVMEM=y
CONFIG_SUN4I_TIMER=y
CONFIG_SUN5I_HSTIMER=y
CONFIG_SUNXI_WATCHDOG=y
+CONFIG_SWIOTLB=y
CONFIG_SWP_EMULATE=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TASKSTATS=y
@@ -381,6 +389,7 @@ CONFIG_TASK_XACCT=y
# CONFIG_THUMB2_KERNEL is not set
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TOUCHSCREEN_SUN4I=y
CONFIG_TREE_PREEMPT_RCU=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UID16=y
@@ -390,9 +399,8 @@ CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
-CONFIG_USB_SUNXI_EHCI=y
CONFIG_USB_SUPPORT=y
# CONFIG_USER_NS is not set
CONFIG_USE_OF=y
diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
deleted file mode 100644
index fa5ebbdc76..0000000000
--- a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <sr@denx.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-/include/ "sun4i-a10.dtsi"
-
-/ {
- model = "Olimex A10-Olinuxino LIME";
- compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10";
-
- soc@01c00000 {
- emac: ethernet@01c0b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&emac_pins_a>;
- phy = <&phy1>;
- status = "okay";
- };
-
- mdio@01c0b080 {
- status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
- };
-
- sdc0: sdc@01c0f000 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
- status = "okay";
- };
-
- sata: ahci@01c18000 {
- pwr-supply = <&reg_ahci_5v>;
- status = "okay";
- };
-
- pinctrl@01c20800 {
- ahci_pwr_pin: ahci_pwr_pin@0 {
- allwinner,pins = "PC3";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-
- mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-
- led_pins_olinuxino: led_pins@0 {
- allwinner,pins = "PH2";
- allwinner,function = "gpio_out";
- allwinner,drive = <1>;
- allwinner,pull = <0>;
- };
-
- usb1_vbus_pin: usb1_vbus_pin@0 {
- allwinner,pins = "PH6";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <2>;
- };
-
- usb2_vbus_pin: usb2_vbus_pin@0 {
- allwinner,pins = "PH3";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <2>;
- };
- };
-
- uart0: serial@01c28000 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_pins_a>;
- status = "okay";
- };
-
- i2c0: i2c@01c2ac00 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
- };
-
- i2c1: i2c@01c2b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins_a>;
- status = "okay";
- };
-
- ehci0: ehci0@0x01c14000 {
- vbus-supply = <&reg_usb1_vbus>;
- status = "okay";
- };
-
- ehci1: ehci1@0x01c1c000 {
- vbus-supply = <&reg_usb2_vbus>;
- status = "okay";
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&led_pins_olinuxino>;
-
- green {
- label = "a10-olinuxino-lime:green:usr";
- gpios = <&pio 7 2 0>;
- default-state = "on";
- };
- };
-
- regulators {
- compatible = "simple-bus";
-
- reg_usb1_vbus: usb1-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-
- reg_usb2_vbus: usb2-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
- };
-
- regulators {
- compatible = "simple-bus";
- pinctrl-names = "default";
-
- reg_ahci_5v: ahci-5v {
- compatible = "regulator-fixed";
- regulator-name = "ahci-5v";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- pinctrl-0 = <&ahci_pwr_pin>;
- gpio = <&pio 2 3 0>;
- enable-active-high;
- };
- };
-};
diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts
deleted file mode 100644
index 0cc7952030..0000000000
--- a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <sr@denx.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-/include/ "sun4i-a10.dtsi"
-
-/ {
- model = "pcDuino";
- compatible = "pcduino,a10-pcduino", "allwinner,sun4i-a10";
-
- aliases {
- serial0 = &uart0;
- serial1 = &uart1;
- };
-
- chosen {
- bootargs = "earlyprintk console=ttyS0,115200";
- };
-
- soc@01c00000 {
- emac: ethernet@01c0b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&emac_pins_a>;
- phy = <&phy1>;
- status = "okay";
- };
-
- mdio@01c0b080 {
- status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
- };
-
- sdc0: sdc@01c0f000 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_pcduino>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
- status = "okay";
- };
-
- pinctrl@01c20800 {
- mmc0_cd_pin_pcduino: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-
- led_pins_pcduino: led_pins@0 {
- allwinner,pins = "PH20", "PH21";
- allwinner,function = "gpio_out";
- allwinner,drive = <1>;
- allwinner,pull = <0>;
- };
-
- usb1_vbus_pin: usb1_vbus_pin@0 {
- allwinner,pins = "PH6";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <2>;
- };
-
- usb2_vbus_pin: usb2_vbus_pin@0 {
- allwinner,pins = "PH3";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <2>;
- };
- };
-
- uart0: serial@01c28000 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_pins_a>;
- status = "okay";
- };
-
- i2c0: i2c@01c2ac00 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
- };
-
- i2c1: i2c@01c2b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins_a>;
- status = "okay";
- };
-
- ehci0: ehci0@0x01c14000 {
- vbus-supply = <&reg_usb1_vbus>;
- status = "okay";
- };
-
- ehci1: ehci1@0x01c1c000 {
- vbus-supply = <&reg_usb2_vbus>;
- status = "okay";
- };
- };
-
- leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&led_pins_pcduino>;
-
- blue {
- label = "pcduino:blue:usr";
- gpios = <&pio 7 21 0>; /* LED1 */
- };
-
- green {
- label = "pcduino:green:usr";
- gpios = <&pio 7 20 0>; /* LED2 */
- linux,default-trigger = "heartbeat";
- };
- };
-
- regulators {
- compatible = "simple-bus";
-
- reg_usb1_vbus: usb1-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-
- reg_usb2_vbus: usb2-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
- };
-
- regulators {
- compatible = "simple-bus";
- pinctrl-names = "default";
-
- vcc_3v3_reg: regulator@0 {
- compatible = "regulator-fixed";
- regulator-name = "vcc_3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
-};
diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index 4ef28fd725..8b1477926b 100644
--- a/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -19,45 +19,7 @@
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
soc@01c00000 {
- sdc0: sdc@01c0f000 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_cubietruck>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
- status = "okay";
- };
-
- ehci0: ehci0@0x01c14000 {
- vbus-supply = <&reg_usb1_vbus>;
- status = "okay";
- };
-
- sata: ahci@01c18000 {
- pwr-supply = <&reg_ahci_5v>;
- status = "okay";
- };
-
- ehci1: ehci1@0x01c1c000 {
- vbus-supply = <&reg_usb2_vbus>;
- status = "okay";
- };
-
pinctrl@01c20800 {
- mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-
- ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
- allwinner,pins = "PH12";
- allwinner,function = "gpio_out";
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-
led_pins_cubietruck: led_pins@0 {
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
allwinner,function = "gpio_out";
@@ -112,41 +74,4 @@
gpios = <&pio 7 7 0>;
};
};
-
- regulators {
- compatible = "simple-bus";
- pinctrl-names = "default";
-
- reg_ahci_5v: ahci-5v {
- compatible = "regulator-fixed";
- regulator-name = "ahci-5v";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
- gpio = <&pio 7 12 0>;
- enable-active-high;
- };
-
- reg_usb1_vbus: usb1-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-
- reg_usb2_vbus: usb2-vbus {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
- };
};
diff --git a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c b/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c
deleted file mode 100644
index e091ebb877..0000000000
--- a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c
+++ /dev/null
@@ -1,908 +0,0 @@
-/*
- * Driver for sunxi SD/MMC host controllers
- * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
- * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
- * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
- * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
- * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include <linux/clk/sunxi.h>
-
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/sd.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-
-#include "sunxi-mci.h"
-
-static void sunxi_mmc_init_host(struct mmc_host *mmc)
-{
- u32 rval;
- struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
-
- /* reset controller */
- rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset;
- mci_writel(smc_host, REG_GCTRL, rval);
-
- mci_writel(smc_host, REG_FTRGL, 0x20070008);
- mci_writel(smc_host, REG_TMOUT, 0xffffffff);
- mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask);
- mci_writel(smc_host, REG_RINTR, 0xffffffff);
- mci_writel(smc_host, REG_DBGC, 0xdeb);
- mci_writel(smc_host, REG_FUNS, 0xceaa0000);
- mci_writel(smc_host, REG_DLBA, smc_host->sg_dma);
- rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb;
- rval &= ~SDXC_AccessDoneDirect;
- mci_writel(smc_host, REG_GCTRL, rval);
-}
-
-static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host)
-{
- mci_writel(smc_host, REG_GCTRL, SDXC_HWReset);
-}
-
-/* /\* UHS-I Operation Modes */
-/* * DS 25MHz 12.5MB/s 3.3V */
-/* * HS 50MHz 25MB/s 3.3V */
-/* * SDR12 25MHz 12.5MB/s 1.8V */
-/* * SDR25 50MHz 25MB/s 1.8V */
-/* * SDR50 100MHz 50MB/s 1.8V */
-/* * SDR104 208MHz 104MB/s 1.8V */
-/* * DDR50 50MHz 50MB/s 1.8V */
-/* * MMC Operation Modes */
-/* * DS 26MHz 26MB/s 3/1.8/1.2V */
-/* * HS 52MHz 52MB/s 3/1.8/1.2V */
-/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */
-/* * HS200 200MHz 200MB/s 1.8/1.2V */
-/* * */
-/* * Spec. Timing */
-/* * SD3.0 */
-/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */
-/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */
-/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */
-/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */
-/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */
-/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */
-/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
-
-/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */
-/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */
-/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */
-/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */
-/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */
-
-/* * eMMC4.5 */
-/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */
-/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
-/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
-/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */
-/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
-/* *\/ */
-
-static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
- struct mmc_data *data)
-{
- struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
- struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
- int i, max_len = (1 << host->idma_des_size_bits);
-
- for (i = 0; i < data->sg_len; i++) {
- pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN |
- SDXC_IDMAC_DES0_DIC;
-
- if (data->sg[i].length == max_len)
- pdes[i].buf_size = 0; /* 0 == max_len */
- else
- pdes[i].buf_size = data->sg[i].length;
-
- pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
- pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
- }
- pdes[0].config |= SDXC_IDMAC_DES0_FD;
- pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD;
-
- wmb(); /* Ensure idma_des hit main mem before we start the idmac */
-}
-
-static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data)
-{
- if (data->flags & MMC_DATA_WRITE)
- return DMA_TO_DEVICE;
- else
- return DMA_FROM_DEVICE;
-}
-
-static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host,
- struct mmc_data *data)
-{
- u32 dma_len;
- u32 i;
- u32 temp;
- struct scatterlist *sg;
-
- dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len,
- sunxi_mmc_get_dma_dir(data));
- if (dma_len == 0) {
- dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n");
- return -ENOMEM;
- }
-
- for_each_sg(data->sg, sg, data->sg_len, i) {
- if (sg->offset & 3 || sg->length & 3) {
- dev_err(mmc_dev(smc_host->mmc),
- "unaligned scatterlist: os %x length %d\n",
- sg->offset, sg->length);
- return -EINVAL;
- }
- }
-
- sunxi_mmc_init_idma_des(smc_host, data);
-
- temp = mci_readl(smc_host, REG_GCTRL);
- temp |= SDXC_DMAEnb;
- mci_writel(smc_host, REG_GCTRL, temp);
- temp |= SDXC_DMAReset;
- mci_writel(smc_host, REG_GCTRL, temp);
-
- mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST);
-
- if (!(data->flags & MMC_DATA_WRITE))
- mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt);
-
- mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn);
-
- return 0;
-}
-
-static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
- struct mmc_request *req)
-{
- u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD
- | SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION;
- u32 ri = 0;
- unsigned long expire = jiffies + msecs_to_jiffies(1000);
-
- mci_writel(host, REG_CARG, 0);
- mci_writel(host, REG_CMDR, cmd_val);
- do {
- ri = mci_readl(host, REG_RINTR);
- } while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) &&
- time_before(jiffies, expire));
-
- if (ri & SDXC_IntErrBit) {
- dev_err(mmc_dev(host->mmc), "send stop command failed\n");
- if (req->stop)
- req->stop->resp[0] = -ETIMEDOUT;
- } else {
- if (req->stop)
- req->stop->resp[0] = mci_readl(host, REG_RESP0);
- }
-
- mci_writel(host, REG_RINTR, 0xffff);
-}
-
-static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host)
-{
- struct mmc_command *cmd = smc_host->mrq->cmd;
- struct mmc_data *data = smc_host->mrq->data;
-
- /* For some cmds timeout is normal with sd/mmc cards */
- if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout &&
- (cmd->opcode == 5 || cmd->opcode == 52))
- return;
-
- dev_err(mmc_dev(smc_host->mmc),
- "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
- smc_host->mmc->index, cmd->opcode,
- data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
- smc_host->int_sum & SDXC_RespErr ? " RE" : "",
- smc_host->int_sum & SDXC_RespCRCErr ? " RCE" : "",
- smc_host->int_sum & SDXC_DataCRCErr ? " DCE" : "",
- smc_host->int_sum & SDXC_RespTimeout ? " RTO" : "",
- smc_host->int_sum & SDXC_DataTimeout ? " DTO" : "",
- smc_host->int_sum & SDXC_FIFORunErr ? " FE" : "",
- smc_host->int_sum & SDXC_HardWLocked ? " HL" : "",
- smc_host->int_sum & SDXC_StartBitErr ? " SBE" : "",
- smc_host->int_sum & SDXC_EndBitErr ? " EBE" : ""
- );
-}
-
-static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host)
-{
- struct mmc_request *mrq;
- unsigned long iflags;
-
- spin_lock_irqsave(&host->lock, iflags);
-
- mrq = host->mrq;
- if (!mrq) {
- spin_unlock_irqrestore(&host->lock, iflags);
- dev_err(mmc_dev(host->mmc), "no request to finalize\n");
- return;
- }
-
- if (host->int_sum & SDXC_IntErrBit) {
- sunxi_mmc_dump_errinfo(host);
- mrq->cmd->error = -ETIMEDOUT;
- if (mrq->data)
- mrq->data->error = -ETIMEDOUT;
- if (mrq->stop)
- mrq->stop->error = -ETIMEDOUT;
- } else {
- if (mrq->cmd->flags & MMC_RSP_136) {
- mrq->cmd->resp[0] = mci_readl(host, REG_RESP3);
- mrq->cmd->resp[1] = mci_readl(host, REG_RESP2);
- mrq->cmd->resp[2] = mci_readl(host, REG_RESP1);
- mrq->cmd->resp[3] = mci_readl(host, REG_RESP0);
- } else {
- mrq->cmd->resp[0] = mci_readl(host, REG_RESP0);
- }
- if (mrq->data)
- mrq->data->bytes_xfered =
- mrq->data->blocks * mrq->data->blksz;
- }
-
- if (mrq->data) {
- struct mmc_data *data = mrq->data;
- u32 temp;
-
- mci_writel(host, REG_IDST, 0x337);
- mci_writel(host, REG_DMAC, 0);
- temp = mci_readl(host, REG_GCTRL);
- mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset);
- temp &= ~SDXC_DMAEnb;
- mci_writel(host, REG_GCTRL, temp);
- temp |= SDXC_FIFOReset;
- mci_writel(host, REG_GCTRL, temp);
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- sunxi_mmc_get_dma_dir(data));
- }
-
- mci_writel(host, REG_RINTR, 0xffff);
-
- dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n",
- mrq->cmd->resp[0], mrq->cmd->resp[1],
- mrq->cmd->resp[2], mrq->cmd->resp[3]);
-
- host->mrq = NULL;
- host->int_sum = 0;
- host->wait_dma = 0;
-
- spin_unlock_irqrestore(&host->lock, iflags);
-
- if (mrq->data && mrq->data->error) {
- dev_err(mmc_dev(host->mmc),
- "data error, sending stop command\n");
- sunxi_mmc_send_manual_stop(host, mrq);
- }
-
- mmc_request_done(host->mmc, mrq);
-}
-
-static s32 sunxi_mmc_get_ro(struct mmc_host *mmc)
-{
- struct sunxi_mmc_host *host = mmc_priv(mmc);
-
- int read_only = 0;
-
- if (gpio_is_valid(host->wp_pin)) {
- pinctrl_request_gpio(host->wp_pin);
- read_only = gpio_get_value(host->wp_pin);
- }
-
- return read_only;
-}
-
-static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id)
-{
- struct sunxi_mmc_host *host = dev_id;
- u32 finalize = 0;
- u32 sdio_int = 0;
- u32 msk_int;
- u32 idma_int;
-
- spin_lock(&host->lock);
-
- idma_int = mci_readl(host, REG_IDST);
- msk_int = mci_readl(host, REG_MISTA);
-
- dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n",
- host->mrq, msk_int, idma_int);
-
- if (host->mrq) {
- if (idma_int & SDXC_IDMACReceiveInt)
- host->wait_dma = 0;
-
- host->int_sum |= msk_int;
-
- /* Wait for CmdDone on RespTimeout before finishing the req */
- if ((host->int_sum & SDXC_RespTimeout) &&
- !(host->int_sum & SDXC_CmdDone))
- mci_writel(host, REG_IMASK,
- host->sdio_imask | SDXC_CmdDone);
- else if (host->int_sum & SDXC_IntErrBit)
- finalize = 1; /* Don't wait for dma on error */
- else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma)
- finalize = 1; /* Done */
-
- if (finalize) {
- mci_writel(host, REG_IMASK, host->sdio_imask);
- mci_writel(host, REG_IDIE, 0);
- }
- }
-
- if (msk_int & SDXC_SDIOInt)
- sdio_int = 1;
-
- mci_writel(host, REG_RINTR, msk_int);
- mci_writel(host, REG_IDST, idma_int);
-
- spin_unlock(&host->lock);
-
- if (finalize)
- tasklet_schedule(&host->tasklet);
-
- if (sdio_int)
- mmc_signal_sdio_irq(host->mmc);
-
- return IRQ_HANDLED;
-}
-
-static void sunxi_mmc_tasklet(unsigned long data)
-{
- struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data;
- sunxi_mmc_finalize_request(smc_host);
-}
-
-static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
-{
- unsigned long expire = jiffies + msecs_to_jiffies(2000);
- u32 rval;
-
- rval = mci_readl(host, REG_CLKCR);
- rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn);
- if (oclk_en)
- rval |= SDXC_CardClkOn;
- if (!host->io_flag)
- rval |= SDXC_LowPowerOn;
- mci_writel(host, REG_CLKCR, rval);
-
- rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver;
- if (host->voltage_switching)
- rval |= SDXC_VolSwitch;
- mci_writel(host, REG_CMDR, rval);
- do {
- rval = mci_readl(host, REG_CMDR);
- } while (time_before(jiffies, expire) && (rval & SDXC_Start));
-
- if (rval & SDXC_Start) {
- dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
- host->ferror = 1;
- }
-}
-
-static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
- u32 oclk_dly, u32 sclk_dly)
-{
- unsigned long iflags;
- struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
-
- spin_lock_irqsave(&smc_host->lock, iflags);
- clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
- spin_unlock_irqrestore(&smc_host->lock, iflags);
-}
-
-struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
- { MMC_CLK_400K, 0, 7 },
- { MMC_CLK_25M, 0, 5 },
- { MMC_CLK_50M, 3, 5 },
- { MMC_CLK_50MDDR, 2, 4 },
- { MMC_CLK_50MDDR_8BIT, 2, 4 },
- { MMC_CLK_100M, 1, 4 },
- { MMC_CLK_200M, 1, 4 },
-};
-
-static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
- unsigned int rate)
-{
- u32 newrate;
- u32 src_clk;
- u32 oclk_dly;
- u32 sclk_dly;
- u32 temp;
- struct sunxi_mmc_clk_dly *dly = NULL;
-
- newrate = clk_round_rate(smc_host->clk_mod, rate);
- if (smc_host->clk_mod_rate == newrate) {
- dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n",
- rate, newrate);
- return;
- }
-
- dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n",
- rate, newrate);
-
- /* setting clock rate */
- clk_disable(smc_host->clk_mod);
- clk_set_rate(smc_host->clk_mod, newrate);
- clk_enable(smc_host->clk_mod);
- smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod);
- dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate);
-
- sunxi_mmc_oclk_onoff(smc_host, 0);
- /* clear internal divider */
- temp = mci_readl(smc_host, REG_CLKCR);
- temp &= ~0xff;
- mci_writel(smc_host, REG_CLKCR, temp);
-
- /* determine delays */
- if (rate <= 400000) {
- dly = &mmc_clk_dly[MMC_CLK_400K];
- } else if (rate <= 25000000) {
- dly = &mmc_clk_dly[MMC_CLK_25M];
- } else if (rate <= 50000000) {
- if (smc_host->ddr) {
- if (smc_host->bus_width == 8)
- dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT];
- else
- dly = &mmc_clk_dly[MMC_CLK_50MDDR];
- } else {
- dly = &mmc_clk_dly[MMC_CLK_50M];
- }
- } else if (rate <= 104000000) {
- dly = &mmc_clk_dly[MMC_CLK_100M];
- } else if (rate <= 208000000) {
- dly = &mmc_clk_dly[MMC_CLK_200M];
- } else
- dly = &mmc_clk_dly[MMC_CLK_50M];
-
- oclk_dly = dly->oclk_dly;
- sclk_dly = dly->sclk_dly;
-
- src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod));
- if (src_clk >= 300000000 && src_clk <= 400000000) {
- if (oclk_dly)
- oclk_dly--;
- if (sclk_dly)
- sclk_dly--;
- }
-
- sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
- sunxi_mmc_oclk_onoff(smc_host, 1);
-
- /* oclk_onoff sets various irq status bits, clear these */
- mci_writel(smc_host, REG_RINTR,
- mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt);
-}
-
-static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
- struct sunxi_mmc_host *host = mmc_priv(mmc);
- u32 temp;
- s32 err;
-
- /* Set the power state */
- switch (ios->power_mode) {
- case MMC_POWER_ON:
- break;
-
- case MMC_POWER_UP:
- if (!IS_ERR(host->vmmc)) {
- mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd);
- udelay(200);
- }
-
- err = clk_prepare_enable(host->clk_ahb);
- if (err) {
- dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err);
- host->ferror = 1;
- return;
- }
- err = clk_prepare_enable(host->clk_mod);
- if (err) {
- dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err);
- host->ferror = 1;
- return;
- }
-
- sunxi_mmc_init_host(mmc);
- enable_irq(host->irq);
-
- dev_dbg(mmc_dev(host->mmc), "power on!\n");
- host->ferror = 0;
- break;
-
- case MMC_POWER_OFF:
- dev_dbg(mmc_dev(host->mmc), "power off!\n");
- disable_irq(host->irq);
- sunxi_mmc_exit_host(host);
- clk_disable_unprepare(host->clk_ahb);
- clk_disable_unprepare(host->clk_mod);
- if (!IS_ERR(host->vmmc))
- mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
- host->ferror = 0;
- break;
- }
-
- /* set bus width */
- switch (ios->bus_width) {
- case MMC_BUS_WIDTH_1:
- mci_writel(host, REG_WIDTH, SDXC_WIDTH1);
- host->bus_width = 1;
- break;
- case MMC_BUS_WIDTH_4:
- mci_writel(host, REG_WIDTH, SDXC_WIDTH4);
- host->bus_width = 4;
- break;
- case MMC_BUS_WIDTH_8:
- mci_writel(host, REG_WIDTH, SDXC_WIDTH8);
- host->bus_width = 8;
- break;
- }
-
- /* set ddr mode */
- temp = mci_readl(host, REG_GCTRL);
- if (ios->timing == MMC_TIMING_UHS_DDR50) {
- temp |= SDXC_DDR_MODE;
- host->ddr = 1;
- } else {
- temp &= ~SDXC_DDR_MODE;
- host->ddr = 0;
- }
- mci_writel(host, REG_GCTRL, temp);
-
- /* set up clock */
- if (ios->clock && ios->power_mode) {
- dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock);
- sunxi_mmc_clk_set_rate(host, ios->clock);
- usleep_range(50000, 55000);
- }
-}
-
-static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
- struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
- unsigned long flags;
- u32 imask;
-
- spin_lock_irqsave(&smc_host->lock, flags);
- imask = mci_readl(smc_host, REG_IMASK);
- if (enable) {
- smc_host->sdio_imask = SDXC_SDIOInt;
- imask |= SDXC_SDIOInt;
- } else {
- smc_host->sdio_imask = 0;
- imask &= ~SDXC_SDIOInt;
- }
- mci_writel(smc_host, REG_IMASK, imask);
- spin_unlock_irqrestore(&smc_host->lock, flags);
-}
-
-static void sunxi_mmc_hw_reset(struct mmc_host *mmc)
-{
- struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
- mci_writel(smc_host, REG_HWRST, 0);
- udelay(10);
- mci_writel(smc_host, REG_HWRST, 1);
- udelay(300);
-}
-
-static int sunxi_mmc_card_present(struct mmc_host *mmc)
-{
- struct sunxi_mmc_host *host = mmc_priv(mmc);
-
- switch (host->cd_mode) {
- case CARD_DETECT_BY_GPIO_POLL:
- return !gpio_get_value(host->cd_pin); /* Signal inverted */
- case CARD_ALWAYS_PRESENT:
- return 1;
- }
- return 0; /* Never reached */
-}
-
-static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
- struct sunxi_mmc_host *host = mmc_priv(mmc);
- struct mmc_command *cmd = mrq->cmd;
- struct mmc_data *data = mrq->data;
- unsigned long iflags;
- u32 imask = SDXC_IntErrBit;
- u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f);
- u32 byte_cnt = 0;
- int ret;
-
- if (!sunxi_mmc_card_present(mmc) || host->ferror) {
- dev_dbg(mmc_dev(host->mmc), "no medium present\n");
- mrq->cmd->error = -ENOMEDIUM;
- mmc_request_done(mmc, mrq);
- return;
- }
-
- if (data) {
- byte_cnt = data->blksz * data->blocks;
- mci_writel(host, REG_BLKSZ, data->blksz);
- mci_writel(host, REG_BCNTR, byte_cnt);
- ret = sunxi_mmc_prepare_dma(host, data);
- if (ret < 0) {
- dev_err(mmc_dev(host->mmc), "prepare DMA failed\n");
- cmd->error = ret;
- cmd->data->error = ret;
- mmc_request_done(host->mmc, mrq);
- return;
- }
- }
-
- if (cmd->opcode == MMC_GO_IDLE_STATE) {
- cmd_val |= SDXC_SendInitSeq;
- imask |= SDXC_CmdDone;
- }
-
- if (cmd->opcode == SD_SWITCH_VOLTAGE) {
- cmd_val |= SDXC_VolSwitch;
- imask |= SDXC_VolChgDone;
- host->voltage_switching = 1;
- sunxi_mmc_oclk_onoff(host, 1);
- }
-
- if (cmd->flags & MMC_RSP_PRESENT) {
- cmd_val |= SDXC_RspExp;
- if (cmd->flags & MMC_RSP_136)
- cmd_val |= SDXC_LongRsp;
- if (cmd->flags & MMC_RSP_CRC)
- cmd_val |= SDXC_CheckRspCRC;
-
- if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) {
- cmd_val |= SDXC_DataExp | SDXC_WaitPreOver;
- if (cmd->data->flags & MMC_DATA_STREAM) {
- imask |= SDXC_AutoCMDDone;
- cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop;
- }
- if (cmd->data->stop) {
- imask |= SDXC_AutoCMDDone;
- cmd_val |= SDXC_SendAutoStop;
- } else
- imask |= SDXC_DataOver;
-
- if (cmd->data->flags & MMC_DATA_WRITE)
- cmd_val |= SDXC_Write;
- else
- host->wait_dma = 1;
- } else
- imask |= SDXC_CmdDone;
- } else
- imask |= SDXC_CmdDone;
-
- dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n",
- cmd_val & 0x3f, cmd_val, cmd->arg, imask,
- mrq->data ? mrq->data->blksz * mrq->data->blocks : 0);
-
- spin_lock_irqsave(&host->lock, iflags);
- host->mrq = mrq;
- mci_writel(host, REG_IMASK, host->sdio_imask | imask);
- spin_unlock_irqrestore(&host->lock, iflags);
-
- mci_writel(host, REG_CARG, cmd->arg);
- mci_writel(host, REG_CMDR, cmd_val);
-}
-
-static const struct of_device_id sunxi_mmc_of_match[] = {
- { .compatible = "allwinner,sun4i-mmc", },
- { .compatible = "allwinner,sun5i-mmc", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
-
-static struct mmc_host_ops sunxi_mmc_ops = {
- .request = sunxi_mmc_request,
- .set_ios = sunxi_mmc_set_ios,
- .get_ro = sunxi_mmc_get_ro,
- .get_cd = sunxi_mmc_card_present,
- .enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
- .hw_reset = sunxi_mmc_hw_reset,
-};
-
-static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
- struct platform_device *pdev)
-{
- struct device_node *np = pdev->dev.of_node;
- int ret;
-
- if (of_device_is_compatible(np, "allwinner,sun4i-mmc"))
- host->idma_des_size_bits = 13;
- else
- host->idma_des_size_bits = 16;
-
- host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc");
- if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- host->reg_base = devm_ioremap_resource(&pdev->dev,
- platform_get_resource(pdev, IORESOURCE_MEM, 0));
- if (IS_ERR(host->reg_base))
- return PTR_ERR(host->reg_base);
-
- host->irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0,
- "sunxi-mci", host);
- if (ret)
- return ret;
- disable_irq(host->irq);
-
- host->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
- if (IS_ERR(host->clk_ahb)) {
- dev_err(&pdev->dev, "Could not get ahb clock\n");
- return PTR_ERR(host->clk_ahb);
- }
-
- host->clk_mod = devm_clk_get(&pdev->dev, "mod");
- if (IS_ERR(host->clk_mod)) {
- dev_err(&pdev->dev, "Could not get mod clock\n");
- return PTR_ERR(host->clk_mod);
- }
-
- of_property_read_u32(np, "bus-width", &host->bus_width);
- if (host->bus_width != 1 && host->bus_width != 4) {
- dev_err(&pdev->dev, "Invalid bus-width %d\n", host->bus_width);
- return -EINVAL;
- }
-
- of_property_read_u32(np, "cd-mode", &host->cd_mode);
- switch (host->cd_mode) {
- case CARD_DETECT_BY_GPIO_POLL:
- host->cd_pin = of_get_named_gpio(np, "cd-gpios", 0);
- if (!gpio_is_valid(host->cd_pin)) {
- dev_err(&pdev->dev, "Invalid cd-gpios\n");
- return -EINVAL;
- }
- ret = devm_gpio_request(&pdev->dev, host->cd_pin, "mmc_cd");
- if (ret) {
- dev_err(&pdev->dev, "Could not get cd-gpios\n");
- return ret;
- }
- gpio_direction_input(host->cd_pin);
- break;
- case CARD_ALWAYS_PRESENT:
- break;
- default:
- dev_err(&pdev->dev, "Invalid cd-mode %d\n", host->cd_mode);
- return -EINVAL;
- }
-
- host->wp_pin = of_get_named_gpio(np, "wp-gpios", 0);
- if (gpio_is_valid(host->wp_pin)) {
- ret = devm_gpio_request(&pdev->dev, host->wp_pin, "mmc_wp");
- if (ret) {
- dev_err(&pdev->dev, "Could not get wp-gpios\n");
- return ret;
- }
- gpio_direction_input(host->wp_pin);
- }
-
- return 0;
-}
-
-static int sunxi_mmc_probe(struct platform_device *pdev)
-{
- struct sunxi_mmc_host *host;
- struct mmc_host *mmc;
- int ret;
-
- mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
- if (!mmc) {
- dev_err(&pdev->dev, "mmc alloc host failed\n");
- return -ENOMEM;
- }
-
- host = mmc_priv(mmc);
- host->mmc = mmc;
- spin_lock_init(&host->lock);
- tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host);
-
- ret = sunxi_mmc_resource_request(host, pdev);
- if (ret)
- goto error_free_host;
-
- host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
- &host->sg_dma, GFP_KERNEL);
- if (!host->sg_cpu) {
- dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n");
- ret = -ENOMEM;
- goto error_free_host;
- }
-
- mmc->ops = &sunxi_mmc_ops;
- mmc->max_blk_count = 8192;
- mmc->max_blk_size = 4096;
- mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des);
- mmc->max_seg_size = (1 << host->idma_des_size_bits);
- mmc->max_req_size = mmc->max_seg_size * mmc->max_segs;
- /* 400kHz ~ 50MHz */
- mmc->f_min = 400000;
- mmc->f_max = 50000000;
- /* available voltages */
- if (!IS_ERR(host->vmmc))
- mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc);
- else
- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-
- mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
- MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
- MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL |
- MMC_CAP_DRIVER_TYPE_A;
- if (host->bus_width == 4)
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
-
- ret = mmc_add_host(mmc);
- if (ret)
- goto error_free_dma;
-
- dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq);
- platform_set_drvdata(pdev, mmc);
- return 0;
-
-error_free_dma:
- dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
-error_free_host:
- mmc_free_host(mmc);
- return ret;
-}
-
-static int sunxi_mmc_remove(struct platform_device *pdev)
-{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct sunxi_mmc_host *host = mmc_priv(mmc);
-
- mmc_remove_host(mmc);
- sunxi_mmc_exit_host(host);
- tasklet_disable(&host->tasklet);
- dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
- mmc_free_host(mmc);
-
- return 0;
-}
-
-static struct platform_driver sunxi_mmc_driver = {
- .driver = {
- .name = "sunxi-mci",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(sunxi_mmc_of_match),
- },
- .probe = sunxi_mmc_probe,
- .remove = sunxi_mmc_remove,
-};
-module_platform_driver(sunxi_mmc_driver);
-
-MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>");
-MODULE_ALIAS("platform:sunxi-mmc");
diff --git a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h b/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h
deleted file mode 100644
index 332d3aee1a..0000000000
--- a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Driver for sunxi SD/MMC host controllers
- * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
- * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
- * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
- * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
- * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-#ifndef __SUNXI_MCI_H__
-#define __SUNXI_MCI_H__
-
-/* register offset define */
-#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */
-#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */
-#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */
-#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */
-#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */
-#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */
-#define SDXC_REG_CMDR (0x18) /* SMC Command Register */
-#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */
-#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */
-#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */
-#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */
-#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */
-#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */
-#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */
-#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */
-#define SDXC_REG_STAS (0x3C) /* SMC Status Register */
-#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */
-#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */
-#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */
-#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */
-#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */
-#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */
-#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */
-#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */
-#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */
-#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */
-#define SDXC_REG_CHDA (0x90)
-#define SDXC_REG_CBDA (0x94)
-
-#define mci_readl(host, reg) \
- __raw_readl((host)->reg_base + SDXC_##reg)
-#define mci_writel(host, reg, value) \
- __raw_writel((value), (host)->reg_base + SDXC_##reg)
-
-/* global control register bits */
-#define SDXC_SoftReset BIT(0)
-#define SDXC_FIFOReset BIT(1)
-#define SDXC_DMAReset BIT(2)
-#define SDXC_HWReset (SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset)
-#define SDXC_INTEnb BIT(4)
-#define SDXC_DMAEnb BIT(5)
-#define SDXC_DebounceEnb BIT(8)
-#define SDXC_PosedgeLatchData BIT(9)
-#define SDXC_DDR_MODE BIT(10)
-#define SDXC_MemAccessDone BIT(29)
-#define SDXC_AccessDoneDirect BIT(30)
-#define SDXC_ACCESS_BY_AHB BIT(31)
-#define SDXC_ACCESS_BY_DMA (0U << 31)
-/* clock control bits */
-#define SDXC_CardClkOn BIT(16)
-#define SDXC_LowPowerOn BIT(17)
-/* bus width */
-#define SDXC_WIDTH1 (0)
-#define SDXC_WIDTH4 (1)
-#define SDXC_WIDTH8 (2)
-/* smc command bits */
-#define SDXC_RspExp BIT(6)
-#define SDXC_LongRsp BIT(7)
-#define SDXC_CheckRspCRC BIT(8)
-#define SDXC_DataExp BIT(9)
-#define SDXC_Write BIT(10)
-#define SDXC_Seqmod BIT(11)
-#define SDXC_SendAutoStop BIT(12)
-#define SDXC_WaitPreOver BIT(13)
-#define SDXC_StopAbortCMD BIT(14)
-#define SDXC_SendInitSeq BIT(15)
-#define SDXC_UPCLKOnly BIT(21)
-#define SDXC_RdCEATADev BIT(22)
-#define SDXC_CCSExp BIT(23)
-#define SDXC_EnbBoot BIT(24)
-#define SDXC_AltBootOpt BIT(25)
-#define SDXC_BootACKExp BIT(26)
-#define SDXC_BootAbort BIT(27)
-#define SDXC_VolSwitch BIT(28)
-#define SDXC_UseHoldReg BIT(29)
-#define SDXC_Start BIT(31)
-/* interrupt bits */
-#define SDXC_RespErr BIT(1)
-#define SDXC_CmdDone BIT(2)
-#define SDXC_DataOver BIT(3)
-#define SDXC_TxDataReq BIT(4)
-#define SDXC_RxDataReq BIT(5)
-#define SDXC_RespCRCErr BIT(6)
-#define SDXC_DataCRCErr BIT(7)
-#define SDXC_RespTimeout BIT(8)
-#define SDXC_DataTimeout BIT(9)
-#define SDXC_VolChgDone BIT(10)
-#define SDXC_FIFORunErr BIT(11)
-#define SDXC_HardWLocked BIT(12)
-#define SDXC_StartBitErr BIT(13)
-#define SDXC_AutoCMDDone BIT(14)
-#define SDXC_EndBitErr BIT(15)
-#define SDXC_SDIOInt BIT(16)
-#define SDXC_CardInsert BIT(30)
-#define SDXC_CardRemove BIT(31)
-#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | \
- SDXC_DataCRCErr | SDXC_RespTimeout | \
- SDXC_DataTimeout | SDXC_FIFORunErr | \
- SDXC_HardWLocked | SDXC_StartBitErr | \
- SDXC_EndBitErr) /* 0xbbc2 */
-#define SDXC_IntDoneBit (SDXC_AutoCMDDone | SDXC_DataOver | \
- SDXC_CmdDone | SDXC_VolChgDone)
-/* status */
-#define SDXC_RXWLFlag BIT(0)
-#define SDXC_TXWLFlag BIT(1)
-#define SDXC_FIFOEmpty BIT(2)
-#define SDXC_FIFOFull BIT(3)
-#define SDXC_CardPresent BIT(8)
-#define SDXC_CardDataBusy BIT(9)
-#define SDXC_DataFSMBusy BIT(10)
-#define SDXC_DMAReq BIT(31)
-#define SDXC_FIFO_SIZE (16)
-/* Function select */
-#define SDXC_CEATAOn (0xceaaU << 16)
-#define SDXC_SendIrqRsp BIT(0)
-#define SDXC_SDIORdWait BIT(1)
-#define SDXC_AbtRdData BIT(2)
-#define SDXC_SendCCSD BIT(8)
-#define SDXC_SendAutoStopCCSD BIT(9)
-#define SDXC_CEATADevIntEnb BIT(10)
-/* IDMA controller bus mod bit field */
-#define SDXC_IDMACSoftRST BIT(0)
-#define SDXC_IDMACFixBurst BIT(1)
-#define SDXC_IDMACIDMAOn BIT(7)
-#define SDXC_IDMACRefetchDES BIT(31)
-/* IDMA status bit field */
-#define SDXC_IDMACTransmitInt BIT(0)
-#define SDXC_IDMACReceiveInt BIT(1)
-#define SDXC_IDMACFatalBusErr BIT(2)
-#define SDXC_IDMACDesInvalid BIT(4)
-#define SDXC_IDMACCardErrSum BIT(5)
-#define SDXC_IDMACNormalIntSum BIT(8)
-#define SDXC_IDMACAbnormalIntSum BIT(9)
-#define SDXC_IDMACHostAbtInTx BIT(10)
-#define SDXC_IDMACHostAbtInRx BIT(10)
-#define SDXC_IDMACIdle (0U << 13)
-#define SDXC_IDMACSuspend (1U << 13)
-#define SDXC_IDMACDESCRd (2U << 13)
-#define SDXC_IDMACDESCCheck (3U << 13)
-#define SDXC_IDMACRdReqWait (4U << 13)
-#define SDXC_IDMACWrReqWait (5U << 13)
-#define SDXC_IDMACRd (6U << 13)
-#define SDXC_IDMACWr (7U << 13)
-#define SDXC_IDMACDESCClose (8U << 13)
-
-struct sunxi_idma_des {
- u32 config;
-#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */
-#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */
-#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */
-#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */
-#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */
-#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */
-#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */
-
- /*
- * If the idma-des-size-bits of property is ie 13, bufsize bits are:
- * Bits 0-12: buf1 size
- * Bits 13-25: buf2 size
- * Bits 26-31: not used
- * Since we only ever set buf1 size, we can simply store it directly.
- */
- u32 buf_size;
- u32 buf_addr_ptr1;
- u32 buf_addr_ptr2;
-};
-
-struct sunxi_mmc_host {
- struct mmc_host *mmc;
- struct regulator *vmmc;
-
- /* IO mapping base */
- void __iomem *reg_base;
-
- spinlock_t lock;
- struct tasklet_struct tasklet;
-
- /* clock management */
- struct clk *clk_ahb;
- struct clk *clk_mod;
-
- /* indicator pins */
- int wp_pin;
- int cd_pin;
- int cd_mode;
-#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */
-#define CARD_ALWAYS_PRESENT (2) /* mmc always present */
-
- /* ios information */
- u32 clk_mod_rate;
- u32 bus_width;
- u32 idma_des_size_bits;
- u32 ddr;
- u32 voltage_switching;
-
- /* irq */
- int irq;
- u32 int_sum;
- u32 sdio_imask;
-
- /* flags */
- u32 power_on:1;
- u32 io_flag:1;
- u32 wait_dma:1;
-
- dma_addr_t sg_dma;
- void *sg_cpu;
-
- struct mmc_request *mrq;
- u32 ferror;
-};
-
-#define MMC_CLK_400K 0
-#define MMC_CLK_25M 1
-#define MMC_CLK_50M 2
-#define MMC_CLK_50MDDR 3
-#define MMC_CLK_50MDDR_8BIT 4
-#define MMC_CLK_100M 5
-#define MMC_CLK_200M 6
-#define MMC_CLK_MOD_NUM 7
-
-struct sunxi_mmc_clk_dly {
- u32 mode;
- u32 oclk_dly;
- u32 sclk_dly;
-};
-
-#endif
diff --git a/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch b/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch
deleted file mode 100644
index db3b2968a7..0000000000
--- a/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 9490107c16c8eaa35b07794e19d5d2eddea8e44b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
-Date: Sat, 14 Sep 2013 20:48:40 -0300
-Subject: [PATCH] clk: sunxi: Implement muxable AHB clock
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-sun5i and sun7i have a mux to change the AHB clock parent, this commit
-adds support for it on the driver.
-
-Signed-off-by: Emilio López <emilio@elopez.com.ar>
----
- Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
- drivers/clk/sunxi/clk-sunxi.c | 37 +++++++++++++++++++++++
- 2 files changed, 38 insertions(+)
-
---- a/Documentation/devicetree/bindings/clock/sunxi.txt
-+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
-@@ -15,6 +15,7 @@ Required properties:
- "allwinner,sun4i-axi-clk" - for the AXI clock
- "allwinner,sun4i-axi-gates-clk" - for the AXI gates
- "allwinner,sun4i-ahb-clk" - for the AHB clock
-+ "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
- "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
- "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
- "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
---- a/drivers/clk/sunxi/clk-sunxi.c
-+++ b/drivers/clk/sunxi/clk-sunxi.c
-@@ -249,7 +249,32 @@ static void sun4i_get_pll5_factors(u32 *
- *n = DIV_ROUND_UP(div, (*k+1));
- }
-
-+/**
-+ * sun5i_get_ahb_factors() - calculates p factor for AHB
-+ * AHB rate is calculated as follows
-+ * rate = parent_rate >> p
-+ */
-+
-+static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate,
-+ u8 *n, u8 *k, u8 *m, u8 *p)
-+{
-+ u8 div;
-+
-+ /* This clock can only divide, so we will never achieve a higher
-+ * rate than the parent's */
-+ if (*freq > parent_rate)
-+ *freq = parent_rate;
-+
-+ /* Normalize value to a parent multiple */
-+ div = *freq / parent_rate;
-+ *freq = parent_rate * div;
-+
-+ /* we were called to round the frequency, we can now return */
-+ if (n == NULL)
-+ return;
-
-+ *p = div;
-+}
-
- /**
- * sun4i_get_apb1_factors() - calculates m, p factors for APB1
-@@ -375,6 +400,11 @@ static struct clk_factors_config sun4i_p
- .kwidth = 2,
- };
-
-+static struct clk_factors_config sun5i_a13_ahb_config = {
-+ .pshift = 4,
-+ .pwidth = 2,
-+};
-+
- static struct clk_factors_config sun4i_apb1_config = {
- .mshift = 0,
- .mwidth = 5,
-@@ -408,6 +438,12 @@ static const struct factors_data sun4i_p
- .getter = sun4i_get_pll5_factors,
- };
-
-+static const struct factors_data sun5i_a13_ahb_data __initconst = {
-+ .mux = 6,
-+ .table = &sun5i_a13_ahb_config,
-+ .getter = sun5i_a13_get_ahb_factors,
-+};
-+
- static const struct factors_data sun4i_apb1_data __initconst = {
- .table = &sun4i_apb1_config,
- .getter = sun4i_get_apb1_factors,
-@@ -916,6 +952,7 @@ free_clkdata:
- static const struct of_device_id clk_factors_match[] __initconst = {
- {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
- {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
-+ {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,},
- {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
- {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
- {}
diff --git a/target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch b/target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch
index 0ec3bb5b96..0ec3bb5b96 100644
--- a/target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch
+++ b/target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch
diff --git a/target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch b/target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch
index 8d0e23abe7..8d0e23abe7 100644
--- a/target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch
+++ b/target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch
diff --git a/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch b/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch
deleted file mode 100644
index cb28aa1374..0000000000
--- a/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From c8fe5648aff581545ce5744f73ee1312080b8ef4 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
-Date: Sat, 14 Sep 2013 20:44:03 -0300
-Subject: [PATCH] ARM: sunxi: dt: Update AHB clock to be muxable on sun[57]i
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-sun5i and sun7i have a mux to select the parent clock for AHB. This
-commit implements the required changes on the device trees.
-
-Signed-off-by: Emilio López <emilio@elopez.com.ar>
----
- arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++--
- arch/arm/boot/dts/sun5i-a13.dtsi | 4 ++--
- arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++--
- 3 files changed, 6 insertions(+), 6 deletions(-)
-
---- a/arch/arm/boot/dts/sun5i-a10s.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -111,9 +111,9 @@
-
- ahb: ahb@01c20054 {
- #clock-cells = <0>;
-- compatible = "allwinner,sun4i-ahb-clk";
-+ compatible = "allwinner,sun5i-a13-ahb-clk";
- reg = <0x01c20054 0x4>;
-- clocks = <&axi>;
-+ clocks = <&axi>, <&cpu>, <&pll6 1>;
- };
-
- ahb_gates: ahb_gates@01c20060 {
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -115,9 +115,9 @@
-
- ahb: ahb@01c20054 {
- #clock-cells = <0>;
-- compatible = "allwinner,sun4i-ahb-clk";
-+ compatible = "allwinner,sun5i-a13-ahb-clk";
- reg = <0x01c20054 0x4>;
-- clocks = <&axi>;
-+ clocks = <&axi>, <&cpu>, <&pll6 1>;
- };
-
- ahb_gates: ahb_gates@01c20060 {
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -101,9 +101,9 @@
-
- ahb: ahb@01c20054 {
- #clock-cells = <0>;
-- compatible = "allwinner,sun4i-ahb-clk";
-+ compatible = "allwinner,sun5i-a13-ahb-clk";
- reg = <0x01c20054 0x4>;
-- clocks = <&axi>;
-+ clocks = <&axi>, <&pll6 1>, <&pll6 2>;
- };
-
- ahb_gates: ahb_gates@01c20060 {
diff --git a/target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch b/target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch
index 102bdbaab6..84ca843c70 100644
--- a/target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch
+++ b/target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch
@@ -1,6 +1,6 @@
-From 6dd612e3d7e0c76f863efaddae4738fadc461f72 Mon Sep 17 00:00:00 2001
+From 0aff0370cbffeadc14456556b904c80e30b3717e Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
-Date: Tue, 24 Dec 2013 21:26:18 +0800
+Date: Wed, 1 Jan 2014 10:30:48 +0800
Subject: [PATCH] ARM: dts: sun7i: external clock outputs
This commit adds the two external clock outputs available on A20 to
@@ -9,13 +9,16 @@ the first input of the clock outputs, which according to AW's A20 user
manual, is the 24MHz oscillator divided by 750.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
- arch/arm/boot/dts/sun7i-a20.dtsi | 27 +++++++++++++++++++++++++++
- 1 file changed, 27 insertions(+)
+ arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index edad6f1..0d54998 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -312,6 +312,33 @@
+@@ -303,6 +303,34 @@
clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
clock-output-names = "mbus";
};
@@ -23,12 +26,13 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+ /*
+ * Dummy clock used by output clocks
+ */
-+ osc24M_32k: osc24M_32k {
++ osc24M_32k: clk@1 {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clock-div = <750>;
+ clock-mult = <1>;
+ clocks = <&osc24M>;
++ clock-output-names = "osc24M_32k";
+ };
+
+ clk_out_a: clk@01c201f0 {
@@ -48,4 +52,7 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+ };
};
- timer {
+ soc@01c00000 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch
new file mode 100644
index 0000000000..dfcdba45b0
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch
@@ -0,0 +1,139 @@
+From dfb12c0c35b6cca5e55f40870b65af87988adb3e Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:41 +0800
+Subject: [PATCH] ARM: dts: sun4i: rename clock node names to clk@N
+
+Device tree naming conventions state that node names should match
+node function. Change fully functioning clock nodes to match and
+add clock-output-names to all sunxi clock nodes.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 28273f9..26cf191 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -58,34 +58,38 @@
+ clock-frequency = <0>;
+ };
+
+- osc24M: osc24M@01c20050 {
++ osc24M: clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-osc-clk";
+ reg = <0x01c20050 0x4>;
+ clock-frequency = <24000000>;
++ clock-output-names = "osc24M";
+ };
+
+- osc32k: osc32k {
++ osc32k: clk@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
+ };
+
+- pll1: pll1@01c20000 {
++ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll1";
+ };
+
+- pll4: pll4@01c20018 {
++ pll4: clk@01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll4";
+ };
+
+- pll5: pll5@01c20020 {
++ pll5: clk@01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+@@ -93,7 +97,7 @@
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+- pll6: pll6@01c20028 {
++ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+@@ -107,6 +111,7 @@
+ compatible = "allwinner,sun4i-cpu-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
++ clock-output-names = "cpu";
+ };
+
+ axi: axi@01c20054 {
+@@ -114,9 +119,10 @@
+ compatible = "allwinner,sun4i-axi-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&cpu>;
++ clock-output-names = "axi";
+ };
+
+- axi_gates: axi_gates@01c2005c {
++ axi_gates: clk@01c2005c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-axi-gates-clk";
+ reg = <0x01c2005c 0x4>;
+@@ -129,9 +135,10 @@
+ compatible = "allwinner,sun4i-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&axi>;
++ clock-output-names = "ahb";
+ };
+
+- ahb_gates: ahb_gates@01c20060 {
++ ahb_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-ahb-gates-clk";
+ reg = <0x01c20060 0x8>;
+@@ -154,9 +161,10 @@
+ compatible = "allwinner,sun4i-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb>;
++ clock-output-names = "apb0";
+ };
+
+- apb0_gates: apb0_gates@01c20068 {
++ apb0_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-apb0-gates-clk";
+ reg = <0x01c20068 0x4>;
+@@ -171,6 +179,7 @@
+ compatible = "allwinner,sun4i-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
++ clock-output-names = "apb1_mux";
+ };
+
+ apb1: apb1@01c20058 {
+@@ -178,9 +187,10 @@
+ compatible = "allwinner,sun4i-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb1_mux>;
++ clock-output-names = "apb1";
+ };
+
+- apb1_gates: apb1_gates@01c2006c {
++ apb1_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-apb1-gates-clk";
+ reg = <0x01c2006c 0x4>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch
new file mode 100644
index 0000000000..1678a8bbb7
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch
@@ -0,0 +1,261 @@
+From 3dce8324949eaa1ab4b750e8422ce78ddceb7aa4 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:42 +0800
+Subject: [PATCH] ARM: dts: sun5i: rename clock node names to clk@N
+
+Device tree naming conventions state that node names should match
+node function. Change fully functioning clock nodes to match and
+add clock-output-names to all sunxi clock nodes.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 30 ++++++++++++++++++++----------
+ arch/arm/boot/dts/sun5i-a13.dtsi | 30 ++++++++++++++++++++----------
+ 2 files changed, 40 insertions(+), 20 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 2318082..b114be7 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -51,34 +51,38 @@
+ clock-frequency = <0>;
+ };
+
+- osc24M: osc24M@01c20050 {
++ osc24M: clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-osc-clk";
+ reg = <0x01c20050 0x4>;
+ clock-frequency = <24000000>;
++ clock-output-names = "osc24M";
+ };
+
+- osc32k: osc32k {
++ osc32k: clk@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
+ };
+
+- pll1: pll1@01c20000 {
++ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll1";
+ };
+
+- pll4: pll4@01c20018 {
++ pll4: clk@01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll4";
+ };
+
+- pll5: pll5@01c20020 {
++ pll5: clk@01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+@@ -86,7 +90,7 @@
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+- pll6: pll6@01c20028 {
++ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+@@ -100,6 +104,7 @@
+ compatible = "allwinner,sun4i-cpu-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
++ clock-output-names = "cpu";
+ };
+
+ axi: axi@01c20054 {
+@@ -107,9 +112,10 @@
+ compatible = "allwinner,sun4i-axi-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&cpu>;
++ clock-output-names = "axi";
+ };
+
+- axi_gates: axi_gates@01c2005c {
++ axi_gates: clk@01c2005c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-axi-gates-clk";
+ reg = <0x01c2005c 0x4>;
+@@ -122,9 +128,10 @@
+ compatible = "allwinner,sun4i-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&axi>;
++ clock-output-names = "ahb";
+ };
+
+- ahb_gates: ahb_gates@01c20060 {
++ ahb_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a10s-ahb-gates-clk";
+ reg = <0x01c20060 0x8>;
+@@ -143,9 +150,10 @@
+ compatible = "allwinner,sun4i-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb>;
++ clock-output-names = "apb0";
+ };
+
+- apb0_gates: apb0_gates@01c20068 {
++ apb0_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a10s-apb0-gates-clk";
+ reg = <0x01c20068 0x4>;
+@@ -159,6 +167,7 @@
+ compatible = "allwinner,sun4i-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
++ clock-output-names = "apb1_mux";
+ };
+
+ apb1: apb1@01c20058 {
+@@ -166,9 +175,10 @@
+ compatible = "allwinner,sun4i-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb1_mux>;
++ clock-output-names = "apb1";
+ };
+
+- apb1_gates: apb1_gates@01c2006c {
++ apb1_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a10s-apb1-gates-clk";
+ reg = <0x01c2006c 0x4>;
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 6de40b6..5c121fc 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -52,34 +52,38 @@
+ clock-frequency = <0>;
+ };
+
+- osc24M: osc24M@01c20050 {
++ osc24M: clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-osc-clk";
+ reg = <0x01c20050 0x4>;
+ clock-frequency = <24000000>;
++ clock-output-names = "osc24M";
+ };
+
+- osc32k: osc32k {
++ osc32k: clk@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
+ };
+
+- pll1: pll1@01c20000 {
++ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll1";
+ };
+
+- pll4: pll4@01c20018 {
++ pll4: clk@01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll4";
+ };
+
+- pll5: pll5@01c20020 {
++ pll5: clk@01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+@@ -87,7 +91,7 @@
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+- pll6: pll6@01c20028 {
++ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+@@ -101,6 +105,7 @@
+ compatible = "allwinner,sun4i-cpu-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
++ clock-output-names = "cpu";
+ };
+
+ axi: axi@01c20054 {
+@@ -108,9 +113,10 @@
+ compatible = "allwinner,sun4i-axi-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&cpu>;
++ clock-output-names = "axi";
+ };
+
+- axi_gates: axi_gates@01c2005c {
++ axi_gates: clk@01c2005c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-axi-gates-clk";
+ reg = <0x01c2005c 0x4>;
+@@ -123,9 +129,10 @@
+ compatible = "allwinner,sun4i-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&axi>;
++ clock-output-names = "ahb";
+ };
+
+- ahb_gates: ahb_gates@01c20060 {
++ ahb_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a13-ahb-gates-clk";
+ reg = <0x01c20060 0x8>;
+@@ -143,9 +150,10 @@
+ compatible = "allwinner,sun4i-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb>;
++ clock-output-names = "apb0";
+ };
+
+- apb0_gates: apb0_gates@01c20068 {
++ apb0_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a13-apb0-gates-clk";
+ reg = <0x01c20068 0x4>;
+@@ -158,6 +166,7 @@
+ compatible = "allwinner,sun4i-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
++ clock-output-names = "apb1_mux";
+ };
+
+ apb1: apb1@01c20058 {
+@@ -165,9 +174,10 @@
+ compatible = "allwinner,sun4i-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb1_mux>;
++ clock-output-names = "apb1";
+ };
+
+- apb1_gates: apb1_gates@01c2006c {
++ apb1_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-a13-apb1-gates-clk";
+ reg = <0x01c2006c 0x4>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch
new file mode 100644
index 0000000000..fe0a1a005f
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch
@@ -0,0 +1,112 @@
+From 5cd0fa24e51d342f175d31ecb72c2e957a6bd0af Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:43 +0800
+Subject: [PATCH] ARM: dts: sun6i: rename clock node names to clk@N
+
+Device tree naming conventions state that node names should match
+node function. Change fully functioning clock nodes to match and
+add clock-output-names to all sunxi clock nodes.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun6i-a31.dtsi | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
+index fc07f70..d3f1995 100644
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -70,17 +70,19 @@
+ clock-frequency = <24000000>;
+ };
+
+- osc32k: osc32k {
++ osc32k: clk@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
+ };
+
+- pll1: pll1@01c20000 {
++ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll1";
+ };
+
+ pll6: clk@01c20028 {
+@@ -103,6 +105,7 @@
+ * Allwinner.
+ */
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
++ clock-output-names = "cpu";
+ };
+
+ axi: axi@01c20050 {
+@@ -110,6 +113,7 @@
+ compatible = "allwinner,sun4i-axi-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&cpu>;
++ clock-output-names = "axi";
+ };
+
+ ahb1_mux: ahb1_mux@01c20054 {
+@@ -117,6 +121,7 @@
+ compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
++ clock-output-names = "ahb1_mux";
+ };
+
+ ahb1: ahb1@01c20054 {
+@@ -124,9 +129,10 @@
+ compatible = "allwinner,sun4i-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1_mux>;
++ clock-output-names = "ahb1";
+ };
+
+- ahb1_gates: ahb1_gates@01c20060 {
++ ahb1_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-ahb1-gates-clk";
+ reg = <0x01c20060 0x8>;
+@@ -152,9 +158,10 @@
+ compatible = "allwinner,sun4i-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1>;
++ clock-output-names = "apb1";
+ };
+
+- apb1_gates: apb1_gates@01c20060 {
++ apb1_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-apb1-gates-clk";
+ reg = <0x01c20068 0x4>;
+@@ -169,6 +176,7 @@
+ compatible = "allwinner,sun4i-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
++ clock-output-names = "apb2_mux";
+ };
+
+ apb2: apb2@01c20058 {
+@@ -176,9 +184,10 @@
+ compatible = "allwinner,sun6i-a31-apb2-div-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb2_mux>;
++ clock-output-names = "apb2";
+ };
+
+- apb2_gates: apb2_gates@01c2006c {
++ apb2_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-apb2-gates-clk";
+ reg = <0x01c2006c 0x4>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch
new file mode 100644
index 0000000000..0fba0bc3ae
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch
@@ -0,0 +1,132 @@
+From cb6050998de262d5acf2207c5451d4f5995a5bff Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:44 +0800
+Subject: [PATCH] ARM: dts: sun7i: rename clock node names to clk@N
+
+Device tree naming conventions state that node names should match
+node function. Change fully functioning clock nodes to match and
+add clock-output-names to all sunxi clock nodes.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index fe0fe47..cefd7ac 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -54,11 +54,12 @@
+ #size-cells = <1>;
+ ranges;
+
+- osc24M: osc24M@01c20050 {
++ osc24M: clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-osc-clk";
+ reg = <0x01c20050 0x4>;
+ clock-frequency = <24000000>;
++ clock-output-names = "osc24M";
+ };
+
+ osc32k: clk@0 {
+@@ -68,21 +69,23 @@
+ clock-output-names = "osc32k";
+ };
+
+- pll1: pll1@01c20000 {
++ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll1";
+ };
+
+- pll4: pll4@01c20018 {
++ pll4: clk@01c20018 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-pll1-clk";
+ reg = <0x01c20018 0x4>;
+ clocks = <&osc24M>;
++ clock-output-names = "pll4";
+ };
+
+- pll5: pll5@01c20020 {
++ pll5: clk@01c20020 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll5-clk";
+ reg = <0x01c20020 0x4>;
+@@ -90,7 +93,7 @@
+ clock-output-names = "pll5_ddr", "pll5_other";
+ };
+
+- pll6: pll6@01c20028 {
++ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-pll6-clk";
+ reg = <0x01c20028 0x4>;
+@@ -103,6 +106,7 @@
+ compatible = "allwinner,sun4i-cpu-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>;
++ clock-output-names = "cpu";
+ };
+
+ axi: axi@01c20054 {
+@@ -110,6 +114,7 @@
+ compatible = "allwinner,sun4i-axi-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&cpu>;
++ clock-output-names = "axi";
+ };
+
+ ahb: ahb@01c20054 {
+@@ -117,9 +122,10 @@
+ compatible = "allwinner,sun4i-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&axi>;
++ clock-output-names = "ahb";
+ };
+
+- ahb_gates: ahb_gates@01c20060 {
++ ahb_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun7i-a20-ahb-gates-clk";
+ reg = <0x01c20060 0x8>;
+@@ -144,9 +150,10 @@
+ compatible = "allwinner,sun4i-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb>;
++ clock-output-names = "apb0";
+ };
+
+- apb0_gates: apb0_gates@01c20068 {
++ apb0_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun7i-a20-apb0-gates-clk";
+ reg = <0x01c20068 0x4>;
+@@ -162,6 +169,7 @@
+ compatible = "allwinner,sun4i-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
++ clock-output-names = "apb1_mux";
+ };
+
+ apb1: apb1@01c20058 {
+@@ -169,9 +177,10 @@
+ compatible = "allwinner,sun4i-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb1_mux>;
++ clock-output-names = "apb1";
+ };
+
+- apb1_gates: apb1_gates@01c2006c {
++ apb1_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun7i-a20-apb1-gates-clk";
+ reg = <0x01c2006c 0x4>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch b/target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch
index cb8b109ef9..cb8b109ef9 100644
--- a/target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch
+++ b/target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch
diff --git a/target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch b/target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch
index 70a57871bc..70a57871bc 100644
--- a/target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch
+++ b/target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch
diff --git a/target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch b/target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch
index 543dd57ad1..543dd57ad1 100644
--- a/target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch
+++ b/target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch
diff --git a/target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch b/target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch
index 4bb315de2e..dc9f8ac362 100644
--- a/target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch
+++ b/target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch
@@ -1,4 +1,4 @@
-From 26523a27f47828e50212201ba25862fe1e2b845c Mon Sep 17 00:00:00 2001
+From fdc4530902ed845fc0f31b9bbcc45e05fefe21da Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 1 Dec 2013 22:40:34 +0100
Subject: [PATCH] ARM: dts: sun7i: Add arch timers
@@ -14,9 +14,11 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index f4ecd79..fa2ef07 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -304,6 +304,14 @@
+@@ -370,6 +370,14 @@
};
};
@@ -31,3 +33,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
soc@01c00000 {
compatible = "simple-bus";
#address-cells = <1>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch b/target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch
index 93b72523ca..93b72523ca 100644
--- a/target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch
+++ b/target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch
diff --git a/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch b/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch
new file mode 100644
index 0000000000..16c0aa0809
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch
@@ -0,0 +1,56 @@
+From bc7a0478e6dac1304fdfdb6f3056f438b632da62 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 10 Feb 2014 18:35:48 +0800
+Subject: [PATCH] ARM: dts: sun7i: Add GMAC clock node to sun7i DTSI
+
+The GMAC uses 1 of 2 sources for its transmit clock, depending on the
+PHY interface mode. Add both sources as dummy clocks, and as parents
+to the GMAC clock node.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index cefd7ac..7d98edc 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -322,6 +322,34 @@
+ };
+
+ /*
++ * The following two are dummy clocks, placeholders used in the gmac_tx
++ * clock. The gmac driver will choose one parent depending on the PHY
++ * interface mode, using clk_set_rate auto-reparenting.
++ * The actual TX clock rate is not controlled by the gmac_tx clock.
++ */
++ mii_phy_tx_clk: clk@2 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <25000000>;
++ clock-output-names = "mii_phy_tx";
++ };
++
++ gmac_int_tx_clk: clk@3 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ clock-output-names = "gmac_int_tx";
++ };
++
++ gmac_tx_clk: clk@01c20164 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun7i-a20-gmac-clk";
++ reg = <0x01c20164 0x4>;
++ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
++ clock-output-names = "gmac_tx";
++ };
++
++ /*
+ * Dummy clock used by output clocks
+ */
+ osc24M_32k: clk@1 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch b/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch
new file mode 100644
index 0000000000..5d68104066
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch
@@ -0,0 +1,39 @@
+From 7584e81f6d9fecf0ad6e2854654b183432adb918 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 10 Feb 2014 18:35:49 +0800
+Subject: [PATCH] ARM: dts: sun7i: Add GMAC controller node to sun7i DTSI
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 7d98edc..87eab0d 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -645,6 +645,21 @@
+ status = "disabled";
+ };
+
++ gmac: ethernet@01c50000 {
++ compatible = "allwinner,sun7i-a20-gmac";
++ reg = <0x01c50000 0x10000>;
++ interrupts = <0 85 4>;
++ interrupt-names = "macirq";
++ clocks = <&ahb_gates 49>, <&gmac_tx_clk>;
++ clock-names = "stmmaceth", "allwinner_gmac_tx";
++ snps,pbl = <2>;
++ snps,fixed-burst;
++ snps,force_sf_dma_mode;
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ hstimer@01c60000 {
+ compatible = "allwinner,sun7i-a20-hstimer";
+ reg = <0x01c60000 0x1000>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch b/target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch
index 34c0fc385c..01523f0d8c 100644
--- a/target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch
+++ b/target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch
@@ -1,6 +1,6 @@
-From 777ba9f88e1a566a6ed26fe1e8dfff4b8c1448fc Mon Sep 17 00:00:00 2001
+From 249ac8d24efdc07f521b796b96796ffa55abe0a5 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:39 +0800
+Date: Mon, 10 Feb 2014 18:35:50 +0800
Subject: [PATCH] ARM: dts: sun7i: Add pin muxing options for the GMAC
The A20 has EMAC and GMAC muxed on the same pins.
@@ -8,37 +8,46 @@ Add pin sets with gmac function for MII and RGMII mode to the DTSI.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
- arch/arm/boot/dts/sun7i-a20.dtsi | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
+ arch/arm/boot/dts/sun7i-a20.dtsi | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 87eab0d..9bb6fdf 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -428,6 +428,28 @@
+@@ -484,6 +484,32 @@
+ allwinner,drive = <0>;
allwinner,pull = <0>;
};
-
-+ gmac_pins_mii: gmac_mii {
++
++ gmac_pins_mii_a: gmac_mii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA9", "PA10",
+ "PA11", "PA12", "PA13", "PA14",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
-+ allwinner,drive = <3>;
++ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
-+ gmac_pins_rgmii: gmac_rgmii {
++ gmac_pins_rgmii_a: gmac_rgmii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA10",
+ "PA11", "PA12", "PA13",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
++ /*
++ * data lines in RGMII mode use DDR mode
++ * and need a higher signal drive strength
++ */
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
-+
- mmc0_pins_a: mmc0@0 {
- allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
- allwinner,function = "mmc0";
+ };
+
+ timer@01c20c00 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch b/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch
new file mode 100644
index 0000000000..2c908ac16d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch
@@ -0,0 +1,50 @@
+From 33ba4079ea8c611c1aeca34f2d6d53a8214c14c5 Mon Sep 17 00:00:00 2001
+From: Rashika Kheria <rashika.kheria@gmail.com>
+Date: Thu, 19 Dec 2013 14:19:44 +0530
+Subject: [PATCH] drivers: net: Mark functions as static in stmmac_platform.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch marks the function stmmac_pltfr_freeze() and
+stmmac_pltfr_restore() in stmmac_platform.c as static because they are
+not used outside this file.
+
+Thus, it also removes the following warnings in
+ethernet/stmicro/stmmac/stmmac_platform.c:
+
+drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:222:5: warning: no previous prototype for ‘stmmac_pltfr_freeze’ [-Wmissing-prototypes]
+drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:236:5: warning: no previous prototype for ‘stmmac_pltfr_restore’ [-Wmissing-prototypes]
+
+Signed-off-by: Rashika Kheria <rashika.kheria@gmail.com>
+Reviewed-by: Josh Triplett <josh@joshtriplett.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 51c9069..38bd1f4 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -219,7 +219,7 @@ static int stmmac_pltfr_resume(struct device *dev)
+ return stmmac_resume(ndev);
+ }
+
+-int stmmac_pltfr_freeze(struct device *dev)
++static int stmmac_pltfr_freeze(struct device *dev)
+ {
+ int ret;
+ struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
+@@ -233,7 +233,7 @@ int stmmac_pltfr_freeze(struct device *dev)
+ return ret;
+ }
+
+-int stmmac_pltfr_restore(struct device *dev)
++static int stmmac_pltfr_restore(struct device *dev)
+ {
+ struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch b/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch
new file mode 100644
index 0000000000..efd7aff3ba
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch
@@ -0,0 +1,77 @@
+From 9cbadf094d9d479413dc8cfa77dff9e732184337 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:51:43 +0000
+Subject: [PATCH] net: stmmac: support max-speed device tree property
+
+This patch adds support to "max-speed" property which is a standard
+Ethernet device tree property. max-speed specifies maximum speed
+(specified in megabits per second) supported the device.
+
+Depending on the clocking schemes some of the boards can only support
+few link speeds, so having a way to limit the link speed in the mac
+driver would allow such setups to work reliably.
+
+Without this patch there is no way to tell the driver to limit the
+link speed.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++++
+ include/linux/stmmac.h | 1 +
+ 3 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index ecdc8ab..15192c0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -776,6 +776,7 @@ static int stmmac_init_phy(struct net_device *dev)
+ char phy_id_fmt[MII_BUS_ID_SIZE + 3];
+ char bus_id[MII_BUS_ID_SIZE];
+ int interface = priv->plat->interface;
++ int max_speed = priv->plat->max_speed;
+ priv->oldlink = 0;
+ priv->speed = 0;
+ priv->oldduplex = -1;
+@@ -800,7 +801,8 @@ static int stmmac_init_phy(struct net_device *dev)
+
+ /* Stop Advertising 1000BASE Capability if interface is not GMII */
+ if ((interface == PHY_INTERFACE_MODE_MII) ||
+- (interface == PHY_INTERFACE_MODE_RMII))
++ (interface == PHY_INTERFACE_MODE_RMII) ||
++ (max_speed < 1000 && max_speed > 0))
+ phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full);
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 38bd1f4..9377ee6 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -42,6 +42,10 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
+ *mac = of_get_mac_address(np);
+ plat->interface = of_get_phy_mode(np);
+
++ /* Get max speed of operation from device tree */
++ if (of_property_read_u32(np, "max-speed", &plat->max_speed))
++ plat->max_speed = -1;
++
+ plat->bus_id = of_alias_get_id(np, "ethernet");
+ if (plat->bus_id < 0)
+ plat->bus_id = 0;
+diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
+index bb5deb0..33ace71 100644
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -110,6 +110,7 @@ struct plat_stmmacenet_data {
+ int force_sf_dma_mode;
+ int force_thresh_dma_mode;
+ int riwt_off;
++ int max_speed;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+ int (*init)(struct platform_device *pdev);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch b/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch
new file mode 100644
index 0000000000..0f2527fa42
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch
@@ -0,0 +1,31 @@
+From 984203ceff27e9d6d94fbae4b043fc9afb658121 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:51:58 +0000
+Subject: [PATCH] net: stmmac: mdio: remove reset gpio free
+
+This patch removes gpio_free for reset line of the phy, driver stores
+the gpio number in its private data-structure to use in future. As the
+driver uses this pin in future this pin should not be freed.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+index fe7bc99..aab12d2 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+@@ -166,7 +166,6 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
+ udelay(data->delays[1]);
+ gpio_set_value(reset_gpio, active_low ? 1 : 0);
+ udelay(data->delays[2]);
+- gpio_free(reset_gpio);
+ }
+ }
+ #endif
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch b/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch
new file mode 100644
index 0000000000..d9c843a132
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch
@@ -0,0 +1,223 @@
+From 09f8d6960b69e474eef9d2aebdd0d536d00af0c8 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:06 +0000
+Subject: [PATCH] net: stmmac: move dma allocation to new function
+
+This patch moves dma resource allocation to a new function
+alloc_dma_desc_resources, the reason for moving this to a new function
+is to keep the memory allocations in a separate function. One more reason
+it to get suspend and hibernation cases working without releasing and
+allocating these resources during suspend-resume and freeze-restore
+cases.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 169 +++++++++++-----------
+ 1 file changed, 85 insertions(+), 84 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 15192c0..532f2b4 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -996,66 +996,6 @@ static int init_dma_desc_rings(struct net_device *dev)
+ pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
+ txsize, rxsize, bfsize);
+
+- if (priv->extend_desc) {
+- priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
+- sizeof(struct
+- dma_extended_desc),
+- &priv->dma_rx_phy,
+- GFP_KERNEL);
+- if (!priv->dma_erx)
+- goto err_dma;
+-
+- priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
+- sizeof(struct
+- dma_extended_desc),
+- &priv->dma_tx_phy,
+- GFP_KERNEL);
+- if (!priv->dma_etx) {
+- dma_free_coherent(priv->device, priv->dma_rx_size *
+- sizeof(struct dma_extended_desc),
+- priv->dma_erx, priv->dma_rx_phy);
+- goto err_dma;
+- }
+- } else {
+- priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
+- sizeof(struct dma_desc),
+- &priv->dma_rx_phy,
+- GFP_KERNEL);
+- if (!priv->dma_rx)
+- goto err_dma;
+-
+- priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
+- sizeof(struct dma_desc),
+- &priv->dma_tx_phy,
+- GFP_KERNEL);
+- if (!priv->dma_tx) {
+- dma_free_coherent(priv->device, priv->dma_rx_size *
+- sizeof(struct dma_desc),
+- priv->dma_rx, priv->dma_rx_phy);
+- goto err_dma;
+- }
+- }
+-
+- priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
+- GFP_KERNEL);
+- if (!priv->rx_skbuff_dma)
+- goto err_rx_skbuff_dma;
+-
+- priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
+- GFP_KERNEL);
+- if (!priv->rx_skbuff)
+- goto err_rx_skbuff;
+-
+- priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+- GFP_KERNEL);
+- if (!priv->tx_skbuff_dma)
+- goto err_tx_skbuff_dma;
+-
+- priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
+- GFP_KERNEL);
+- if (!priv->tx_skbuff)
+- goto err_tx_skbuff;
+-
+ if (netif_msg_probe(priv)) {
+ pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
+ (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
+@@ -1123,30 +1063,6 @@ static int init_dma_desc_rings(struct net_device *dev)
+ err_init_rx_buffers:
+ while (--i >= 0)
+ stmmac_free_rx_buffers(priv, i);
+- kfree(priv->tx_skbuff);
+-err_tx_skbuff:
+- kfree(priv->tx_skbuff_dma);
+-err_tx_skbuff_dma:
+- kfree(priv->rx_skbuff);
+-err_rx_skbuff:
+- kfree(priv->rx_skbuff_dma);
+-err_rx_skbuff_dma:
+- if (priv->extend_desc) {
+- dma_free_coherent(priv->device, priv->dma_tx_size *
+- sizeof(struct dma_extended_desc),
+- priv->dma_etx, priv->dma_tx_phy);
+- dma_free_coherent(priv->device, priv->dma_rx_size *
+- sizeof(struct dma_extended_desc),
+- priv->dma_erx, priv->dma_rx_phy);
+- } else {
+- dma_free_coherent(priv->device,
+- priv->dma_tx_size * sizeof(struct dma_desc),
+- priv->dma_tx, priv->dma_tx_phy);
+- dma_free_coherent(priv->device,
+- priv->dma_rx_size * sizeof(struct dma_desc),
+- priv->dma_rx, priv->dma_rx_phy);
+- }
+-err_dma:
+ return ret;
+ }
+
+@@ -1182,6 +1098,85 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
+ }
+ }
+
++static int alloc_dma_desc_resources(struct stmmac_priv *priv)
++{
++ unsigned int txsize = priv->dma_tx_size;
++ unsigned int rxsize = priv->dma_rx_size;
++ int ret = -ENOMEM;
++
++ priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
++ GFP_KERNEL);
++ if (!priv->rx_skbuff_dma)
++ return -ENOMEM;
++
++ priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
++ GFP_KERNEL);
++ if (!priv->rx_skbuff)
++ goto err_rx_skbuff;
++
++ priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
++ GFP_KERNEL);
++ if (!priv->tx_skbuff_dma)
++ goto err_tx_skbuff_dma;
++
++ priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
++ GFP_KERNEL);
++ if (!priv->tx_skbuff)
++ goto err_tx_skbuff;
++
++ if (priv->extend_desc) {
++ priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
++ sizeof(struct
++ dma_extended_desc),
++ &priv->dma_rx_phy,
++ GFP_KERNEL);
++ if (!priv->dma_erx)
++ goto err_dma;
++
++ priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
++ sizeof(struct
++ dma_extended_desc),
++ &priv->dma_tx_phy,
++ GFP_KERNEL);
++ if (!priv->dma_etx) {
++ dma_free_coherent(priv->device, priv->dma_rx_size *
++ sizeof(struct dma_extended_desc),
++ priv->dma_erx, priv->dma_rx_phy);
++ goto err_dma;
++ }
++ } else {
++ priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
++ sizeof(struct dma_desc),
++ &priv->dma_rx_phy,
++ GFP_KERNEL);
++ if (!priv->dma_rx)
++ goto err_dma;
++
++ priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
++ sizeof(struct dma_desc),
++ &priv->dma_tx_phy,
++ GFP_KERNEL);
++ if (!priv->dma_tx) {
++ dma_free_coherent(priv->device, priv->dma_rx_size *
++ sizeof(struct dma_desc),
++ priv->dma_rx, priv->dma_rx_phy);
++ goto err_dma;
++ }
++ }
++
++ return 0;
++
++err_dma:
++ kfree(priv->tx_skbuff);
++err_tx_skbuff:
++ kfree(priv->tx_skbuff_dma);
++err_tx_skbuff_dma:
++ kfree(priv->rx_skbuff);
++err_rx_skbuff:
++ kfree(priv->rx_skbuff_dma);
++ return ret;
++}
++
+ static void free_dma_desc_resources(struct stmmac_priv *priv)
+ {
+ /* Release the DMA TX/RX socket buffers */
+@@ -1623,6 +1618,12 @@ static int stmmac_open(struct net_device *dev)
+ priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
+ priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+
++ alloc_dma_desc_resources(priv);
++ if (ret < 0) {
++ pr_err("%s: DMA descriptors allocation failed\n", __func__);
++ goto dma_desc_error;
++ }
++
+ ret = init_dma_desc_rings(dev);
+ if (ret < 0) {
+ pr_err("%s: DMA descriptors initialization failed\n", __func__);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch b/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch
new file mode 100644
index 0000000000..e006fda7dd
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch
@@ -0,0 +1,214 @@
+From 523f11b5d4fd72efb72b04cd7006bfd1d1d4f341 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:14 +0000
+Subject: [PATCH] net: stmmac: move hardware setup for stmmac_open to new
+ function
+
+This patch moves hardware setup part of the code in stmmac_open to a new
+function stmmac_hw_setup, the reason for doing this is to make hw
+initialization independent function so that PM functions can re-use it to
+re-initialize the IP after returning from low power state.
+This will also avoid code duplication across stmmac_resume/restore and
+stmmac_open.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 155 ++++++++++++----------
+ 1 file changed, 88 insertions(+), 67 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 532f2b4..341c8dc3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -1586,6 +1586,86 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+ }
+
+ /**
++ * stmmac_hw_setup: setup mac in a usable state.
++ * @dev : pointer to the device structure.
++ * Description:
++ * This function sets up the ip in a usable state.
++ * Return value:
++ * 0 on success and an appropriate (-)ve integer as defined in errno.h
++ * file on failure.
++ */
++static int stmmac_hw_setup(struct net_device *dev)
++{
++ struct stmmac_priv *priv = netdev_priv(dev);
++ int ret;
++
++ ret = init_dma_desc_rings(dev);
++ if (ret < 0) {
++ pr_err("%s: DMA descriptors initialization failed\n", __func__);
++ return ret;
++ }
++ /* DMA initialization and SW reset */
++ ret = stmmac_init_dma_engine(priv);
++ if (ret < 0) {
++ pr_err("%s: DMA engine initialization failed\n", __func__);
++ return ret;
++ }
++
++ /* Copy the MAC addr into the HW */
++ priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
++
++ /* If required, perform hw setup of the bus. */
++ if (priv->plat->bus_setup)
++ priv->plat->bus_setup(priv->ioaddr);
++
++ /* Initialize the MAC Core */
++ priv->hw->mac->core_init(priv->ioaddr);
++
++ /* Enable the MAC Rx/Tx */
++ stmmac_set_mac(priv->ioaddr, true);
++
++ /* Set the HW DMA mode and the COE */
++ stmmac_dma_operation_mode(priv);
++
++ stmmac_mmc_setup(priv);
++
++ ret = stmmac_init_ptp(priv);
++ if (ret)
++ pr_warn("%s: failed PTP initialisation\n", __func__);
++
++#ifdef CONFIG_STMMAC_DEBUG_FS
++ ret = stmmac_init_fs(dev);
++ if (ret < 0)
++ pr_warn("%s: failed debugFS registration\n", __func__);
++#endif
++ /* Start the ball rolling... */
++ pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
++ priv->hw->dma->start_tx(priv->ioaddr);
++ priv->hw->dma->start_rx(priv->ioaddr);
++
++ /* Dump DMA/MAC registers */
++ if (netif_msg_hw(priv)) {
++ priv->hw->mac->dump_regs(priv->ioaddr);
++ priv->hw->dma->dump_regs(priv->ioaddr);
++ }
++ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
++
++ priv->eee_enabled = stmmac_eee_init(priv);
++
++ stmmac_init_tx_coalesce(priv);
++
++ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
++ priv->rx_riwt = MAX_DMA_RIWT;
++ priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
++ }
++
++ if (priv->pcs && priv->hw->mac->ctrl_ane)
++ priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
++
++ return 0;
++}
++
++/**
+ * stmmac_open - open entry point of the driver
+ * @dev : pointer to the device structure.
+ * Description:
+@@ -1613,6 +1693,10 @@ static int stmmac_open(struct net_device *dev)
+ }
+ }
+
++ /* Extra statistics */
++ memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
++ priv->xstats.threshold = tc;
++
+ /* Create and initialize the TX/RX descriptors chains. */
+ priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
+ priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
+@@ -1624,28 +1708,14 @@ static int stmmac_open(struct net_device *dev)
+ goto dma_desc_error;
+ }
+
+- ret = init_dma_desc_rings(dev);
++ ret = stmmac_hw_setup(dev);
+ if (ret < 0) {
+- pr_err("%s: DMA descriptors initialization failed\n", __func__);
+- goto dma_desc_error;
+- }
+-
+- /* DMA initialization and SW reset */
+- ret = stmmac_init_dma_engine(priv);
+- if (ret < 0) {
+- pr_err("%s: DMA engine initialization failed\n", __func__);
++ pr_err("%s: Hw setup failed\n", __func__);
+ goto init_error;
+ }
+
+- /* Copy the MAC addr into the HW */
+- priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+-
+- /* If required, perform hw setup of the bus. */
+- if (priv->plat->bus_setup)
+- priv->plat->bus_setup(priv->ioaddr);
+-
+- /* Initialize the MAC Core */
+- priv->hw->mac->core_init(priv->ioaddr);
++ if (priv->phydev)
++ phy_start(priv->phydev);
+
+ /* Request the IRQ lines */
+ ret = request_irq(dev->irq, stmmac_interrupt,
+@@ -1678,55 +1748,6 @@ static int stmmac_open(struct net_device *dev)
+ }
+ }
+
+- /* Enable the MAC Rx/Tx */
+- stmmac_set_mac(priv->ioaddr, true);
+-
+- /* Set the HW DMA mode and the COE */
+- stmmac_dma_operation_mode(priv);
+-
+- /* Extra statistics */
+- memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
+- priv->xstats.threshold = tc;
+-
+- stmmac_mmc_setup(priv);
+-
+- ret = stmmac_init_ptp(priv);
+- if (ret)
+- pr_warn("%s: failed PTP initialisation\n", __func__);
+-
+-#ifdef CONFIG_STMMAC_DEBUG_FS
+- ret = stmmac_init_fs(dev);
+- if (ret < 0)
+- pr_warn("%s: failed debugFS registration\n", __func__);
+-#endif
+- /* Start the ball rolling... */
+- pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
+- priv->hw->dma->start_tx(priv->ioaddr);
+- priv->hw->dma->start_rx(priv->ioaddr);
+-
+- /* Dump DMA/MAC registers */
+- if (netif_msg_hw(priv)) {
+- priv->hw->mac->dump_regs(priv->ioaddr);
+- priv->hw->dma->dump_regs(priv->ioaddr);
+- }
+-
+- if (priv->phydev)
+- phy_start(priv->phydev);
+-
+- priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
+-
+- priv->eee_enabled = stmmac_eee_init(priv);
+-
+- stmmac_init_tx_coalesce(priv);
+-
+- if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+- priv->rx_riwt = MAX_DMA_RIWT;
+- priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
+- }
+-
+- if (priv->pcs && priv->hw->mac->ctrl_ane)
+- priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+-
+ napi_enable(&priv->napi);
+ netif_start_queue(dev);
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch b/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch
new file mode 100644
index 0000000000..1a60574297
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch
@@ -0,0 +1,45 @@
+From 073752aa59b3db120b2508d5bdd0598ada25fd25 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:27 +0000
+Subject: [PATCH] net: stmmac: make stmmac_mdio_reset non-static
+
+This patch promotes stmmac_mdio_reset function from static to
+non-static, so that power management functions can decide to reset if
+the IP comes out from lowe power state specially hibernation cases.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
+ drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 92be6b3..5a568015 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -110,6 +110,7 @@ struct stmmac_priv {
+
+ int stmmac_mdio_unregister(struct net_device *ndev);
+ int stmmac_mdio_register(struct net_device *ndev);
++int stmmac_mdio_reset(struct mii_bus *mii);
+ void stmmac_set_ethtool_ops(struct net_device *netdev);
+ extern const struct stmmac_desc_ops enh_desc_ops;
+ extern const struct stmmac_desc_ops ndesc_ops;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+index aab12d2..a468eb1 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+@@ -128,7 +128,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
+ * @bus: points to the mii_bus structure
+ * Description: reset the MII bus
+ */
+-static int stmmac_mdio_reset(struct mii_bus *bus)
++int stmmac_mdio_reset(struct mii_bus *bus)
+ {
+ #if defined(CONFIG_STMMAC_PLATFORM)
+ struct net_device *ndev = bus->priv;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch b/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch
new file mode 100644
index 0000000000..25564c66a8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch
@@ -0,0 +1,57 @@
+From 623997fb90eab7a135c2c68a332c8450a488baca Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:35 +0000
+Subject: [PATCH] net: stmmac: fix power management suspend-resume case
+
+The driver PM resume assumes that the IP is still powered up and the
+all the register contents are not disturbed when it comes out of low
+power suspend case. This assumption is wrong, basically the driver
+should not consider any state of registers after it comes out of low
+power. However driver can keep the part of the IP powered up if its a
+wake up source. But it can not assume the register state of the IP. Also
+its possible that SOC glue layer can take the power off the IP if its
+not wake-up source to reduce the power consumption.
+
+This patch re initializes hardware by calling stmmac_hw_setup function in
+resume case.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 341c8dc3..742a83f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2887,18 +2887,19 @@ int stmmac_resume(struct net_device *ndev)
+ * this bit because it can generate problems while resuming
+ * from another devices (e.g. serial console).
+ */
+- if (device_may_wakeup(priv->device))
++ if (device_may_wakeup(priv->device)) {
+ priv->hw->mac->pmt(priv->ioaddr, 0);
+- else
++ } else {
+ /* enable the clk prevously disabled */
+ clk_prepare_enable(priv->stmmac_clk);
++ /* reset the phy so that it's ready */
++ if (priv->mii)
++ stmmac_mdio_reset(priv->mii);
++ }
+
+ netif_device_attach(ndev);
+
+- /* Enable the MAC and DMA */
+- stmmac_set_mac(priv->ioaddr, true);
+- priv->hw->dma->start_tx(priv->ioaddr);
+- priv->hw->dma->start_rx(priv->ioaddr);
++ stmmac_hw_setup(ndev);
+
+ napi_enable(&priv->napi);
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch b/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch
new file mode 100644
index 0000000000..67e0c5bd78
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch
@@ -0,0 +1,146 @@
+From 33a23e223749c45ff8099ff9baa235301a3ad07f Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:44 +0000
+Subject: [PATCH] net: stmmac: use suspend functions for hibernation
+
+In hibernation freeze case the driver just releases the resources like
+dma buffers, irqs, unregisters the drivers and during restore it does
+register, request the resources. This is not really necessary, as part
+of power management all the data structures are intact, all the
+previously allocated resources can be used after coming out of low
+power.
+
+This patch uses the suspend and resume callbacks for freeze and
+restore which initializes the hardware correctly without unregistering
+or releasing the resources, this should also help in reducing the time
+to restore.
+
+Also this patch fixes a bug in stmmac_pltfr_restore and
+stmmac_pltfr_freeze where it tries to get hold of platform data via
+dev_get_platdata call, which would return NULL in device tree cases and
+the next if statement would crash as there is no NULL check.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 -
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 --------
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 ++++++----------------
+ 3 files changed, 12 insertions(+), 50 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 5a568015..027f1dd 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -117,8 +117,6 @@ struct stmmac_priv {
+ extern const struct stmmac_hwtimestamp stmmac_ptp;
+ int stmmac_ptp_register(struct stmmac_priv *priv);
+ void stmmac_ptp_unregister(struct stmmac_priv *priv);
+-int stmmac_freeze(struct net_device *ndev);
+-int stmmac_restore(struct net_device *ndev);
+ int stmmac_resume(struct net_device *ndev);
+ int stmmac_suspend(struct net_device *ndev);
+ int stmmac_dvr_remove(struct net_device *ndev);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 742a83f..c1298a0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2912,22 +2912,6 @@ int stmmac_resume(struct net_device *ndev)
+
+ return 0;
+ }
+-
+-int stmmac_freeze(struct net_device *ndev)
+-{
+- if (!ndev || !netif_running(ndev))
+- return 0;
+-
+- return stmmac_release(ndev);
+-}
+-
+-int stmmac_restore(struct net_device *ndev)
+-{
+- if (!ndev || !netif_running(ndev))
+- return 0;
+-
+- return stmmac_open(ndev);
+-}
+ #endif /* CONFIG_PM */
+
+ /* Driver can be configured w/ and w/ both PCI and Platf drivers
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 9377ee6..6d0bf22 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -211,55 +211,35 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM
+ static int stmmac_pltfr_suspend(struct device *dev)
+ {
+- struct net_device *ndev = dev_get_drvdata(dev);
+-
+- return stmmac_suspend(ndev);
+-}
+-
+-static int stmmac_pltfr_resume(struct device *dev)
+-{
+- struct net_device *ndev = dev_get_drvdata(dev);
+-
+- return stmmac_resume(ndev);
+-}
+-
+-static int stmmac_pltfr_freeze(struct device *dev)
+-{
+ int ret;
+- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
++ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct platform_device *pdev = to_platform_device(dev);
+
+- ret = stmmac_freeze(ndev);
+- if (plat_dat->exit)
+- plat_dat->exit(pdev);
++ ret = stmmac_suspend(ndev);
++ if (priv->plat->exit)
++ priv->plat->exit(pdev);
+
+ return ret;
+ }
+
+-static int stmmac_pltfr_restore(struct device *dev)
++static int stmmac_pltfr_resume(struct device *dev)
+ {
+- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
++ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct platform_device *pdev = to_platform_device(dev);
+
+- if (plat_dat->init)
+- plat_dat->init(pdev);
++ if (priv->plat->init)
++ priv->plat->init(pdev);
+
+- return stmmac_restore(ndev);
++ return stmmac_resume(ndev);
+ }
+
+-static const struct dev_pm_ops stmmac_pltfr_pm_ops = {
+- .suspend = stmmac_pltfr_suspend,
+- .resume = stmmac_pltfr_resume,
+- .freeze = stmmac_pltfr_freeze,
+- .thaw = stmmac_pltfr_restore,
+- .restore = stmmac_pltfr_restore,
+-};
+-#else
+-static const struct dev_pm_ops stmmac_pltfr_pm_ops;
+ #endif /* CONFIG_PM */
+
++static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
++ stmmac_pltfr_suspend, stmmac_pltfr_resume);
++
+ static const struct of_device_id stmmac_dt_ids[] = {
+ { .compatible = "st,spear600-gmac"},
+ { .compatible = "snps,dwmac-3.610"},
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch b/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch
new file mode 100644
index 0000000000..b4ffecbc12
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch
@@ -0,0 +1,50 @@
+From db88f10ad6a84c5bcb71bf51f0988a4bb1733bea Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:52:52 +0000
+Subject: [PATCH] net: stmmac: restore pinstate in pm resume.
+
+This patch adds code to restore default pinstate of the pins when it
+comes back from low power state. Without this patch the state of the
+pins would be unknown and the driver would not work.
+
+This patch also adds code to put the pins in to sleep state when the
+driver enters low power state.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index c1298a0..df7d8d6 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -43,6 +43,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
+ #include <linux/prefetch.h>
++#include <linux/pinctrl/consumer.h>
+ #ifdef CONFIG_STMMAC_DEBUG_FS
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+@@ -2864,6 +2865,7 @@ int stmmac_suspend(struct net_device *ndev)
+ priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+ else {
+ stmmac_set_mac(priv->ioaddr, false);
++ pinctrl_pm_select_sleep_state(priv->device);
+ /* Disable clock in case of PWM is off */
+ clk_disable_unprepare(priv->stmmac_clk);
+ }
+@@ -2890,6 +2892,7 @@ int stmmac_resume(struct net_device *ndev)
+ if (device_may_wakeup(priv->device)) {
+ priv->hw->mac->pmt(priv->ioaddr, 0);
+ } else {
++ pinctrl_pm_select_default_state(priv->device);
+ /* enable the clk prevously disabled */
+ clk_prepare_enable(priv->stmmac_clk);
+ /* reset the phy so that it's ready */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch b/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch
new file mode 100644
index 0000000000..5d6e6a5bbf
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch
@@ -0,0 +1,73 @@
+From 89f7f2cfdd7ade55d5230501c21271690790ceda Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Date: Thu, 16 Jan 2014 10:53:00 +0000
+Subject: [PATCH] net: stmmac: notify the PM core of a wakeup event.
+
+In PM_SUSPEND_FREEZE and WOL(Wakeup On Lan) case, when the driver gets a
+wakeup event, either the driver or platform specific PM code should notify
+the pm core about it, so that the system can wakeup from low power.
+
+In cases where there is no involvement of platform specific PM, it
+becomes driver responsibility to notify the PM core to wakeup the
+system.
+
+Without this WOL with PM_SUSPEND_FREEZE does not work on STi based SOCs.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
+Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 027f1dd..73709e9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -105,6 +105,7 @@ struct stmmac_priv {
+ unsigned int default_addend;
+ u32 adv_ts;
+ int use_riwt;
++ int irq_wake;
+ spinlock_t ptp_lock;
+ };
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index df7d8d6..cddcf76 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2320,6 +2320,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct stmmac_priv *priv = netdev_priv(dev);
+
++ if (priv->irq_wake)
++ pm_wakeup_event(priv->device, 0);
++
+ if (unlikely(!dev)) {
+ pr_err("%s: invalid dev pointer\n", __func__);
+ return IRQ_NONE;
+@@ -2861,9 +2864,10 @@ int stmmac_suspend(struct net_device *ndev)
+ stmmac_clear_descriptors(priv);
+
+ /* Enable Power down mode by programming the PMT regs */
+- if (device_may_wakeup(priv->device))
++ if (device_may_wakeup(priv->device)) {
+ priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+- else {
++ priv->irq_wake = 1;
++ } else {
+ stmmac_set_mac(priv->ioaddr, false);
+ pinctrl_pm_select_sleep_state(priv->device);
+ /* Disable clock in case of PWM is off */
+@@ -2891,6 +2895,7 @@ int stmmac_resume(struct net_device *ndev)
+ */
+ if (device_may_wakeup(priv->device)) {
+ priv->hw->mac->pmt(priv->ioaddr, 0);
++ priv->irq_wake = 0;
+ } else {
+ pinctrl_pm_select_default_state(priv->device);
+ /* enable the clk prevously disabled */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch b/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch
new file mode 100644
index 0000000000..323f86128d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch
@@ -0,0 +1,38 @@
+From 957f00fbab201f429ad81cc87ee3177e4289567d Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 10 Feb 2014 18:35:51 +0800
+Subject: [PATCH] ARM: dts: sun7i: cubietruck: Enable the GMAC
+
+The CubieTruck uses the GMAC with an RGMII phy.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+index f9dcb61..025ce52 100644
+--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+@@ -51,6 +51,18 @@
+ pinctrl-0 = <&i2c2_pins_a>;
+ status = "okay";
+ };
++
++ gmac: ethernet@01c50000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&gmac_pins_rgmii_a>;
++ phy = <&phy1>;
++ phy-mode = "rgmii";
++ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
++ };
+ };
+
+ leds {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch b/target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch
index e76cd0325c..0f1471ad3d 100644
--- a/target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch
+++ b/target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch
@@ -1,6 +1,6 @@
-From e28b63650ff934751b9fe56415dc2491a6c6b704 Mon Sep 17 00:00:00 2001
+From 7405ae68d251191677e51aadb4308d6ce5212bbe Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:41 +0800
+Date: Mon, 10 Feb 2014 18:35:52 +0800
Subject: [PATCH] ARM: dts: sun7i: cubieboard2: Enable GMAC instead of EMAC
GMAC has better performance and fewer hardware issues.
@@ -8,9 +8,11 @@ Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 ++++++++---------------
- 1 file changed, 8 insertions(+), 15 deletions(-)
+ arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 ++++++++++++---------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+index 5c51cb8..7bf4935 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -19,21 +19,6 @@
@@ -32,21 +34,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
- };
- };
-
- mmc0: mmc@01c0f000 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins_a>;
-@@ -111,6 +96,14 @@
- vbus-supply = <&reg_usb2_vbus>;
+ pinctrl@01c20800 {
+ led_pins_cubieboard2: led_pins@0 {
+ allwinner,pins = "PH20", "PH21";
+@@ -60,6 +45,18 @@
+ pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
-+ pinctrl-0 = <&gmac_pins_mii>;
-+ snps,phy-addr = <1>;
++ pinctrl-0 = <&gmac_pins_mii_a>;
++ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
+ };
};
leds {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch b/target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch
index 42526af088..d58dccbe25 100644
--- a/target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch
+++ b/target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch
@@ -1,16 +1,19 @@
-From e39d51b2236ab17628fe5d110296cd33a9c4427e Mon Sep 17 00:00:00 2001
+From e401b86036245d2d62d825f0e3e12286c111b281 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:42 +0800
-Subject: [PATCH] ARM: dts: sun7i: olinuxino-micro: Enable GMAC instead of EMAC
+Date: Mon, 10 Feb 2014 18:35:53 +0800
+Subject: [PATCH] ARM: dts: sun7i: a20-olinuxino-micro: Enable GMAC instead of
+ EMAC
GMAC has better performance and fewer hardware issues.
Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
- arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++---------------
- 1 file changed, 8 insertions(+), 15 deletions(-)
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 27 +++++++++++--------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index ead3013..b02a796 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -19,21 +19,6 @@
@@ -32,21 +35,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
- };
- };
-
- mmc0: mmc@01c0f000 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins_a>;
-@@ -146,6 +131,14 @@
- vbus-supply = <&reg_usb2_vbus>;
+ pinctrl@01c20800 {
+ led_pins_olinuxino: led_pins@0 {
+ allwinner,pins = "PH2";
+@@ -78,6 +63,18 @@
+ pinctrl-0 = <&i2c2_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
-+ pinctrl-0 = <&gmac_pins_mii>;
-+ snps,phy-addr = <1>;
++ pinctrl-0 = <&gmac_pins_mii_a>;
++ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
+ };
};
leds {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch b/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch
deleted file mode 100644
index fcf34977c0..0000000000
--- a/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 447675f817b95881e9922f002de3fc7f6d6e9207 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
-Date: Fri, 6 Sep 2013 22:34:33 +0200
-Subject: [PATCH] ARM: sunxi-mci: Add driver for SD/MMC hosts found within
- Allwinner A1X SoCs
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/mmc/host/Kconfig | 8 +
- drivers/mmc/host/Makefile | 2 +
- drivers/mmc/host/sunxi-mci.c | 1056 ++++++++++++++++++++++++++++++++++++++++++
- drivers/mmc/host/sunxi-mci.h | 334 +++++++++++++
- 4 files changed, 1400 insertions(+)
- create mode 100644 drivers/mmc/host/sunxi-mci.c
- create mode 100644 drivers/mmc/host/sunxi-mci.h
-
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -690,3 +690,11 @@ config MMC_REALTEK_PCI
- help
- Say Y here to include driver code to support SD/MMC card interface
- of Realtek PCI-E card reader
-+
-+config MMC_SUNXI
-+ tristate "Allwinner A1X SD/MMC Host Controller support"
-+ depends on ARCH_SUNXI
-+ default y
-+ help
-+ This selects support for the SD/MMC Host Controller on
-+ Allwinner A1X based SoCs.
---- a/drivers/mmc/host/Makefile
-+++ b/drivers/mmc/host/Makefile
-@@ -53,6 +53,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
-
- obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
-
-+obj-$(CONFIG_MMC_SUNXI) += sunxi-mci.o
-+
- obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
- obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
- obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
diff --git a/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch b/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch
deleted file mode 100644
index 1c5a45364e..0000000000
--- a/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From 677631fa522e4ac24f636535e3abb5cd1a5ef40e Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sat, 14 Dec 2013 22:58:12 +0100
-Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun4i-a10-a1000.dts | 16 ++++++++++++++++
- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++
- arch/arm/boot/dts/sun4i-a10.dtsi | 17 +++++++++++++++++
- 3 files changed, 49 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
-@@ -39,7 +39,23 @@
- };
- };
-
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_a1000>;
-+ cd-gpios = <&pio 7 1 0>; /* PH1 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_a1000: mmc0_cd_pin@0 {
-+ allwinner,pins = "PH1";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- emac_power_pin_a1000: emac_power_pin@0 {
- allwinner,pins = "PH15";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-@@ -42,7 +42,23 @@
- };
- };
-
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_cubieboard>;
-+ cd-gpios = <&pio 7 1 0>; /* PH1 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 {
-+ allwinner,pins = "PH1";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_cubieboard: led_pins@0 {
- allwinner,pins = "PH20", "PH21";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun4i-a10.dtsi
-+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
-@@ -328,6 +328,16 @@
- #size-cells = <0>;
- };
-
-+ mmc0: mmc@01c0f000 {
-+ compatible = "allwinner,sun4i-a10-mmc";
-+ reg = <0x01c0f000 0x1000>;
-+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
-+ clock-names = "ahb", "mod";
-+ interrupts = <32>;
-+ bus-width = <4>;
-+ status = "disabled";
-+ };
-+
- intc: interrupt-controller@01c20400 {
- compatible = "allwinner,sun4i-ic";
- reg = <0x01c20400 0x400>;
-@@ -398,6 +408,13 @@
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-+
-+ mmc0_pins_a: mmc0@0 {
-+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
-+ allwinner,function = "mmc0";
-+ allwinner,drive = <3>;
-+ allwinner,pull = <0>;
-+ };
- };
-
- timer@01c20c00 {
diff --git a/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch b/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch
new file mode 100644
index 0000000000..e8137fb924
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch
@@ -0,0 +1,96 @@
+From 62866e98737e77c87f9dec99edea76ab54360770 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:40 +0800
+Subject: [PATCH] net: stmmac: Enable stmmac main clock when probing hardware
+
+The stmmac driver does not enable the main clock during the probe phase.
+If the clock was not enabled by the boot loader or was disabled by the
+kernel, hardware features and the MDIO bus would not be probed properly.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index cddcf76..0d2c4cb 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -1680,8 +1680,6 @@ static int stmmac_open(struct net_device *dev)
+ struct stmmac_priv *priv = netdev_priv(dev);
+ int ret;
+
+- clk_prepare_enable(priv->stmmac_clk);
+-
+ stmmac_check_ether_addr(priv);
+
+ if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
+@@ -1819,7 +1817,6 @@ static int stmmac_release(struct net_device *dev)
+ #ifdef CONFIG_STMMAC_DEBUG_FS
+ stmmac_exit_fs();
+ #endif
+- clk_disable_unprepare(priv->stmmac_clk);
+
+ stmmac_release_ptp(priv);
+
+@@ -2727,10 +2724,18 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ if ((phyaddr >= 0) && (phyaddr <= 31))
+ priv->plat->phy_addr = phyaddr;
+
++ priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
++ if (IS_ERR(priv->stmmac_clk)) {
++ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
++ __func__);
++ goto error_clk_get;
++ }
++ clk_prepare_enable(priv->stmmac_clk);
++
+ /* Init MAC and get the capabilities */
+ ret = stmmac_hw_init(priv);
+ if (ret)
+- goto error_free_netdev;
++ goto error_hw_init;
+
+ ndev->netdev_ops = &stmmac_netdev_ops;
+
+@@ -2768,12 +2773,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ goto error_netdev_register;
+ }
+
+- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
+- if (IS_ERR(priv->stmmac_clk)) {
+- pr_warn("%s: warning: cannot get CSR clock\n", __func__);
+- goto error_clk_get;
+- }
+-
+ /* If a specific clk_csr value is passed from the platform
+ * this means that the CSR Clock Range selection cannot be
+ * changed at run-time and it is fixed. Viceversa the driver'll try to
+@@ -2801,12 +2800,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ return priv;
+
+ error_mdio_register:
+- clk_put(priv->stmmac_clk);
+-error_clk_get:
+ unregister_netdev(ndev);
+ error_netdev_register:
+ netif_napi_del(&priv->napi);
+-error_free_netdev:
++error_hw_init:
++ clk_disable_unprepare(priv->stmmac_clk);
++error_clk_get:
+ free_netdev(ndev);
+
+ return NULL;
+@@ -2833,6 +2832,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
+ stmmac_mdio_unregister(ndev);
+ netif_carrier_off(ndev);
+ unregister_netdev(ndev);
++ clk_disable_unprepare(priv->stmmac_clk);
+ free_netdev(ndev);
+
+ return 0;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch b/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch
new file mode 100644
index 0000000000..188eaf0075
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch
@@ -0,0 +1,158 @@
+From c5e4ddbdfa1134a36589c1466ed4abb85fe6f976 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:41 +0800
+Subject: [PATCH] net: stmmac: Add support for optional reset control
+
+The DWMAC has a reset assert line, which is used on some SoCs. Add an
+optional reset control to stmmac driver core.
+
+To support reset control deferred probing, this patch changes the driver
+probe function to return the actual error, instead of just -EINVAL.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ Documentation/devicetree/bindings/net/stmmac.txt | 3 +++
+ drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++++++-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 ++--
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
+ 6 files changed, 28 insertions(+), 5 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
+index eba0e5e..d132513 100644
+--- a/Documentation/devicetree/bindings/net/stmmac.txt
++++ b/Documentation/devicetree/bindings/net/stmmac.txt
+@@ -30,6 +30,9 @@ Required properties:
+
+ Optional properties:
+ - mac-address: 6 bytes, mac address
++- resets: Should contain a phandle to the STMMAC reset signal, if any
++- reset-names: Should contain the reset signal name "stmmaceth", if a
++ reset phandle is given
+
+ Examples:
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+index 6e52c0f..b59d1ef 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -5,6 +5,7 @@ config STMMAC_ETH
+ select PHYLIB
+ select CRC32
+ select PTP_1588_CLOCK
++ select RESET_CONTROLLER
+ ---help---
+ This is the driver for the Ethernet IPs are built around a
+ Synopsys IP Core and only tested on the STMicroelectronics
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 73709e9..c1c141f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -32,6 +32,7 @@
+ #include <linux/pci.h>
+ #include "common.h"
+ #include <linux/ptp_clock_kernel.h>
++#include <linux/reset.h>
+
+ struct stmmac_priv {
+ /* Frequently used values are kept adjacent for cache effect */
+@@ -91,6 +92,7 @@ struct stmmac_priv {
+ int wolopts;
+ int wol_irq;
+ struct clk *stmmac_clk;
++ struct reset_control *stmmac_rst;
+ int clk_csr;
+ struct timer_list eee_ctrl_timer;
+ int lpi_irq;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 0d2c4cb..0c5c120 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -51,6 +51,7 @@
+ #include <linux/net_tstamp.h>
+ #include "stmmac_ptp.h"
+ #include "stmmac.h"
++#include <linux/reset.h>
+
+ #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
+ #define JUMBO_LEN 9000
+@@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ if (IS_ERR(priv->stmmac_clk)) {
+ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
+ __func__);
++ ret = PTR_ERR(priv->stmmac_clk);
+ goto error_clk_get;
+ }
+ clk_prepare_enable(priv->stmmac_clk);
+
++ priv->stmmac_rst = devm_reset_control_get(priv->device,
++ STMMAC_RESOURCE_NAME);
++ if (IS_ERR(priv->stmmac_rst)) {
++ if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
++ ret = -EPROBE_DEFER;
++ goto error_hw_init;
++ }
++ dev_info(priv->device, "no reset control found\n");
++ priv->stmmac_rst = NULL;
++ }
++ if (priv->stmmac_rst)
++ reset_control_deassert(priv->stmmac_rst);
++
+ /* Init MAC and get the capabilities */
+ ret = stmmac_hw_init(priv);
+ if (ret)
+@@ -2808,7 +2823,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ error_clk_get:
+ free_netdev(ndev);
+
+- return NULL;
++ return ERR_PTR(ret);
+ }
+
+ /**
+@@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
+ stmmac_mdio_unregister(ndev);
+ netif_carrier_off(ndev);
+ unregister_netdev(ndev);
++ if (priv->stmmac_rst)
++ reset_control_assert(priv->stmmac_rst);
+ clk_disable_unprepare(priv->stmmac_clk);
+ free_netdev(ndev);
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 37ba2e0..2916089 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ stmmac_default_data();
+
+ priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
+- if (!priv) {
++ if (IS_ERR(priv)) {
+ pr_err("%s: main driver probe failed", __func__);
+- ret = -ENODEV;
++ ret = PTR_ERR(priv);
+ goto err_out;
+ }
+ priv->dev->irq = pdev->irq;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 6d0bf22..cc6b89a7 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
+ }
+
+ priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
+- if (!priv) {
++ if (IS_ERR(priv)) {
+ pr_err("%s: main driver probe failed", __func__);
+- return -ENODEV;
++ return PTR_ERR(priv);
+ }
+
+ /* Get MAC address if available (DT) */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch b/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch
deleted file mode 100644
index e0368a1ed1..0000000000
--- a/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-From 3cce544eb5964c14653dddde731cac4cbff97d90 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sat, 14 Dec 2013 22:58:15 +0100
-Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 16 ++++++++++++
- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 16 ++++++++++++
- arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 32 +++++++++++++++++++++++
- arch/arm/boot/dts/sun7i-a20.dtsi | 34 +++++++++++++++++++++++++
- 4 files changed, 98 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-@@ -34,7 +34,23 @@
- };
- };
-
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_cubieboard2>;
-+ cd-gpios = <&pio 7 1 0>; /* PH1 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 {
-+ allwinner,pins = "PH1";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_cubieboard2: led_pins@0 {
- allwinner,pins = "PH20", "PH21";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-@@ -34,7 +34,39 @@
- };
- };
-
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
-+ cd-gpios = <&pio 7 1 0>; /* PH1 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
-+ mmc3: mmc@01c12000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc3_pins_a>;
-+ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
-+ cd-gpios = <&pio 7 11 0>; /* PH11 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
-+ allwinner,pins = "PH1";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
-+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
-+ allwinner,pins = "PH11";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_olinuxino: led_pins@0 {
- allwinner,pins = "PH2";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -334,6 +334,26 @@
- #size-cells = <0>;
- };
-
-+ mmc0: mmc@01c0f000 {
-+ compatible = "allwinner,sun5i-a13-mmc";
-+ reg = <0x01c0f000 0x1000>;
-+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
-+ clock-names = "ahb", "mod";
-+ interrupts = <0 32 4>;
-+ bus-width = <4>;
-+ status = "disabled";
-+ };
-+
-+ mmc3: mmc@01c12000 {
-+ compatible = "allwinner,sun5i-a13-mmc";
-+ reg = <0x01c12000 0x1000>;
-+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
-+ clock-names = "ahb", "mod";
-+ interrupts = <0 35 4>;
-+ bus-width = <4>;
-+ status = "disabled";
-+ };
-+
- pio: pinctrl@01c20800 {
- compatible = "allwinner,sun7i-a20-pinctrl";
- reg = <0x01c20800 0x400>;
-@@ -397,6 +417,20 @@
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-+
-+ mmc0_pins_a: mmc0@0 {
-+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
-+ allwinner,function = "mmc0";
-+ allwinner,drive = <3>;
-+ allwinner,pull = <0>;
-+ };
-+
-+ mmc3_pins_a: mmc3@0 {
-+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
-+ allwinner,function = "mmc3";
-+ allwinner,drive = <3>;
-+ allwinner,pull = <0>;
-+ };
- };
-
- timer@01c20c00 {
diff --git a/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch b/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch
new file mode 100644
index 0000000000..2c477c5259
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch
@@ -0,0 +1,124 @@
+From 938dfdaa3c0f92e9a490d324f3bce43bbaef7632 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:42 +0800
+Subject: [PATCH] net: stmmac: Allocate and pass soc/board specific data to
+ callbacks
+
+The current .init and .exit callbacks requires access to driver
+private data structures. This is not a good seperation and abstraction.
+
+Instead, we add a new .setup callback for allocating private data, and
+pass the returned pointer to the other callbacks.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ Documentation/networking/stmmac.txt | 12 ++++++++----
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 18 ++++++++++++++----
+ include/linux/stmmac.h | 6 ++++--
+ 3 files changed, 26 insertions(+), 10 deletions(-)
+
+diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
+index cdd916d..2090895 100644
+--- a/Documentation/networking/stmmac.txt
++++ b/Documentation/networking/stmmac.txt
+@@ -127,8 +127,9 @@ struct plat_stmmacenet_data {
+ int riwt_off;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+- int (*init)(struct platform_device *pdev);
+- void (*exit)(struct platform_device *pdev);
++ void *(*setup)(struct platform_device *pdev);
++ int (*init)(struct platform_device *pdev, void *priv);
++ void (*exit)(struct platform_device *pdev, void *priv);
+ void *custom_cfg;
+ void *custom_data;
+ void *bsp_priv;
+@@ -169,10 +170,13 @@ Where:
+ o bus_setup: perform HW setup of the bus. For example, on some ST platforms
+ this field is used to configure the AMBA bridge to generate more
+ efficient STBus traffic.
+- o init/exit: callbacks used for calling a custom initialization;
++ o setup/init/exit: callbacks used for calling a custom initialization;
+ this is sometime necessary on some platforms (e.g. ST boxes)
+ where the HW needs to have set some PIO lines or system cfg
+- registers.
++ registers. setup should return a pointer to private data,
++ which will be stored in bsp_priv, and then passed to init and
++ exit callbacks. init/exit callbacks should not use or modify
++ platform data.
+ o custom_cfg/custom_data: this is a custom configuration that can be passed
+ while initializing the resources.
+ o bsp_priv: another private pointer.
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index cc6b89a7..704a5e0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -144,9 +144,16 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
+ }
+ }
+
++ /* Custom setup (if needed) */
++ if (plat_dat->setup) {
++ plat_dat->bsp_priv = plat_dat->setup(pdev);
++ if (IS_ERR(plat_dat->bsp_priv))
++ return PTR_ERR(plat_dat->bsp_priv);
++ }
++
+ /* Custom initialisation (if needed)*/
+ if (plat_dat->init) {
+- ret = plat_dat->init(pdev);
++ ret = plat_dat->init(pdev, plat_dat->bsp_priv);
+ if (unlikely(ret))
+ return ret;
+ }
+@@ -203,7 +210,10 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
+ int ret = stmmac_dvr_remove(ndev);
+
+ if (priv->plat->exit)
+- priv->plat->exit(pdev);
++ priv->plat->exit(pdev, priv->plat->bsp_priv);
++
++ if (priv->plat->free)
++ priv->plat->free(pdev, priv->plat->bsp_priv);
+
+ return ret;
+ }
+@@ -218,7 +228,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
+
+ ret = stmmac_suspend(ndev);
+ if (priv->plat->exit)
+- priv->plat->exit(pdev);
++ priv->plat->exit(pdev, priv->plat->bsp_priv);
+
+ return ret;
+ }
+@@ -230,7 +240,7 @@ static int stmmac_pltfr_resume(struct device *dev)
+ struct platform_device *pdev = to_platform_device(dev);
+
+ if (priv->plat->init)
+- priv->plat->init(pdev);
++ priv->plat->init(pdev, priv->plat->bsp_priv);
+
+ return stmmac_resume(ndev);
+ }
+diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
+index 33ace71..0a5a7ac 100644
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -113,8 +113,10 @@ struct plat_stmmacenet_data {
+ int max_speed;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+- int (*init)(struct platform_device *pdev);
+- void (*exit)(struct platform_device *pdev);
++ void *(*setup)(struct platform_device *pdev);
++ void (*free)(struct platform_device *pdev, void *priv);
++ int (*init)(struct platform_device *pdev, void *priv);
++ void (*exit)(struct platform_device *pdev, void *priv);
+ void *custom_cfg;
+ void *custom_data;
+ void *bsp_priv;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch b/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch
new file mode 100644
index 0000000000..17caee3cf7
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch
@@ -0,0 +1,31 @@
+From 6aedb8c06df732625cf998c1428396914f3139b4 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:44 +0800
+Subject: [PATCH] net: stmmac: Honor DT parameter to force DMA store and
+ forward mode
+
+"snps,force_sf_dma_mode" is documented in stmmac device tree bindings,
+but is never handled by the driver.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 704a5e0..634260e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -56,6 +56,8 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
+ sizeof(struct stmmac_mdio_bus_data),
+ GFP_KERNEL);
+
++ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
++
+ /*
+ * Currently only the properties needed on SPEAr600
+ * are provided. All other properties should be added
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch b/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch
new file mode 100644
index 0000000000..5b9b09c672
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch
@@ -0,0 +1,55 @@
+From 436f7ecdcc08f71ddc106b7bbe3bcbf1785f3bff Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:45 +0800
+Subject: [PATCH] net: stmmac: Deprecate snps, phy-addr and auto-detect PHY
+ address
+
+The snps,phy-addr device tree property is non-standard, and should be
+removed in favor of proper phy node support. Remove it from the binding
+documents and warn if the property is still used.
+
+Most PHYs respond to address 0, but a few don't, so auto-detect PHY
+address by default, to make up for the lack of explicit address selection.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ Documentation/devicetree/bindings/net/stmmac.txt | 1 -
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 9 ++++++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
+index d132513..aefb639 100644
+--- a/Documentation/devicetree/bindings/net/stmmac.txt
++++ b/Documentation/devicetree/bindings/net/stmmac.txt
+@@ -12,7 +12,6 @@ Required properties:
+ property
+ - phy-mode: String, operation mode of the PHY interface.
+ Supported values are: "mii", "rmii", "gmii", "rgmii".
+-- snps,phy-addr phy address to connect to.
+ - snps,reset-gpio gpio number for phy reset.
+ - snps,reset-active-low boolean flag to indicate if phy reset is active low.
+ - snps,reset-delays-us is triplet of delays
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 634260e..82110f1 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -50,7 +50,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
+ if (plat->bus_id < 0)
+ plat->bus_id = 0;
+
+- of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr);
++ /* Default to phy auto-detection */
++ plat->phy_addr = -1;
++
++ /* "snps,phy-addr" is not a standard property. Mark it as deprecated
++ * and warn of its use. Remove this when phy node support is added.
++ */
++ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
++ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+
+ plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
+ sizeof(struct stmmac_mdio_bus_data),
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch b/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch
new file mode 100644
index 0000000000..99ccd34372
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch
@@ -0,0 +1,123 @@
+From 022066f50f53000679d31eb407693085f37b3f14 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:46 +0800
+Subject: [PATCH] net: stmmac: Use driver data and callbacks tied with
+ compatible strings
+
+The stmmac driver core allows passing feature flags and callbacks via
+platform data. Add a similar stmmac_of_data to pass flags and callbacks
+tied to compatible strings. This allows us to extend stmmac with glue
+layers for different SoCs.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++++++++++++++++-----
+ include/linux/stmmac.h | 18 +++++++++
+ 2 files changed, 52 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index 82110f1..bf119db 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -26,8 +26,20 @@
+ #include <linux/io.h>
+ #include <linux/of.h>
+ #include <linux/of_net.h>
++#include <linux/of_device.h>
+ #include "stmmac.h"
+
++static const struct of_device_id stmmac_dt_ids[] = {
++ /* SoC specific glue layers should come before generic bindings */
++ { .compatible = "st,spear600-gmac"},
++ { .compatible = "snps,dwmac-3.610"},
++ { .compatible = "snps,dwmac-3.70a"},
++ { .compatible = "snps,dwmac-3.710"},
++ { .compatible = "snps,dwmac"},
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
++
+ #ifdef CONFIG_OF
+ static int stmmac_probe_config_dt(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+@@ -35,10 +47,32 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
+ {
+ struct device_node *np = pdev->dev.of_node;
+ struct stmmac_dma_cfg *dma_cfg;
++ const struct of_device_id *device;
+
+ if (!np)
+ return -ENODEV;
+
++ device = of_match_device(stmmac_dt_ids, &pdev->dev);
++ if (!device)
++ return -ENODEV;
++
++ if (device->data) {
++ const struct stmmac_of_data *data = device->data;
++ plat->has_gmac = data->has_gmac;
++ plat->enh_desc = data->enh_desc;
++ plat->tx_coe = data->tx_coe;
++ plat->rx_coe = data->rx_coe;
++ plat->bugged_jumbo = data->bugged_jumbo;
++ plat->pmt = data->pmt;
++ plat->riwt_off = data->riwt_off;
++ plat->fix_mac_speed = data->fix_mac_speed;
++ plat->bus_setup = data->bus_setup;
++ plat->setup = data->setup;
++ plat->free = data->free;
++ plat->init = data->init;
++ plat->exit = data->exit;
++ }
++
+ *mac = of_get_mac_address(np);
+ plat->interface = of_get_phy_mode(np);
+
+@@ -259,16 +293,6 @@ static int stmmac_pltfr_resume(struct device *dev)
+ static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
+ stmmac_pltfr_suspend, stmmac_pltfr_resume);
+
+-static const struct of_device_id stmmac_dt_ids[] = {
+- { .compatible = "st,spear600-gmac"},
+- { .compatible = "snps,dwmac-3.610"},
+- { .compatible = "snps,dwmac-3.70a"},
+- { .compatible = "snps,dwmac-3.710"},
+- { .compatible = "snps,dwmac"},
+- { /* sentinel */ }
+-};
+-MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
+-
+ struct platform_driver stmmac_pltfr_driver = {
+ .probe = stmmac_pltfr_probe,
+ .remove = stmmac_pltfr_remove,
+diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
+index 0a5a7ac..1367974 100644
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -121,4 +121,22 @@ struct plat_stmmacenet_data {
+ void *custom_data;
+ void *bsp_priv;
+ };
++
++/* of_data for SoC glue layer device tree bindings */
++
++struct stmmac_of_data {
++ int has_gmac;
++ int enh_desc;
++ int tx_coe;
++ int rx_coe;
++ int bugged_jumbo;
++ int pmt;
++ int riwt_off;
++ void (*fix_mac_speed)(void *priv, unsigned int speed);
++ void (*bus_setup)(void __iomem *ioaddr);
++ void *(*setup)(struct platform_device *pdev);
++ void (*free)(struct platform_device *pdev, void *priv);
++ int (*init)(struct platform_device *pdev, void *priv);
++ void (*exit)(struct platform_device *pdev, void *priv);
++};
+ #endif
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch
new file mode 100644
index 0000000000..d0d9f13646
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch
@@ -0,0 +1,273 @@
+From af0bd4e9ba809391f275d0c094ac0bfbfbb3f430 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Fri, 17 Jan 2014 21:24:47 +0800
+Subject: [PATCH] net: stmmac: sunxi platform extensions for GMAC in Allwinner
+ A20 SoC's
+
+The Allwinner A20 has an ethernet controller that seems to be
+an early version of Synopsys DesignWare MAC 10/100/1000 Universal,
+which is supported by the stmmac driver.
+
+Allwinner's GMAC requires setting additional registers in the SoC's
+clock control unit.
+
+The exact version of the DWMAC IP that Allwinner uses is unknown,
+thus the exact feature set is unknown.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ .../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++
+ drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
+ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
+ drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 140 +++++++++++++++++++++
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
+ 6 files changed, 185 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+
+diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
+new file mode 100644
+index 0000000..ea4d752
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
+@@ -0,0 +1,27 @@
++* Allwinner GMAC ethernet controller
++
++This device is a platform glue layer for stmmac.
++Please see stmmac.txt for the other unchanged properties.
++
++Required properties:
++ - compatible: Should be "allwinner,sun7i-a20-gmac"
++ - clocks: Should contain the GMAC main clock, and tx clock
++ The tx clock type should be "allwinner,sun7i-a20-gmac-clk"
++ - clock-names: Should contain the clock names "stmmaceth",
++ and "allwinner_gmac_tx"
++
++Optional properties:
++- phy-supply: phandle to a regulator if the PHY needs one
++
++Examples:
++
++ gmac: ethernet@01c50000 {
++ compatible = "allwinner,sun7i-a20-gmac";
++ reg = <0x01c50000 0x10000>,
++ <0x01c20164 0x4>;
++ interrupts = <0 85 1>;
++ interrupt-names = "macirq";
++ clocks = <&ahb_gates 49>, <&gmac_tx>;
++ clock-names = "stmmaceth", "allwinner_gmac_tx";
++ phy-mode = "mii";
++ };
+diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+index b59d1ef..e2f202e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -26,6 +26,17 @@ config STMMAC_PLATFORM
+
+ If unsure, say N.
+
++config DWMAC_SUNXI
++ bool "Allwinner GMAC support"
++ depends on STMMAC_PLATFORM && ARCH_SUNXI
++ default y
++ ---help---
++ Support for Allwinner A20/A31 GMAC ethernet controllers.
++
++ This selects Allwinner SoC glue layer support for the
++ stmmac device driver. This driver is used for A20/A31
++ GMAC ethernet controller.
++
+ config STMMAC_PCI
+ bool "STMMAC PCI bus support"
+ depends on STMMAC_ETH && PCI
+diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
+index 356a9dd..ecadece 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -1,6 +1,7 @@
+ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
+ stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
+ stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
++stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
+ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
+ chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
+ dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+new file mode 100644
+index 0000000..771cd15f
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+@@ -0,0 +1,140 @@
++/**
++ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
++ *
++ * Copyright (C) 2013 Chen-Yu Tsai
++ *
++ * Chen-Yu Tsai <wens@csie.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/stmmac.h>
++#include <linux/clk.h>
++#include <linux/phy.h>
++#include <linux/of_net.h>
++#include <linux/regulator/consumer.h>
++
++struct sunxi_priv_data {
++ int interface;
++ int clk_enabled;
++ struct clk *tx_clk;
++ struct regulator *regulator;
++};
++
++static void *sun7i_gmac_setup(struct platform_device *pdev)
++{
++ struct sunxi_priv_data *gmac;
++ struct device *dev = &pdev->dev;
++
++ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
++ if (!gmac)
++ return ERR_PTR(-ENOMEM);
++
++ gmac->interface = of_get_phy_mode(dev->of_node);
++
++ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
++ if (IS_ERR(gmac->tx_clk)) {
++ dev_err(dev, "could not get tx clock\n");
++ return gmac->tx_clk;
++ }
++
++ /* Optional regulator for PHY */
++ gmac->regulator = devm_regulator_get_optional(dev, "phy");
++ if (IS_ERR(gmac->regulator)) {
++ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
++ return ERR_PTR(-EPROBE_DEFER);
++ dev_info(dev, "no regulator found\n");
++ gmac->regulator = NULL;
++ }
++
++ return gmac;
++}
++
++#define SUN7I_GMAC_GMII_RGMII_RATE 125000000
++#define SUN7I_GMAC_MII_RATE 25000000
++
++static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
++{
++ struct sunxi_priv_data *gmac = priv;
++ int ret;
++
++ if (gmac->regulator) {
++ ret = regulator_enable(gmac->regulator);
++ if (ret)
++ return ret;
++ }
++
++ /* Set GMAC interface port mode
++ *
++ * The GMAC TX clock lines are configured by setting the clock
++ * rate, which then uses the auto-reparenting feature of the
++ * clock driver, and enabling/disabling the clock.
++ */
++ if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
++ clk_prepare_enable(gmac->tx_clk);
++ gmac->clk_enabled = 1;
++ } else {
++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
++ clk_prepare(gmac->tx_clk);
++ }
++
++ return 0;
++}
++
++static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
++{
++ struct sunxi_priv_data *gmac = priv;
++
++ if (gmac->clk_enabled) {
++ clk_disable(gmac->tx_clk);
++ gmac->clk_enabled = 0;
++ }
++ clk_unprepare(gmac->tx_clk);
++
++ if (gmac->regulator)
++ regulator_disable(gmac->regulator);
++}
++
++static void sun7i_fix_speed(void *priv, unsigned int speed)
++{
++ struct sunxi_priv_data *gmac = priv;
++
++ /* only GMII mode requires us to reconfigure the clock lines */
++ if (gmac->interface != PHY_INTERFACE_MODE_GMII)
++ return;
++
++ if (gmac->clk_enabled) {
++ clk_disable(gmac->tx_clk);
++ gmac->clk_enabled = 0;
++ }
++ clk_unprepare(gmac->tx_clk);
++
++ if (speed == 1000) {
++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
++ clk_prepare_enable(gmac->tx_clk);
++ gmac->clk_enabled = 1;
++ } else {
++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
++ clk_prepare(gmac->tx_clk);
++ }
++}
++
++/* of_data specifying hardware features and callbacks.
++ * hardware features were copied from Allwinner drivers. */
++const struct stmmac_of_data sun7i_gmac_data = {
++ .has_gmac = 1,
++ .tx_coe = 1,
++ .fix_mac_speed = sun7i_fix_speed,
++ .setup = sun7i_gmac_setup,
++ .init = sun7i_gmac_init,
++ .exit = sun7i_gmac_exit,
++};
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index c1c141f..d9af26e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -130,6 +130,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+ bool stmmac_eee_init(struct stmmac_priv *priv);
+
+ #ifdef CONFIG_STMMAC_PLATFORM
++#ifdef CONFIG_DWMAC_SUNXI
++extern const struct stmmac_of_data sun7i_gmac_data;
++#endif
+ extern struct platform_driver stmmac_pltfr_driver;
+ static inline int stmmac_register_platform(void)
+ {
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+index bf119db..9d4baa8 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -30,6 +30,9 @@
+ #include "stmmac.h"
+
+ static const struct of_device_id stmmac_dt_ids[] = {
++#ifdef CONFIG_DWMAC_SUNXI
++ { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
++#endif
+ /* SoC specific glue layers should come before generic bindings */
+ { .compatible = "st,spear600-gmac"},
+ { .compatible = "snps,dwmac-3.610"},
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch b/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch
deleted file mode 100644
index 0be3ac4f96..0000000000
--- a/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/drivers/mmc/host/sunxi-mci.c
-+++ b/drivers/mmc/host/sunxi-mci.c
-@@ -715,8 +715,8 @@ static void sunxi_mmc_request(struct mmc
- }
-
- static const struct of_device_id sunxi_mmc_of_match[] = {
-- { .compatible = "allwinner,sun4i-mmc", },
-- { .compatible = "allwinner,sun5i-mmc", },
-+ { .compatible = "allwinner,sun4i-a10-mmc", },
-+ { .compatible = "allwinner,sun5i-a13-mmc", },
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
-@@ -736,7 +736,7 @@ static int sunxi_mmc_resource_request(st
- struct device_node *np = pdev->dev.of_node;
- int ret;
-
-- if (of_device_is_compatible(np, "allwinner,sun4i-mmc"))
-+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc"))
- host->idma_des_size_bits = 13;
- else
- host->idma_des_size_bits = 16;
diff --git a/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch b/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch
new file mode 100644
index 0000000000..bc6f0e9e92
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch
@@ -0,0 +1,45 @@
+From cc8e5932c671ba2d3ce511a15c19c47b015bc4ab Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 5 Jan 2014 00:00:30 +0100
+Subject: [PATCH] phy-core: phy_get: Leave error logging to the caller
+
+In various cases errors may be expected, ie probe-deferral or a call to
+phy_get from a driver where the use of a phy is optional.
+
+Rather then adding all sort of complicated checks for this, and/or adding
+special functions like devm_phy_get_optional, simply don't log an error,
+and let deciding if get_phy returning an error really should result in a
+dev_err up to the caller.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/phy/phy-core.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
+index 5f5b0f4..b355553 100644
+--- a/drivers/phy/phy-core.c
++++ b/drivers/phy/phy-core.c
+@@ -404,17 +404,11 @@ struct phy *phy_get(struct device *dev, const char *string)
+ index = of_property_match_string(dev->of_node, "phy-names",
+ string);
+ phy = of_phy_get(dev, index);
+- if (IS_ERR(phy)) {
+- dev_err(dev, "unable to find phy\n");
+- return phy;
+- }
+ } else {
+ phy = phy_lookup(dev, string);
+- if (IS_ERR(phy)) {
+- dev_err(dev, "unable to find phy\n");
+- return phy;
+- }
+ }
++ if (IS_ERR(phy))
++ return phy;
+
+ if (!try_module_get(phy->ops->owner))
+ return ERR_PTR(-EPROBE_DEFER);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch b/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch
new file mode 100644
index 0000000000..5caeb8bd27
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch
@@ -0,0 +1,40 @@
+From 37e3cce7288f7d5c34ae630f16faf48bd3d01c18 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 5 Jan 2014 22:40:39 +0100
+Subject: [PATCH] phy-core: Don't propagate -ENOSUPP from
+ phy_pm_runtime_get_sync to caller
+
+The phy-core allows phy_init and phy_power_on to be called multiple times,
+but before this patch -ENOSUPP from phy_pm_runtime_get_sync would be
+propagated to the caller for the 2nd and later calls.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/phy/phy-core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
+index b355553..6c73837 100644
+--- a/drivers/phy/phy-core.c
++++ b/drivers/phy/phy-core.c
+@@ -176,6 +176,8 @@ int phy_init(struct phy *phy)
+ dev_err(&phy->dev, "phy init failed --> %d\n", ret);
+ goto out;
+ }
++ } else {
++ ret = 0; /* Override possible ret == -ENOTSUPP */
+ }
+ ++phy->init_count;
+
+@@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy)
+ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+ goto out;
+ }
++ } else {
++ ret = 0; /* Override possible ret == -ENOTSUPP */
+ }
+ ++phy->power_count;
+ mutex_unlock(&phy->mutex);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch b/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch
new file mode 100644
index 0000000000..15be07e676
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch
@@ -0,0 +1,48 @@
+From 87c01c9ef0602abaa909771c6c6eab1f4c2c384d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 11 Feb 2014 16:55:57 +0100
+Subject: [PATCH] phy-core: Don't allow building phy-core as a module
+
+include/phy/phy.h has stub code in there for when building without the
+phy-core enabled. This is useful for generic drivers such as ahci-platform,
+ehci-platoform and ohci-platform which have support for driving an optional
+phy passed to them through the devicetree.
+
+Since on some boards this phy functionality is not needed, being able to
+disable the phy subsystem without needing a lot of #ifdef magic in the
+driver using it is quite useful.
+
+However this breaks when the module using the phy subsystem is build-in and
+the phy-core is not, which leads to the build failing with missing symbol
+errors in the linking stage of the zImage.
+
+Which leads to gems such as this being added to the Kconfig for achi_platform:
+
+ depends on GENERIC_PHY || !GENERIC_PHY
+
+Rather then duplicating this code in a lot of places using the phy-core,
+I believe it is better to simply not allow the phy-core to be built as a
+module. The phy core is quite small and has no external dependencies, so
+always building it in when enabling it should not be an issue.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/phy/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
+index afa2354..4ef8755 100644
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -5,7 +5,7 @@
+ menu "PHY Subsystem"
+
+ config GENERIC_PHY
+- tristate "PHY Core"
++ bool "PHY Core"
+ help
+ Generic PHY support.
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch b/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch
new file mode 100644
index 0000000000..518c8d7c5c
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch
@@ -0,0 +1,222 @@
+From 9b10bc9f84fc221fcef9ddca92972af9b442f49d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 2 Dec 2013 16:13:32 +0100
+Subject: [PATCH] libahci: Allow drivers to override start_engine
+
+Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a
+special register to be poked before starting the DMA engine.
+
+This register gets reset on an ahci_stop_engine call, so there is no other
+place then ahci_start_engine where this poking can be done.
+
+This commit allows drivers to override ahci_start_engine behavior for use by
+the Allwinner AHCI driver (and potentially other drivers in the future).
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci.c | 6 ++++--
+ drivers/ata/ahci.h | 6 ++++++
+ drivers/ata/libahci.c | 26 +++++++++++++++++++-------
+ drivers/ata/sata_highbank.c | 3 ++-
+ 4 files changed, 31 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index dc2756f..eda68b4 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -564,6 +564,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ bool online;
+ int rc;
+
+@@ -574,7 +575,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+ deadline, &online, NULL);
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+
+@@ -589,6 +590,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ {
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
+ bool online;
+@@ -604,7 +606,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+ deadline, &online, NULL);
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ /* The pseudo configuration device on SIMG4726 attached to
+ * ASUS P5W-DH Deluxe doesn't send signature FIS after
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 2289efd..64d1a99d 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -323,6 +323,12 @@ struct ahci_host_priv {
+ u32 em_msg_type; /* EM message type */
+ struct clk *clk; /* Only for platforms supporting clk */
+ void *plat_data; /* Other platform data */
++ /*
++ * Optional ahci_start_engine override, if not set this gets set to the
++ * default ahci_start_engine during ahci_save_initial_config, this can
++ * be overridden anytime before the host is activated.
++ */
++ void (*start_engine)(struct ata_port *ap);
+ };
+
+ extern int ahci_ignore_sss;
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index 36605ab..f839bb3 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -394,6 +394,9 @@ static ssize_t ahci_show_em_supported(struct device *dev,
+ *
+ * If inconsistent, config values are fixed up by this function.
+ *
++ * If it is not set already this function sets hpriv->start_engine to
++ * ahci_start_engine.
++ *
+ * LOCKING:
+ * None.
+ */
+@@ -500,6 +503,9 @@ void ahci_save_initial_config(struct device *dev,
+ hpriv->cap = cap;
+ hpriv->cap2 = cap2;
+ hpriv->port_map = port_map;
++
++ if (!hpriv->start_engine)
++ hpriv->start_engine = ahci_start_engine;
+ }
+ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
+
+@@ -766,7 +772,7 @@ static void ahci_start_port(struct ata_port *ap)
+
+ /* enable DMA */
+ if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ /* turn on LEDs */
+ if (ap->flags & ATA_FLAG_EM) {
+@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap)
+
+ /* restart engine */
+ out_restart:
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+ return rc;
+ }
+ EXPORT_SYMBOL_GPL(ahci_kick_engine);
+@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
+ bool online;
+@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ rc = sata_link_hardreset(link, timing, deadline, &online,
+ ahci_check_ready);
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ if (online)
+ *class = ahci_dev_classify(ap);
+@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap)
+
+ void ahci_error_handler(struct ata_port *ap)
+ {
++ struct ahci_host_priv *hpriv = ap->host->private_data;
++
+ if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+ /* restart engine */
+ ahci_stop_engine(ap);
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+ }
+
+ sata_pmp_error_handler(ap);
+@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+
+ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
+ {
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ struct ata_device *dev = ap->link.device;
+ u32 devslp, dm, dito, mdat, deto;
+@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
+ PORT_DEVSLP_ADSE);
+ writel(devslp, port_mmio + PORT_DEVSLP);
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ /* enable device sleep feature for the drive */
+ err_mask = ata_dev_set_feature(dev,
+@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
+
+ static void ahci_enable_fbs(struct ata_port *ap)
+ {
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 fbs;
+@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap)
+ } else
+ dev_err(ap->host->dev, "Failed to enable FBS\n");
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+ }
+
+ static void ahci_disable_fbs(struct ata_port *ap)
+ {
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 fbs;
+@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
+ pp->fbs_enabled = false;
+ }
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+ }
+
+ static void ahci_pmp_attach(struct ata_port *ap)
+diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
+index 870b11e..b3b18d1 100644
+--- a/drivers/ata/sata_highbank.c
++++ b/drivers/ata/sata_highbank.c
+@@ -403,6 +403,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
+ static const unsigned long timing[] = { 5, 100, 500};
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
++ struct ahci_host_priv *hpriv = ap->host->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
+ bool online;
+@@ -431,7 +432,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
+ break;
+ } while (!online && retry--);
+
+- ahci_start_engine(ap);
++ hpriv->start_engine(ap);
+
+ if (online)
+ *class = ahci_dev_classify(ap);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch b/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch
new file mode 100644
index 0000000000..11d9a2c244
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch
@@ -0,0 +1,255 @@
+From bdad8090b5efdb24fa9db00d8e2891927b68dcec Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 16 Jan 2014 14:32:35 +0100
+Subject: [PATCH] ahci-platform: Add support for devices with more then 1 clock
+
+The allwinner-sun4i AHCI controller needs 2 clocks to be enabled and the
+imx AHCI controller needs 3 clocks to be enabled.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../devicetree/bindings/ata/ahci-platform.txt | 1 +
+ drivers/ata/ahci.h | 3 +-
+ drivers/ata/ahci_platform.c | 119 ++++++++++++++++-----
+ include/linux/ahci_platform.h | 4 +
+ 4 files changed, 99 insertions(+), 28 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+index 89de156..3ced07d 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+@@ -10,6 +10,7 @@ Required properties:
+
+ Optional properties:
+ - dma-coherent : Present if dma operations are coherent
++- clocks : a list of phandle + clock specifier pairs
+
+ Example:
+ sata@ffe08000 {
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 64d1a99d..c12862b 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -51,6 +51,7 @@
+
+ enum {
+ AHCI_MAX_PORTS = 32,
++ AHCI_MAX_CLKS = 3,
+ AHCI_MAX_SG = 168, /* hardware max is 64K */
+ AHCI_DMA_BOUNDARY = 0xffffffff,
+ AHCI_MAX_CMDS = 32,
+@@ -321,7 +322,7 @@ struct ahci_host_priv {
+ u32 em_loc; /* enclosure management location */
+ u32 em_buf_sz; /* EM buffer size in byte */
+ u32 em_msg_type; /* EM message type */
+- struct clk *clk; /* Only for platforms supporting clk */
++ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
+ void *plat_data; /* Other platform data */
+ /*
+ * Optional ahci_start_engine override, if not set this gets set to the
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 4b231ba..609975d 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -87,6 +87,66 @@ struct ata_port_operations ahci_platform_ops = {
+ AHCI_SHT("ahci_platform"),
+ };
+
++/**
++ * ahci_platform_enable_clks - Enable platform clocks
++ * @hpriv: host private area to store config values
++ *
++ * This function enables all the clks found in hpriv->clks, starting
++ * at index 0. If any clk fails to enable it disables all the clks
++ * already enabled in reverse order, and then returns an error.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
++{
++ int c, rc;
++
++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
++ rc = clk_prepare_enable(hpriv->clks[c]);
++ if (rc)
++ goto disable_unprepare_clk;
++ }
++ return 0;
++
++disable_unprepare_clk:
++ while (--c >= 0)
++ clk_disable_unprepare(hpriv->clks[c]);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
++
++/**
++ * ahci_platform_disable_clks - Disable platform clocks
++ * @hpriv: host private area to store config values
++ *
++ * This function disables all the clks found in hpriv->clks, in reverse
++ * order of ahci_platform_enable_clks (starting at the end of the array).
++ *
++ * LOCKING:
++ * None.
++ */
++void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
++{
++ int c;
++
++ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
++ if (hpriv->clks[c])
++ clk_disable_unprepare(hpriv->clks[c]);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
++
++static void ahci_put_clks(struct ahci_host_priv *hpriv)
++{
++ int c;
++
++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
++ clk_put(hpriv->clks[c]);
++}
++
+ static int ahci_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -97,6 +157,7 @@ static int ahci_probe(struct platform_device *pdev)
+ struct ahci_host_priv *hpriv;
+ struct ata_host *host;
+ struct resource *mem;
++ struct clk *clk;
+ int irq;
+ int n_ports;
+ int i;
+@@ -131,17 +192,31 @@ static int ahci_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
+- hpriv->clk = clk_get(dev, NULL);
+- if (IS_ERR(hpriv->clk)) {
+- dev_err(dev, "can't get clock\n");
+- } else {
+- rc = clk_prepare_enable(hpriv->clk);
+- if (rc) {
+- dev_err(dev, "clock prepare enable failed");
+- goto free_clk;
++ for (i = 0; i < AHCI_MAX_CLKS; i++) {
++ /*
++ * For now we must use clk_get(dev, NULL) for the first clock,
++ * because some platforms (da850, spear13xx) are not yet
++ * converted to use devicetree for clocks. For new platforms
++ * this is equivalent to of_clk_get(dev->of_node, 0).
++ */
++ if (i == 0)
++ clk = clk_get(dev, NULL);
++ else
++ clk = of_clk_get(dev->of_node, i);
++
++ if (IS_ERR(clk)) {
++ rc = PTR_ERR(clk);
++ if (rc == -EPROBE_DEFER)
++ goto free_clk;
++ break;
+ }
++ hpriv->clks[i] = clk;
+ }
+
++ rc = ahci_enable_clks(dev, hpriv);
++ if (rc)
++ goto free_clk;
++
+ /*
+ * Some platforms might need to prepare for mmio region access,
+ * which could be done in the following init call. So, the mmio
+@@ -222,11 +297,9 @@ static int ahci_probe(struct platform_device *pdev)
+ if (pdata && pdata->exit)
+ pdata->exit(dev);
+ disable_unprepare_clk:
+- if (!IS_ERR(hpriv->clk))
+- clk_disable_unprepare(hpriv->clk);
++ ahci_disable_clks(hpriv);
+ free_clk:
+- if (!IS_ERR(hpriv->clk))
+- clk_put(hpriv->clk);
++ ahci_put_clks(hpriv);
+ return rc;
+ }
+
+@@ -239,10 +312,8 @@ static void ahci_host_stop(struct ata_host *host)
+ if (pdata && pdata->exit)
+ pdata->exit(dev);
+
+- if (!IS_ERR(hpriv->clk)) {
+- clk_disable_unprepare(hpriv->clk);
+- clk_put(hpriv->clk);
+- }
++ ahci_disable_clks(hpriv);
++ ahci_put_clks(hpriv);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+@@ -277,8 +348,7 @@ static int ahci_suspend(struct device *dev)
+ if (pdata && pdata->suspend)
+ return pdata->suspend(dev);
+
+- if (!IS_ERR(hpriv->clk))
+- clk_disable_unprepare(hpriv->clk);
++ ahci_disable_clks(hpriv);
+
+ return 0;
+ }
+@@ -290,13 +360,9 @@ static int ahci_resume(struct device *dev)
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+- if (!IS_ERR(hpriv->clk)) {
+- rc = clk_prepare_enable(hpriv->clk);
+- if (rc) {
+- dev_err(dev, "clock prepare enable failed");
+- return rc;
+- }
+- }
++ rc = ahci_enable_clks(dev, hpriv);
++ if (rc)
++ return rc;
+
+ if (pdata && pdata->resume) {
+ rc = pdata->resume(dev);
+@@ -317,8 +383,7 @@ static int ahci_resume(struct device *dev)
+ return 0;
+
+ disable_unprepare_clk:
+- if (!IS_ERR(hpriv->clk))
+- clk_disable_unprepare(hpriv->clk);
++ ahci_disable_clks(hpriv);
+
+ return rc;
+ }
+diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
+index 73a2500..769d065 100644
+--- a/include/linux/ahci_platform.h
++++ b/include/linux/ahci_platform.h
+@@ -19,6 +19,7 @@
+
+ struct device;
+ struct ata_port_info;
++struct ahci_host_priv;
+
+ struct ahci_platform_data {
+ int (*init)(struct device *dev, void __iomem *addr);
+@@ -30,4 +31,7 @@ struct ahci_platform_data {
+ unsigned int mask_port_map;
+ };
+
++int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
++void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
++
+ #endif /* _AHCI_PLATFORM_H */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch b/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch
new file mode 100644
index 0000000000..fad0a7fae2
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch
@@ -0,0 +1,141 @@
+From ba6850946d9e1959be1b00f6ae06454546350c75 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 17 Jan 2014 13:23:21 +0100
+Subject: [PATCH] ahci-platform: Add support for an optional regulator for
+ sata-target power
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../devicetree/bindings/ata/ahci-platform.txt | 1 +
+ drivers/ata/ahci.h | 2 ++
+ drivers/ata/ahci_platform.c | 36 ++++++++++++++++++++--
+ 3 files changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+index 3ced07d..1ac807f 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+@@ -11,6 +11,7 @@ Required properties:
+ Optional properties:
+ - dma-coherent : Present if dma operations are coherent
+ - clocks : a list of phandle + clock specifier pairs
++- target-supply : regulator for SATA target power
+
+ Example:
+ sata@ffe08000 {
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index c12862b..bf8100c 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -37,6 +37,7 @@
+
+ #include <linux/clk.h>
+ #include <linux/libata.h>
++#include <linux/regulator/consumer.h>
+
+ /* Enclosure Management Control */
+ #define EM_CTRL_MSG_TYPE 0x000f0000
+@@ -323,6 +324,7 @@ struct ahci_host_priv {
+ u32 em_buf_sz; /* EM buffer size in byte */
+ u32 em_msg_type; /* EM message type */
+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
++ struct regulator *target_pwr; /* Optional */
+ void *plat_data; /* Other platform data */
+ /*
+ * Optional ahci_start_engine override, if not set this gets set to the
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 609975d..907c076 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -192,6 +192,14 @@ static int ahci_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
++ hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
++ if (IS_ERR(hpriv->target_pwr)) {
++ rc = PTR_ERR(hpriv->target_pwr);
++ if (rc == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++ hpriv->target_pwr = NULL;
++ }
++
+ for (i = 0; i < AHCI_MAX_CLKS; i++) {
+ /*
+ * For now we must use clk_get(dev, NULL) for the first clock,
+@@ -213,9 +221,15 @@ static int ahci_probe(struct platform_device *pdev)
+ hpriv->clks[i] = clk;
+ }
+
++ if (hpriv->target_pwr) {
++ rc = regulator_enable(hpriv->target_pwr);
++ if (rc)
++ goto free_clk;
++ }
++
+ rc = ahci_enable_clks(dev, hpriv);
+ if (rc)
+- goto free_clk;
++ goto disable_regulator;
+
+ /*
+ * Some platforms might need to prepare for mmio region access,
+@@ -298,6 +312,9 @@ static int ahci_probe(struct platform_device *pdev)
+ pdata->exit(dev);
+ disable_unprepare_clk:
+ ahci_disable_clks(hpriv);
++disable_regulator:
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
+ free_clk:
+ ahci_put_clks(hpriv);
+ return rc;
+@@ -314,6 +331,9 @@ static void ahci_host_stop(struct ata_host *host)
+
+ ahci_disable_clks(hpriv);
+ ahci_put_clks(hpriv);
++
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+@@ -350,6 +370,9 @@ static int ahci_suspend(struct device *dev)
+
+ ahci_disable_clks(hpriv);
+
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
++
+ return 0;
+ }
+
+@@ -360,9 +383,15 @@ static int ahci_resume(struct device *dev)
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
++ if (hpriv->target_pwr) {
++ rc = regulator_enable(hpriv->target_pwr);
++ if (rc)
++ return rc;
++ }
++
+ rc = ahci_enable_clks(dev, hpriv);
+ if (rc)
+- return rc;
++ goto disable_regulator;
+
+ if (pdata && pdata->resume) {
+ rc = pdata->resume(dev);
+@@ -384,6 +413,9 @@ static int ahci_resume(struct device *dev)
+
+ disable_unprepare_clk:
+ ahci_disable_clks(hpriv);
++disable_regulator:
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
+
+ return rc;
+ }
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch b/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch
new file mode 100644
index 0000000000..0fdc87dd94
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch
@@ -0,0 +1,211 @@
+From 05d5a60ae336c122e478cc002afccc880d462b3b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 20 Jan 2014 14:54:40 +0100
+Subject: [PATCH] ahci-platform: Add enable_ / disable_resources helper
+ functions
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_platform.c | 112 ++++++++++++++++++++++++++++--------------
+ include/linux/ahci_platform.h | 2 +
+ 2 files changed, 77 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 907c076..6ebbc17 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -139,6 +139,68 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
+ }
+ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
+
++/**
++ * ahci_platform_enable_resources - Enable platform resources
++ * @hpriv: host private area to store config values
++ *
++ * This function enables all ahci_platform managed resources in
++ * the following order:
++ * 1) Regulator
++ * 2) Clocks (through ahci_platform_enable_clks)
++ *
++ * If resource enabling fails at any point the previous enabled
++ * resources are disabled in reverse order.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
++{
++ int rc;
++
++ if (hpriv->target_pwr) {
++ rc = regulator_enable(hpriv->target_pwr);
++ if (rc)
++ return rc;
++ }
++
++ rc = ahci_platform_enable_clks(hpriv);
++ if (rc)
++ goto disable_regulator;
++
++ return 0;
++
++disable_regulator:
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
++
++/**
++ * ahci_platform_disable_resources - Disable platform resources
++ * @hpriv: host private area to store config values
++ *
++ * This function disables all ahci_platform managed resources in
++ * the following order:
++ * 1) Clocks (through ahci_platform_disable_clks)
++ * 2) Regulator
++ *
++ * LOCKING:
++ * None.
++ */
++void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
++{
++ ahci_platform_disable_clks(hpriv);
++
++ if (hpriv->target_pwr)
++ regulator_disable(hpriv->target_pwr);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
++
+ static void ahci_put_clks(struct ahci_host_priv *hpriv)
+ {
+ int c;
+@@ -221,15 +283,9 @@ static int ahci_probe(struct platform_device *pdev)
+ hpriv->clks[i] = clk;
+ }
+
+- if (hpriv->target_pwr) {
+- rc = regulator_enable(hpriv->target_pwr);
+- if (rc)
+- goto free_clk;
+- }
+-
+- rc = ahci_enable_clks(dev, hpriv);
++ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+- goto disable_regulator;
++ goto free_clk;
+
+ /*
+ * Some platforms might need to prepare for mmio region access,
+@@ -240,7 +296,7 @@ static int ahci_probe(struct platform_device *pdev)
+ if (pdata && pdata->init) {
+ rc = pdata->init(dev, hpriv->mmio);
+ if (rc)
+- goto disable_unprepare_clk;
++ goto disable_resources;
+ }
+
+ ahci_save_initial_config(dev, hpriv,
+@@ -310,11 +366,8 @@ static int ahci_probe(struct platform_device *pdev)
+ pdata_exit:
+ if (pdata && pdata->exit)
+ pdata->exit(dev);
+-disable_unprepare_clk:
+- ahci_disable_clks(hpriv);
+-disable_regulator:
+- if (hpriv->target_pwr)
+- regulator_disable(hpriv->target_pwr);
++disable_resources:
++ ahci_platform_disable_resources(hpriv);
+ free_clk:
+ ahci_put_clks(hpriv);
+ return rc;
+@@ -329,11 +382,8 @@ static void ahci_host_stop(struct ata_host *host)
+ if (pdata && pdata->exit)
+ pdata->exit(dev);
+
+- ahci_disable_clks(hpriv);
++ ahci_platform_disable_resources(hpriv);
+ ahci_put_clks(hpriv);
+-
+- if (hpriv->target_pwr)
+- regulator_disable(hpriv->target_pwr);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+@@ -368,10 +418,7 @@ static int ahci_suspend(struct device *dev)
+ if (pdata && pdata->suspend)
+ return pdata->suspend(dev);
+
+- ahci_disable_clks(hpriv);
+-
+- if (hpriv->target_pwr)
+- regulator_disable(hpriv->target_pwr);
++ ahci_platform_disable_resources(hpriv);
+
+ return 0;
+ }
+@@ -383,26 +430,20 @@ static int ahci_resume(struct device *dev)
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+- if (hpriv->target_pwr) {
+- rc = regulator_enable(hpriv->target_pwr);
+- if (rc)
+- return rc;
+- }
+-
+- rc = ahci_enable_clks(dev, hpriv);
++ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+- goto disable_regulator;
++ return rc;
+
+ if (pdata && pdata->resume) {
+ rc = pdata->resume(dev);
+ if (rc)
+- goto disable_unprepare_clk;
++ goto disable_resources;
+ }
+
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+ rc = ahci_reset_controller(host);
+ if (rc)
+- goto disable_unprepare_clk;
++ goto disable_resources;
+
+ ahci_init_controller(host);
+ }
+@@ -411,11 +452,8 @@ static int ahci_resume(struct device *dev)
+
+ return 0;
+
+-disable_unprepare_clk:
+- ahci_disable_clks(hpriv);
+-disable_regulator:
+- if (hpriv->target_pwr)
+- regulator_disable(hpriv->target_pwr);
++disable_resources:
++ ahci_platform_disable_resources(hpriv);
+
+ return rc;
+ }
+diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
+index 769d065..b674b01 100644
+--- a/include/linux/ahci_platform.h
++++ b/include/linux/ahci_platform.h
+@@ -33,5 +33,7 @@ struct ahci_platform_data {
+
+ int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
+ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
++int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
++void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
+
+ #endif /* _AHCI_PLATFORM_H */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch b/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch
new file mode 100644
index 0000000000..8f0ba4c2cd
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch
@@ -0,0 +1,344 @@
+From 98601575da5276173233dd575bdd61cccdeb861a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 20 Jan 2014 14:58:04 +0100
+Subject: [PATCH] ahci-platform: "Library-ise" ahci_probe functionality
+
+ahci_probe consists of 3 steps:
+1) Get resources (get mmio, clks, regulator)
+2) Enable resources, handled by ahci_platform_enable_resouces
+3) The more or less standard ahci-host controller init sequence
+
+This commit refactors step 1 and 3 into separate functions, so the platform
+drivers for AHCI implementations which need a specific order in step 2,
+and / or need to do some custom register poking at some time, can re-use
+ahci-platform.c code without needing to copy and paste it.
+
+Note that ahci_platform_init_host's prototype takes the 3 non function
+members of ahci_platform_data as arguments, the idea is that drivers using
+the new exported utility functions will not use ahci_platform_data at all,
+and hopefully in the future ahci_platform_data can go away entirely.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_platform.c | 195 ++++++++++++++++++++++++++++--------------
+ include/linux/ahci_platform.h | 14 +++
+ 2 files changed, 144 insertions(+), 65 deletions(-)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 6ebbc17..7f3f2ac 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -201,64 +201,64 @@ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
+ }
+ EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
+
+-static void ahci_put_clks(struct ahci_host_priv *hpriv)
++static void ahci_platform_put_resources(struct device *dev, void *res)
+ {
++ struct ahci_host_priv *hpriv = res;
+ int c;
+
+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+ clk_put(hpriv->clks[c]);
+ }
+
+-static int ahci_probe(struct platform_device *pdev)
++/**
++ * ahci_platform_get_resources - Get platform resources
++ * @pdev: platform device to get resources for
++ *
++ * This function allocates an ahci_host_priv struct, and gets the
++ * following resources, storing a reference to them inside the returned
++ * struct:
++ *
++ * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
++ * 2) regulator for controlling the targets power (optional)
++ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
++ * or for non devicetree enabled platforms a single clock
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
++ */
++struct ahci_host_priv *ahci_platform_get_resources(
++ struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+- struct ahci_platform_data *pdata = dev_get_platdata(dev);
+- const struct platform_device_id *id = platform_get_device_id(pdev);
+- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
+- const struct ata_port_info *ppi[] = { &pi, NULL };
+ struct ahci_host_priv *hpriv;
+- struct ata_host *host;
+- struct resource *mem;
+ struct clk *clk;
+- int irq;
+- int n_ports;
+- int i;
+- int rc;
++ int i, rc = -ENOMEM;
+
+- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!mem) {
+- dev_err(dev, "no mmio space\n");
+- return -EINVAL;
+- }
++ if (!devres_open_group(dev, NULL, GFP_KERNEL))
++ return ERR_PTR(-ENOMEM);
+
+- irq = platform_get_irq(pdev, 0);
+- if (irq <= 0) {
+- dev_err(dev, "no irq\n");
+- return -EINVAL;
+- }
++ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
++ GFP_KERNEL);
++ if (!hpriv)
++ goto err_out;
+
+- if (pdata && pdata->ata_port_info)
+- pi = *pdata->ata_port_info;
++ devres_add(dev, hpriv);
+
+- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+- if (!hpriv) {
+- dev_err(dev, "can't alloc ahci_host_priv\n");
+- return -ENOMEM;
+- }
+-
+- hpriv->flags |= (unsigned long)pi.private_data;
+-
+- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
++ hpriv->mmio = devm_ioremap_resource(dev,
++ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (!hpriv->mmio) {
+- dev_err(dev, "can't map %pR\n", mem);
+- return -ENOMEM;
++ dev_err(dev, "no mmio space\n");
++ goto err_out;
+ }
+
+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
+ if (IS_ERR(hpriv->target_pwr)) {
+ rc = PTR_ERR(hpriv->target_pwr);
+ if (rc == -EPROBE_DEFER)
+- return -EPROBE_DEFER;
++ goto err_out;
+ hpriv->target_pwr = NULL;
+ }
+
+@@ -277,33 +277,62 @@ static int ahci_probe(struct platform_device *pdev)
+ if (IS_ERR(clk)) {
+ rc = PTR_ERR(clk);
+ if (rc == -EPROBE_DEFER)
+- goto free_clk;
++ goto err_out;
+ break;
+ }
+ hpriv->clks[i] = clk;
+ }
+
+- rc = ahci_platform_enable_resources(hpriv);
+- if (rc)
+- goto free_clk;
++ devres_remove_group(dev, NULL);
++ return hpriv;
+
+- /*
+- * Some platforms might need to prepare for mmio region access,
+- * which could be done in the following init call. So, the mmio
+- * region shouldn't be accessed before init (if provided) has
+- * returned successfully.
+- */
+- if (pdata && pdata->init) {
+- rc = pdata->init(dev, hpriv->mmio);
+- if (rc)
+- goto disable_resources;
+- }
++err_out:
++ devres_release_group(dev, NULL);
++ return ERR_PTR(rc);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
++
++/**
++ * ahci_platform_init_host - Bring up an ahci-platform host
++ * @pdev: platform device pointer for the host
++ * @hpriv: ahci-host private data for the host
++ * @pi_template: template for the ata_port_info to use
++ * @force_port_map: param passed to ahci_save_initial_config
++ * @mask_port_map: param passed to ahci_save_initial_config
++ *
++ * This function does all the usual steps needed to bring up an
++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
++ * must be initialized / enabled before calling this.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_init_host(struct platform_device *pdev,
++ struct ahci_host_priv *hpriv,
++ const struct ata_port_info *pi_template,
++ unsigned int force_port_map,
++ unsigned int mask_port_map)
++{
++ struct device *dev = &pdev->dev;
++ struct ata_port_info pi = *pi_template;
++ const struct ata_port_info *ppi[] = { &pi, NULL };
++ struct ata_host *host;
++ int i, irq, n_ports, rc;
+
+- ahci_save_initial_config(dev, hpriv,
+- pdata ? pdata->force_port_map : 0,
+- pdata ? pdata->mask_port_map : 0);
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0) {
++ dev_err(dev, "no irq\n");
++ return -EINVAL;
++ }
+
+ /* prepare host */
++ hpriv->flags |= (unsigned long)pi.private_data;
++
++ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
++
+ if (hpriv->cap & HOST_CAP_NCQ)
+ pi.flags |= ATA_FLAG_NCQ;
+
+@@ -320,10 +349,8 @@ static int ahci_probe(struct platform_device *pdev)
+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+ host = ata_host_alloc_pinfo(dev, ppi, n_ports);
+- if (!host) {
+- rc = -ENOMEM;
+- goto pdata_exit;
+- }
++ if (!host)
++ return -ENOMEM;
+
+ host->private_data = hpriv;
+
+@@ -338,7 +365,8 @@ static int ahci_probe(struct platform_device *pdev)
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+- ata_port_desc(ap, "mmio %pR", mem);
++ ata_port_desc(ap, "mmio %pR",
++ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
+
+ /* set enclosure management message type */
+@@ -352,13 +380,53 @@ static int ahci_probe(struct platform_device *pdev)
+
+ rc = ahci_reset_controller(host);
+ if (rc)
+- goto pdata_exit;
++ return rc;
+
+ ahci_init_controller(host);
+ ahci_print_info(host, "platform");
+
+- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
+- &ahci_platform_sht);
++ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
++ &ahci_platform_sht);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_init_host);
++
++static int ahci_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct ahci_platform_data *pdata = dev_get_platdata(dev);
++ const struct platform_device_id *id = platform_get_device_id(pdev);
++ const struct ata_port_info *pi_template;
++ struct ahci_host_priv *hpriv;
++ int rc;
++
++ hpriv = ahci_platform_get_resources(pdev);
++ if (IS_ERR(hpriv))
++ return PTR_ERR(hpriv);
++
++ rc = ahci_platform_enable_resources(hpriv);
++ if (rc)
++ return rc;
++
++ /*
++ * Some platforms might need to prepare for mmio region access,
++ * which could be done in the following init call. So, the mmio
++ * region shouldn't be accessed before init (if provided) has
++ * returned successfully.
++ */
++ if (pdata && pdata->init) {
++ rc = pdata->init(dev, hpriv->mmio);
++ if (rc)
++ goto disable_resources;
++ }
++
++ if (pdata && pdata->ata_port_info)
++ pi_template = pdata->ata_port_info;
++ else
++ pi_template = &ahci_port_info[id ? id->driver_data : 0];
++
++ rc = ahci_platform_init_host(pdev, hpriv, pi_template,
++ pdata ? pdata->force_port_map : 0,
++ pdata ? pdata->mask_port_map : 0);
+ if (rc)
+ goto pdata_exit;
+
+@@ -368,8 +436,6 @@ static int ahci_probe(struct platform_device *pdev)
+ pdata->exit(dev);
+ disable_resources:
+ ahci_platform_disable_resources(hpriv);
+-free_clk:
+- ahci_put_clks(hpriv);
+ return rc;
+ }
+
+@@ -383,7 +449,6 @@ static void ahci_host_stop(struct ata_host *host)
+ pdata->exit(dev);
+
+ ahci_platform_disable_resources(hpriv);
+- ahci_put_clks(hpriv);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
+index b674b01..b80c51c 100644
+--- a/include/linux/ahci_platform.h
++++ b/include/linux/ahci_platform.h
+@@ -20,7 +20,14 @@
+ struct device;
+ struct ata_port_info;
+ struct ahci_host_priv;
++struct platform_device;
+
++/*
++ * Note ahci_platform_data is deprecated, it is only kept around for use
++ * by the old da850 and spear13xx ahci code.
++ * New drivers should instead declare their own platform_driver struct, and
++ * use ahci_platform* functions in their own probe, suspend and resume methods.
++ */
+ struct ahci_platform_data {
+ int (*init)(struct device *dev, void __iomem *addr);
+ void (*exit)(struct device *dev);
+@@ -35,5 +42,12 @@ struct ahci_platform_data {
+ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
+ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
++struct ahci_host_priv *ahci_platform_get_resources(
++ struct platform_device *pdev);
++int ahci_platform_init_host(struct platform_device *pdev,
++ struct ahci_host_priv *hpriv,
++ const struct ata_port_info *pi_template,
++ unsigned int force_port_map,
++ unsigned int mask_port_map);
+
+ #endif /* _AHCI_PLATFORM_H */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch b/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch
new file mode 100644
index 0000000000..49ddac0b5e
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch
@@ -0,0 +1,188 @@
+From 041cf8356a4eb91ee8118004b2bc9c78cdd7866c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 20 Jan 2014 15:52:07 +0100
+Subject: [PATCH] ahci-platform: "Library-ise" suspend / resume functionality
+
+Split suspend / resume code into host suspend / resume functionality and
+resource enable / disabling phases, and export the new suspend_ / resume_host
+functions.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_platform.c | 109 ++++++++++++++++++++++++++++++++++++------
+ include/linux/ahci_platform.h | 5 ++
+ 2 files changed, 99 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 7f3f2ac..bdadec1 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -452,14 +452,26 @@ static void ahci_host_stop(struct ata_host *host)
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+-static int ahci_suspend(struct device *dev)
++/**
++ * ahci_platform_suspend_host - Suspend an ahci-platform host
++ * @dev: device pointer for the host
++ *
++ * This function does all the usual steps needed to suspend an
++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
++ * must be disabled after calling this.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_suspend_host(struct device *dev)
+ {
+- struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ void __iomem *mmio = hpriv->mmio;
+ u32 ctl;
+- int rc;
+
+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+ dev_err(dev, "firmware update required for suspend/resume\n");
+@@ -476,7 +488,64 @@ static int ahci_suspend(struct device *dev)
+ writel(ctl, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
+
+- rc = ata_host_suspend(host, PMSG_SUSPEND);
++ return ata_host_suspend(host, PMSG_SUSPEND);
++}
++EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
++
++/**
++ * ahci_platform_resume_host - Resume an ahci-platform host
++ * @dev: device pointer for the host
++ *
++ * This function does all the usual steps needed to resume an
++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
++ * must be initialized / enabled before calling this.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_resume_host(struct device *dev)
++{
++ struct ata_host *host = dev_get_drvdata(dev);
++ int rc;
++
++ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
++ rc = ahci_reset_controller(host);
++ if (rc)
++ return rc;
++
++ ahci_init_controller(host);
++ }
++
++ ata_host_resume(host);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
++
++/**
++ * ahci_platform_suspend - Suspend an ahci-platform device
++ * @dev: the platform device to suspend
++ *
++ * This function suspends the host associated with the device, followed
++ * by disabling all the resources of the device.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_suspend(struct device *dev)
++{
++ struct ahci_platform_data *pdata = dev_get_platdata(dev);
++ struct ata_host *host = dev_get_drvdata(dev);
++ struct ahci_host_priv *hpriv = host->private_data;
++ int rc;
++
++ rc = ahci_platform_suspend_host(dev);
+ if (rc)
+ return rc;
+
+@@ -487,8 +556,22 @@ static int ahci_suspend(struct device *dev)
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(ahci_platform_suspend);
+
+-static int ahci_resume(struct device *dev)
++/**
++ * ahci_platform_resume - Resume an ahci-platform device
++ * @dev: the platform device to resume
++ *
++ * This function enables all the resources of the device followed by
++ * resuming the host associated with the device.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * 0 on success otherwise a negative error code
++ */
++int ahci_platform_resume(struct device *dev)
+ {
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ struct ata_host *host = dev_get_drvdata(dev);
+@@ -505,15 +588,9 @@ static int ahci_resume(struct device *dev)
+ goto disable_resources;
+ }
+
+- if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+- rc = ahci_reset_controller(host);
+- if (rc)
+- goto disable_resources;
+-
+- ahci_init_controller(host);
+- }
+-
+- ata_host_resume(host);
++ rc = ahci_platform_resume_host(dev);
++ if (rc)
++ goto disable_resources;
+
+ return 0;
+
+@@ -522,9 +599,11 @@ static int ahci_resume(struct device *dev)
+
+ return rc;
+ }
++EXPORT_SYMBOL_GPL(ahci_platform_resume);
+ #endif
+
+-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
++static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
++ ahci_platform_resume);
+
+ static const struct of_device_id ahci_of_match[] = {
+ { .compatible = "snps,spear-ahci", },
+diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
+index b80c51c..542f268 100644
+--- a/include/linux/ahci_platform.h
++++ b/include/linux/ahci_platform.h
+@@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
+ unsigned int force_port_map,
+ unsigned int mask_port_map);
+
++int ahci_platform_suspend_host(struct device *dev);
++int ahci_platform_resume_host(struct device *dev);
++int ahci_platform_suspend(struct device *dev);
++int ahci_platform_resume(struct device *dev);
++
+ #endif /* _AHCI_PLATFORM_H */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch b/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch
deleted file mode 100644
index b832dc4d97..0000000000
--- a/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 3eec76bc21d78e56ac8404b59f29dd9dbbd1528a Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <oliver@schinagl.nl>
-Date: Mon, 2 Dec 2013 16:13:32 +0100
-Subject: [PATCH] libahci: Add a pre ahci_start_engine hook
-
-Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which need a
-special register to be poked before starting the DMA engine.
-
-This register gets reset on an ahci_stop_engine call, so there is no other
-place then ahci_start_engine where this poking can be done.
-
-This commit adds a pre ahci_start_engine hook for use by the Allwinner AHCI
-driver (and potentially other drivers in the future).
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/ata/ahci.h | 2 ++
- drivers/ata/libahci.c | 4 ++++
- 2 files changed, 6 insertions(+)
-
---- a/drivers/ata/ahci.h
-+++ b/drivers/ata/ahci.h
-@@ -323,6 +323,8 @@ struct ahci_host_priv {
- u32 em_msg_type; /* EM message type */
- struct clk *clk; /* Only for platforms supporting clk */
- void *plat_data; /* Other platform data */
-+ /* Optional pre ahci_start_engine hook */
-+ void (*pre_start_engine)(struct ata_port *ap);
- };
-
- extern int ahci_ignore_sss;
---- a/drivers/ata/libahci.c
-+++ b/drivers/ata/libahci.c
-@@ -568,8 +568,12 @@ static int ahci_scr_write(struct ata_lin
- void ahci_start_engine(struct ata_port *ap)
- {
- void __iomem *port_mmio = ahci_port_base(ap);
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
- u32 tmp;
-
-+ if (hpriv->pre_start_engine)
-+ hpriv->pre_start_engine(ap);
-+
- /* start DMA */
- tmp = readl(port_mmio + PORT_CMD);
- tmp |= PORT_CMD_START;
diff --git a/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch b/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch
new file mode 100644
index 0000000000..b7c9064d33
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch
@@ -0,0 +1,352 @@
+From 93dd2c512a24c552f1146d746aac112da7677430 Mon Sep 17 00:00:00 2001
+From: Olliver Schinagl <oliver@schinagl.nl>
+Date: Sat, 18 Jan 2014 15:00:45 +0100
+Subject: [PATCH] ARM: sunxi: Add support for Allwinner SUNXi SoCs sata to
+ ahci_platform
+
+This patch adds support for the ahci sata controler found on Allwinner A10
+and A20 SoCs to the ahci_platform driver.
+
+Orignally written by Olliver Schinagl using the approach of having a platform
+device which probe method creates a new child platform device which gets
+driven by ahci_platform.c, as done by ahci_imx.c .
+
+Refactored by Hans de Goede to add most of the non sunxi specific functionality
+to ahci_platform.c and use a platform_data pointer from of_device_id for the
+sunxi specific bits.
+
+Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../devicetree/bindings/ata/ahci-platform.txt | 15 +-
+ drivers/ata/Kconfig | 9 +
+ drivers/ata/Makefile | 1 +
+ drivers/ata/ahci_sunxi.c | 249 +++++++++++++++++++++
+ 4 files changed, 271 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/ata/ahci_sunxi.c
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+index 1ac807f..499bfed 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+@@ -4,7 +4,9 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
+ Each SATA controller should have its own node.
+
+ Required properties:
+-- compatible : compatible list, contains "snps,spear-ahci"
++- compatible : compatible list, one of "snps,spear-ahci",
++ "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
++ "allwinner,sun4i-a10-ahci"
+ - interrupts : <interrupt mapping for SATA IRQ>
+ - reg : <registers mapping>
+
+@@ -13,10 +15,17 @@ Optional properties:
+ - clocks : a list of phandle + clock specifier pairs
+ - target-supply : regulator for SATA target power
+
+-Example:
++Examples:
+ sata@ffe08000 {
+ compatible = "snps,spear-ahci";
+ reg = <0xffe08000 0x1000>;
+ interrupts = <115>;
+-
+ };
++
++ ahci: sata@01c18000 {
++ compatible = "allwinner,sun4i-a10-ahci";
++ reg = <0x01c18000 0x1000>;
++ interrupts = <56>;
++ clocks = <&pll6 0>, <&ahb_gates 25>;
++ target-supply = <&reg_ahci_5v>;
++ };
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index 4e73772..cc67cc0 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -106,6 +106,15 @@ config AHCI_IMX
+
+ If unsure, say N.
+
++config AHCI_SUNXI
++ tristate "Allwinner sunxi AHCI SATA support"
++ depends on ARCH_SUNXI && SATA_AHCI_PLATFORM
++ help
++ This option enables support for the Allwinner sunxi SoC's
++ onboard AHCI SATA.
++
++ If unsure, say N.
++
+ config SATA_FSL
+ tristate "Freescale 3.0Gbps SATA support"
+ depends on FSL_SOC
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index 46518c6..246050b 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
+ obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
+ obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
+ obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
++obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o
+
+ # SFF w/ custom DMA
+ obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
+diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
+new file mode 100644
+index 0000000..001f7dfc
+--- /dev/null
++++ b/drivers/ata/ahci_sunxi.c
+@@ -0,0 +1,249 @@
++/*
++ * Allwinner sunxi AHCI SATA platform driver
++ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
++ *
++ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
++ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
++ * Daniel Wang <danielwang@allwinnertech.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#include <linux/ahci_platform.h>
++#include <linux/clk.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include "ahci.h"
++
++#define AHCI_BISTAFR 0x00a0
++#define AHCI_BISTCR 0x00a4
++#define AHCI_BISTFCTR 0x00a8
++#define AHCI_BISTSR 0x00ac
++#define AHCI_BISTDECR 0x00b0
++#define AHCI_DIAGNR0 0x00b4
++#define AHCI_DIAGNR1 0x00b8
++#define AHCI_OOBR 0x00bc
++#define AHCI_PHYCS0R 0x00c0
++#define AHCI_PHYCS1R 0x00c4
++#define AHCI_PHYCS2R 0x00c8
++#define AHCI_TIMER1MS 0x00e0
++#define AHCI_GPARAM1R 0x00e8
++#define AHCI_GPARAM2R 0x00ec
++#define AHCI_PPARAMR 0x00f0
++#define AHCI_TESTR 0x00f4
++#define AHCI_VERSIONR 0x00f8
++#define AHCI_IDR 0x00fc
++#define AHCI_RWCR 0x00fc
++#define AHCI_P0DMACR 0x0170
++#define AHCI_P0PHYCR 0x0178
++#define AHCI_P0PHYSR 0x017c
++
++static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
++{
++ u32 reg_val;
++
++ reg_val = readl(reg);
++ reg_val &= ~(clr_val);
++ writel(reg_val, reg);
++}
++
++static void sunxi_setbits(void __iomem *reg, u32 set_val)
++{
++ u32 reg_val;
++
++ reg_val = readl(reg);
++ reg_val |= set_val;
++ writel(reg_val, reg);
++}
++
++static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
++{
++ u32 reg_val;
++
++ reg_val = readl(reg);
++ reg_val &= ~(clr_val);
++ reg_val |= set_val;
++ writel(reg_val, reg);
++}
++
++static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
++{
++ return (readl(reg) >> shift) & mask;
++}
++
++static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
++{
++ u32 reg_val;
++ int timeout;
++
++ /* This magic is from the original code */
++ writel(0, reg_base + AHCI_RWCR);
++ mdelay(5);
++
++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
++ (0x7 << 24),
++ (0x5 << 24) | BIT(23) | BIT(18));
++ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
++ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
++ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
++ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
++ (0x7 << 20), (0x3 << 20));
++ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
++ (0x1f << 5), (0x19 << 5));
++ mdelay(5);
++
++ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
++
++ timeout = 250; /* Power up takes aprox 50 us */
++ do {
++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
++ if (reg_val == 0x02)
++ break;
++
++ if (--timeout == 0) {
++ dev_err(dev, "PHY power up failed.\n");
++ return -EIO;
++ }
++ udelay(1);
++ } while (1);
++
++ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
++
++ timeout = 100; /* Calibration takes aprox 10 us */
++ do {
++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
++ if (reg_val == 0x00)
++ break;
++
++ if (--timeout == 0) {
++ dev_err(dev, "PHY calibration failed.\n");
++ return -EIO;
++ }
++ udelay(1);
++ } while (1);
++
++ mdelay(15);
++
++ writel(0x7, reg_base + AHCI_RWCR);
++
++ return 0;
++}
++
++static void ahci_sunxi_start_engine(struct ata_port *ap)
++{
++ void __iomem *port_mmio = ahci_port_base(ap);
++ struct ahci_host_priv *hpriv = ap->host->private_data;
++
++ /* Setup DMA before DMA start */
++ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
++
++ /* Start DMA */
++ sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
++}
++
++static const struct ata_port_info ahci_sunxi_port_info = {
++ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
++ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
++ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
++ .pio_mask = ATA_PIO4,
++ .udma_mask = ATA_UDMA6,
++ .port_ops = &ahci_platform_ops,
++};
++
++static int ahci_sunxi_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct ahci_host_priv *hpriv;
++ int rc;
++
++ hpriv = ahci_platform_get_resources(pdev);
++ if (IS_ERR(hpriv))
++ return PTR_ERR(hpriv);
++
++ hpriv->start_engine = ahci_sunxi_start_engine;
++
++ rc = ahci_platform_enable_resources(hpriv);
++ if (rc)
++ return rc;
++
++ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
++ if (rc)
++ goto disable_resources;
++
++ rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0);
++ if (rc)
++ goto disable_resources;
++
++ return 0;
++
++disable_resources:
++ ahci_platform_disable_resources(hpriv);
++ return rc;
++}
++
++#ifdef CONFIG_PM_SLEEP
++int ahci_sunxi_resume(struct device *dev)
++{
++ struct ata_host *host = dev_get_drvdata(dev);
++ struct ahci_host_priv *hpriv = host->private_data;
++ int rc;
++
++ rc = ahci_platform_enable_resources(hpriv);
++ if (rc)
++ return rc;
++
++ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
++ if (rc)
++ goto disable_resources;
++
++ rc = ahci_platform_resume_host(dev);
++ if (rc)
++ goto disable_resources;
++
++ return 0;
++
++disable_resources:
++ ahci_platform_disable_resources(hpriv);
++ return rc;
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
++ ahci_sunxi_resume);
++
++static const struct of_device_id ahci_sunxi_of_match[] = {
++ { .compatible = "allwinner,sun4i-a10-ahci", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
++
++static struct platform_driver ahci_sunxi_driver = {
++ .probe = ahci_sunxi_probe,
++ .remove = ata_platform_remove_one,
++ .driver = {
++ .name = "ahci-sunxi",
++ .owner = THIS_MODULE,
++ .of_match_table = ahci_sunxi_of_match,
++ .pm = &ahci_sunxi_pm_ops,
++ },
++};
++module_platform_driver(ahci_sunxi_driver);
++
++MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
++MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
++MODULE_LICENSE("GPL");
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch b/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch
deleted file mode 100644
index 9731b9c568..0000000000
--- a/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch
+++ /dev/null
@@ -1,436 +0,0 @@
-From 22345cc059de4a6ea1dc7657dd6ad86ca16a8814 Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <oliver@schinagl.nl>
-Date: Tue, 3 Dec 2013 12:07:01 +0100
-Subject: [PATCH] ARM: sunxi: Add ahci-sunxi driver for the Allwinner SUNXi
- SoCs sata
-
-This patch adds support for the ahci sata controler found on Allwinner A10
-and A20 SoCs.
-
-Orignally written by Olliver Schinagl using the approach of having a platform
-device which probe method creates a new child platform device which gets
-driven by ahci_platform.c, as done by ahci_imx.c .
-
-Given that almost all functionality already is shared through libahci /
-ata-core, and that ahci_platform.c cannot cleanly handle somewhat more complex
-platform specific ahci cases, such as the sunxi case, it was refactored into
-a stand-alone platform driver by Hans de Goede.
-
-Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- .../devicetree/bindings/ata/ahci-sunxi.txt | 24 ++
- drivers/ata/Kconfig | 9 +
- drivers/ata/Makefile | 1 +
- drivers/ata/ahci_sunxi.c | 349 +++++++++++++++++++++
- 4 files changed, 383 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/ata/ahci-sunxi.txt
- create mode 100644 drivers/ata/ahci_sunxi.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt
-@@ -0,0 +1,24 @@
-+Allwinner SUNXI AHCI SATA Controller
-+
-+SATA nodes are defined to describe on-chip Serial ATA controllers.
-+Each SATA controller should have its own node.
-+
-+Required properties:
-+- compatible : compatible list, contains "allwinner,sun4i-a10-ahci"
-+- reg : <registers mapping>
-+- interrupts : <interrupt mapping for AHCI IRQ>
-+- clocks : clocks for ACHI
-+- clock-names : clock names for AHCI
-+
-+Optional properties:
-+- pwr-supply : regulator to control the power supply GPIO
-+
-+Example:
-+ ahci@01c18000 {
-+ compatible = "allwinner,sun4i-a10-ahci";
-+ reg = <0x01c18000 0x1000>;
-+ interrupts = <0 56 1>;
-+ clocks = <&ahb_gates 25>, <&pll6 0>;
-+ clock-names = "ahb_sata", "pll6_sata";
-+ pwr-supply = <&reg_ahci_5v>;
-+ };
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -106,6 +106,15 @@ config AHCI_IMX
-
- If unsure, say N.
-
-+config AHCI_SUNXI
-+ tristate "Allwinner sunxi AHCI SATA support"
-+ depends on ARCH_SUNXI
-+ help
-+ This option enables support for the Allwinner sunxi SoC's
-+ onboard AHCI SATA.
-+
-+ If unsure, say N.
-+
- config SATA_FSL
- tristate "Freescale 3.0Gbps SATA support"
- depends on FSL_SOC
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
- obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
- obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
- obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
-+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o
-
- # SFF w/ custom DMA
- obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
---- /dev/null
-+++ b/drivers/ata/ahci_sunxi.c
-@@ -0,0 +1,349 @@
-+/*
-+ * Allwinner sunxi AHCI SATA platform driver
-+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
-+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
-+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
-+ * Daniel Wang <danielwang@allwinnertech.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/regulator/consumer.h>
-+#include "ahci.h"
-+
-+#define AHCI_BISTAFR 0x00a0
-+#define AHCI_BISTCR 0x00a4
-+#define AHCI_BISTFCTR 0x00a8
-+#define AHCI_BISTSR 0x00ac
-+#define AHCI_BISTDECR 0x00b0
-+#define AHCI_DIAGNR0 0x00b4
-+#define AHCI_DIAGNR1 0x00b8
-+#define AHCI_OOBR 0x00bc
-+#define AHCI_PHYCS0R 0x00c0
-+#define AHCI_PHYCS1R 0x00c4
-+#define AHCI_PHYCS2R 0x00c8
-+#define AHCI_TIMER1MS 0x00e0
-+#define AHCI_GPARAM1R 0x00e8
-+#define AHCI_GPARAM2R 0x00ec
-+#define AHCI_PPARAMR 0x00f0
-+#define AHCI_TESTR 0x00f4
-+#define AHCI_VERSIONR 0x00f8
-+#define AHCI_IDR 0x00fc
-+#define AHCI_RWCR 0x00fc
-+#define AHCI_P0DMACR 0x0170
-+#define AHCI_P0PHYCR 0x0178
-+#define AHCI_P0PHYSR 0x017c
-+
-+struct sunxi_ahci {
-+ struct ahci_host_priv hpriv;
-+ struct regulator *pwr;
-+ struct clk *sata_clk;
-+ struct clk *ahb_clk;
-+};
-+
-+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
-+{
-+ u32 reg_val;
-+
-+ reg_val = readl(reg);
-+ reg_val &= ~(clr_val);
-+ writel(reg_val, reg);
-+}
-+
-+static void sunxi_setbits(void __iomem *reg, u32 set_val)
-+{
-+ u32 reg_val;
-+
-+ reg_val = readl(reg);
-+ reg_val |= set_val;
-+ writel(reg_val, reg);
-+}
-+
-+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
-+{
-+ u32 reg_val;
-+
-+ reg_val = readl(reg);
-+ reg_val &= ~(clr_val);
-+ reg_val |= set_val;
-+ writel(reg_val, reg);
-+}
-+
-+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
-+{
-+ return (readl(reg) >> shift) & mask;
-+}
-+
-+static int sunxi_ahci_phy_init(struct device *dev, void __iomem *reg_base)
-+{
-+ u32 reg_val;
-+ int timeout;
-+
-+ /* This magic is from the original code */
-+ writel(0, reg_base + AHCI_RWCR);
-+ mdelay(5);
-+
-+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
-+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
-+ (0x7 << 24),
-+ (0x5 << 24) | BIT(23) | BIT(18));
-+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
-+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
-+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
-+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
-+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
-+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
-+ (0x7 << 20), (0x3 << 20));
-+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
-+ (0x1f << 5), (0x19 << 5));
-+ mdelay(5);
-+
-+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
-+
-+ timeout = 0x100000;
-+ do {
-+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
-+ } while (--timeout && (reg_val != 0x2));
-+ if (!timeout) {
-+ dev_err(dev, "PHY power up failed.\n");
-+ return -EIO;
-+ }
-+
-+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
-+
-+ timeout = 0x100000;
-+ do {
-+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
-+ } while (--timeout && reg_val);
-+ if (!timeout) {
-+ dev_err(dev, "PHY calibration failed.\n");
-+ return -EIO;
-+ }
-+ mdelay(15);
-+
-+ writel(0x7, reg_base + AHCI_RWCR);
-+
-+ return 0;
-+}
-+
-+void sunxi_ahci_pre_start_engine(struct ata_port *ap)
-+{
-+ struct ahci_host_priv *hpriv = ap->host->private_data;
-+
-+ /* Setup DMA before DMA start */
-+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
-+}
-+
-+static int sunxi_ahci_enable_clks(struct sunxi_ahci *ahci)
-+{
-+ int ret;
-+
-+ ret = clk_prepare_enable(ahci->sata_clk);
-+ if (ret)
-+ return ret;
-+
-+ ret = clk_prepare_enable(ahci->ahb_clk);
-+ if (ret)
-+ clk_disable_unprepare(ahci->sata_clk);
-+
-+ return ret;
-+}
-+
-+static void sunxi_ahci_disable_clks(struct sunxi_ahci *ahci)
-+{
-+ clk_disable_unprepare(ahci->ahb_clk);
-+ clk_disable_unprepare(ahci->sata_clk);
-+}
-+
-+static void sunxi_ahci_host_stop(struct ata_host *host)
-+{
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ struct sunxi_ahci *ahci = hpriv->plat_data;
-+
-+ if (!IS_ERR(ahci->pwr))
-+ regulator_disable(ahci->pwr);
-+
-+ sunxi_ahci_disable_clks(ahci);
-+}
-+
-+static struct ata_port_operations sunxi_ahci_platform_ops = {
-+ .inherits = &ahci_ops,
-+ .host_stop = sunxi_ahci_host_stop,
-+};
-+
-+static const struct ata_port_info sunxiahci_port_info = {
-+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
-+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
-+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
-+ .pio_mask = ATA_PIO4,
-+ .udma_mask = ATA_UDMA6,
-+ .port_ops = &sunxi_ahci_platform_ops,
-+};
-+
-+static struct scsi_host_template sunxi_ahci_platform_sht = {
-+ AHCI_SHT("sunxi_ahci"),
-+};
-+
-+static int sunxi_ahci_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ const struct ata_port_info *ppi[] = { &sunxiahci_port_info, NULL };
-+ struct sunxi_ahci *ahci;
-+ struct ata_host *host;
-+ int ret;
-+
-+ ahci = devm_kzalloc(&pdev->dev, sizeof(*ahci), GFP_KERNEL);
-+ if (!ahci)
-+ return -ENOMEM;
-+
-+ ahci->pwr = devm_regulator_get_optional(dev, "pwr");
-+ if (IS_ERR(ahci->pwr) && PTR_ERR(ahci->pwr) == -EPROBE_DEFER)
-+ return -EPROBE_DEFER;
-+
-+ host = ata_host_alloc_pinfo(dev, ppi, 1);
-+ if (!host)
-+ return -ENOMEM;
-+
-+ host->private_data = &ahci->hpriv;
-+ host->flags |= ATA_HOST_PARALLEL_SCAN;
-+
-+ ahci->hpriv.flags = (unsigned long)ppi[0]->private_data;
-+ ahci->hpriv.plat_data = ahci;
-+ ahci->hpriv.pre_start_engine = sunxi_ahci_pre_start_engine;
-+ ahci->hpriv.mmio = devm_ioremap_resource(dev,
-+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
-+ if (IS_ERR(ahci->hpriv.mmio))
-+ return PTR_ERR(ahci->hpriv.mmio);
-+
-+ ahci->ahb_clk = devm_clk_get(&pdev->dev, "ahb_sata");
-+ if (IS_ERR(ahci->ahb_clk))
-+ return PTR_ERR(ahci->ahb_clk);
-+
-+ ahci->sata_clk = devm_clk_get(&pdev->dev, "pll6_sata");
-+ if (IS_ERR(ahci->sata_clk))
-+ return PTR_ERR(ahci->sata_clk);
-+
-+ ret = sunxi_ahci_enable_clks(ahci);
-+ if (ret)
-+ return ret;
-+
-+ if (!IS_ERR(ahci->pwr)) {
-+ ret = regulator_enable(ahci->pwr);
-+ if (ret) {
-+ sunxi_ahci_disable_clks(ahci);
-+ return ret;
-+ }
-+ }
-+
-+ ret = sunxi_ahci_phy_init(dev, ahci->hpriv.mmio);
-+ if (ret) {
-+ sunxi_ahci_host_stop(host);
-+ return ret;
-+ }
-+
-+ ahci_save_initial_config(dev, &ahci->hpriv, 0, 0);
-+
-+ ret = ahci_reset_controller(host);
-+ if (ret) {
-+ sunxi_ahci_host_stop(host);
-+ return ret;
-+ }
-+
-+ ahci_init_controller(host);
-+ ahci_print_info(host, "sunxi");
-+
-+ ret = ata_host_activate(host, platform_get_irq(pdev, 0),
-+ ahci_interrupt, 0, &sunxi_ahci_platform_sht);
-+ if (ret)
-+ sunxi_ahci_host_stop(host);
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int sunxi_ahci_susp(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ struct sunxi_ahci *ahci = hpriv->plat_data;
-+ int ret;
-+
-+ /*
-+ * AHCI spec rev1.1 section 8.3.3:
-+ * Software must disable interrupts prior to requesting a
-+ * transition of the HBA to D3 state.
-+ */
-+ sunxi_clrbits(hpriv->mmio + HOST_CTL, HOST_IRQ_EN);
-+
-+ ret = ata_host_suspend(host, PMSG_SUSPEND);
-+ if (ret)
-+ return ret;
-+
-+ sunxi_ahci_disable_clks(ahci);
-+
-+ return 0;
-+}
-+
-+static int sunxi_ahci_resume(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ struct sunxi_ahci *ahci = hpriv->plat_data;
-+ int ret;
-+
-+ ret = sunxi_ahci_enable_clks(ahci);
-+ if (ret)
-+ return ret;
-+
-+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
-+ ret = ahci_reset_controller(host);
-+ if (ret)
-+ return ret;
-+
-+ ahci_init_controller(host);
-+ }
-+
-+ ata_host_resume(host);
-+
-+ return 0;
-+}
-+#endif
-+
-+static SIMPLE_DEV_PM_OPS(sunxi_ahci_pmo, sunxi_ahci_susp, sunxi_ahci_resume);
-+
-+static const struct of_device_id sunxi_ahci_of_match[] = {
-+ { .compatible = "allwinner,sun4i-a10-ahci" },
-+ { /* sentinel */ },
-+};
-+MODULE_DEVICE_TABLE(of, sunxi_ahci_of_match);
-+
-+static struct platform_driver sunxi_ahci_driver = {
-+ .probe = sunxi_ahci_probe,
-+ .remove = ata_platform_remove_one,
-+ .driver = {
-+ .name = "sunxi-ahci",
-+ .owner = THIS_MODULE,
-+ .of_match_table = sunxi_ahci_of_match,
-+ .pm = &sunxi_ahci_pmo,
-+ },
-+};
-+module_platform_driver(sunxi_ahci_driver);
-+
-+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA platform driver");
-+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch b/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch
new file mode 100644
index 0000000000..3fea6ce527
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch
@@ -0,0 +1,31 @@
+From 90189e2c18e983da0ce22e44cd610f9ce2db69b1 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 20 Jan 2014 16:32:33 +0200
+Subject: [PATCH] ata: ahci_platform: Add DT compatible for Synopsis DWC AHCI
+ controller
+
+Add compatible string "snps,dwc-ahci", which should be used
+for Synopsis Designware SATA cores. e.g. on TI OMAP5 and DRA7 platforms.
+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_platform.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index bdadec1..d7e55ba 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -609,6 +609,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+ { .compatible = "snps,spear-ahci", },
+ { .compatible = "snps,exynos5440-ahci", },
+ { .compatible = "ibm,476gtr-ahci", },
++ { .compatible = "snps,dwc-ahci", },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, ahci_of_match);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch b/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch
deleted file mode 100644
index 6d2afac76d..0000000000
--- a/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-From 23af610e09f78822ade4067a400ff9ceb5b020ea Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <oliver@schinagl.nl>
-Date: Tue, 3 Dec 2013 12:10:11 +0100
-Subject: [PATCH] ARM: sun4i: dts: Add ahci / sata support
-
-This patch adds sunxi sata support to A10 boards that have such a connector.
-Some boards also feature a regulator via a GPIO and support for this is also
-added.
-
-Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 27 +++++++++++++++++++++++++++
- arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++
- 3 files changed, 40 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
-@@ -48,6 +48,10 @@
- status = "okay";
- };
-
-+ sata: ahci@01c18000 {
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
- mmc0_cd_pin_a1000: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-@@ -51,7 +51,19 @@
- status = "okay";
- };
-
-+ sata: ahci@01c18000 {
-+ pwr-supply = <&reg_ahci_5v>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ ahci_pwr_pin_cubieboard: ahci_pwr_pin@0 {
-+ allwinner,pins = "PB8";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
-@@ -102,4 +114,19 @@
- linux,default-trigger = "heartbeat";
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+ pinctrl-names = "default";
-+
-+ reg_ahci_5v: ahci-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ahci-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ pinctrl-0 = <&ahci_pwr_pin_cubieboard>;
-+ gpio = <&pio 1 8 0>;
-+ enable-active-high;
-+ };
-+ };
- };
---- a/arch/arm/boot/dts/sun4i-a10.dtsi
-+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
-@@ -338,6 +338,15 @@
- status = "disabled";
- };
-
-+ sata: ahci@01c18000 {
-+ compatible = "allwinner,sun4i-a10-ahci";
-+ reg = <0x01c18000 0x1000>;
-+ interrupts = <56>;
-+ clocks = <&ahb_gates 25>, <&pll6 0>;
-+ clock-names = "ahb_sata", "pll6_sata";
-+ status = "disabled";
-+ };
-+
- intc: interrupt-controller@01c20400 {
- compatible = "allwinner,sun4i-ic";
- reg = <0x01c20400 0x400>;
diff --git a/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch b/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch
new file mode 100644
index 0000000000..1ab704beda
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch
@@ -0,0 +1,142 @@
+From 154a670a945c54300749d5ba008f30bbd6089017 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Mon, 27 Jan 2014 16:41:18 +0200
+Subject: [PATCH] ata: ahci_platform: Manage SATA PHY
+
+Some platforms have a PHY hooked up to the
+SATA controller. The PHY needs to be initialized
+and powered up for SATA to work. We do that
+using the PHY framework.
+
+CC: Balaji T K <balajitk@ti.com>
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci.h | 2 ++
+ drivers/ata/ahci_platform.c | 47 +++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 47 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index bf8100c..3ab7ac9 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -37,6 +37,7 @@
+
+ #include <linux/clk.h>
+ #include <linux/libata.h>
++#include <linux/phy/phy.h>
+ #include <linux/regulator/consumer.h>
+
+ /* Enclosure Management Control */
+@@ -325,6 +326,7 @@ struct ahci_host_priv {
+ u32 em_msg_type; /* EM message type */
+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
+ struct regulator *target_pwr; /* Optional */
++ struct phy *phy; /* If platform uses phy */
+ void *plat_data; /* Other platform data */
+ /*
+ * Optional ahci_start_engine override, if not set this gets set to the
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index d7e55ba..99d38c1 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -23,6 +23,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/libata.h>
+ #include <linux/ahci_platform.h>
++#include <linux/phy/phy.h>
+ #include "ahci.h"
+
+ static void ahci_host_stop(struct ata_host *host);
+@@ -147,6 +148,7 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
+ * the following order:
+ * 1) Regulator
+ * 2) Clocks (through ahci_platform_enable_clks)
++ * 3) Phy
+ *
+ * If resource enabling fails at any point the previous enabled
+ * resources are disabled in reverse order.
+@@ -171,8 +173,23 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
+ if (rc)
+ goto disable_regulator;
+
++ if (hpriv->phy) {
++ rc = phy_init(hpriv->phy);
++ if (rc)
++ goto disable_clks;
++
++ rc = phy_power_on(hpriv->phy);
++ if (rc) {
++ phy_exit(hpriv->phy);
++ goto disable_clks;
++ }
++ }
++
+ return 0;
+
++disable_clks:
++ ahci_platform_disable_clks(hpriv);
++
+ disable_regulator:
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
+@@ -186,14 +203,20 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
+ *
+ * This function disables all ahci_platform managed resources in
+ * the following order:
+- * 1) Clocks (through ahci_platform_disable_clks)
+- * 2) Regulator
++ * 1) Phy
++ * 2) Clocks (through ahci_platform_disable_clks)
++ * 3) Regulator
+ *
+ * LOCKING:
+ * None.
+ */
+ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
+ {
++ if (hpriv->phy) {
++ phy_power_off(hpriv->phy);
++ phy_exit(hpriv->phy);
++ }
++
+ ahci_platform_disable_clks(hpriv);
+
+ if (hpriv->target_pwr)
+@@ -222,6 +245,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
+ * 2) regulator for controlling the targets power (optional)
+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
+ * or for non devicetree enabled platforms a single clock
++ * 4) phy (optional)
+ *
+ * LOCKING:
+ * None.
+@@ -283,6 +307,25 @@ struct ahci_host_priv *ahci_platform_get_resources(
+ hpriv->clks[i] = clk;
+ }
+
++ hpriv->phy = devm_phy_get(dev, "sata-phy");
++ if (IS_ERR(hpriv->phy)) {
++ rc = PTR_ERR(hpriv->phy);
++ switch (rc) {
++ case -ENODEV:
++ case -ENOSYS:
++ /* continue normally */
++ hpriv->phy = NULL;
++ break;
++
++ case -EPROBE_DEFER:
++ goto err_out;
++
++ default:
++ dev_err(dev, "couldn't get sata-phy\n");
++ goto err_out;
++ }
++ }
++
+ devres_remove_group(dev, NULL);
+ return hpriv;
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch b/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch
deleted file mode 100644
index 5532a3f194..0000000000
--- a/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch
+++ /dev/null
@@ -1,167 +0,0 @@
-From 4ce1f4c3ab04a697e9861b77582077b905b3f8a0 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Fri, 3 Jan 2014 10:27:51 +0100
-Subject: [PATCH] ARM: sun7i: dts: Add ahci / sata support
-
-This patch adds sunxi sata support to A20 boards that have such a connector.
-Some boards also feature a regulator via a GPIO and support for this is also
-added.
-
-Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 +++++++++++++++++++++++++
- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 27 +++++++++++++++++++++++++
- arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 26 ++++++++++++++++++++++++
- arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++
- 4 files changed, 89 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-@@ -43,7 +43,19 @@
- status = "okay";
- };
-
-+ sata: ahci@01c18000 {
-+ pwr-supply = <&reg_ahci_5v>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ ahci_pwr_pin_cubieboard2: ahci_pwr_pin@0 {
-+ allwinner,pins = "PB8";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
-@@ -93,4 +105,19 @@
- gpios = <&pio 7 20 0>;
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+ pinctrl-names = "default";
-+
-+ reg_ahci_5v: ahci-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ahci-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ pinctrl-0 = <&ahci_pwr_pin_cubieboard2>;
-+ gpio = <&pio 1 8 0>;
-+ enable-active-high;
-+ };
-+ };
- };
---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-@@ -43,6 +43,11 @@
- status = "okay";
- };
-
-+ sata: ahci@01c18000 {
-+ pwr-supply = <&reg_ahci_5v>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
- mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
-@@ -58,6 +63,13 @@
- allwinner,pull = <0>;
- };
-
-+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
-+ allwinner,pins = "PH12";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_cubietruck: led_pins@0 {
- allwinner,pins = "PH7", "PH11", "PH20", "PH21";
- allwinner,function = "gpio_out";
-@@ -149,4 +161,19 @@
- gpio = <&pio 7 3 0>;
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+ pinctrl-names = "default";
-+
-+ reg_ahci_5v: ahci-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ahci-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
-+ gpio = <&pio 7 12 0>;
-+ enable-active-high;
-+ };
-+ };
- };
---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-@@ -52,7 +52,19 @@
- status = "okay";
- };
-
-+ sata: ahci@01c18000 {
-+ pwr-supply = <&reg_ahci_5v>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ ahci_pwr_pin_olinuxinom: ahci_pwr_pin@0 {
-+ allwinner,pins = "PB8";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
- allwinner,function = "gpio_in";
-@@ -123,4 +135,18 @@
- default-state = "on";
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+
-+ reg_ahci_5v: ahci-5v {
-+ compatible = "regulator-fixed";
-+ regulator-name = "ahci-5v";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ pinctrl-0 = <&ahci_pwr_pin_olinuxinom>;
-+ gpio = <&pio 1 8 0>;
-+ enable-active-high;
-+ };
-+ };
- };
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -433,6 +433,15 @@
- };
- };
-
-+ sata: ahci@01c18000 {
-+ compatible = "allwinner,sun4i-a10-ahci";
-+ reg = <0x01c18000 0x1000>;
-+ interrupts = <0 56 1>;
-+ clocks = <&ahb_gates 25>, <&pll6 0>;
-+ clock-names = "ahb_sata", "pll6_sata";
-+ status = "disabled";
-+ };
-+
- timer@01c20c00 {
- compatible = "allwinner,sun4i-timer";
- reg = <0x01c20c00 0x90>;
diff --git a/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch b/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch
new file mode 100644
index 0000000000..18953d1046
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch
@@ -0,0 +1,85 @@
+From 48379fed3987d587a25a48e155872e9d3125490d Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Wed, 9 Oct 2013 15:08:59 +0300
+Subject: [PATCH] ata: ahci_platform: runtime resume the device before use
+
+On OMAP platforms the device needs to be runtime resumed before
+it can be accessed. The OMAP HWMOD framework takes care of
+enabling the module and its resources based on the
+device's runtime PM state.
+
+In this patch we runtime resume during .probe() and runtime suspend
+after .remove().
+
+We also update the runtime PM state during .resume().
+
+CC: Balaji T K <balajitk@ti.com>
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci.h | 1 +
+ drivers/ata/ahci_platform.c | 15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 3ab7ac9..51af275b 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -324,6 +324,7 @@ struct ahci_host_priv {
+ u32 em_loc; /* enclosure management location */
+ u32 em_buf_sz; /* EM buffer size in byte */
+ u32 em_msg_type; /* EM message type */
++ bool got_runtime_pm; /* Did we do pm_runtime_get? */
+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
+ struct regulator *target_pwr; /* Optional */
+ struct phy *phy; /* If platform uses phy */
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 99d38c1..75698a4 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -24,6 +24,7 @@
+ #include <linux/libata.h>
+ #include <linux/ahci_platform.h>
+ #include <linux/phy/phy.h>
++#include <linux/pm_runtime.h>
+ #include "ahci.h"
+
+ static void ahci_host_stop(struct ata_host *host);
+@@ -229,6 +230,11 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
+ struct ahci_host_priv *hpriv = res;
+ int c;
+
++ if (hpriv->got_runtime_pm) {
++ pm_runtime_put_sync(dev);
++ pm_runtime_disable(dev);
++ }
++
+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+ clk_put(hpriv->clks[c]);
+ }
+@@ -326,6 +332,10 @@ struct ahci_host_priv *ahci_platform_get_resources(
+ }
+ }
+
++ pm_runtime_enable(dev);
++ pm_runtime_get_sync(dev);
++ hpriv->got_runtime_pm = true;
++
+ devres_remove_group(dev, NULL);
+ return hpriv;
+
+@@ -635,6 +645,11 @@ int ahci_platform_resume(struct device *dev)
+ if (rc)
+ goto disable_resources;
+
++ /* We resumed so update PM runtime state */
++ pm_runtime_disable(dev);
++ pm_runtime_set_active(dev);
++ pm_runtime_enable(dev);
++
+ return 0;
+
+ disable_resources:
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch b/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch
new file mode 100644
index 0000000000..4be6c15706
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch
@@ -0,0 +1,47 @@
+From 09de09bc2c236dccb0ed5ed38015e829550a5c28 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 23 Feb 2014 11:37:17 +0100
+Subject: [PATCH] ahci_sunxi: Use msleep instead of mdelay
+
+ahci_sunxi_phy_init is called from the probe and resume code paths, and
+sleeping is safe in both, so use msleep instead of mdelay.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/ata/ahci_sunxi.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
+index 001f7dfc..d1bf3f7 100644
+--- a/drivers/ata/ahci_sunxi.c
++++ b/drivers/ata/ahci_sunxi.c
+@@ -90,7 +90,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+
+ /* This magic is from the original code */
+ writel(0, reg_base + AHCI_RWCR);
+- mdelay(5);
++ msleep(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+@@ -105,7 +105,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+ (0x7 << 20), (0x3 << 20));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+ (0x1f << 5), (0x19 << 5));
+- mdelay(5);
++ msleep(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+@@ -137,7 +137,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+ udelay(1);
+ } while (1);
+
+- mdelay(15);
++ msleep(15);
+
+ writel(0x7, reg_base + AHCI_RWCR);
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch b/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch
new file mode 100644
index 0000000000..88063ed5f0
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch
@@ -0,0 +1,122 @@
+From 3cae1df0e62432a80db86c80e261eb9bbed326ee Mon Sep 17 00:00:00 2001
+From: Oliver Schinagl <oliver@schinagl.nl>
+Date: Tue, 3 Dec 2013 12:10:11 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add ahci / sata support
+
+This patch adds sunxi sata support to A10 boards that have such a connector.
+Some boards also feature a regulator via a GPIO and support for this is also
+added.
+
+Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 6 +++++
+ arch/arm/boot/dts/sun4i-a10.dtsi | 8 +++++++
+ arch/arm/boot/dts/sunxi-ahci-reg.dtsi | 36 ++++++++++++++++++++++++++++++
+ 4 files changed, 54 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sunxi-ahci-reg.dtsi
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+index cbd2e13..d6ec839 100644
+--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+@@ -35,6 +35,10 @@
+ };
+ };
+
++ ahci: sata@01c18000 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ emac_power_pin_a1000: emac_power_pin@0 {
+ allwinner,pins = "PH15";
+diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+index b139ee6..6df237d8 100644
+--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+@@ -12,6 +12,7 @@
+
+ /dts-v1/;
+ /include/ "sun4i-a10.dtsi"
++/include/ "sunxi-ahci-reg.dtsi"
+
+ / {
+ model = "Cubietech Cubieboard";
+@@ -33,6 +34,11 @@
+ };
+ };
+
++ ahci: sata@01c18000 {
++ target-supply = <&reg_ahci_5v>;
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ led_pins_cubieboard: led_pins@0 {
+ allwinner,pins = "PH20", "PH21";
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 336dbec..454077a 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -338,6 +338,14 @@
+ #size-cells = <0>;
+ };
+
++ ahci: sata@01c18000 {
++ compatible = "allwinner,sun4i-a10-ahci";
++ reg = <0x01c18000 0x1000>;
++ interrupts = <56>;
++ clocks = <&pll6 0>, <&ahb_gates 25>;
++ status = "disabled";
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+diff --git a/arch/arm/boot/dts/sunxi-ahci-reg.dtsi b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
+new file mode 100644
+index 0000000..7072af1
+--- /dev/null
++++ b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
+@@ -0,0 +1,36 @@
++/*
++ * sunxi boards sata target power supply common code
++ *
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/ {
++ soc@01c00000 {
++ pio: pinctrl@01c20800 {
++ ahci_pwr_pin_a: ahci_pwr_pin@0 {
++ allwinner,pins = "PB8";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++ };
++ };
++
++ reg_ahci_5v: ahci-5v {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ pinctrl-0 = <&ahci_pwr_pin_a>;
++ regulator-name = "ahci-5v";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ enable-active-high;
++ gpio = <&pio 1 8 0>;
++ };
++};
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch b/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch
new file mode 100644
index 0000000000..d43dab8dc8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch
@@ -0,0 +1,127 @@
+From c7b99b7afc3882c1b38a15da8d1625dd448c6fee Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 3 Jan 2014 10:27:51 +0100
+Subject: [PATCH] ARM: sun7i: dt: Add ahci / sata support
+
+This patch adds sunxi sata support to A20 boards that have such a connector.
+Some boards also feature a regulator via a GPIO and support for this is also
+added.
+
+Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 6 ++++++
+ arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 18 ++++++++++++++++++
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 6 ++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
+ 4 files changed, 38 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+index 7bf4935..07823c2 100644
+--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+@@ -13,12 +13,18 @@
+
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
++/include/ "sunxi-ahci-reg.dtsi"
+
+ / {
+ model = "Cubietech Cubieboard2";
+ compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
++ ahci: sata@01c18000 {
++ target-supply = <&reg_ahci_5v>;
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ led_pins_cubieboard2: led_pins@0 {
+ allwinner,pins = "PH20", "PH21";
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+index 025ce52..403bd2e 100644
+--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+@@ -13,13 +13,26 @@
+
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
++/include/ "sunxi-ahci-reg.dtsi"
+
+ / {
+ model = "Cubietech Cubietruck";
+ compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
++ ahci: sata@01c18000 {
++ target-supply = <&reg_ahci_5v>;
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
++ ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
++ allwinner,pins = "PH12";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++
+ led_pins_cubietruck: led_pins@0 {
+ allwinner,pins = "PH7", "PH11", "PH20", "PH21";
+ allwinner,function = "gpio_out";
+@@ -90,4 +103,9 @@
+ gpios = <&pio 7 7 0>;
+ };
+ };
++
++ reg_ahci_5v: ahci-5v {
++ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
++ gpio = <&pio 7 12 0>;
++ };
+ };
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index b02a796..d5c6799 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -13,12 +13,18 @@
+
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
++/include/ "sunxi-ahci-reg.dtsi"
+
+ / {
+ model = "Olimex A20-Olinuxino Micro";
+ compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
++ ahci: sata@01c18000 {
++ target-supply = <&reg_ahci_5v>;
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ led_pins_olinuxino: led_pins@0 {
+ allwinner,pins = "PH2";
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index daaafd0..3385994 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -392,6 +392,14 @@
+ #size-cells = <0>;
+ };
+
++ ahci: sata@01c18000 {
++ compatible = "allwinner,sun4i-a10-ahci";
++ reg = <0x01c18000 0x1000>;
++ interrupts = <0 56 4>;
++ clocks = <&pll6 0>, <&ahb_gates 25>;
++ status = "disabled";
++ };
++
+ pio: pinctrl@01c20800 {
+ compatible = "allwinner,sun7i-a20-pinctrl";
+ reg = <0x01c20800 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch b/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch
new file mode 100644
index 0000000000..99bb3439cf
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch
@@ -0,0 +1,1187 @@
+From 00f082cbfe43bd45ddcff3572875ee9fbeafdfdd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
+Date: Sat, 15 Feb 2014 16:37:33 +0100
+Subject: [PATCH] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner
+ sunxi SoCs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is based on the driver Allwinner ships in their Android kernel sources.
+
+Initial porting to upstream kernels done by David Lanzendörfer, additional
+fixes and cleanups by Hans de Goede.
+
+It uses dma in bus-master mode using a built-in designware idmac controller,
+which is identical to the one found in the mmc-dw hosts.
+The rest of the host is not identical to mmc-dw.
+
+Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/Kconfig | 7 +
+ drivers/mmc/host/Makefile | 2 +
+ drivers/mmc/host/sunxi-mmc.c | 876 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/mmc/host/sunxi-mmc.h | 239 ++++++++++++
+ 4 files changed, 1124 insertions(+)
+ create mode 100644 drivers/mmc/host/sunxi-mmc.c
+ create mode 100644 drivers/mmc/host/sunxi-mmc.h
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 1384f67..7caf266 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -689,3 +689,10 @@ config MMC_REALTEK_PCI
+ help
+ Say Y here to include driver code to support SD/MMC card interface
+ of Realtek PCI-E card reader
++
++config MMC_SUNXI
++ tristate "Allwinner sunxi SD/MMC Host Controller support"
++ depends on ARCH_SUNXI
++ help
++ This selects support for the SD/MMC Host Controller on
++ Allwinner sunxi SoCs.
+diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
+index 3483b6b..f3c7c243 100644
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -54,6 +54,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
+
+ obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
+
++obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o
++
+ obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+ obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
+ obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+new file mode 100644
+index 0000000..2dc446c
+--- /dev/null
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -0,0 +1,876 @@
++/*
++ * Driver for sunxi SD/MMC host controllers
++ * (C) Copyright 2014-2015 Reuuimlla Technology Co., Ltd.
++ * (C) Copyright 2014-2015 Aaron Maoye <leafy.myeh@reuuimllatech.com>
++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch>
++ * (C) Copyright 2014-2015 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
++ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++
++#include <linux/clk.h>
++#include <linux/clk-private.h>
++#include <linux/clk/sunxi.h>
++
++#include <linux/gpio.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/scatterlist.h>
++#include <linux/dma-mapping.h>
++#include <linux/slab.h>
++#include <linux/regulator/consumer.h>
++
++#include <linux/of_address.h>
++#include <linux/of_gpio.h>
++#include <linux/of_platform.h>
++
++#include <linux/mmc/host.h>
++#include <linux/mmc/sd.h>
++#include <linux/mmc/sdio.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/core.h>
++#include <linux/mmc/card.h>
++#include <linux/mmc/slot-gpio.h>
++
++#include "sunxi-mmc.h"
++
++static int sunxi_mmc_init_host(struct mmc_host *mmc)
++{
++ u32 rval;
++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
++ int ret;
++
++ ret = clk_prepare_enable(smc_host->clk_ahb);
++ if (ret) {
++ dev_err(mmc_dev(smc_host->mmc), "AHB clk err %d\n", ret);
++ return ret;
++ }
++ ret = clk_prepare_enable(smc_host->clk_mod);
++ if (ret) {
++ dev_err(mmc_dev(smc_host->mmc), "MOD clk err %d\n", ret);
++ clk_disable_unprepare(smc_host->clk_ahb);
++ return ret;
++ }
++
++ /* reset controller */
++ rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HARDWARE_RESET;
++ mci_writel(smc_host, REG_GCTRL, rval);
++
++ mci_writel(smc_host, REG_FTRGL, 0x20070008);
++ mci_writel(smc_host, REG_TMOUT, 0xffffffff);
++ mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask);
++ mci_writel(smc_host, REG_RINTR, 0xffffffff);
++ mci_writel(smc_host, REG_DBGC, 0xdeb);
++ mci_writel(smc_host, REG_FUNS, 0xceaa0000);
++ mci_writel(smc_host, REG_DLBA, smc_host->sg_dma);
++ rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTERRUPT_ENABLE_BIT;
++ rval &= ~SDXC_ACCESS_DONE_DIRECT;
++ mci_writel(smc_host, REG_GCTRL, rval);
++
++ return 0;
++}
++
++static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host)
++{
++ mci_writel(smc_host, REG_GCTRL, SDXC_HARDWARE_RESET);
++ clk_disable_unprepare(smc_host->clk_ahb);
++ clk_disable_unprepare(smc_host->clk_mod);
++}
++
++/* /\* UHS-I Operation Modes */
++/* * DS 25MHz 12.5MB/s 3.3V */
++/* * HS 50MHz 25MB/s 3.3V */
++/* * SDR12 25MHz 12.5MB/s 1.8V */
++/* * SDR25 50MHz 25MB/s 1.8V */
++/* * SDR50 100MHz 50MB/s 1.8V */
++/* * SDR104 208MHz 104MB/s 1.8V */
++/* * DDR50 50MHz 50MB/s 1.8V */
++/* * MMC Operation Modes */
++/* * DS 26MHz 26MB/s 3/1.8/1.2V */
++/* * HS 52MHz 52MB/s 3/1.8/1.2V */
++/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */
++/* * HS200 200MHz 200MB/s 1.8/1.2V */
++/* * */
++/* * Spec. Timing */
++/* * SD3.0 */
++/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */
++/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */
++/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */
++/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */
++/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */
++/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */
++/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
++
++/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */
++/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */
++/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */
++/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */
++/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */
++
++/* * eMMC4.5 */
++/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */
++/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
++/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
++/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */
++/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
++/* *\/ */
++
++static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
++ struct mmc_data *data)
++{
++ struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
++ struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
++ int i, max_len = (1 << host->idma_des_size_bits);
++
++ for (i = 0; i < data->sg_len; i++) {
++ pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN |
++ SDXC_IDMAC_DES0_DIC;
++
++ if (data->sg[i].length == max_len)
++ pdes[i].buf_size = 0; /* 0 == max_len */
++ else
++ pdes[i].buf_size = data->sg[i].length;
++
++ pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
++ pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
++ }
++
++ pdes[0].config |= SDXC_IDMAC_DES0_FD;
++ pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD;
++
++ wmb(); /* Ensure idma_des hit main mem before we start the idmac */
++}
++
++static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data)
++{
++ if (data->flags & MMC_DATA_WRITE)
++ return DMA_TO_DEVICE;
++ else
++ return DMA_FROM_DEVICE;
++}
++
++static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host,
++ struct mmc_data *data)
++{
++ u32 dma_len;
++ u32 i;
++ u32 temp;
++ struct scatterlist *sg;
++
++ dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len,
++ sunxi_mmc_get_dma_dir(data));
++ if (dma_len == 0) {
++ dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n");
++ return -ENOMEM;
++ }
++
++ for_each_sg(data->sg, sg, data->sg_len, i) {
++ if (sg->offset & 3 || sg->length & 3) {
++ dev_err(mmc_dev(smc_host->mmc),
++ "unaligned scatterlist: os %x length %d\n",
++ sg->offset, sg->length);
++ return -EINVAL;
++ }
++ }
++
++ sunxi_mmc_init_idma_des(smc_host, data);
++
++ temp = mci_readl(smc_host, REG_GCTRL);
++ temp |= SDXC_DMA_ENABLE_BIT;
++ mci_writel(smc_host, REG_GCTRL, temp);
++ temp |= SDXC_DMA_RESET;
++ mci_writel(smc_host, REG_GCTRL, temp);
++ mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_SOFT_RESET);
++
++ if (!(data->flags & MMC_DATA_WRITE))
++ mci_writel(smc_host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT);
++
++ mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON);
++
++ return 0;
++}
++
++static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
++ struct mmc_request *req)
++{
++ u32 cmd_val = SDXC_START | SDXC_RESPONSE_EXPIRE | SDXC_STOP_ABORT_CMD
++ | SDXC_CHECK_RESPONSE_CRC | MMC_STOP_TRANSMISSION;
++ u32 ri = 0;
++ unsigned long expire = jiffies + msecs_to_jiffies(1000);
++
++ mci_writel(host, REG_CARG, 0);
++ mci_writel(host, REG_CMDR, cmd_val);
++
++ do {
++ ri = mci_readl(host, REG_RINTR);
++ } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) &&
++ time_before(jiffies, expire));
++
++ if (ri & SDXC_INTERRUPT_ERROR_BIT) {
++ dev_err(mmc_dev(host->mmc), "send stop command failed\n");
++ if (req->stop)
++ req->stop->resp[0] = -ETIMEDOUT;
++ } else {
++ if (req->stop)
++ req->stop->resp[0] = mci_readl(host, REG_RESP0);
++ }
++
++ mci_writel(host, REG_RINTR, 0xffff);
++}
++
++static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host)
++{
++ struct mmc_command *cmd = smc_host->mrq->cmd;
++ struct mmc_data *data = smc_host->mrq->data;
++
++ /* For some cmds timeout is normal with sd/mmc cards */
++ if ((smc_host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == SDXC_RESPONSE_TIMEOUT &&
++ (cmd->opcode == SD_IO_SEND_OP_COND || cmd->opcode == SD_IO_RW_DIRECT))
++ return;
++
++ dev_err(mmc_dev(smc_host->mmc),
++ "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
++ smc_host->mmc->index, cmd->opcode,
++ data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
++ smc_host->int_sum & SDXC_RESPONSE_ERROR ? " RE" : "",
++ smc_host->int_sum & SDXC_RESPONSE_CRC_ERROR ? " RCE" : "",
++ smc_host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "",
++ smc_host->int_sum & SDXC_RESPONSE_TIMEOUT ? " RTO" : "",
++ smc_host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "",
++ smc_host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "",
++ smc_host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "",
++ smc_host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "",
++ smc_host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : ""
++ );
++}
++
++static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host)
++{
++ struct mmc_request *mrq;
++ unsigned long iflags;
++
++ spin_lock_irqsave(&host->lock, iflags);
++
++ mrq = host->mrq;
++ if (!mrq) {
++ spin_unlock_irqrestore(&host->lock, iflags);
++ dev_err(mmc_dev(host->mmc), "no request to finalize\n");
++ return;
++ }
++
++ if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) {
++ sunxi_mmc_dump_errinfo(host);
++ mrq->cmd->error = -ETIMEDOUT;
++ if (mrq->data)
++ mrq->data->error = -ETIMEDOUT;
++ if (mrq->stop)
++ mrq->stop->error = -ETIMEDOUT;
++ } else {
++ if (mrq->cmd->flags & MMC_RSP_136) {
++ mrq->cmd->resp[0] = mci_readl(host, REG_RESP3);
++ mrq->cmd->resp[1] = mci_readl(host, REG_RESP2);
++ mrq->cmd->resp[2] = mci_readl(host, REG_RESP1);
++ mrq->cmd->resp[3] = mci_readl(host, REG_RESP0);
++ } else {
++ mrq->cmd->resp[0] = mci_readl(host, REG_RESP0);
++ }
++ if (mrq->data)
++ mrq->data->bytes_xfered =
++ mrq->data->blocks * mrq->data->blksz;
++ }
++
++ if (mrq->data) {
++ struct mmc_data *data = mrq->data;
++ u32 temp;
++
++ mci_writel(host, REG_IDST, 0x337);
++ mci_writel(host, REG_DMAC, 0);
++ temp = mci_readl(host, REG_GCTRL);
++ mci_writel(host, REG_GCTRL, temp|SDXC_DMA_RESET);
++ temp &= ~SDXC_DMA_ENABLE_BIT;
++ mci_writel(host, REG_GCTRL, temp);
++ temp |= SDXC_FIFO_RESET;
++ mci_writel(host, REG_GCTRL, temp);
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++ sunxi_mmc_get_dma_dir(data));
++ }
++
++ mci_writel(host, REG_RINTR, 0xffff);
++
++ dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n",
++ mrq->cmd->resp[0], mrq->cmd->resp[1],
++ mrq->cmd->resp[2], mrq->cmd->resp[3]);
++
++ host->mrq = NULL;
++ host->int_sum = 0;
++ host->wait_dma = 0;
++
++ spin_unlock_irqrestore(&host->lock, iflags);
++
++ if (mrq->data && mrq->data->error) {
++ dev_err(mmc_dev(host->mmc),
++ "data error, sending stop command\n");
++ sunxi_mmc_send_manual_stop(host, mrq);
++ }
++
++ mmc_request_done(host->mmc, mrq);
++}
++
++static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id)
++{
++ struct sunxi_mmc_host *host = dev_id;
++ u32 finalize = 0;
++ u32 sdio_int = 0;
++ u32 msk_int;
++ u32 idma_int;
++
++ spin_lock(&host->lock);
++
++ idma_int = mci_readl(host, REG_IDST);
++ msk_int = mci_readl(host, REG_MISTA);
++
++ dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n",
++ host->mrq, msk_int, idma_int);
++
++ if (host->mrq) {
++ if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT)
++ host->wait_dma = 0;
++
++ host->int_sum |= msk_int;
++
++ /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finishing the req */
++ if ((host->int_sum & SDXC_RESPONSE_TIMEOUT) &&
++ !(host->int_sum & SDXC_COMMAND_DONE))
++ mci_writel(host, REG_IMASK,
++ host->sdio_imask | SDXC_COMMAND_DONE);
++ else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT)
++ finalize = 1; /* Don't wait for dma on error */
++ else if (host->int_sum & SDXC_INTERRUPT_DONE_BIT && !host->wait_dma)
++ finalize = 1; /* Done */
++
++ if (finalize) {
++ mci_writel(host, REG_IMASK, host->sdio_imask);
++ mci_writel(host, REG_IDIE, 0);
++ }
++ }
++
++ if (msk_int & SDXC_SDIO_INTERRUPT)
++ sdio_int = 1;
++
++ mci_writel(host, REG_RINTR, msk_int);
++ mci_writel(host, REG_IDST, idma_int);
++
++ spin_unlock(&host->lock);
++
++ if (finalize)
++ tasklet_schedule(&host->tasklet);
++
++ if (sdio_int)
++ mmc_signal_sdio_irq(host->mmc);
++
++ return IRQ_HANDLED;
++}
++
++static void sunxi_mmc_tasklet(unsigned long data)
++{
++ struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data;
++ sunxi_mmc_finalize_request(smc_host);
++}
++
++static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
++{
++ unsigned long expire = jiffies + msecs_to_jiffies(2000);
++ u32 rval;
++
++ rval = mci_readl(host, REG_CLKCR);
++ rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
++
++ if (oclk_en)
++ rval |= SDXC_CARD_CLOCK_ON;
++
++ if (!host->io_flag)
++ rval |= SDXC_LOW_POWER_ON;
++
++ mci_writel(host, REG_CLKCR, rval);
++
++ rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER;
++ if (host->voltage_switching)
++ rval |= SDXC_VOLTAGE_SWITCH;
++ mci_writel(host, REG_CMDR, rval);
++
++ do {
++ rval = mci_readl(host, REG_CMDR);
++ } while (time_before(jiffies, expire) && (rval & SDXC_START));
++
++ if (rval & SDXC_START) {
++ dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
++ host->ferror = 1;
++ }
++}
++
++static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
++ u32 oclk_dly, u32 sclk_dly)
++{
++ unsigned long iflags;
++ struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
++
++ spin_lock_irqsave(&smc_host->lock, iflags);
++ clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
++ spin_unlock_irqrestore(&smc_host->lock, iflags);
++}
++
++struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
++ { MMC_CLK_400K, 0, 7 },
++ { MMC_CLK_25M, 0, 5 },
++ { MMC_CLK_50M, 3, 5 },
++ { MMC_CLK_50MDDR, 2, 4 },
++ { MMC_CLK_50MDDR_8BIT, 2, 4 },
++ { MMC_CLK_100M, 1, 4 },
++ { MMC_CLK_200M, 1, 4 },
++};
++
++static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
++ unsigned int rate)
++{
++ u32 newrate;
++ u32 src_clk;
++ u32 oclk_dly;
++ u32 sclk_dly;
++ u32 temp;
++ struct sunxi_mmc_clk_dly *dly = NULL;
++
++ newrate = clk_round_rate(smc_host->clk_mod, rate);
++ if (smc_host->clk_mod_rate == newrate) {
++ dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n",
++ rate, newrate);
++ return;
++ }
++
++ dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n",
++ rate, newrate);
++
++ /* setting clock rate */
++ clk_disable(smc_host->clk_mod);
++ clk_set_rate(smc_host->clk_mod, newrate);
++ clk_enable(smc_host->clk_mod);
++ smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod);
++ dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate);
++
++ sunxi_mmc_oclk_onoff(smc_host, 0);
++ /* clear internal divider */
++ temp = mci_readl(smc_host, REG_CLKCR);
++ temp &= ~0xff;
++ mci_writel(smc_host, REG_CLKCR, temp);
++
++ /* determine delays */
++ if (rate <= 400000) {
++ dly = &mmc_clk_dly[MMC_CLK_400K];
++ } else if (rate <= 25000000) {
++ dly = &mmc_clk_dly[MMC_CLK_25M];
++ } else if (rate <= 50000000) {
++ if (smc_host->ddr) {
++ if (smc_host->bus_width == 8)
++ dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT];
++ else
++ dly = &mmc_clk_dly[MMC_CLK_50MDDR];
++ } else {
++ dly = &mmc_clk_dly[MMC_CLK_50M];
++ }
++ } else if (rate <= 104000000) {
++ dly = &mmc_clk_dly[MMC_CLK_100M];
++ } else if (rate <= 208000000) {
++ dly = &mmc_clk_dly[MMC_CLK_200M];
++ } else {
++ dly = &mmc_clk_dly[MMC_CLK_50M];
++ }
++
++ oclk_dly = dly->oclk_dly;
++ sclk_dly = dly->sclk_dly;
++
++ src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod));
++
++ if (src_clk >= 300000000 && src_clk <= 400000000) {
++ if (oclk_dly)
++ oclk_dly--;
++ if (sclk_dly)
++ sclk_dly--;
++ }
++
++ sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
++ sunxi_mmc_oclk_onoff(smc_host, 1);
++
++ /* oclk_onoff sets various irq status bits, clear these */
++ mci_writel(smc_host, REG_RINTR,
++ mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT);
++}
++
++static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct sunxi_mmc_host *host = mmc_priv(mmc);
++ u32 temp;
++ s32 err;
++
++ /* Set the power state */
++ switch (ios->power_mode) {
++ case MMC_POWER_ON:
++ break;
++
++ case MMC_POWER_UP:
++ if (!IS_ERR(host->vmmc)) {
++ mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd);
++ udelay(200);
++ }
++
++ err = sunxi_mmc_init_host(mmc);
++ if (err) {
++ host->ferror = 1;
++ return;
++ }
++ enable_irq(host->irq);
++
++ dev_dbg(mmc_dev(host->mmc), "power on!\n");
++ host->ferror = 0;
++ break;
++
++ case MMC_POWER_OFF:
++ dev_dbg(mmc_dev(host->mmc), "power off!\n");
++ disable_irq(host->irq);
++ sunxi_mmc_exit_host(host);
++ if (!IS_ERR(host->vmmc))
++ mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
++ host->ferror = 0;
++ break;
++ }
++
++ /* set bus width */
++ switch (ios->bus_width) {
++ case MMC_BUS_WIDTH_1:
++ mci_writel(host, REG_WIDTH, SDXC_WIDTH1);
++ host->bus_width = 1;
++ break;
++ case MMC_BUS_WIDTH_4:
++ mci_writel(host, REG_WIDTH, SDXC_WIDTH4);
++ host->bus_width = 4;
++ break;
++ case MMC_BUS_WIDTH_8:
++ mci_writel(host, REG_WIDTH, SDXC_WIDTH8);
++ host->bus_width = 8;
++ break;
++ }
++
++ /* set ddr mode */
++ temp = mci_readl(host, REG_GCTRL);
++ if (ios->timing == MMC_TIMING_UHS_DDR50) {
++ temp |= SDXC_DDR_MODE;
++ host->ddr = 1;
++ } else {
++ temp &= ~SDXC_DDR_MODE;
++ host->ddr = 0;
++ }
++ mci_writel(host, REG_GCTRL, temp);
++
++ /* set up clock */
++ if (ios->clock && ios->power_mode) {
++ dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock);
++ sunxi_mmc_clk_set_rate(host, ios->clock);
++ usleep_range(50000, 55000);
++ }
++}
++
++static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
++ unsigned long flags;
++ int ret;
++ u32 imask;
++
++ spin_lock_irqsave(&smc_host->lock, flags);
++
++ /* Make sure the controller is in a sane state before enabling irqs */
++ ret = sunxi_mmc_init_host(host->mmc);
++ if (ret) {
++ spin_unlock_irqrestore(&smc_host->lock, flags);
++ return ret;
++ }
++
++ imask = mci_readl(smc_host, REG_IMASK);
++ if (enable) {
++ smc_host->sdio_imask = SDXC_SDIO_INTERRUPT;
++ imask |= SDXC_SDIO_INTERRUPT;
++ } else {
++ smc_host->sdio_imask = 0;
++ imask &= ~SDXC_SDIO_INTERRUPT;
++ }
++ mci_writel(smc_host, REG_IMASK, imask);
++ spin_unlock_irqrestore(&smc_host->lock, flags);
++}
++
++static void sunxi_mmc_hw_reset(struct mmc_host *mmc)
++{
++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
++ mci_writel(smc_host, REG_HWRST, 0);
++ udelay(10);
++ mci_writel(smc_host, REG_HWRST, 1);
++ udelay(300);
++}
++
++static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct sunxi_mmc_host *host = mmc_priv(mmc);
++ struct mmc_command *cmd = mrq->cmd;
++ struct mmc_data *data = mrq->data;
++ unsigned long iflags;
++ u32 imask = SDXC_INTERRUPT_ERROR_BIT;
++ u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f);
++ u32 byte_cnt = 0;
++ int ret;
++
++ if (!mmc_gpio_get_cd(mmc) || host->ferror) {
++ dev_dbg(mmc_dev(host->mmc), "no medium present\n");
++ mrq->cmd->error = -ENOMEDIUM;
++ mmc_request_done(mmc, mrq);
++ return;
++ }
++
++ if (data) {
++ byte_cnt = data->blksz * data->blocks;
++ mci_writel(host, REG_BLKSZ, data->blksz);
++ mci_writel(host, REG_BCNTR, byte_cnt);
++ ret = sunxi_mmc_prepare_dma(host, data);
++ if (ret < 0) {
++ dev_err(mmc_dev(host->mmc), "prepare DMA failed\n");
++ cmd->error = ret;
++ cmd->data->error = ret;
++ mmc_request_done(host->mmc, mrq);
++ return;
++ }
++ }
++
++ if (cmd->opcode == MMC_GO_IDLE_STATE) {
++ cmd_val |= SDXC_SEND_INIT_SEQUENCE;
++ imask |= SDXC_COMMAND_DONE;
++ }
++
++ if (cmd->opcode == SD_SWITCH_VOLTAGE) {
++ cmd_val |= SDXC_VOLTAGE_SWITCH;
++ imask |= SDXC_VOLTAGE_CHANGE_DONE;
++ host->voltage_switching = 1;
++ sunxi_mmc_oclk_onoff(host, 1);
++ }
++
++ if (cmd->flags & MMC_RSP_PRESENT) {
++ cmd_val |= SDXC_RESPONSE_EXPIRE;
++ if (cmd->flags & MMC_RSP_136)
++ cmd_val |= SDXC_LONG_RESPONSE;
++ if (cmd->flags & MMC_RSP_CRC)
++ cmd_val |= SDXC_CHECK_RESPONSE_CRC;
++
++ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) {
++ cmd_val |= SDXC_DATA_EXPIRE | SDXC_WAIT_PRE_OVER;
++ if (cmd->data->flags & MMC_DATA_STREAM) {
++ imask |= SDXC_AUTO_COMMAND_DONE;
++ cmd_val |= SDXC_SEQUENCE_MODE | SDXC_SEND_AUTO_STOP;
++ }
++ if (cmd->data->stop) {
++ imask |= SDXC_AUTO_COMMAND_DONE;
++ cmd_val |= SDXC_SEND_AUTO_STOP;
++ } else
++ imask |= SDXC_DATA_OVER;
++
++ if (cmd->data->flags & MMC_DATA_WRITE)
++ cmd_val |= SDXC_WRITE;
++ else
++ host->wait_dma = 1;
++ } else
++ imask |= SDXC_COMMAND_DONE;
++ } else
++ imask |= SDXC_COMMAND_DONE;
++
++ dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n",
++ cmd_val & 0x3f, cmd_val, cmd->arg, imask,
++ mrq->data ? mrq->data->blksz * mrq->data->blocks : 0);
++
++ spin_lock_irqsave(&host->lock, iflags);
++ host->mrq = mrq;
++ mci_writel(host, REG_IMASK, host->sdio_imask | imask);
++ spin_unlock_irqrestore(&host->lock, iflags);
++
++ mci_writel(host, REG_CARG, cmd->arg);
++ mci_writel(host, REG_CMDR, cmd_val);
++}
++
++static const struct of_device_id sunxi_mmc_of_match[] = {
++ { .compatible = "allwinner,sun4i-a10-mmc", },
++ { .compatible = "allwinner,sun5i-a13-mmc", },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
++
++static struct mmc_host_ops sunxi_mmc_ops = {
++ .request = sunxi_mmc_request,
++ .set_ios = sunxi_mmc_set_ios,
++ .get_ro = mmc_gpio_get_ro,
++ .get_cd = mmc_gpio_get_cd,
++ .enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
++ .hw_reset = sunxi_mmc_hw_reset,
++};
++
++static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
++ struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ int ret;
++
++ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc"))
++ host->idma_des_size_bits = 13;
++ else
++ host->idma_des_size_bits = 16;
++
++ host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc");
++ if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
++ host->reg_base = devm_ioremap_resource(&pdev->dev,
++ platform_get_resource(pdev, IORESOURCE_MEM, 0));
++ if (IS_ERR(host->reg_base))
++ return PTR_ERR(host->reg_base);
++
++ host->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
++ if (IS_ERR(host->clk_ahb)) {
++ dev_err(&pdev->dev, "Could not get ahb clock\n");
++ return PTR_ERR(host->clk_ahb);
++ }
++
++ host->clk_mod = devm_clk_get(&pdev->dev, "mod");
++ if (IS_ERR(host->clk_mod)) {
++ dev_err(&pdev->dev, "Could not get mod clock\n");
++ return PTR_ERR(host->clk_mod);
++ }
++
++ /* Make sure the controller is in a sane state before enabling irqs */
++ ret = sunxi_mmc_init_host(host->mmc);
++ if (ret)
++ return ret;
++
++ host->irq = platform_get_irq(pdev, 0);
++ ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0,
++ "sunxi-mmc", host);
++ if (ret == 0)
++ disable_irq(host->irq);
++
++ /* And put it back in reset */
++ sunxi_mmc_exit_host(host);
++
++ return ret;
++}
++
++static int sunxi_mmc_probe(struct platform_device *pdev)
++{
++ struct sunxi_mmc_host *host;
++ struct mmc_host *mmc;
++ int ret;
++
++ mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
++ if (!mmc) {
++ dev_err(&pdev->dev, "mmc alloc host failed\n");
++ return -ENOMEM;
++ }
++
++ ret = mmc_of_parse(mmc);
++ if (ret)
++ goto error_free_host;
++
++ host = mmc_priv(mmc);
++ host->mmc = mmc;
++ spin_lock_init(&host->lock);
++ tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host);
++
++ ret = sunxi_mmc_resource_request(host, pdev);
++ if (ret)
++ goto error_free_host;
++
++ host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
++ &host->sg_dma, GFP_KERNEL);
++ if (!host->sg_cpu) {
++ dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n");
++ ret = -ENOMEM;
++ goto error_free_host;
++ }
++
++ mmc->ops = &sunxi_mmc_ops;
++ mmc->max_blk_count = 8192;
++ mmc->max_blk_size = 4096;
++ mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des);
++ mmc->max_seg_size = (1 << host->idma_des_size_bits);
++ mmc->max_req_size = mmc->max_seg_size * mmc->max_segs;
++ /* 400kHz ~ 50MHz */
++ mmc->f_min = 400000;
++ mmc->f_max = 50000000;
++ /* available voltages */
++ if (!IS_ERR(host->vmmc))
++ mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc);
++ else
++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++
++ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
++ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
++ MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_DRIVER_TYPE_A;
++ mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
++
++ ret = mmc_add_host(mmc);
++
++ if (ret)
++ goto error_free_dma;
++
++ dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq);
++ platform_set_drvdata(pdev, mmc);
++ return 0;
++
++error_free_dma:
++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
++error_free_host:
++ mmc_free_host(mmc);
++ return ret;
++}
++
++static int sunxi_mmc_remove(struct platform_device *pdev)
++{
++ struct mmc_host *mmc = platform_get_drvdata(pdev);
++ struct sunxi_mmc_host *host = mmc_priv(mmc);
++
++ mmc_remove_host(mmc);
++ sunxi_mmc_exit_host(host);
++ tasklet_disable(&host->tasklet);
++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
++ mmc_free_host(mmc);
++
++ return 0;
++}
++
++static struct platform_driver sunxi_mmc_driver = {
++ .driver = {
++ .name = "sunxi-mmc",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(sunxi_mmc_of_match),
++ },
++ .probe = sunxi_mmc_probe,
++ .remove = sunxi_mmc_remove,
++};
++module_platform_driver(sunxi_mmc_driver);
++
++MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>");
++MODULE_ALIAS("platform:sunxi-mmc");
+diff --git a/drivers/mmc/host/sunxi-mmc.h b/drivers/mmc/host/sunxi-mmc.h
+new file mode 100644
+index 0000000..cbd6d49
+--- /dev/null
++++ b/drivers/mmc/host/sunxi-mmc.h
+@@ -0,0 +1,239 @@
++/*
++ * Driver for sunxi SD/MMC host controllers
++ * (C) Copyright 2014-2015 Reuuimlla Technology Co., Ltd.
++ * (C) Copyright 2014-2015 Aaron Maoye <leafy.myeh@reuuimllatech.com>
++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch>
++ * (C) Copyright 2014-2015 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
++ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ */
++
++#ifndef __SUNXI_MCI_H__
++#define __SUNXI_MCI_H__
++
++/* register offset define */
++#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */
++#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */
++#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */
++#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */
++#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */
++#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */
++#define SDXC_REG_CMDR (0x18) /* SMC Command Register */
++#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */
++#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */
++#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */
++#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */
++#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */
++#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */
++#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */
++#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */
++#define SDXC_REG_STAS (0x3C) /* SMC Status Register */
++#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */
++#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */
++#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */
++#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */
++#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */
++#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */
++#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */
++#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */
++#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */
++#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */
++#define SDXC_REG_CHDA (0x90)
++#define SDXC_REG_CBDA (0x94)
++
++#define mci_readl(host, reg) \
++ readl((host)->reg_base + SDXC_##reg)
++#define mci_writel(host, reg, value) \
++ writel((value), (host)->reg_base + SDXC_##reg)
++
++/* global control register bits */
++#define SDXC_SOFT_RESET BIT(0)
++#define SDXC_FIFO_RESET BIT(1)
++#define SDXC_DMA_RESET BIT(2)
++#define SDXC_HARDWARE_RESET (SDXC_SOFT_RESET|SDXC_FIFO_RESET|SDXC_DMA_RESET)
++#define SDXC_INTERRUPT_ENABLE_BIT BIT(4)
++#define SDXC_DMA_ENABLE_BIT BIT(5)
++#define SDXC_DEBOUNCE_ENABLE_BIT BIT(8)
++#define SDXC_POSEDGE_LATCH_DATA BIT(9)
++#define SDXC_DDR_MODE BIT(10)
++#define SDXC_MEMORY_ACCESS_DONE BIT(29)
++#define SDXC_ACCESS_DONE_DIRECT BIT(30)
++#define SDXC_ACCESS_BY_AHB BIT(31)
++#define SDXC_ACCESS_BY_DMA (0U << 31)
++/* clock control bits */
++#define SDXC_CARD_CLOCK_ON BIT(16)
++#define SDXC_LOW_POWER_ON BIT(17)
++/* bus width */
++#define SDXC_WIDTH1 (0)
++#define SDXC_WIDTH4 (1)
++#define SDXC_WIDTH8 (2)
++/* smc command bits */
++#define SDXC_RESPONSE_EXPIRE BIT(6)
++#define SDXC_LONG_RESPONSE BIT(7)
++#define SDXC_CHECK_RESPONSE_CRC BIT(8)
++#define SDXC_DATA_EXPIRE BIT(9)
++#define SDXC_WRITE BIT(10)
++#define SDXC_SEQUENCE_MODE BIT(11)
++#define SDXC_SEND_AUTO_STOP BIT(12)
++#define SDXC_WAIT_PRE_OVER BIT(13)
++#define SDXC_STOP_ABORT_CMD BIT(14)
++#define SDXC_SEND_INIT_SEQUENCE BIT(15)
++#define SDXC_UPCLK_ONLY BIT(21)
++#define SDXC_READ_CEATA_DEV BIT(22)
++#define SDXC_CCS_EXPIRE BIT(23)
++#define SDXC_ENABLE_BIT_BOOT BIT(24)
++#define SDXC_ALT_BOOT_OPTIONS BIT(25)
++#define SDXC_BOOT_ACK_EXPIRE BIT(26)
++#define SDXC_BOOT_ABORT BIT(27)
++#define SDXC_VOLTAGE_SWITCH BIT(28)
++#define SDXC_USE_HOLD_REGISTER BIT(29)
++#define SDXC_START BIT(31)
++/* interrupt bits */
++#define SDXC_RESPONSE_ERROR BIT(1)
++#define SDXC_COMMAND_DONE BIT(2)
++#define SDXC_DATA_OVER BIT(3)
++#define SDXC_TX_DATA_REQUEST BIT(4)
++#define SDXC_RX_DATA_REQUEST BIT(5)
++#define SDXC_RESPONSE_CRC_ERROR BIT(6)
++#define SDXC_DATA_CRC_ERROR BIT(7)
++#define SDXC_RESPONSE_TIMEOUT BIT(8)
++#define SDXC_DATA_TIMEOUT BIT(9)
++#define SDXC_VOLTAGE_CHANGE_DONE BIT(10)
++#define SDXC_FIFO_RUN_ERROR BIT(11)
++#define SDXC_HARD_WARE_LOCKED BIT(12)
++#define SDXC_START_BIT_ERROR BIT(13)
++#define SDXC_AUTO_COMMAND_DONE BIT(14)
++#define SDXC_END_BIT_ERROR BIT(15)
++#define SDXC_SDIO_INTERRUPT BIT(16)
++#define SDXC_CARD_INSERT BIT(30)
++#define SDXC_CARD_REMOVE BIT(31)
++#define SDXC_INTERRUPT_ERROR_BIT (SDXC_RESPONSE_ERROR | SDXC_RESPONSE_CRC_ERROR | \
++ SDXC_DATA_CRC_ERROR | SDXC_RESPONSE_TIMEOUT | \
++ SDXC_DATA_TIMEOUT | SDXC_FIFO_RUN_ERROR | \
++ SDXC_HARD_WARE_LOCKED | SDXC_START_BIT_ERROR | \
++ SDXC_END_BIT_ERROR) /* 0xbbc2 */
++#define SDXC_INTERRUPT_DONE_BIT (SDXC_AUTO_COMMAND_DONE | SDXC_DATA_OVER | \
++ SDXC_COMMAND_DONE | SDXC_VOLTAGE_CHANGE_DONE)
++/* status */
++#define SDXC_RXWL_FLAG BIT(0)
++#define SDXC_TXWL_FLAG BIT(1)
++#define SDXC_FIFO_EMPTY BIT(2)
++#define SDXC_FIFO_FULL BIT(3)
++#define SDXC_CARD_PRESENT BIT(8)
++#define SDXC_CARD_DATA_BUSY BIT(9)
++#define SDXC_DATA_FSM_BUSY BIT(10)
++#define SDXC_DMA_REQUEST BIT(31)
++#define SDXC_FIFO_SIZE (16)
++/* Function select */
++#define SDXC_CEATA_ON (0xceaaU << 16)
++#define SDXC_SEND_IRQ_RESPONSE BIT(0)
++#define SDXC_SDIO_READ_WAIT BIT(1)
++#define SDXC_ABORT_READ_DATA BIT(2)
++#define SDXC_SEND_CCSD BIT(8)
++#define SDXC_SEND_AUTO_STOPCCSD BIT(9)
++#define SDXC_CEATA_DEV_INTERRUPT_ENABLE_BIT BIT(10)
++/* IDMA controller bus mod bit field */
++#define SDXC_IDMAC_SOFT_RESET BIT(0)
++#define SDXC_IDMAC_FIX_BURST BIT(1)
++#define SDXC_IDMAC_IDMA_ON BIT(7)
++#define SDXC_IDMAC_REFETCH_DES BIT(31)
++/* IDMA status bit field */
++#define SDXC_IDMAC_TRANSMIT_INTERRUPT BIT(0)
++#define SDXC_IDMAC_RECEIVE_INTERRUPT BIT(1)
++#define SDXC_IDMAC_FATAL_BUS_ERROR BIT(2)
++#define SDXC_IDMAC_DESTINATION_INVALID BIT(4)
++#define SDXC_IDMAC_CARD_ERROR_SUM BIT(5)
++#define SDXC_IDMAC_NORMAL_INTERRUPT_SUM BIT(8)
++#define SDXC_IDMAC_ABNORMAL_INTERRUPT_SUM BIT(9)
++#define SDXC_IDMAC_HOST_ABORT_INTERRUPT_TX BIT(10)
++#define SDXC_IDMAC_HOST_ABORT_INTERRUPT_RX BIT(10)
++#define SDXC_IDMAC_IDLE (0U << 13)
++#define SDXC_IDMAC_SUSPEND (1U << 13)
++#define SDXC_IDMAC_DESC_READ (2U << 13)
++#define SDXC_IDMAC_DESC_CHECK (3U << 13)
++#define SDXC_IDMAC_READ_REQUEST_WAIT (4U << 13)
++#define SDXC_IDMAC_WRITE_REQUEST_WAIT (5U << 13)
++#define SDXC_IDMAC_READ (6U << 13)
++#define SDXC_IDMAC_WRITE (7U << 13)
++#define SDXC_IDMAC_DESC_CLOSE (8U << 13)
++
++/*
++* If the idma-des-size-bits of property is ie 13, bufsize bits are:
++* Bits 0-12: buf1 size
++* Bits 13-25: buf2 size
++* Bits 26-31: not used
++* Since we only ever set buf1 size, we can simply store it directly.
++*/
++#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */
++#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */
++#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */
++#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */
++#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */
++#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */
++#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */
++
++struct sunxi_idma_des {
++ u32 config;
++ u32 buf_size;
++ u32 buf_addr_ptr1;
++ u32 buf_addr_ptr2;
++};
++
++struct sunxi_mmc_host {
++ struct mmc_host *mmc;
++ struct regulator *vmmc;
++
++ /* IO mapping base */
++ void __iomem *reg_base;
++
++ spinlock_t lock;
++ struct tasklet_struct tasklet;
++
++ /* clock management */
++ struct clk *clk_ahb;
++ struct clk *clk_mod;
++
++ /* ios information */
++ u32 clk_mod_rate;
++ u32 bus_width;
++ u32 idma_des_size_bits;
++ u32 ddr;
++ u32 voltage_switching;
++
++ /* irq */
++ int irq;
++ u32 int_sum;
++ u32 sdio_imask;
++
++ /* flags */
++ u32 power_on:1;
++ u32 io_flag:1;
++ u32 wait_dma:1;
++
++ dma_addr_t sg_dma;
++ void *sg_cpu;
++
++ struct mmc_request *mrq;
++ u32 ferror;
++};
++
++#define MMC_CLK_400K 0
++#define MMC_CLK_25M 1
++#define MMC_CLK_50M 2
++#define MMC_CLK_50MDDR 3
++#define MMC_CLK_50MDDR_8BIT 4
++#define MMC_CLK_100M 5
++#define MMC_CLK_200M 6
++#define MMC_CLK_MOD_NUM 7
++
++struct sunxi_mmc_clk_dly {
++ u32 mode;
++ u32 oclk_dly;
++ u32 sclk_dly;
++};
++
++#endif
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch b/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch
new file mode 100644
index 0000000000..e9685768c8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch
@@ -0,0 +1,56 @@
+From 40889884d53094fe9987a45f9df99fdf1f311910 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 16 Feb 2014 10:47:51 +0100
+Subject: [PATCH] sunxi-mmc: Simplify clk delay setting
+
+clk_sunxi_mmc_phase_control() does its own locking, so there is no need to
+lock at the host. Without the locking having a separate sunxi_mmc_set_clk_dly()
+makes no sense, so simply call clk_sunxi_mmc_phase_control() directly.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 14 ++------------
+ 1 file changed, 2 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index f33bc30..f4bfaf0 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -420,17 +420,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
+ }
+ }
+
+-static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
+- u32 oclk_dly, u32 sclk_dly)
+-{
+- unsigned long iflags;
+- struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
+-
+- spin_lock_irqsave(&smc_host->lock, iflags);
+- clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
+- spin_unlock_irqrestore(&smc_host->lock, iflags);
+-}
+-
+ struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
+ { MMC_CLK_400K, 0, 7 },
+ { MMC_CLK_25M, 0, 5 },
+@@ -450,6 +439,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
+ u32 sclk_dly;
+ u32 temp;
+ struct sunxi_mmc_clk_dly *dly = NULL;
++ struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
+
+ newrate = clk_round_rate(smc_host->clk_mod, rate);
+ if (smc_host->clk_mod_rate == newrate) {
+@@ -508,7 +498,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
+ sclk_dly--;
+ }
+
+- sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
++ clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
+ sunxi_mmc_oclk_onoff(smc_host, 1);
+
+ /* oclk_onoff sets various irq status bits, clear these */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch b/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch
new file mode 100644
index 0000000000..843d39ef62
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch
@@ -0,0 +1,49 @@
+From 0a6ec6db90c73b037428bf3a94a6281754007c25 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 16:55:54 +0100
+Subject: [PATCH] sunxi-mmc: Don't set mmc clk in low power mode
+
+The android driver uses an io-flag to descern whether a controller is
+hooked up to a sdcard slot, or to an onboard sdio dev. And for sdcard slots
+it sets the clock in a low-power mode.
+
+This is causing transmission errors when talking to the sdio-wifi on the
+cubietruck, and this may be the cause of problems with some type sdcards
+too. This patch fixes things by simply never setting the clk in low power
+mode.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 3 ---
+ drivers/mmc/host/sunxi-mmc.h | 1 -
+ 2 files changed, 4 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index f4bfaf0..c1a9d8a 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -400,9 +400,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
+ if (oclk_en)
+ rval |= SDXC_CARD_CLOCK_ON;
+
+- if (!host->io_flag)
+- rval |= SDXC_LOW_POWER_ON;
+-
+ mci_writel(host, REG_CLKCR, rval);
+
+ rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER;
+diff --git a/drivers/mmc/host/sunxi-mmc.h b/drivers/mmc/host/sunxi-mmc.h
+index cbd6d49..a738850 100644
+--- a/drivers/mmc/host/sunxi-mmc.h
++++ b/drivers/mmc/host/sunxi-mmc.h
+@@ -211,7 +211,6 @@ struct sunxi_mmc_host {
+
+ /* flags */
+ u32 power_on:1;
+- u32 io_flag:1;
+ u32 wait_dma:1;
+
+ dma_addr_t sg_dma;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch b/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch
new file mode 100644
index 0000000000..2ff34be50c
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch
@@ -0,0 +1,32 @@
+From 3ec947a9717509e204c7f09609717951beb7ef04 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 17:11:58 +0100
+Subject: [PATCH] sunxi-mmc: Stop claiming UHS modes
+
+UHS requires a regulator to set the signaling voltage, as well as special
+code to handle the signal voltage switching. We've never added the code
+for this from the android driver to the upstream driver, so stop claiming
+support for this.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index c1a9d8a..2eaed10 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -803,8 +803,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+- MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
+- MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_DRIVER_TYPE_A;
++ MMC_CAP_SDIO_IRQ;
+ mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
+
+ ret = mmc_add_host(mmc);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch b/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch
new file mode 100644
index 0000000000..9118563053
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch
@@ -0,0 +1,34 @@
+From dffb4d4d1fe3a6ba93102756152ec4518dbeac00 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 17:13:19 +0100
+Subject: [PATCH] sunxi-mmc: Or in caps, rather then overriding them
+
+Now that we use mmc_of_parse() there are already some caps set by mmc_of_parse,
+so or in our driver caps, rather then using an assignment. This fixes the
+card running only in 1 bit mode instead of 4 bit mode problem we've had
+since we switched to using mmc_of_parse().
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index 2eaed10..d5e8ff9 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -802,9 +802,9 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
+ else
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+- mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+ MMC_CAP_SDIO_IRQ;
+- mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
++ mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
+
+ ret = mmc_add_host(mmc);
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch b/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch
new file mode 100644
index 0000000000..21aee136c5
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch
@@ -0,0 +1,45 @@
+From 73797537f3904fec60a647b3b209bf7add092ad5 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 21:59:08 +0100
+Subject: [PATCH] sunxi-mmc: Don't call mmc_of_parse until we're ready to
+
+mmc_of_parse registers an irq handler for the gpio pins for cd, this irq
+handler will reference host->ops, so don't call mmc_of_parse until we're
+done setting everything up.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index d5e8ff9..cceae68 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -766,10 +766,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
+- ret = mmc_of_parse(mmc);
+- if (ret)
+- goto error_free_host;
+-
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ spin_lock_init(&host->lock);
+@@ -806,8 +802,11 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
+ MMC_CAP_SDIO_IRQ;
+ mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
+
+- ret = mmc_add_host(mmc);
++ ret = mmc_of_parse(mmc);
++ if (ret)
++ goto error_free_dma;
+
++ ret = mmc_add_host(mmc);
+ if (ret)
+ goto error_free_dma;
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch b/target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch
index 6601ebbf7b..f9cdcc67ec 100644
--- a/target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch
+++ b/target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch
@@ -1,4 +1,4 @@
-From a8cfe8ebdb18e6724b6520e08602b8e72e762ab9 Mon Sep 17 00:00:00 2001
+From 7bd0d82ef525e8949425fe271fb86eacf3822821 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 15 Dec 2013 19:44:01 +0100
Subject: [PATCH] ARM: sunxi: clk: export clk_sunxi_mmc_phase_control
@@ -9,6 +9,9 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 file changed, 22 insertions(+)
create mode 100644 include/linux/clk/sunxi.h
+diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
+new file mode 100644
+index 0000000..1ef5c89
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
@@ -34,3 +37,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
+
+#endif
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch b/target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch
index e31358b742..f3b7f5ae91 100644
--- a/target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch
+++ b/target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch
@@ -1,4 +1,4 @@
-From 4f43ab43125a12dbc23e352ac0eb4fd80a876fb5 Mon Sep 17 00:00:00 2001
+From fcba369ee1af8657353bb1e37807aa492c462263 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Fri, 20 Sep 2013 20:29:17 -0300
Subject: [PATCH] clk: sunxi: Implement MMC phase control
@@ -11,9 +11,11 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar>
drivers/clk/sunxi/clk-sunxi.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 3283179..46a38b4 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
-@@ -361,6 +361,41 @@ static void sun4i_get_mod0_factors(u32 *
+@@ -500,6 +500,41 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
/**
@@ -55,3 +57,6 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar>
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch b/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch
new file mode 100644
index 0000000000..90727f3e0b
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch
@@ -0,0 +1,44 @@
+From 0483aa124d32bdcafc84623a31141a49e71cc72d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 16 Feb 2014 08:54:20 +0100
+Subject: [PATCH] sunxi-mmc: fixup: revert "add host initialization for when
+ the sdio irq is enabled"
+
+This is not necessary since when the host is not initialized at this point
+yet the irq line from the mmc controller is not enabled, so writing the
+host controller interrupt mask cannot cause interrupts at this point.
+
+More over doing this is wrong, as it leads to unbalanced calling of
+clk_prepare_enable and regulator_power_on.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/mmc/host/sunxi-mmc.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index 2dc446c..f33bc30 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -593,18 +593,9 @@ static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+ {
+ struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
+ unsigned long flags;
+- int ret;
+ u32 imask;
+
+ spin_lock_irqsave(&smc_host->lock, flags);
+-
+- /* Make sure the controller is in a sane state before enabling irqs */
+- ret = sunxi_mmc_init_host(host->mmc);
+- if (ret) {
+- spin_unlock_irqrestore(&smc_host->lock, flags);
+- return ret;
+- }
+-
+ imask = mci_readl(smc_host, REG_IMASK);
+ if (enable) {
+ smc_host->sdio_imask = SDXC_SDIO_INTERRUPT;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch b/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch
deleted file mode 100644
index f058f56f08..0000000000
--- a/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 109e7dc17a77f84d56e76dea873363a8262bc806 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Thu, 19 Sep 2013 21:59:32 +0200
-Subject: [PATCH] clk: sunxi: Add support for USB clocks
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/clk/sunxi/clk-sunxi.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/clk/sunxi/clk-sunxi.c
-+++ b/drivers/clk/sunxi/clk-sunxi.c
-@@ -705,6 +705,10 @@ static const struct gates_data sun4i_ahb
- .mask = {0x7F77FFF, 0x14FB3F},
- };
-
-+static const struct gates_data sun47i_usb_gates_data __initconst = {
-+ .mask = {0x1C0},
-+};
-+
- static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
- .mask = {0x147667e7, 0x185915},
- };
-@@ -1021,6 +1025,7 @@ static const struct of_device_id clk_mux
- static const struct of_device_id clk_gates_match[] __initconst = {
- {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
- {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
-+ {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
- {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
- {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
- {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
diff --git a/target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch b/target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch
index 1ee908164a..60c6448cd4 100644
--- a/target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch
+++ b/target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch
@@ -1,7 +1,7 @@
-From 33b0123664b627005728cfe7b1967b790392ceec Mon Sep 17 00:00:00 2001
+From 85f17a0d652853455ac633fc965cea8431038518 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 14 Dec 2013 17:20:13 +0100
-Subject: [PATCH] ARM: sunxi: fix sun5i-a13 port F multiplexing
+Subject: [PATCH] pinctrl-sunxi: Fix sun5i-a13 port F multiplexing
The correct value for selecting the mmc0 function on port F pins is 2 not 4,
as per the data-sheet:
@@ -13,9 +13,11 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
drivers/pinctrl/pinctrl-sunxi-pins.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
+diff --git a/drivers/pinctrl/pinctrl-sunxi-pins.h b/drivers/pinctrl/pinctrl-sunxi-pins.h
+index 6fd8d4d..3d60669 100644
--- a/drivers/pinctrl/pinctrl-sunxi-pins.h
+++ b/drivers/pinctrl/pinctrl-sunxi-pins.h
-@@ -1932,27 +1932,27 @@ static const struct sunxi_desc_pin sun5i
+@@ -1932,27 +1932,27 @@
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
@@ -49,3 +51,6 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
SUNXI_FUNCTION(0x0, "gpio_in"),
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch b/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch
new file mode 100644
index 0000000000..84710c6328
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch
@@ -0,0 +1,49 @@
+From 613c8489f6b576166aa31d32cbd573f6b7952e06 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 15 Feb 2014 12:58:17 +0100
+Subject: [PATCH] pinctrl-sunxi: Fix hang on gpio irq
+
+Our irq handler was missing chained_irq_enter / exit calls, causing a
+hard hang as soon as a gpio irq happened.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/pinctrl/pinctrl-sunxi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
+index 74635cc..cc9bd1b 100644
+--- a/drivers/pinctrl/pinctrl-sunxi.c
++++ b/drivers/pinctrl/pinctrl-sunxi.c
+@@ -13,6 +13,7 @@
+ #include <linux/io.h>
+ #include <linux/clk.h>
+ #include <linux/gpio.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+@@ -665,9 +666,12 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
+
+ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
+ {
++ struct irq_chip *chip = irq_get_chip(irq);
+ struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
+ const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
+
++ chained_irq_enter(chip, desc);
++
+ /* Clear all interrupts */
+ writel(reg, pctl->membase + IRQ_STATUS_REG);
+
+@@ -679,6 +683,7 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
+ generic_handle_irq(pin_irq);
+ }
+ }
++ chained_irq_exit(chip, desc);
+ }
+
+ static struct of_device_id sunxi_pinctrl_match[] = {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch b/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch
new file mode 100644
index 0000000000..f600a82c6c
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch
@@ -0,0 +1,26 @@
+From 9d506cbf0e7b0e017d78f244e2b4c0fc71206c6c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 15 Feb 2014 12:56:42 +0100
+Subject: [PATCH] pinctrl-sunxi: Fix masking when setting irq type
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/pinctrl/pinctrl-sunxi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
+index cc9bd1b..917af0a 100644
+--- a/drivers/pinctrl/pinctrl-sunxi.c
++++ b/drivers/pinctrl/pinctrl-sunxi.c
+@@ -583,7 +583,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
+ spin_lock_irqsave(&pctl->lock, flags);
+
+ regval = readl(pctl->membase + reg);
+- regval &= ~IRQ_CFG_IRQ_MASK;
++ regval &= ~(IRQ_CFG_IRQ_MASK << index);
+ writel(regval | (mode << index), pctl->membase + reg);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch b/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch
new file mode 100644
index 0000000000..182cf73b27
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch
@@ -0,0 +1,46 @@
+From a5f3d2672d5b9efe93be0bf66d69156bf806220b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 22:04:20 +0100
+Subject: [PATCH] pinctrl-sunxi: Fix interrupt register offset calculation
+
+This fixing setting the interrupt type for eints >= 8.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/pinctrl/pinctrl-sunxi.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
+index 01c494f..552b0e9 100644
+--- a/drivers/pinctrl/pinctrl-sunxi.h
++++ b/drivers/pinctrl/pinctrl-sunxi.h
+@@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin)
+
+ static inline u32 sunxi_irq_cfg_reg(u16 irq)
+ {
+- u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
++ u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
+ return reg + IRQ_CFG_REG;
+ }
+
+@@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
+
+ static inline u32 sunxi_irq_ctrl_reg(u16 irq)
+ {
+- u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
++ u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
+ return reg + IRQ_CTRL_REG;
+ }
+
+@@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
+
+ static inline u32 sunxi_irq_status_reg(u16 irq)
+ {
+- u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
++ u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
+ return reg + IRQ_STATUS_REG;
+ }
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch b/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch
deleted file mode 100644
index 00a95618f5..0000000000
--- a/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 6b5cb5cada555c90562aed82e8891439a35009ab Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Sun, 6 Oct 2013 14:04:50 +0200
-Subject: [PATCH] clk: sun5i: Add support for USB clocks
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/clk/sunxi/clk-sunxi.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/clk/sunxi/clk-sunxi.c
-+++ b/drivers/clk/sunxi/clk-sunxi.c
-@@ -709,6 +709,10 @@ static const struct gates_data sun47i_us
- .mask = {0x1C0},
- };
-
-+static const struct gates_data sun5i_usb_gates_data __initconst = {
-+ .mask = {0x140},
-+};
-+
- static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
- .mask = {0x147667e7, 0x185915},
- };
-@@ -1028,6 +1032,7 @@ static const struct of_device_id clk_gat
- {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
- {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
- {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
-+ {.compatible = "allwinner,sun5i-usb-gates-clk", .data = &sun5i_usb_gates_data,},
- {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
- {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
- {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
diff --git a/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch b/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch
deleted file mode 100644
index 8ff1fc5ce0..0000000000
--- a/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch
+++ /dev/null
@@ -1,493 +0,0 @@
-From 825ce97e1faa39bfd30c3dca95fba5eb021cb534 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Wed, 18 Sep 2013 21:45:03 +0200
-Subject: [PATCH] ARM: sunxi: usb: Add Allwinner sunXi EHCI driver
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-
-Conflicts:
- drivers/usb/host/Makefile
----
- drivers/usb/host/Kconfig | 9 +
- drivers/usb/host/Makefile | 1 +
- drivers/usb/host/ehci-sunxi.c | 446 ++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 456 insertions(+)
- create mode 100644 drivers/usb/host/ehci-sunxi.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -273,6 +273,15 @@ config USB_OCTEON_EHCI
- USB 2.0 device support. All CN6XXX based chips with USB are
- supported.
-
-+config USB_SUNXI_EHCI
-+ tristate "Allwinner sunXi EHCI support"
-+ depends on ARCH_SUNXI
-+ default n
-+ help
-+ Enable support for the Allwinner sunXi on-chip EHCI
-+ controller. It is needed for high-speed (480Mbit/sec)
-+ USB 2.0 device support.
-+
- endif # USB_EHCI_HCD
-
- config USB_OXU210HP_HCD
---- a/drivers/usb/host/Makefile
-+++ b/drivers/usb/host/Makefile
-@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-
- obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
- obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
- obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o
-+obj-$(CONFIG_USB_SUNXI_EHCI) += ehci-sunxi.o
-
- obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
- obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
---- /dev/null
-+++ b/drivers/usb/host/ehci-sunxi.c
-@@ -0,0 +1,446 @@
-+/*
-+ * Copyright (C) 2013 Roman Byshko
-+ *
-+ * Roman Byshko <rbyshko@gmail.com>
-+ *
-+ * Based on code from
-+ * Allwinner Technology Co., Ltd. <www.allwinnertech.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/clk.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/reset.h>
-+#include <linux/usb.h>
-+#include <linux/usb/hcd.h>
-+
-+#include "ehci.h"
-+
-+#define DRV_DESC "Allwinner sunXi EHCI driver"
-+#define DRV_NAME "sunxi-ehci"
-+
-+#define SUNXI_USB_PASSBY_EN 1
-+
-+#define SUNXI_EHCI_AHB_ICHR8_EN BIT(10)
-+#define SUNXI_EHCI_AHB_INCR4_BURST_EN BIT(9)
-+#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN BIT(8)
-+#define SUNXI_EHCI_ULPI_BYPASS_EN BIT(0)
-+
-+struct sunxi_ehci_hcd {
-+ struct clk *phy_clk;
-+ struct clk *ahb_ehci_clk;
-+ struct reset_control *reset;
-+ struct regulator *vbus_reg;
-+ void __iomem *csr;
-+ void __iomem *pmuirq;
-+ int irq;
-+ int id;
-+};
-+
-+
-+static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci,u32 addr, u32 data, u32 len)
-+{
-+ u32 j = 0;
-+ u32 temp = 0;
-+ u32 usbc_bit = 0;
-+ void __iomem *dest = sunxi_ehci->csr;
-+
-+ usbc_bit = BIT(sunxi_ehci->id << 1);
-+
-+ for (j = 0; j < len; j++) {
-+ temp = readl(dest);
-+
-+ /* clear the address portion */
-+ temp &= ~(0xff << 8);
-+
-+ /* set the address */
-+ temp |= ((addr + j) << 8);
-+ writel(temp, dest);
-+
-+ /* set the data bit and clear usbc bit*/
-+ temp = readb(dest);
-+ if (data & 0x1)
-+ temp |= BIT(7);
-+ else
-+ temp &= ~BIT(7);
-+ temp &= ~usbc_bit;
-+ writeb(temp, dest);
-+
-+ /* flip usbc_bit */
-+ __set_bit(usbc_bit, dest);
-+ __clear_bit(usbc_bit, dest);
-+
-+ data >>= 1;
-+ }
-+}
-+
-+/* FIXME: should this function be protected by a lock?
-+ * ehci1 and ehci0 could call it concurrently with same csr.
-+ */
-+static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci)
-+{
-+ /* The following comments are machine
-+ * translated from Chinese, you have been warned!
-+ */
-+
-+ /* adjust PHY's magnitude and rate */
-+ usb_phy_write(sunxi_ehci, 0x20, 0x14, 5);
-+
-+ /* threshold adjustment disconnect */
-+ usb_phy_write(sunxi_ehci, 0x2a, 3, 2);
-+
-+ return;
-+}
-+
-+static void sunxi_usb_passby(struct sunxi_ehci_hcd *sunxi_ehci, int enable)
-+{
-+ unsigned long reg_value = 0;
-+ unsigned long bits = 0;
-+ static DEFINE_SPINLOCK(lock);
-+ unsigned long flags = 0;
-+ void __iomem *addr = sunxi_ehci->pmuirq;
-+
-+ bits = SUNXI_EHCI_AHB_ICHR8_EN |
-+ SUNXI_EHCI_AHB_INCR4_BURST_EN |
-+ SUNXI_EHCI_AHB_INCRX_ALIGN_EN |
-+ SUNXI_EHCI_ULPI_BYPASS_EN;
-+
-+ spin_lock_irqsave(&lock, flags);
-+
-+ reg_value = readl(addr);
-+
-+ if (enable)
-+ reg_value |= bits;
-+ else
-+ reg_value &= ~bits;
-+
-+ writel(reg_value, addr);
-+
-+ spin_unlock_irqrestore(&lock, flags);
-+
-+ return;
-+}
-+
-+static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci)
-+{
-+ regulator_disable(sunxi_ehci->vbus_reg);
-+
-+ sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN);
-+
-+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
-+ clk_disable_unprepare(sunxi_ehci->phy_clk);
-+
-+ reset_control_assert(sunxi_ehci->reset);
-+}
-+
-+static int sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci)
-+{
-+ int ret;
-+
-+ ret = clk_prepare_enable(sunxi_ehci->phy_clk);
-+ if (ret)
-+ return ret;
-+
-+ ret = reset_control_deassert(sunxi_ehci->reset);
-+ if (ret)
-+ goto fail1;
-+
-+ ret = clk_prepare_enable(sunxi_ehci->ahb_ehci_clk);
-+ if (ret)
-+ goto fail2;
-+
-+ sunxi_usb_phy_init(sunxi_ehci);
-+
-+ sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN);
-+
-+ ret = regulator_enable(sunxi_ehci->vbus_reg);
-+ if (ret)
-+ goto fail3;
-+
-+ return 0;
-+
-+fail3:
-+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
-+fail2:
-+ reset_control_assert(sunxi_ehci->reset);
-+fail1:
-+ clk_disable_unprepare(sunxi_ehci->phy_clk);
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_PM
-+static int sunxi_ehci_suspend(struct device *dev)
-+{
-+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
-+ struct usb_hcd *hcd = dev_get_drvdata(dev);
-+ int ret;
-+
-+ bool do_wakeup = device_may_wakeup(dev);
-+
-+ ret = ehci_suspend(hcd, do_wakeup);
-+
-+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
-+
-+ sunxi_ehci_disable(sunxi_ehci);
-+
-+ return ret;
-+}
-+
-+static int sunxi_ehci_resume(struct device *dev)
-+{
-+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
-+ struct usb_hcd *hcd = dev_get_drvdata(dev);
-+ int ret;
-+
-+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
-+
-+ ret = sunxi_ehci_enable(sunxi_ehci);
-+ if (ret)
-+ return ret;
-+
-+ return ehci_resume(hcd, false);
-+}
-+
-+
-+static const struct dev_pm_ops sunxi_ehci_pmops = {
-+ .suspend = sunxi_ehci_suspend,
-+ .resume = sunxi_ehci_resume,
-+};
-+
-+#define SUNXI_EHCI_PMOPS (&sunxi_ehci_pmops)
-+#else /* !CONFIG_PM */
-+#define SUNXI_EHCI_PMOPS NULL
-+#endif /* CONFIG_PM */
-+
-+static const struct ehci_driver_overrides sunxi_overrides __initconst = {
-+ .reset = NULL,
-+ .extra_priv_size = sizeof(struct sunxi_ehci_hcd),
-+};
-+
-+/* FIXME: Should there be two instances of hc_driver,
-+ * or one is enough to handle two EHCI controllers? */
-+static struct hc_driver __read_mostly sunxi_ehci_hc_driver;
-+
-+static int sunxi_ehci_init(struct platform_device *pdev, struct usb_hcd *hcd,
-+ struct sunxi_ehci_hcd *sunxi_ehci)
-+{
-+ void __iomem *ehci_regs = NULL;
-+ struct resource *res = NULL;
-+
-+ sunxi_ehci->vbus_reg = devm_regulator_get(&pdev->dev, "vbus");
-+ if (IS_ERR(sunxi_ehci->vbus_reg)) {
-+ if (PTR_ERR(sunxi_ehci->vbus_reg) == -EPROBE_DEFER)
-+ return -EPROBE_DEFER;
-+
-+ dev_info(&pdev->dev, "no USB VBUS power supply found\n");
-+ }
-+
-+ sunxi_ehci->id = of_alias_get_id(pdev->dev.of_node, "ehci");
-+ if (sunxi_ehci->id < 0)
-+ return sunxi_ehci->id;
-+
-+ /* FIXME: should res be freed on some failure? */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to get I/O memory\n");
-+ return -ENXIO;
-+ }
-+ ehci_regs = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(ehci_regs))
-+ return PTR_ERR(ehci_regs);
-+
-+ hcd->rsrc_start = res->start;
-+ hcd->rsrc_len = resource_size(res);
-+ hcd->regs = ehci_regs;
-+ hcd_to_ehci(hcd)->caps = ehci_regs;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to get I/O memory\n");
-+ return -ENXIO;
-+ }
-+ sunxi_ehci->pmuirq = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(sunxi_ehci->pmuirq))
-+ return PTR_ERR(sunxi_ehci->pmuirq);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to get I/O memory\n");
-+ return -ENXIO;
-+ }
-+
-+ /* FIXME: this one byte needs to be shared between both EHCIs,
-+ * that is why ioremap instead of devm_ioremap_resource,
-+ * memory is not unmaped back for now.
-+ */
-+ sunxi_ehci->csr = ioremap(res->start, resource_size(res));
-+ if (IS_ERR(sunxi_ehci->csr)) {
-+ dev_err(&pdev->dev, "failed to remap memory\n");
-+ return PTR_ERR(sunxi_ehci->csr);
-+ }
-+
-+ sunxi_ehci->irq = platform_get_irq(pdev, 0);
-+ if (!sunxi_ehci->irq) {
-+ dev_err(&pdev->dev, "failed to get IRQ\n");
-+ return -ENODEV;
-+ }
-+
-+ sunxi_ehci->phy_clk = devm_clk_get(&pdev->dev, "usb_phy");
-+ if (IS_ERR(sunxi_ehci->phy_clk)) {
-+ dev_err(&pdev->dev, "failed to get usb_phy clock\n");
-+ return PTR_ERR(sunxi_ehci->phy_clk);
-+ }
-+ sunxi_ehci->ahb_ehci_clk = devm_clk_get(&pdev->dev, "ahb_ehci");
-+ if (IS_ERR(sunxi_ehci->ahb_ehci_clk)) {
-+ dev_err(&pdev->dev, "failed to get ahb_ehci clock\n");
-+ return PTR_ERR(sunxi_ehci->ahb_ehci_clk);
-+ }
-+
-+ sunxi_ehci->reset = reset_control_get(&pdev->dev, "ehci_reset");
-+ if (IS_ERR(sunxi_ehci->reset))
-+ {
-+ dev_err(&pdev->dev, "failed to get ehci_reset reset line\n");
-+ return PTR_ERR(sunxi_ehci->reset);
-+ }
-+
-+ return 0;
-+}
-+
-+static int sunxi_ehci_probe(struct platform_device *pdev)
-+{
-+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
-+ struct usb_hcd *hcd = NULL;
-+ int ret;
-+
-+ if (pdev->num_resources != 4) {
-+ dev_err(&pdev->dev, "invalid number of resources: %i\n",
-+ pdev->num_resources);
-+ return -ENODEV;
-+ }
-+
-+ if (pdev->resource[0].flags != IORESOURCE_MEM
-+ || pdev->resource[1].flags != IORESOURCE_MEM
-+ || pdev->resource[2].flags != IORESOURCE_MEM
-+ || pdev->resource[3].flags != IORESOURCE_IRQ) {
-+ dev_err(&pdev->dev, "invalid resource type\n");
-+ return -ENODEV;
-+ }
-+
-+ if (!pdev->dev.dma_mask)
-+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-+ if (!pdev->dev.coherent_dma_mask)
-+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-+
-+ hcd = usb_create_hcd(&sunxi_ehci_hc_driver, &pdev->dev,
-+ dev_name(&pdev->dev));
-+ if (!hcd) {
-+ dev_err(&pdev->dev, "unable to create HCD\n");
-+ return -ENOMEM;
-+ }
-+
-+ platform_set_drvdata(pdev, hcd);
-+
-+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
-+ ret = sunxi_ehci_init(pdev, hcd, sunxi_ehci);
-+ if (ret)
-+ goto fail1;
-+
-+ ret = sunxi_ehci_enable(sunxi_ehci);
-+ if (ret)
-+ goto fail1;
-+
-+ ret = usb_add_hcd(hcd, sunxi_ehci->irq, IRQF_SHARED | IRQF_DISABLED);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to add USB HCD\n");
-+ goto fail2;
-+ }
-+
-+ return 0;
-+
-+fail2:
-+ sunxi_ehci_disable(sunxi_ehci);
-+
-+fail1:
-+ usb_put_hcd(hcd);
-+ return ret;
-+}
-+
-+static int sunxi_ehci_remove(struct platform_device *pdev)
-+{
-+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
-+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
-+
-+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
-+
-+ usb_remove_hcd(hcd);
-+
-+ sunxi_ehci_disable(sunxi_ehci);
-+
-+ usb_put_hcd(hcd);
-+
-+ return 0;
-+}
-+
-+static void sunxi_ehci_shutdown(struct platform_device *pdev)
-+{
-+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
-+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
-+
-+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
-+
-+ usb_hcd_platform_shutdown(pdev);
-+
-+ sunxi_ehci_disable(sunxi_ehci);
-+}
-+
-+static const struct of_device_id ehci_of_match[] = {
-+ {.compatible = "allwinner,sunxi-ehci"},
-+ {},
-+};
-+
-+static struct platform_driver ehci_sunxi_driver = {
-+ .driver = {
-+ .of_match_table = ehci_of_match,
-+ .name = DRV_NAME,
-+ .pm = SUNXI_EHCI_PMOPS,
-+ },
-+ .probe = sunxi_ehci_probe,
-+ .remove = sunxi_ehci_remove,
-+ .shutdown = sunxi_ehci_shutdown,
-+};
-+
-+static int __init sunxi_ehci_init_module(void)
-+{
-+ if (usb_disabled())
-+ return -ENODEV;
-+
-+ pr_info(DRV_NAME ": " DRV_DESC "\n");
-+
-+ ehci_init_driver(&sunxi_ehci_hc_driver, &sunxi_overrides);
-+
-+ return platform_driver_register(&ehci_sunxi_driver);
-+}
-+module_init(sunxi_ehci_init_module);
-+
-+static void __exit sunxi_ehci_exit_module(void)
-+{
-+ platform_driver_unregister(&ehci_sunxi_driver);
-+}
-+module_exit(sunxi_ehci_exit_module);
-+
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:" DRV_NAME);
-+MODULE_DEVICE_TABLE(of, ehci_of_match);
-+MODULE_AUTHOR("Roman Byshko <rbyshko@gmail.com>");
diff --git a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch
new file mode 100644
index 0000000000..4bdbb049e5
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch
@@ -0,0 +1,129 @@
+From 6c6bc98f6a2b1f91071564efdb77c90307610018 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
+Date: Sat, 15 Feb 2014 14:02:51 +0100
+Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 +++++
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 +++++
+ arch/arm/boot/dts/sun4i-a10.dtsi | 54 ++++++++++++++++++++++++++++++
+ 3 files changed, 70 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+index d6ec839..4b2a694 100644
+--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+@@ -35,6 +35,14 @@
+ };
+ };
+
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+index 6df237d8..ef85b8e 100644
+--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+@@ -34,6 +34,14 @@
+ };
+ };
+
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 454077a..a8e0df3 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -338,6 +338,46 @@
+ #size-cells = <0>;
+ };
+
++ mmc0: mmc@01c0f000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c0f000 0x1000>;
++ clocks = <&ahb_gates 8>, <&mmc0_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <32>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc1: mmc@01c10000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c10000 0x1000>;
++ clocks = <&ahb_gates 9>, <&mmc1_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <33>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc2: mmc@01c11000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c11000 0x1000>;
++ clocks = <&ahb_gates 10>, <&mmc2_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <34>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc3: mmc@01c12000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c12000 0x1000>;
++ clocks = <&ahb_gates 11>, <&mmc3_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <35>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -416,6 +456,20 @@
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
++
++ mmc0_pins_a: mmc0@0 {
++ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
++ allwinner,function = "mmc0";
++ allwinner,drive = <3>;
++ allwinner,pull = <0>;
++ };
++
++ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
++ allwinner,pins = "PH1";
++ allwinner,function = "gpio_in";
++ allwinner,drive = <0>;
++ allwinner,pull = <1>;
++ };
+ };
+
+ timer@01c20c00 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch
deleted file mode 100644
index 947f06bcc8..0000000000
--- a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 04f41bafdff26bd895f2a1f894fd427779d7ed51 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Thu, 19 Sep 2013 21:58:47 +0200
-Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10.dtsi
-+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
-@@ -93,6 +93,14 @@
- clock-output-names = "pll6_sata", "pll6_other", "pll6";
- };
-
-+ usb:usb@0x01c200cc {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun47i-usb-gates-clk";
-+ reg = <0x01c200cc 0x4>;
-+ clocks = <&pll6 1>;
-+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
-+ };
-+
- /* dummy is 200M */
- cpu: cpu@01c20054 {
- #clock-cells = <0>;
diff --git a/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch
deleted file mode 100644
index 3e6971407e..0000000000
--- a/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From ec53e86224acaa3891148fa298bb1504f3579d6b Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Wed, 18 Sep 2013 00:30:04 +0200
-Subject: [PATCH] ARM: sun4i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-
-Conflicts:
- arch/arm/boot/dts/sun4i-a10.dtsi
----
- arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10.dtsi
-+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
-@@ -17,6 +17,8 @@
-
- aliases {
- ethernet0 = &emac;
-+ ehci1 = &ehci0;
-+ ehci2 = &ehci1;
- };
-
- cpus {
-@@ -563,5 +565,33 @@
- clock-frequency = <100000>;
- status = "disabled";
- };
-+
-+ usb_rst: reset@0x01c200cc {
-+ #reset-cells = <1>;
-+ compatible = "allwinner,sun4i-clock-reset";
-+ reg = <0x01c200cc 0x4>;
-+ };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ compatible = "allwinner,sunxi-ehci";
-+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
-+ interrupts = <39>;
-+ resets = <&usb_rst 1>;
-+ reset-names = "ehci_reset";
-+ clocks = <&usb 8>, <&ahb_gates 1>;
-+ clock-names = "usb_phy", "ahb_ehci";
-+ status = "disabled";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ compatible = "allwinner,sunxi-ehci";
-+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
-+ interrupts = <40>;
-+ resets = <&usb_rst 2>;
-+ reset-names = "ehci_reset";
-+ clocks = <&usb 8>, <&ahb_gates 3>;
-+ clock-names = "usb_phy", "ahb_ehci";
-+ status = "disabled";
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch
index dfeabf7dc1..f688b6c965 100644
--- a/target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch
+++ b/target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch
@@ -1,38 +1,42 @@
-From 48332fd7217cf5b06b438503513e54e6138e0637 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sat, 14 Dec 2013 22:58:14 +0100
+From 5bfbb46a8685de4c67f084aea983fc9a50c882ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
+Date: Sat, 15 Feb 2014 14:02:29 +0100
Subject: [PATCH] ARM: dts: sun5i: Add support for mmc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
- arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 32 ++++++++++++++++++++++
- arch/arm/boot/dts/sun5i-a10s.dtsi | 34 ++++++++++++++++++++++++
- arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 16 +++++++++++
- arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 16 +++++++++++
- arch/arm/boot/dts/sun5i-a13.dtsi | 17 ++++++++++++
- 5 files changed, 115 insertions(+)
+ arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 30 ++++++++++++++++
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 44 ++++++++++++++++++++++++
+ arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 15 ++++++++
+ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 15 ++++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi | 37 ++++++++++++++++++++
+ 5 files changed, 141 insertions(+)
+diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+index 3c9f8b3..5c7b454 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
-@@ -34,7 +34,39 @@
+@@ -34,7 +34,37 @@
};
};
+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
++ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxino_micro>;
+ cd-gpios = <&pio 6 1 0>; /* PG1 */
-+ cd-mode = <1>;
+ status = "okay";
+ };
+
+ mmc1: mmc@01c10000 {
-+ pinctrl-names = "default";
++ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc1_pins_a>;
+ pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>;
+ cd-gpios = <&pio 6 13 0>; /* PG13 */
-+ cd-mode = <1>;
+ status = "okay";
+ };
+
@@ -41,22 +45,24 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
++ allwinner,pull = <1>;
+ };
+
+ mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 {
+ allwinner,pins = "PG13";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
++ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PE3";
allwinner,function = "gpio_out";
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 3a9b33d..3a7039e 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -293,6 +293,26 @@
+@@ -299,6 +299,36 @@
#size-cells = <0>;
};
@@ -80,10 +86,20 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ status = "disabled";
+ };
+
++ mmc2: mmc@01c11000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c11000 0x1000>;
++ clocks = <&ahb_gates 10>, <&mmc2_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <34>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
-@@ -363,6 +383,20 @@
+@@ -369,6 +399,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
@@ -104,18 +120,19 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
};
timer@01c20c00 {
+diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+index fe2ce0a..2f08bb2 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
-@@ -20,7 +20,23 @@
+@@ -20,7 +20,22 @@
compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
++ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
-+ cd-mode = <1>;
+ status = "okay";
+ };
+
@@ -124,24 +141,25 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
++ allwinner,pull = <1>;
+ };
+
led_pins_olinuxinom: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
+diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+index a4ba5ff..a7280f5 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-@@ -23,7 +23,23 @@
- };
+@@ -19,7 +19,22 @@
+ compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
++ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
-+ cd-mode = <1>;
+ status = "okay";
+ };
+
@@ -150,15 +168,17 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
++ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 9612c52..63a35b8 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -274,6 +274,16 @@
+@@ -281,6 +281,36 @@
#size-cells = <1>;
ranges;
@@ -172,10 +192,30 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ status = "disabled";
+ };
+
++ mmc1: mmc@01c10000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c10000 0x1000>;
++ clocks = <&ahb_gates 9>, <&mmc1_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <33>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc2: mmc@01c11000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c11000 0x1000>;
++ clocks = <&ahb_gates 10>, <&mmc2_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <34>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
-@@ -326,6 +336,13 @@
+@@ -333,6 +363,13 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
@@ -189,3 +229,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
};
timer@01c20c00 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch b/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch
deleted file mode 100644
index 7b7daa7b29..0000000000
--- a/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 875bbd46c296e4b9ed130848bc64be5cf39669c8 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Wed, 18 Sep 2013 22:45:06 +0200
-Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to Cubieboard-A10
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-
-Conflicts:
- arch/arm/boot/dts/sun4i-a10-cubieboard.dts
----
- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 46 ++++++++++++++++++++++++++++++
- 1 file changed, 46 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-@@ -77,6 +77,20 @@
- allwinner,drive = <1>;
- allwinner,pull = <0>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PH6";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
-+
-+ usb2_vbus_pin: usb2_vbus_pin@0 {
-+ allwinner,pins = "PH3";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart0: serial@01c28000 {
-@@ -96,6 +110,16 @@
- pinctrl-0 = <&i2c1_pins_a>;
- status = "okay";
- };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ vbus-supply = <&reg_usb2_vbus>;
-+ status = "okay";
-+ };
- };
-
- leds {
-@@ -128,5 +152,27 @@
- gpio = <&pio 1 8 0>;
- enable-active-high;
- };
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 6 0>;
-+ };
-+
-+ reg_usb2_vbus: usb2-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb2_vbus_pin>;
-+ regulator-name = "usb2-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 3 0>;
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch
new file mode 100644
index 0000000000..3fb2c6f0e7
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch
@@ -0,0 +1,160 @@
+From a3bddfdd19c49f0bde7aa2ff496773c575763d07 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
+Date: Sat, 15 Feb 2014 14:02:01 +0100
+Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++
+ arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi | 61 +++++++++++++++++++++++++
+ 4 files changed, 100 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+index 07823c2..a8186f5 100644
+--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+@@ -20,6 +20,14 @@
+ compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+index 403bd2e..6cd7cca 100644
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index d5c6799..d4e2355 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -20,12 +20,35 @@
+ compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
++ mmc3: mmc@01c12000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc3_pins_a>;
++ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
++ cd-gpios = <&pio 7 11 0>; /* PH11 */
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
+ pinctrl@01c20800 {
++ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
++ allwinner,pins = "PH11";
++ allwinner,function = "gpio_in";
++ allwinner,drive = <0>;
++ allwinner,pull = <1>;
++ };
++
+ led_pins_olinuxino: led_pins@0 {
+ allwinner,pins = "PH2";
+ allwinner,function = "gpio_out";
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 3385994..3bc6ac5 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -392,6 +392,46 @@
+ #size-cells = <0>;
+ };
+
++ mmc0: mmc@01c0f000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c0f000 0x1000>;
++ clocks = <&ahb_gates 8>, <&mmc0_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <0 32 4>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc1: mmc@01c10000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c10000 0x1000>;
++ clocks = <&ahb_gates 9>, <&mmc1_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <0 33 4>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc2: mmc@01c11000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c11000 0x1000>;
++ clocks = <&ahb_gates 10>, <&mmc2_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <0 34 4>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
++ mmc3: mmc@01c12000 {
++ compatible = "allwinner,sun5i-a13-mmc";
++ reg = <0x01c12000 0x1000>;
++ clocks = <&ahb_gates 11>, <&mmc3_clk>;
++ clock-names = "ahb", "mod";
++ interrupts = <0 35 4>;
++ bus-width = <4>;
++ status = "disabled";
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -510,6 +550,27 @@
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
++
++ mmc0_pins_a: mmc0@0 {
++ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
++ allwinner,function = "mmc0";
++ allwinner,drive = <3>;
++ allwinner,pull = <0>;
++ };
++
++ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
++ allwinner,pins = "PH1";
++ allwinner,function = "gpio_in";
++ allwinner,drive = <0>;
++ allwinner,pull = <1>;
++ };
++
++ mmc3_pins_a: mmc3@0 {
++ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
++ allwinner,function = "mmc3";
++ allwinner,drive = <3>;
++ allwinner,pull = <0>;
++ };
+ };
+
+ timer@01c20c00 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch
deleted file mode 100644
index c1b2505819..0000000000
--- a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 9a86b6c16abc11b1090fbf4e102b4eed1d474d96 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Wed, 18 Sep 2013 00:30:40 +0200
-Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to the Mele A1000
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun4i-a10-a1000.dts | 46 +++++++++++++++++++++++++++++++++++
- 1 file changed, 46 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
-@@ -73,6 +73,20 @@
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PH6";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
-+
-+ usb2_vbus_pin: usb2_vbus_pin@0 {
-+ allwinner,pins = "PH3";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart0: serial@01c28000 {
-@@ -86,6 +100,16 @@
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
- };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ vbus-supply = <&reg_usb2_vbus>;
-+ status = "okay";
-+ };
- };
-
- leds {
-@@ -117,5 +141,27 @@
- enable-active-high;
- gpio = <&pio 7 15 0>;
- };
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 6 0>;
-+ };
-+
-+ reg_usb2_vbus: usb2-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb2_vbus_pin>;
-+ regulator-name = "usb2-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 3 0>;
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch
new file mode 100644
index 0000000000..e9e209be29
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch
@@ -0,0 +1,64 @@
+From 11347c2a116f36b95d6cc3b315a1f269da6d42a0 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 17:20:21 +0100
+Subject: [PATCH] ARM: sun4i: dt: Fixup mmc bindings
+
+1) Now that we're no longer overriding the caps set by mmc_of_parse we need
+to set cd-inverted for our card detection to work.
+
+2) Now that we no longer claim UHS modes support we will never use any DDR
+modes, so drive-strength 2 is enough for the mmc data pins.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index a8e0df3..ba05e6e 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -345,6 +345,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <32>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -355,6 +356,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <33>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -365,6 +367,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -375,6 +378,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <35>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -460,7 +464,7 @@
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch
new file mode 100644
index 0000000000..7bbe566243
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch
@@ -0,0 +1,107 @@
+From 1fa41bc5a6659e453ca19086f195b02a23dc3bbe Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 17:25:54 +0100
+Subject: [PATCH] ARM: sun5i: dt: Fixup mmc bindings
+
+1) Now that we're no longer overriding the caps set by mmc_of_parse we need
+to set cd-inverted for our card detection to work.
+
+2) Now that we no longer claim UHS modes support we will never use any DDR
+modes, so drive-strength 2 is enough for the mmc data pins.
+
+3) mmc1 on the A13 is not routed to any pins, and thus unusable, remove it
+from the dtsi
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++--
+ arch/arm/boot/dts/sun5i-a13.dtsi | 14 +++-----------
+ 2 files changed, 8 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 3a7039e..15dfa9a 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -306,6 +306,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <32>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -316,6 +317,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <33>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -326,6 +328,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -403,14 +406,14 @@
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+ mmc1_pins_a: mmc1@0 {
+ allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8";
+ allwinner,function = "mmc1";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+ };
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 63a35b8..14a99d0 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -288,16 +288,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <32>;
+ bus-width = <4>;
+- status = "disabled";
+- };
+-
+- mmc1: mmc@01c10000 {
+- compatible = "allwinner,sun5i-a13-mmc";
+- reg = <0x01c10000 0x1000>;
+- clocks = <&ahb_gates 9>, <&mmc1_clk>;
+- clock-names = "ahb", "mod";
+- interrupts = <33>;
+- bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -308,6 +299,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -367,7 +359,7 @@
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch
new file mode 100644
index 0000000000..c1784e3c44
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch
@@ -0,0 +1,73 @@
+From e48e7ba7f97e883a24036df04cb474cf7cd22574 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 17:16:08 +0100
+Subject: [PATCH] ARM: sun7i: dt: Fixup mmc bindings
+
+1) Now that we're no longer overriding the caps set by mmc_of_parse we need
+to set cd-inverted for our card detection to work.
+
+2) Now that we no longer claim UHS modes support we will never use any DDR
+modes, so drive-strength 2 is enough for the mmc data pins.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 3bc6ac5..f4ecd79 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -399,6 +399,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <0 32 4>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -409,6 +410,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <0 33 4>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -419,6 +421,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <0 34 4>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -429,6 +432,7 @@
+ clock-names = "ahb", "mod";
+ interrupts = <0 35 4>;
+ bus-width = <4>;
++ cd-inverted;
+ status = "disabled";
+ };
+
+@@ -554,7 +558,7 @@
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+@@ -568,7 +572,7 @@
+ mmc3_pins_a: mmc3@0 {
+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
+ allwinner,function = "mmc3";
+- allwinner,drive = <3>;
++ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch
deleted file mode 100644
index 2ecd8d7d90..0000000000
--- a/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From b7739d837e1176b2206ee541075c9eba0a263695 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Thu, 19 Sep 2013 21:24:20 +0200
-Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -89,6 +89,14 @@
- clock-output-names = "pll6_sata", "pll6_other", "pll6";
- };
-
-+ usb:usb@0x01c200cc {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun47i-usb-gates-clk";
-+ reg = <0x01c200cc 0x4>;
-+ clocks = <&pll6 1>;
-+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
-+ };
-+
- cpu: cpu@01c20054 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-cpu-clk";
diff --git a/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch
deleted file mode 100644
index 4b2f9c2229..0000000000
--- a/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From a82eb088ea3fa4c25b256400690a30f4b0392e91 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Thu, 19 Sep 2013 21:36:10 +0200
-Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-
-Conflicts:
- arch/arm/boot/dts/sun7i-a20.dtsi
----
- arch/arm/boot/dts/sun7i-a20.dtsi | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -18,6 +18,8 @@
-
- aliases {
- ethernet0 = &gmac;
-+ ehci1 = &ehci0;
-+ ehci2 = &ehci1;
- };
-
- cpus {
-@@ -623,5 +625,33 @@
- #interrupt-cells = <3>;
- interrupts = <1 9 0xf04>;
- };
-+
-+ usb_rst: reset@0x01c200cc {
-+ #reset-cells = <1>;
-+ compatible = "allwinner,sun4i-clock-reset";
-+ reg = <0x01c200cc 0x4>;
-+ };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ compatible = "allwinner,sunxi-ehci";
-+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
-+ interrupts = <0 39 1>;
-+ resets = <&usb_rst 1>;
-+ reset-names = "ehci_reset";
-+ clocks = <&usb 8>, <&ahb_gates 1>;
-+ clock-names = "usb_phy", "ahb_ehci";
-+ status = "disabled";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ compatible = "allwinner,sunxi-ehci";
-+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
-+ interrupts = <0 40 1>;
-+ resets = <&usb_rst 2>;
-+ reset-names = "ehci_reset";
-+ clocks = <&usb 8>, <&ahb_gates 3>;
-+ clock-names = "usb_phy", "ahb_ehci";
-+ status = "disabled";
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch b/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch
deleted file mode 100644
index 2c6164e4ec..0000000000
--- a/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From 8ba068f40cce9612d2ac0879b6978274ab497d31 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Thu, 19 Sep 2013 21:29:45 +0200
-Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings for Cubieboard2
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-
-Conflicts:
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
----
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 45 +++++++++++++++++++++++++++++
- 1 file changed, 45 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-@@ -69,6 +69,20 @@
- allwinner,drive = <0>;
- allwinner,pull = <0>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PH6";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
-+
-+ usb2_vbus_pin: usb2_vbus_pin@0 {
-+ allwinner,pins = "PH3";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart0: serial@01c28000 {
-@@ -86,6 +100,15 @@
- i2c1: i2c@01c2b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins_a>;
-+ };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ vbus-supply = <&reg_usb2_vbus>;
- status = "okay";
- };
- };
-@@ -119,5 +142,27 @@
- gpio = <&pio 1 8 0>;
- enable-active-high;
- };
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 6 0>;
-+ };
-+
-+ reg_usb2_vbus: usb2-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb2_vbus_pin>;
-+ regulator-name = "usb2-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 7 3 0>;
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch b/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch
deleted file mode 100644
index 1df7e5eb94..0000000000
--- a/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From 5031cb9d88fe9ea4a37fe342ec5f8e2f0f930e00 Mon Sep 17 00:00:00 2001
-From: Zalan Blenessy <zalan.blenessy@gmail.com>
-Date: Sun, 22 Dec 2013 17:08:10 +0100
-Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to Olinuxino A20 Micro dts
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 47 +++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
-@@ -85,6 +85,20 @@
- allwinner,drive = <1>;
- allwinner,pull = <0>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PH6";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
-+
-+ usb2_vbus_pin: usb2_vbus_pin@0 {
-+ allwinner,pins = "PH3";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart0: serial@01c28000 {
-@@ -122,6 +136,16 @@
- pinctrl-0 = <&i2c2_pins_a>;
- status = "okay";
- };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
-+
-+ ehci1: ehci1@0x01c1c000 {
-+ vbus-supply = <&reg_usb2_vbus>;
-+ status = "okay";
-+ };
- };
-
- leds {
-@@ -138,6 +162,7 @@
-
- regulators {
- compatible = "simple-bus";
-+ pinctrl-names = "default";
-
- reg_ahci_5v: ahci-5v {
- compatible = "regulator-fixed";
-@@ -148,5 +173,27 @@
- gpio = <&pio 1 8 0>;
- enable-active-high;
- };
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ enable-active-high;
-+ gpio = <&pio 7 6 0>;
-+ };
-+
-+ reg_usb2_vbus: usb2-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb2_vbus_pin>;
-+ regulator-name = "usb2-vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ enable-active-high;
-+ gpio = <&pio 7 3 0>;
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch b/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch
deleted file mode 100644
index f95833e293..0000000000
--- a/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 90cab9a5e7c43bfbda25dd114a838f4e4b50b6ff Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 17 Dec 2013 23:04:57 +0100
-Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to cubietruck dts
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 46 ++++++++++++++++++++++++++++++
- 1 file changed, 46 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-@@ -43,11 +43,21 @@
- status = "okay";
- };
-
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
-+
- sata: ahci@01c18000 {
- pwr-supply = <&reg_ahci_5v>;
- status = "okay";
- };
-
-+ ehci1: ehci1@0x01c1c000 {
-+ vbus-supply = <&reg_usb2_vbus>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
- mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
- allwinner,pins = "PH1";
-@@ -90,6 +100,20 @@
- allwinner,drive = <0>;
- allwinner,pull = <2>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PH6";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
-+
-+ usb2_vbus_pin: usb2_vbus_pin@0 {
-+ allwinner,pins = "PH3";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart0: serial@01c28000 {
-@@ -175,5 +199,27 @@
- gpio = <&pio 7 12 0>;
- enable-active-high;
- };
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ enable-active-high;
-+ gpio = <&pio 7 6 0>;
-+ };
-+
-+ reg_usb2_vbus: usb2-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb2_vbus_pin>;
-+ regulator-name = "usb2-vbus";
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
-+ enable-active-high;
-+ gpio = <&pio 7 3 0>;
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch
deleted file mode 100644
index eb706c7a78..0000000000
--- a/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From f017ea35bd87e7935fbf5a03bc016d8b1efa03c0 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Tue, 24 Sep 2013 20:02:39 +0200
-Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB Host clocks
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -90,6 +90,14 @@
- clock-output-names = "pll6_sata", "pll6_other", "pll6";
- };
-
-+ usb:usb@0x01c200cc {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun5i-usb-gates-clk";
-+ reg = <0x01c200cc 0x4>;
-+ clocks = <&pll6 1>;
-+ clock-output-names = "usb_ohci0", "usb_phy";
-+ };
-+
- /* dummy is 200M */
- cpu: cpu@01c20054 {
- #clock-cells = <0>;
diff --git a/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch
deleted file mode 100644
index 0dff48f8e1..0000000000
--- a/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 3d3aa5f5c67d3f860b68def6a0ffce5e7175f85e Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Tue, 24 Sep 2013 20:03:40 +0200
-Subject: [PATCH] ARM: sun5i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun5i-a13.dtsi | 21 +++++++++++++++++++++
- 1 file changed, 21 insertions(+)
-
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -16,6 +16,10 @@
- / {
- interrupt-parent = <&intc>;
-
-+ aliases {
-+ ehci1 = &ehci0;
-+ };
-+
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-@@ -423,5 +427,22 @@
- interrupts = <82>, <83>;
- clocks = <&ahb_gates 28>;
- };
-+
-+ usb_rst: reset@0x01c200cc {
-+ #reset-cells = <1>;
-+ compatible = "allwinner,sun4i-clock-reset";
-+ reg = <0x01c200cc 0x4>;
-+ };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ compatible = "allwinner,sunxi-ehci";
-+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
-+ interrupts = <39>;
-+ resets = <&usb_rst 1>;
-+ reset-names = "ehci_reset";
-+ clocks = <&usb 8>, <&ahb_gates 1>;
-+ clock-names = "usb_phy", "ahb_ehci";
-+ status = "disabled";
-+ };
- };
- };
diff --git a/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch b/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch
deleted file mode 100644
index 05a7981045..0000000000
--- a/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 586c4aa0aeb07dacccb25a419a7b6625521ddea8 Mon Sep 17 00:00:00 2001
-From: arokux <arokux@gmail.com>
-Date: Tue, 24 Sep 2013 20:07:53 +0200
-Subject: [PATCH] ARM: sun5i: dt: Add EHCI bindings to A13-Olinuxino
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 27 +++++++++++++++++++++++++++
- 1 file changed, 27 insertions(+)
-
---- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-@@ -46,6 +46,13 @@
- allwinner,drive = <1>;
- allwinner,pull = <0>;
- };
-+
-+ usb1_vbus_pin: usb1_vbus_pin@0 {
-+ allwinner,pins = "PG11";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <2>;
-+ };
- };
-
- uart1: serial@01c28400 {
-@@ -71,6 +78,11 @@
- pinctrl-0 = <&i2c2_pins_a>;
- status = "okay";
- };
-+
-+ ehci0: ehci0@0x01c14000 {
-+ vbus-supply = <&reg_usb1_vbus>;
-+ status = "okay";
-+ };
- };
-
- leds {
-@@ -83,4 +95,19 @@
- default-state = "on";
- };
- };
-+
-+ regulators {
-+ compatible = "simple-bus";
-+
-+ reg_usb1_vbus: usb1-vbus {
-+ compatible = "regulator-fixed";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&usb1_vbus_pin>;
-+ regulator-name = "usb1-vbus";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ enable-active-high;
-+ gpio = <&pio 6 11 0>;
-+ };
-+ };
- };
diff --git a/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch b/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch
new file mode 100644
index 0000000000..dc69d171b1
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch
@@ -0,0 +1,339 @@
+From 14cf22b1db1b6e6b7333e8a7245055966f5497e3 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 1 Jan 2014 19:44:49 +0100
+Subject: [PATCH] input: Add new sun4i-lradc-keys driver
+
+Allwinnner sunxi SoCs have a low resolution adc (called lradc) which is
+specifically designed to have various (tablet) keys (ie home, back, search,
+etc). attached to it using a resistor network. This adds a driver for this.
+
+There are 2 channels, currently this driver only supports chan0 since there
+are no boards known to use chan1. The devicetree properties are already
+prefixed with chan0 as preparation for chan1 support in the future.
+
+This has been tested on an olimex a10s-olinuxino-micro, a13-olinuxino, and
+a20-olinuxino-micro.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../devicetree/bindings/input/sun4i-lradc-keys.txt | 22 ++
+ drivers/input/keyboard/Kconfig | 10 +
+ drivers/input/keyboard/Makefile | 1 +
+ drivers/input/keyboard/sun4i-lradc-keys.c | 243 +++++++++++++++++++++
+ 4 files changed, 276 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
+ create mode 100644 drivers/input/keyboard/sun4i-lradc-keys.c
+
+diff --git a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
+new file mode 100644
+index 0000000..7801264
+--- /dev/null
++++ b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
+@@ -0,0 +1,22 @@
++Allwinner sun4i low res adc attached tablet keys
++------------------------------------------------
++
++Required properties:
++ - compatible: "allwinner,sun4i-lradc-keys"
++ - reg: mmio address range of the chip
++ - interrupts: interrupt to which the chip is connected
++ - allwinner,chan0-step: step in mV between keys must be 150 or 200
++ - linux,chan0-keycodes: array of dt-bindings/input/input.h KEY_ codes
++
++Example:
++
++#include <dt-bindings/input/input.h>
++
++ lradc: lradc@01c22800 {
++ compatible = "allwinner,sun4i-lradc-keys";
++ reg = <0x01c22800 0x100>;
++ interrupts = <31>;
++ allwinner,chan0-step = <200>;
++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
++ KEY_MENU KEY_ENTER KEY_HOME>;
++ };
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index a673c9f..d8a51cd 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -544,6 +544,16 @@ config KEYBOARD_STMPE
+ To compile this driver as a module, choose M here: the module will be
+ called stmpe-keypad.
+
++config KEYBOARD_SUN4I_LRADC
++ tristate "Allwinner sun4i low res adc attached tablet keys support"
++ depends on ARCH_SUNXI
++ help
++ This selects support for the Allwinner low res adc attached tablet
++ keys found on Allwinner sunxi SoCs.
++
++ To compile this driver as a module, choose M here: the
++ module will be called sun4i-lradc-keys.
++
+ config KEYBOARD_DAVINCI
+ tristate "TI DaVinci Key Scan"
+ depends on ARCH_DAVINCI_DM365
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index a699b61..f3265bd 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
+ obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
+ obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
+ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
++obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o
+ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
+ obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
+ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
+diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c
+new file mode 100644
+index 0000000..5c55e17
+--- /dev/null
++++ b/drivers/input/keyboard/sun4i-lradc-keys.c
+@@ -0,0 +1,243 @@
++/*
++ * Allwinner sun4i low res adc attached tablet keys driver
++ *
++ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++/*
++ * Allwinnner sunxi SoCs have a lradc which is specifically designed to have
++ * various (tablet) keys (ie home, back, search, etc). attached to it using
++ * a resistor network. This driver is for the keys on such boards.
++ *
++ * There are 2 channels, currently this driver only supports chan0 since there
++ * are no boards known to use chan1. The devicetree properties are already
++ * prefixed with chan0 as preparation for chan1 support in the future.
++ */
++
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define LRADC_CTRL 0x00
++#define LRADC_INTC 0x04
++#define LRADC_INTS 0x08
++#define LRADC_DATA0 0x0c
++#define LRADC_DATA1 0x10
++
++/* LRADC_CTRL bits */
++#define FIRST_CONVERT_DLY(x) ((x) << 24) /* 8 bits */
++#define CHAN_SELECT(x) ((x) << 22) /* 2 bits */
++#define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */
++#define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */
++#define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */
++#define HOLD_EN(x) ((x) << 6)
++#define LEVELB_VOL(x) ((x) << 4) /* 2 bits */
++#define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */
++#define ENABLE(x) ((x) << 0)
++
++/* LRADC_INTC and LRADC_INTS bits */
++#define CHAN1_KEYUP_IRQ BIT(12)
++#define CHAN1_ALRDY_HOLD_IRQ BIT(11)
++#define CHAN1_HOLD_IRQ BIT(10)
++#define CHAN1_KEYDOWN_IRQ BIT(9)
++#define CHAN1_DATA_IRQ BIT(8)
++#define CHAN0_KEYUP_IRQ BIT(4)
++#define CHAN0_ALRDY_HOLD_IRQ BIT(3)
++#define CHAN0_HOLD_IRQ BIT(2)
++#define CHAN0_KEYDOWN_IRQ BIT(1)
++#define CHAN0_DATA_IRQ BIT(0)
++
++#define MAX_KEYS 13
++
++/* Lookup table to map the adc val to a keycode index for 150 mv step size */
++static const u8 adc_val_to_key_index_step150[64] = {
++ 0, 0, 0,
++ 1, 1, 1, 1, 1,
++ 2, 2, 2, 2, 2,
++ 3, 3, 3, 3,
++ 4, 4, 4, 4, 4,
++ 5, 5, 5, 5, 5,
++ 6, 6, 6, 6, 6,
++ 7, 7, 7, 7,
++ 8, 8, 8, 8, 8,
++ 9, 9, 9, 9, 9,
++ 10, 10, 10, 10,
++ 11, 11, 11, 11,
++ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
++};
++
++/* Lookup table to map the adc val to a keycode index for 200 mv step size */
++static const u8 adc_val_to_key_index_step200[64] = {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 1, 1, 1, 1, 1, 1, 1,
++ 2, 2, 2, 2, 2, 2, 2,
++ 3, 3, 3, 3, 3, 3,
++ 4, 4, 4, 4, 4, 4,
++ 5, 5, 5, 5, 5, 5,
++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
++};
++
++struct sun4i_lradc_data {
++ struct device *dev;
++ struct input_dev *input;
++ void __iomem *base;
++ u32 chan0_step;
++ u32 chan0_keycode;
++ u32 chan0_keycodes[MAX_KEYS];
++};
++
++static irqreturn_t sun4i_lradc_irq(int irq, void *dev_id)
++{
++ struct sun4i_lradc_data *lradc = dev_id;
++ u32 ints, val;
++
++ ints = readl(lradc->base + LRADC_INTS);
++
++ /*
++ * lradc supports only one keypress at a time, release does not give
++ * any info as to which key was released, so we cache the keycode.
++ */
++ if ((ints & CHAN0_KEYDOWN_IRQ) && lradc->chan0_keycode == 0) {
++ val = readl(lradc->base + LRADC_DATA0);
++ if (lradc->chan0_step == 150)
++ val = adc_val_to_key_index_step150[val];
++ else
++ val = adc_val_to_key_index_step200[val];
++
++ lradc->chan0_keycode = lradc->chan0_keycodes[val];
++ input_report_key(lradc->input, lradc->chan0_keycode, 1);
++ }
++
++ if (ints & CHAN0_KEYUP_IRQ) {
++ input_report_key(lradc->input, lradc->chan0_keycode, 0);
++ lradc->chan0_keycode = 0;
++ }
++
++ input_sync(lradc->input);
++
++ writel(ints, lradc->base + LRADC_INTS);
++
++ return IRQ_HANDLED;
++}
++
++static int sun4i_lradc_open(struct input_dev *dev)
++{
++ struct sun4i_lradc_data *lradc = input_get_drvdata(dev);
++
++ /*
++ * Set sample time to 16 ms / 62.5 Hz. Wait 2 * 16 ms for key to
++ * stabilize on press, wait (1 + 1) * 16 ms for key release
++ */
++ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) |
++ SAMPLE_RATE(2) | ENABLE(1), lradc->base + LRADC_CTRL);
++
++ writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC);
++
++ return 0;
++}
++
++static void sun4i_lradc_close(struct input_dev *dev)
++{
++ struct sun4i_lradc_data *lradc = input_get_drvdata(dev);
++
++ /* Disable lradc, leave other settings unchanged */
++ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) |
++ SAMPLE_RATE(2), lradc->base + LRADC_CTRL);
++ writel(0, lradc->base + LRADC_INTC);
++}
++
++static int sun4i_lradc_probe(struct platform_device *pdev)
++{
++ struct sun4i_lradc_data *lradc;
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ int i, ret;
++
++ lradc = devm_kzalloc(dev, sizeof(struct sun4i_lradc_data), GFP_KERNEL);
++ if (!lradc)
++ return -ENOMEM;
++
++ ret = of_property_read_u32(np, "allwinner,chan0-step",
++ &lradc->chan0_step);
++ if (ret || (lradc->chan0_step != 150 && lradc->chan0_step != 200)) {
++ dev_err(dev, "Invalid allwinner,chan0-step dt-property\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; i < MAX_KEYS; i++)
++ of_property_read_u32_index(np, "linux,chan0-keycodes",
++ i, &lradc->chan0_keycodes[i]);
++
++ lradc->dev = dev;
++ lradc->input = devm_input_allocate_device(dev);
++ if (!lradc->input)
++ return -ENOMEM;
++
++ lradc->input->name = pdev->name;
++ lradc->input->phys = "sun4i_lradc/input0";
++ lradc->input->open = sun4i_lradc_open;
++ lradc->input->close = sun4i_lradc_close;
++ lradc->input->id.bustype = BUS_HOST;
++ lradc->input->id.vendor = 0x0001;
++ lradc->input->id.product = 0x0001;
++ lradc->input->id.version = 0x0100;
++ lradc->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY);
++ for (i = 0; i < MAX_KEYS; i++)
++ set_bit(lradc->chan0_keycodes[i], lradc->input->keybit);
++ input_set_drvdata(lradc->input, lradc);
++
++ lradc->base = devm_ioremap_resource(dev,
++ platform_get_resource(pdev, IORESOURCE_MEM, 0));
++ if (IS_ERR(lradc->base))
++ return PTR_ERR(lradc->base);
++
++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), sun4i_lradc_irq,
++ 0, "sun4i-lradc-keys", lradc);
++ if (ret)
++ return ret;
++
++ ret = input_register_device(lradc->input);
++ if (ret)
++ return ret;
++
++ platform_set_drvdata(pdev, lradc);
++ return 0;
++}
++
++static const struct of_device_id sun4i_lradc_of_match[] = {
++ { .compatible = "allwinner,sun4i-lradc-keys", },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match);
++
++static struct platform_driver sun4i_lradc_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "sun4i-lradc-keys",
++ .of_match_table = of_match_ptr(sun4i_lradc_of_match),
++ },
++ .probe = sun4i_lradc_probe,
++};
++
++module_platform_driver(sun4i_lradc_driver);
++
++MODULE_DESCRIPTION("Allwinner sun4i low res adc attached tablet keys driver");
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_LICENSE("GPL");
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch
new file mode 100644
index 0000000000..f23ad66409
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch
@@ -0,0 +1,59 @@
+From 0b35a283be3dcd9495bb7c0e13ef2cd58a5d2afc Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 1 Jan 2014 20:26:21 +0100
+Subject: [PATCH] ARM: dts: sun7i: Add lradc node
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 9 +++++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index d4e2355..aef289f 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -14,6 +14,7 @@
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
+ /include/ "sunxi-ahci-reg.dtsi"
++#include <dt-bindings/input/input.h>
+
+ / {
+ model = "Olimex A20-Olinuxino Micro";
+@@ -57,6 +58,14 @@
+ };
+ };
+
++ lradc: lradc@01c22800 {
++ allwinner,chan0-step = <200>;
++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
++ KEY_MENU KEY_SEARCH KEY_HOME
++ KEY_ESC KEY_ENTER>;
++ status = "okay";
++ };
++
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index fa2ef07..b58ce25 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -608,6 +608,13 @@
+ interrupts = <0 24 1>;
+ };
+
++ lradc: lradc@01c22800 {
++ compatible = "allwinner,sun4i-lradc-keys";
++ reg = <0x01c22800 0x100>;
++ interrupts = <0 31 4>;
++ status = "disabled";
++ };
++
+ sid: eeprom@01c23800 {
+ compatible = "allwinner,sun7i-a20-sid";
+ reg = <0x01c23800 0x200>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch
new file mode 100644
index 0000000000..9183d9cfa6
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch
@@ -0,0 +1,31 @@
+From 7d6d16c0c9b96695cd0f5e5845ac192209f0811d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 1 Jan 2014 19:51:36 +0100
+Subject: [PATCH] ARM: dts: sun4i: Add lradc node
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index ba05e6e..1a9ab7e 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -494,6 +494,13 @@
+ interrupts = <24>;
+ };
+
++ lradc: lradc@01c22800 {
++ compatible = "allwinner,sun4i-lradc-keys";
++ reg = <0x01c22800 0x100>;
++ interrupts = <31>;
++ status = "disabled";
++ };
++
+ sid: eeprom@01c23800 {
+ compatible = "allwinner,sun4i-sid";
+ reg = <0x01c23800 0x10>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch
new file mode 100644
index 0000000000..c73b52b049
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch
@@ -0,0 +1,104 @@
+From 23f834fe6efd9f97e9b336cc53d902e6a0158cc5 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 1 Jan 2014 19:50:33 +0100
+Subject: [PATCH] ARM: dts: sun5i: Add lradc node
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 8 ++++++++
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++
+ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 8 ++++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++
+ 4 files changed, 30 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+index 5c7b454..2cbca7b 100644
+--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+@@ -13,6 +13,7 @@
+
+ /dts-v1/;
+ /include/ "sun5i-a10s.dtsi"
++#include <dt-bindings/input/input.h>
+
+ / {
+ model = "Olimex A10s-Olinuxino Micro";
+@@ -73,6 +74,13 @@
+ };
+ };
+
++ lradc: lradc@01c22800 {
++ allwinner,chan0-step = <200>;
++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
++ KEY_MENU KEY_ENTER KEY_HOME>;
++ status = "okay";
++ };
++
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 15dfa9a..95cb245 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -430,6 +430,13 @@
+ reg = <0x01c20c90 0x10>;
+ };
+
++ lradc: lradc@01c22800 {
++ compatible = "allwinner,sun4i-lradc-keys";
++ reg = <0x01c22800 0x100>;
++ interrupts = <31>;
++ status = "disabled";
++ };
++
+ sid: eeprom@01c23800 {
+ compatible = "allwinner,sun4i-sid";
+ reg = <0x01c23800 0x10>;
+diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+index a7280f5..ba32a41 100644
+--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+@@ -13,6 +13,7 @@
+
+ /dts-v1/;
+ /include/ "sun5i-a13.dtsi"
++#include <dt-bindings/input/input.h>
+
+ / {
+ model = "Olimex A13-Olinuxino";
+@@ -43,6 +44,13 @@
+ };
+ };
+
++ lradc: lradc@01c22800 {
++ allwinner,chan0-step = <200>;
++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
++ KEY_MENU KEY_ENTER KEY_HOME>;
++ status = "okay";
++ };
++
+ uart1: serial@01c28400 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins_b>;
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 14a99d0..bae0f5f 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -376,6 +376,13 @@
+ reg = <0x01c20c90 0x10>;
+ };
+
++ lradc: lradc@01c22800 {
++ compatible = "allwinner,sun4i-lradc-keys";
++ reg = <0x01c22800 0x100>;
++ interrupts = <31>;
++ status = "disabled";
++ };
++
+ sid: eeprom@01c23800 {
+ compatible = "allwinner,sun4i-sid";
+ reg = <0x01c23800 0x10>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch b/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch
deleted file mode 100644
index f4014bdc2c..0000000000
--- a/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From b0a614458fb67fdb53e1b5518dabb85d688b196e Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 17 Dec 2013 22:59:17 +0100
-Subject: [PATCH] ARM: dts: sunxi: usb Vbus is 5v not 3.3v
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 ++++----
- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 ++++----
- arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 4 ++--
- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++----
- 4 files changed, 14 insertions(+), 14 deletions(-)
-
---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
-@@ -147,8 +147,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-@@ -158,8 +158,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
-@@ -158,8 +158,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-@@ -169,8 +169,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
---- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-@@ -104,8 +104,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 6 11 0>;
- };
---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
-@@ -148,8 +148,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb1_vbus_pin>;
- regulator-name = "usb1-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 6 0>;
- };
-@@ -159,8 +159,8 @@
- pinctrl-names = "default";
- pinctrl-0 = <&usb2_vbus_pin>;
- regulator-name = "usb2-vbus";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-+ regulator-min-microvolt = <5000000>;
-+ regulator-max-microvolt = <5000000>;
- enable-active-high;
- gpio = <&pio 7 3 0>;
- };
diff --git a/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch b/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch
deleted file mode 100644
index b2ee15008b..0000000000
--- a/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 06285d1c64552291f136eb197b6f05bc9d9c1d0e Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 17 Dec 2013 23:26:45 +0100
-Subject: [PATCH] ARM: dts: sun7i: Fix ehci interrupt types
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -635,7 +635,7 @@
- ehci0: ehci0@0x01c14000 {
- compatible = "allwinner,sunxi-ehci";
- reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
-- interrupts = <0 39 1>;
-+ interrupts = <0 39 4>;
- resets = <&usb_rst 1>;
- reset-names = "ehci_reset";
- clocks = <&usb 8>, <&ahb_gates 1>;
-@@ -646,7 +646,7 @@
- ehci1: ehci1@0x01c1c000 {
- compatible = "allwinner,sunxi-ehci";
- reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
-- interrupts = <0 40 1>;
-+ interrupts = <0 40 4>;
- resets = <&usb_rst 2>;
- reset-names = "ehci_reset";
- clocks = <&usb 8>, <&ahb_gates 3>;
diff --git a/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch b/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch
deleted file mode 100644
index 20779a57d8..0000000000
--- a/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From e772c9c2f552740ae735328cbd06b1d7f8e9d885 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 17 Dec 2013 23:27:03 +0100
-Subject: [PATCH] ARM: sunxi-ehci: Fix resource check
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/usb/host/ehci-sunxi.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/usb/host/ehci-sunxi.c
-+++ b/drivers/usb/host/ehci-sunxi.c
-@@ -332,7 +332,8 @@ static int sunxi_ehci_probe(struct platf
- if (pdev->resource[0].flags != IORESOURCE_MEM
- || pdev->resource[1].flags != IORESOURCE_MEM
- || pdev->resource[2].flags != IORESOURCE_MEM
-- || pdev->resource[3].flags != IORESOURCE_IRQ) {
-+ || (pdev->resource[3].flags & IORESOURCE_TYPE_BITS)
-+ != IORESOURCE_IRQ) {
- dev_err(&pdev->dev, "invalid resource type\n");
- return -ENODEV;
- }
diff --git a/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch b/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch
new file mode 100644
index 0000000000..5ae391a248
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch
@@ -0,0 +1,896 @@
+From 3c9740a117d40a74412775b5d3fe2b88a7635a0e Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@freescale.com>
+Date: Tue, 5 Nov 2013 10:46:02 +0800
+Subject: [PATCH] usb: hcd: move controller wakeup setting initialization to
+ individual driver
+
+Individual controller driver has different requirement for wakeup
+setting, so move it from core to itself. In order to align with
+current etting the default wakeup setting is enabled (except for
+chipidea host).
+
+Pass compile test with below commands:
+ make O=outout/all allmodconfig
+ make -j$CPU_NUM O=outout/all drivers/usb
+
+Signed-off-by: Peter Chen <peter.chen@freescale.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/dwc2/hcd.c | 2 ++
+ drivers/staging/octeon-usb/octeon-hcd.c | 1 +
+ drivers/staging/ozwpan/ozhcd.c | 2 ++
+ drivers/usb/c67x00/c67x00-hcd.c | 2 ++
+ drivers/usb/core/hcd-pci.c | 1 +
+ drivers/usb/core/hcd.c | 6 ------
+ drivers/usb/host/ehci-atmel.c | 1 +
+ drivers/usb/host/ehci-exynos.c | 1 +
+ drivers/usb/host/ehci-fsl.c | 1 +
+ drivers/usb/host/ehci-grlib.c | 1 +
+ drivers/usb/host/ehci-mv.c | 1 +
+ drivers/usb/host/ehci-mxc.c | 1 +
+ drivers/usb/host/ehci-octeon.c | 1 +
+ drivers/usb/host/ehci-omap.c | 1 +
+ drivers/usb/host/ehci-orion.c | 1 +
+ drivers/usb/host/ehci-platform.c | 1 +
+ drivers/usb/host/ehci-pmcmsp.c | 4 +++-
+ drivers/usb/host/ehci-ppc-of.c | 1 +
+ drivers/usb/host/ehci-ps3.c | 1 +
+ drivers/usb/host/ehci-sead3.c | 1 +
+ drivers/usb/host/ehci-sh.c | 1 +
+ drivers/usb/host/ehci-spear.c | 1 +
+ drivers/usb/host/ehci-tegra.c | 1 +
+ drivers/usb/host/ehci-tilegx.c | 1 +
+ drivers/usb/host/ehci-w90x900.c | 1 +
+ drivers/usb/host/ehci-xilinx-of.c | 4 +++-
+ drivers/usb/host/fhci-hcd.c | 2 ++
+ drivers/usb/host/fotg210-hcd.c | 1 +
+ drivers/usb/host/fusbh200-hcd.c | 1 +
+ drivers/usb/host/hwa-hc.c | 1 +
+ drivers/usb/host/imx21-hcd.c | 1 +
+ drivers/usb/host/isp116x-hcd.c | 2 ++
+ drivers/usb/host/isp1362-hcd.c | 2 ++
+ drivers/usb/host/isp1760-hcd.c | 1 +
+ drivers/usb/host/ohci-at91.c | 4 +++-
+ drivers/usb/host/ohci-da8xx.c | 2 ++
+ drivers/usb/host/ohci-exynos.c | 1 +
+ drivers/usb/host/ohci-jz4740.c | 1 +
+ drivers/usb/host/ohci-nxp.c | 4 +++-
+ drivers/usb/host/ohci-octeon.c | 2 ++
+ drivers/usb/host/ohci-omap.c | 1 +
+ drivers/usb/host/ohci-omap3.c | 1 +
+ drivers/usb/host/ohci-platform.c | 2 ++
+ drivers/usb/host/ohci-ppc-of.c | 4 +++-
+ drivers/usb/host/ohci-ps3.c | 1 +
+ drivers/usb/host/ohci-pxa27x.c | 4 +++-
+ drivers/usb/host/ohci-s3c2410.c | 1 +
+ drivers/usb/host/ohci-sa1111.c | 4 +++-
+ drivers/usb/host/ohci-sm501.c | 1 +
+ drivers/usb/host/ohci-spear.c | 4 +++-
+ drivers/usb/host/ohci-tilegx.c | 1 +
+ drivers/usb/host/ohci-tmio.c | 1 +
+ drivers/usb/host/oxu210hp-hcd.c | 1 +
+ drivers/usb/host/r8a66597-hcd.c | 1 +
+ drivers/usb/host/sl811-hcd.c | 2 ++
+ drivers/usb/host/u132-hcd.c | 1 +
+ drivers/usb/host/uhci-grlib.c | 1 +
+ drivers/usb/host/uhci-platform.c | 1 +
+ drivers/usb/host/whci/hcd.c | 1 +
+ drivers/usb/host/xhci-plat.c | 1 +
+ drivers/usb/musb/musb_host.c | 1 +
+ drivers/usb/phy/phy-msm-usb.c | 1 +
+ drivers/usb/phy/phy-mv-usb.c | 6 ++++--
+ drivers/usb/renesas_usbhs/mod_host.c | 1 +
+ 64 files changed, 92 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c
+index 3cfd2d5..078cd91 100644
+--- a/drivers/staging/dwc2/hcd.c
++++ b/drivers/staging/dwc2/hcd.c
+@@ -2921,6 +2921,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
+ if (retval < 0)
+ goto error3;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ dwc2_hcd_dump_state(hsotg);
+
+ dwc2_enable_global_interrupts(hsotg);
+diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
+index d118952..47e0a91 100644
+--- a/drivers/staging/octeon-usb/octeon-hcd.c
++++ b/drivers/staging/octeon-usb/octeon-hcd.c
+@@ -3498,6 +3498,7 @@ static int octeon_usb_driver_probe(struct device *dev)
+ kfree(hcd);
+ return -1;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
+
+diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
+index d9c43c3..efaf26f 100644
+--- a/drivers/staging/ozwpan/ozhcd.c
++++ b/drivers/staging/ozwpan/ozhcd.c
+@@ -2270,6 +2270,8 @@ static int oz_plat_probe(struct platform_device *dev)
+ usb_put_hcd(hcd);
+ return -1;
+ }
++ device_wakeup_enable(hcd->self.controller);
++
+ spin_lock_bh(&g_hcdlock);
+ g_ozhcd = ozhcd;
+ spin_unlock_bh(&g_hcdlock);
+diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c
+index 75e47b8..20ec4ee 100644
+--- a/drivers/usb/c67x00/c67x00-hcd.c
++++ b/drivers/usb/c67x00/c67x00-hcd.c
+@@ -384,6 +384,8 @@ int c67x00_hcd_probe(struct c67x00_sie *sie)
+ goto err2;
+ }
+
++ device_wakeup_enable(hcd->self.controller);
++
+ spin_lock_irqsave(&sie->lock, flags);
+ sie->private_data = c67x00;
+ sie->irq = c67x00_hcd_irq;
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index dfe9d0f..d59d993 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -282,6 +282,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+
+ if (retval != 0)
+ goto unmap_registers;
++ device_wakeup_enable(hcd->self.controller);
+
+ if (pci_dev_run_wake(dev))
+ pm_runtime_put_noidle(&dev->dev);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index d3a9bcd..6297c9e 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2712,12 +2712,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
+ usb_hcd_poll_rh_status(hcd);
+
+- /*
+- * Host controllers don't generate their own wakeup requests;
+- * they only forward requests from the root hub. Therefore
+- * controllers should always be enabled for remote wakeup.
+- */
+- device_wakeup_enable(hcd->self.controller);
+ return retval;
+
+ error_create_attr_group:
+diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
+index 284f841..ec9f7b7 100644
+--- a/drivers/usb/host/ehci-atmel.c
++++ b/drivers/usb/host/ehci-atmel.c
+@@ -153,6 +153,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval)
+ goto fail_add_hcd;
++ device_wakeup_enable(hcd->self.controller);
+
+ return retval;
+
+diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
+index e97c198..d1d8c47 100644
+--- a/drivers/usb/host/ehci-exynos.c
++++ b/drivers/usb/host/ehci-exynos.c
+@@ -166,6 +166,7 @@ static int exynos_ehci_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add USB HCD\n");
+ goto fail_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ platform_set_drvdata(pdev, hcd);
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 87a7426..854a68f 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -138,6 +138,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval != 0)
+ goto err4;
++ device_wakeup_enable(hcd->self.controller);
+
+ #ifdef CONFIG_USB_OTG
+ if (pdata->operating_mode == FSL_USB2_DR_OTG) {
+diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
+index b52a66c..054792c 100644
+--- a/drivers/usb/host/ehci-grlib.c
++++ b/drivers/usb/host/ehci-grlib.c
+@@ -140,6 +140,7 @@ static int ehci_hcd_grlib_probe(struct platform_device *op)
+ if (rv)
+ goto err_ioremap;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_ioremap:
+diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
+index 6e8afca..bd61612 100644
+--- a/drivers/usb/host/ehci-mv.c
++++ b/drivers/usb/host/ehci-mv.c
+@@ -257,6 +257,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
+ "failed to add hcd with err %d\n", retval);
+ goto err_set_vbus;
+ }
++ device_wakeup_enable(hcd->self.controller);
+ }
+
+ if (pdata->private_init)
+diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
+index 0528dc4..dbe5e4e 100644
+--- a/drivers/usb/host/ehci-mxc.c
++++ b/drivers/usb/host/ehci-mxc.c
+@@ -155,6 +155,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
+ if (ret)
+ goto err_add;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_add:
+diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
+index 4c528b2..c4ad7ed 100644
+--- a/drivers/usb/host/ehci-octeon.c
++++ b/drivers/usb/host/ehci-octeon.c
+@@ -158,6 +158,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
+ dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+ goto err3;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ platform_set_drvdata(pdev, hcd);
+
+diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
+index 6fa82d6..a24720b 100644
+--- a/drivers/usb/host/ehci-omap.c
++++ b/drivers/usb/host/ehci-omap.c
+@@ -215,6 +215,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
+ dev_err(dev, "failed to add hcd with err %d\n", ret);
+ goto err_pm_runtime;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ /*
+ * Bring PHYs out of reset for non PHY modes.
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index 2ba7673..aa8b92b 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -252,6 +252,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
+ if (err)
+ goto err4;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err4:
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 7f30b71..01536cf 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -132,6 +132,7 @@ static int ehci_platform_probe(struct platform_device *dev)
+ if (err)
+ goto err_put_hcd;
+
++ device_wakeup_enable(hcd->self.controller);
+ platform_set_drvdata(dev, hcd);
+
+ return err;
+diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
+index 893b707f..af3974a 100644
+--- a/drivers/usb/host/ehci-pmcmsp.c
++++ b/drivers/usb/host/ehci-pmcmsp.c
+@@ -210,8 +210,10 @@ int usb_hcd_msp_probe(const struct hc_driver *driver,
+
+
+ retval = usb_add_hcd(hcd, res->start, IRQF_SHARED);
+- if (retval == 0)
++ if (retval == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
++ }
+
+ usb_remove_hcd(hcd);
+ err3:
+diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
+index 875d2fc..b0965eb 100644
+--- a/drivers/usb/host/ehci-ppc-of.c
++++ b/drivers/usb/host/ehci-ppc-of.c
+@@ -169,6 +169,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op)
+ if (rv)
+ goto err_ioremap;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_ioremap:
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index 8188542..7934ff9 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -189,6 +189,7 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
+ goto fail_add_hcd;
+ }
+
++ device_wakeup_enable(hcd->self.controller);
+ return result;
+
+ fail_add_hcd:
+diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
+index 8a73449..cf12676 100644
+--- a/drivers/usb/host/ehci-sead3.c
++++ b/drivers/usb/host/ehci-sead3.c
+@@ -126,6 +126,7 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev)
+ IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
++ device_wakeup_enable(hcd->self.controller);
+ return ret;
+ }
+
+diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
+index dc899eb..9b9b9f5 100644
+--- a/drivers/usb/host/ehci-sh.c
++++ b/drivers/usb/host/ehci-sh.c
+@@ -151,6 +151,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add hcd");
+ goto fail_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ priv->hcd = hcd;
+ platform_set_drvdata(pdev, priv);
+diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
+index ee6f9ff..8bd915b 100644
+--- a/drivers/usb/host/ehci-spear.c
++++ b/drivers/usb/host/ehci-spear.c
+@@ -130,6 +130,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
+ if (retval)
+ goto err_stop_ehci;
+
++ device_wakeup_enable(hcd->self.controller);
+ return retval;
+
+ err_stop_ehci:
+diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
+index b9fd039..a8f4471 100644
+--- a/drivers/usb/host/ehci-tegra.c
++++ b/drivers/usb/host/ehci-tegra.c
+@@ -455,6 +455,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add USB HCD\n");
+ goto cleanup_otg_set_host;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return err;
+
+diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c
+index 67026ff..f3713d3 100644
+--- a/drivers/usb/host/ehci-tilegx.c
++++ b/drivers/usb/host/ehci-tilegx.c
+@@ -170,6 +170,7 @@ static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev)
+ ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
++ device_wakeup_enable(hcd->self.controller);
+ return ret;
+ }
+
+diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
+index cdad843..12c1a56 100644
+--- a/drivers/usb/host/ehci-w90x900.c
++++ b/drivers/usb/host/ehci-w90x900.c
+@@ -94,6 +94,7 @@ static int usb_w90x900_probe(const struct hc_driver *driver,
+ if (retval != 0)
+ goto err4;
+
++ device_wakeup_enable(hcd->self.controller);
+ return retval;
+ err4:
+ iounmap(hcd->regs);
+diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
+index 95979f9..3cd2efa 100644
+--- a/drivers/usb/host/ehci-xilinx-of.c
++++ b/drivers/usb/host/ehci-xilinx-of.c
+@@ -191,8 +191,10 @@ static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
+ ehci->caps = hcd->regs + 0x100;
+
+ rv = usb_add_hcd(hcd, irq, 0);
+- if (rv == 0)
++ if (rv == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
++ }
+
+ err_irq:
+ usb_put_hcd(hcd);
+diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
+index 0551c0a..1cf68ea 100644
+--- a/drivers/usb/host/fhci-hcd.c
++++ b/drivers/usb/host/fhci-hcd.c
+@@ -754,6 +754,8 @@ static int of_fhci_probe(struct platform_device *ofdev)
+ if (ret < 0)
+ goto err_add_hcd;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ fhci_dfs_create(fhci);
+
+ return 0;
+diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
+index 97d6939..98a89d1 100644
+--- a/drivers/usb/host/fotg210-hcd.c
++++ b/drivers/usb/host/fotg210-hcd.c
+@@ -5889,6 +5889,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
+ dev_err(dev, "failed to add hcd with err %d\n", retval);
+ goto fail_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return retval;
+
+diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c
+index 9ea85b6..ba94990 100644
+--- a/drivers/usb/host/fusbh200-hcd.c
++++ b/drivers/usb/host/fusbh200-hcd.c
+@@ -5798,6 +5798,7 @@ static int fusbh200_hcd_probe(struct platform_device *pdev)
+ dev_err(dev, "failed to add hcd with err %d\n", retval);
+ goto fail_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return retval;
+
+diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
+index a4ec9e6..7fd3f9b 100644
+--- a/drivers/usb/host/hwa-hc.c
++++ b/drivers/usb/host/hwa-hc.c
+@@ -791,6 +791,7 @@ static int hwahc_probe(struct usb_interface *usb_iface,
+ dev_err(dev, "Cannot add HCD: %d\n", result);
+ goto error_add_hcd;
+ }
++ device_wakeup_enable(usb_hcd->self.controller);
+ result = wusbhc_b_create(&hwahc->wusbhc);
+ if (result < 0) {
+ dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result);
+diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
+index 0122624..207bad9 100644
+--- a/drivers/usb/host/imx21-hcd.c
++++ b/drivers/usb/host/imx21-hcd.c
+@@ -1910,6 +1910,7 @@ static int imx21_probe(struct platform_device *pdev)
+ dev_err(imx21->dev, "usb_add_hcd() returned %d\n", ret);
+ goto failed_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return 0;
+
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 7722ec6..2740f65 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1645,6 +1645,8 @@ static int isp116x_probe(struct platform_device *pdev)
+ if (ret)
+ goto err6;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ ret = create_debug_file(isp116x);
+ if (ret) {
+ ERR("Couldn't create debugfs entry\n");
+diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
+index cd94b10..34645ae 100644
+--- a/drivers/usb/host/isp1362-hcd.c
++++ b/drivers/usb/host/isp1362-hcd.c
+@@ -2746,6 +2746,8 @@ static int isp1362_probe(struct platform_device *pdev)
+ retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_SHARED);
+ if (retval != 0)
+ goto err6;
++ device_wakeup_enable(hcd->self.controller);
++
+ pr_info("%s, irq %d\n", hcd->product_desc, irq);
+
+ create_debug_file(isp1362_hcd);
+diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
+index 2facee5..51a0ae9 100644
+--- a/drivers/usb/host/isp1760-hcd.c
++++ b/drivers/usb/host/isp1760-hcd.c
+@@ -2250,6 +2250,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
+ ret = usb_add_hcd(hcd, irq, irqflags);
+ if (ret)
+ goto err_unmap;
++ device_wakeup_enable(hcd->self.controller);
+
+ return hcd;
+
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index cc9462f..29d2093 100644
+diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
+index 71dbd85..f0fe0d2 100644
+--- a/drivers/usb/host/ohci-da8xx.c
++++ b/drivers/usb/host/ohci-da8xx.c
+@@ -348,6 +348,8 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
+ if (error)
+ goto err4;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ if (hub->ocic_notify) {
+ error = hub->ocic_notify(ohci_da8xx_ocic_handler);
+ if (!error)
+diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
+index 9897d70..68588d8 100644
+--- a/drivers/usb/host/ohci-exynos.c
++++ b/drivers/usb/host/ohci-exynos.c
+@@ -146,6 +146,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add USB HCD\n");
+ goto fail_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ fail_add_hcd:
+diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c
+index d4ef539..efe31f3 100644
+--- a/drivers/usb/host/ohci-jz4740.c
++++ b/drivers/usb/host/ohci-jz4740.c
+@@ -217,6 +217,7 @@ static int jz4740_ohci_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret);
+ goto err_disable;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return 0;
+
+diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
+index e99db8a..719f28e 100644
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -274,8 +274,10 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
+
+ dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
+ ret = usb_add_hcd(hcd, irq, 0);
+- if (ret == 0)
++ if (ret == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return ret;
++ }
+
+ ohci_nxp_stop_hc();
+ fail_resource:
+diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c
+index 6c16dce..49b220d 100644
+--- a/drivers/usb/host/ohci-octeon.c
++++ b/drivers/usb/host/ohci-octeon.c
+@@ -171,6 +171,8 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev)
+ goto err3;
+ }
+
++ device_wakeup_enable(hcd->self.controller);
++
+ platform_set_drvdata(pdev, hcd);
+
+ return 0;
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index f253214..a44a4fe 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -367,6 +367,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
+ if (retval)
+ goto err3;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+ err3:
+ iounmap(hcd->regs);
+diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
+index 2145741..ec15aeb 100644
+--- a/drivers/usb/host/ohci-omap3.c
++++ b/drivers/usb/host/ohci-omap3.c
+@@ -130,6 +130,7 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
+ dev_dbg(dev, "failed to add hcd with err %d\n", ret);
+ goto err_add_hcd;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return 0;
+
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index f351ff5..68f674c 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -108,6 +108,8 @@ static int ohci_platform_probe(struct platform_device *dev)
+ if (err)
+ goto err_put_hcd;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ platform_set_drvdata(dev, hcd);
+
+ return err;
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index 81f3eba..83e33d4 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -147,8 +147,10 @@ static int ohci_hcd_ppc_of_probe(struct platform_device *op)
+ ohci_hcd_init(ohci);
+
+ rv = usb_add_hcd(hcd, irq, 0);
+- if (rv == 0)
++ if (rv == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
++ }
+
+ /* by now, 440epx is known to show usb_23 erratum */
+ np = of_find_compatible_node(NULL, NULL, "ibm,usb-ehci-440epx");
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 7d35cd9..71d8bc4 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -173,6 +173,7 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
+ goto fail_add_hcd;
+ }
+
++ device_wakeup_enable(hcd->self.controller);
+ return result;
+
+ fail_add_hcd:
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index e89ac4d..5343ecf 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -442,8 +442,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
+ ohci->num_ports = 3;
+
+ retval = usb_add_hcd(hcd, irq, 0);
+- if (retval == 0)
++ if (retval == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return retval;
++ }
+
+ pxa27x_stop_hc(pxa_ohci, &pdev->dev);
+ err3:
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index 83cd1dc..ff7c8f1 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -395,6 +395,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
+ if (retval != 0)
+ goto err_ioremap;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_ioremap:
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index aa9e127..2ac266d 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -211,8 +211,10 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev)
+ goto err2;
+
+ ret = usb_add_hcd(hcd, dev->irq[1], 0);
+- if (ret == 0)
++ if (ret == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return ret;
++ }
+
+ sa1111_stop_hc(dev);
+ err2:
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 2a5de5f..4e81c80 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -168,6 +168,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval)
+ goto err5;
++ device_wakeup_enable(hcd->self.controller);
+
+ /* enable power and unmask interrupts */
+
+diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
+index e418c19..4cb98ab 100644
+--- a/drivers/usb/host/ohci-spear.c
++++ b/drivers/usb/host/ohci-spear.c
+@@ -103,8 +103,10 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
+ ohci = hcd_to_ohci(hcd);
+
+ retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0);
+- if (retval == 0)
++ if (retval == 0) {
++ device_wakeup_enable(hcd->self.controller);
+ return retval;
++ }
+
+ clk_disable_unprepare(sohci_p->clk);
+ err_put_hcd:
+diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c
+index 22540ab..0b183e0 100644
+--- a/drivers/usb/host/ohci-tilegx.c
++++ b/drivers/usb/host/ohci-tilegx.c
+@@ -159,6 +159,7 @@ static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev)
+ ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
++ device_wakeup_enable(hcd->self.controller);
+ return ret;
+ }
+
+diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
+index ecb09a5..9c44093 100644
+--- a/drivers/usb/host/ohci-tmio.c
++++ b/drivers/usb/host/ohci-tmio.c
+@@ -250,6 +250,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
+ if (ret)
+ goto err_add_hcd;
+
++ device_wakeup_enable(hcd->self.controller);
+ if (ret == 0)
+ return ret;
+
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index 4a05148..778eeaf 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -3751,6 +3751,7 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev,
+ if (ret < 0)
+ return ERR_PTR(ret);
+
++ device_wakeup_enable(hcd->self.controller);
+ return hcd;
+ }
+
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 3bddfcf..47b1322 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -2514,6 +2514,7 @@ static int r8a66597_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "Failed to add hcd\n");
+ goto clean_up3;
+ }
++ device_wakeup_enable(hcd->self.controller);
+
+ return 0;
+
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 79620c3..0115e7f 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -1732,6 +1732,8 @@ static void remove_debug_file(struct sl811 *sl811)
+ if (retval != 0)
+ goto err6;
+
++ device_wakeup_enable(hcd->self.controller);
++
+ create_debug_file(sl811);
+ return retval;
+
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 46236e9..c067175 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -3133,6 +3133,7 @@ static int u132_probe(struct platform_device *pdev)
+ u132_u132_put_kref(u132);
+ return retval;
+ } else {
++ device_wakeup_enable(hcd->self.controller);
+ u132_monitor_queue_work(u132, 100);
+ return 0;
+ }
+diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
+index 53c23ff..ab25dc3 100644
+--- a/drivers/usb/host/uhci-grlib.c
++++ b/drivers/usb/host/uhci-grlib.c
+@@ -141,6 +141,7 @@ static int uhci_hcd_grlib_probe(struct platform_device *op)
+ if (rv)
+ goto err_uhci;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_uhci:
+diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
+index 3003fef..44e6c9d 100644
+--- a/drivers/usb/host/uhci-platform.c
++++ b/drivers/usb/host/uhci-platform.c
+@@ -108,6 +108,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
+ if (ret)
+ goto err_uhci;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+
+ err_uhci:
+diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
+index 1b0888f..d7b363a 100644
+--- a/drivers/usb/host/whci/hcd.c
++++ b/drivers/usb/host/whci/hcd.c
+@@ -293,6 +293,7 @@ static int whc_probe(struct umc_dev *umc)
+ dev_err(dev, "cannot add HCD: %d\n", ret);
+ goto error_usb_add_hcd;
+ }
++ device_wakeup_enable(usb_hcd->self.controller);
+
+ ret = wusbhc_b_create(wusbhc);
+ if (ret) {
+diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
+index d9c169f..9d29aa1 100644
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -139,6 +139,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
+ ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (ret)
+ goto unmap_registers;
++ device_wakeup_enable(hcd->self.controller);
+
+ /* USB 2.0 roothub is stored in the platform_device now. */
+ hcd = platform_get_drvdata(pdev);
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 6582a20..e208375 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2657,6 +2657,7 @@ int musb_host_setup(struct musb *musb, int power_budget)
+ if (ret < 0)
+ return ret;
+
++ device_wakeup_enable(hcd->self.controller);
+ return 0;
+ }
+
+diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
+index e9d4cd9..3775283 100644
+--- a/drivers/usb/phy/phy-msm-usb.c
++++ b/drivers/usb/phy/phy-msm-usb.c
+@@ -669,6 +669,7 @@ static void msm_otg_start_host(struct usb_phy *phy, int on)
+ pdata->setup_gpio(OTG_STATE_A_HOST);
+ #ifdef CONFIG_USB
+ usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
++ device_wakeup_enable(hcd->self.controller);
+ #endif
+ } else {
+ dev_dbg(phy->dev, "host off\n");
+diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
+index 98f6ac6..44f316e 100644
+--- a/drivers/usb/phy/phy-mv-usb.c
++++ b/drivers/usb/phy/phy-mv-usb.c
+@@ -213,10 +213,12 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on)
+
+ hcd = bus_to_hcd(otg->host);
+
+- if (on)
++ if (on) {
+ usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+- else
++ device_wakeup_enable(hcd->self.controller);
++ } else {
+ usb_remove_hcd(hcd);
++ }
+ #endif /* CONFIG_USB */
+ }
+
+diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
+index e40f565..10e1ded 100644
+--- a/drivers/usb/renesas_usbhs/mod_host.c
++++ b/drivers/usb/renesas_usbhs/mod_host.c
+@@ -1469,6 +1469,7 @@ static int usbhsh_start(struct usbhs_priv *priv)
+ ret = usb_add_hcd(hcd, 0, 0);
+ if (ret < 0)
+ return 0;
++ device_wakeup_enable(hcd->self.controller);
+
+ /*
+ * pipe initialize and enable DCP
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch b/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch
new file mode 100644
index 0000000000..070f4f4cd5
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch
@@ -0,0 +1,322 @@
+From 6b63b9b2093258541dd79a3ed311cd1d0412b846 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 5 Jan 2014 14:42:39 +0100
+Subject: [PATCH] ohci-platform: Add support for devicetree instantiation
+
+Add support for ohci-platform instantiation from devicetree, including
+optionally getting clks and a phy from devicetree, and enabling / disabling
+those on power_on / off.
+
+This should allow using ohci-platform from devicetree in various cases.
+Specifically after this commit it can be used for the ohci controller found
+on Allwinner sunxi SoCs.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+---
+ Documentation/devicetree/bindings/usb/usb-ohci.txt | 22 +++
+ drivers/usb/host/ohci-platform.c | 162 ++++++++++++++++++---
+ 2 files changed, 162 insertions(+), 22 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-ohci.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+new file mode 100644
+index 0000000..6ba38d9
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+@@ -0,0 +1,22 @@
++USB OHCI controllers
++
++Required properties:
++- compatible : "usb-ohci"
++- reg : ohci controller register range (address and length)
++- interrupts : ohci controller interrupt
++
++Optional properties:
++- clocks : a list of phandle + clock specifier pairs
++- phys : phandle + phy specifier pair
++- phy-names : "usb"
++
++Example:
++
++ ohci0: usb@01c14400 {
++ compatible = "allwinner,sun4i-a10-ohci", "usb-ohci";
++ reg = <0x01c14400 0x100>;
++ interrupts = <64>;
++ clocks = <&usb_clk 6>, <&ahb_gates 2>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ };
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index 68f674c..49304dd 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -3,6 +3,7 @@
+ *
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Derived from the OCHI-SSB driver
+ * Derived from the OHCI-PCI driver
+@@ -14,11 +15,14 @@
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
+ #include <linux/hrtimer.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/err.h>
++#include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+ #include <linux/usb/ohci_pdriver.h>
+ #include <linux/usb.h>
+@@ -27,6 +31,13 @@
+ #include "ohci.h"
+
+ #define DRIVER_DESC "OHCI generic platform driver"
++#define OHCI_MAX_CLKS 3
++#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
++
++struct ohci_platform_priv {
++ struct clk *clks[OHCI_MAX_CLKS];
++ struct phy *phy;
++};
+
+ static const char hcd_name[] = "ohci-platform";
+
+@@ -48,11 +59,67 @@ static int ohci_platform_reset(struct usb_hcd *hcd)
+ return ohci_setup(hcd);
+ }
+
++static int ohci_platform_power_on(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
++ int clk, ret;
++
++ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
++ ret = clk_prepare_enable(priv->clks[clk]);
++ if (ret)
++ goto err_disable_clks;
++ }
++
++ if (priv->phy) {
++ ret = phy_init(priv->phy);
++ if (ret)
++ goto err_disable_clks;
++
++ ret = phy_power_on(priv->phy);
++ if (ret)
++ goto err_exit_phy;
++ }
++
++ return 0;
++
++err_exit_phy:
++ phy_exit(priv->phy);
++err_disable_clks:
++ while (--clk >= 0)
++ clk_disable_unprepare(priv->clks[clk]);
++
++ return ret;
++}
++
++static void ohci_platform_power_off(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
++ int clk;
++
++ if (priv->phy) {
++ phy_power_off(priv->phy);
++ phy_exit(priv->phy);
++ }
++
++ for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
++ if (priv->clks[clk])
++ clk_disable_unprepare(priv->clks[clk]);
++}
++
+ static struct hc_driver __read_mostly ohci_platform_hc_driver;
+
+ static const struct ohci_driver_overrides platform_overrides __initconst = {
+- .product_desc = "Generic Platform OHCI controller",
+- .reset = ohci_platform_reset,
++ .product_desc = "Generic Platform OHCI controller",
++ .reset = ohci_platform_reset,
++ .extra_priv_size = sizeof(struct ohci_platform_priv),
++};
++
++static struct usb_ohci_pdata ohci_platform_defaults = {
++ .power_on = ohci_platform_power_on,
++ .power_suspend = ohci_platform_power_off,
++ .power_off = ohci_platform_power_off,
+ };
+
+ static int ohci_platform_probe(struct platform_device *dev)
+@@ -60,17 +127,23 @@ static int ohci_platform_probe(struct platform_device *dev)
+ struct usb_hcd *hcd;
+ struct resource *res_mem;
+ struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
+- int irq;
+- int err = -ENOMEM;
+-
+- if (!pdata) {
+- WARN_ON(1);
+- return -ENODEV;
+- }
++ struct ohci_platform_priv *priv;
++ int err, irq, clk = 0;
+
+ if (usb_disabled())
+ return -ENODEV;
+
++ /*
++ * Use reasonable defaults so platforms don't have to provide these
++ * with DT probing on ARM.
++ */
++ if (!pdata)
++ pdata = &ohci_platform_defaults;
++
++ err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
++ if (err)
++ return err;
++
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0) {
+ dev_err(&dev->dev, "no irq provided");
+@@ -83,17 +156,40 @@ static int ohci_platform_probe(struct platform_device *dev)
+ return -ENXIO;
+ }
+
++ hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
++ dev_name(&dev->dev));
++ if (!hcd)
++ return -ENOMEM;
++
++ platform_set_drvdata(dev, hcd);
++ dev->dev.platform_data = pdata;
++ priv = hcd_to_ohci_priv(hcd);
++
++ if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
++ priv->phy = devm_phy_get(&dev->dev, "usb");
++ if (IS_ERR(priv->phy)) {
++ err = PTR_ERR(priv->phy);
++ if (err == -EPROBE_DEFER)
++ goto err_put_hcd;
++ priv->phy = NULL;
++ }
++
++ for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
++ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
++ if (IS_ERR(priv->clks[clk])) {
++ err = PTR_ERR(priv->clks[clk]);
++ if (err == -EPROBE_DEFER)
++ goto err_put_clks;
++ priv->clks[clk] = NULL;
++ break;
++ }
++ }
++ }
++
+ if (pdata->power_on) {
+ err = pdata->power_on(dev);
+ if (err < 0)
+- return err;
+- }
+-
+- hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+- dev_name(&dev->dev));
+- if (!hcd) {
+- err = -ENOMEM;
+- goto err_power;
++ goto err_put_clks;
+ }
+
+ hcd->rsrc_start = res_mem->start;
+@@ -102,11 +198,11 @@ static int ohci_platform_probe(struct platform_device *dev)
+ hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
+ if (IS_ERR(hcd->regs)) {
+ err = PTR_ERR(hcd->regs);
+- goto err_put_hcd;
++ goto err_power;
+ }
+ err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (err)
+- goto err_put_hcd;
++ goto err_power;
+
+ device_wakeup_enable(hcd->self.controller);
+
+@@ -114,11 +210,17 @@ static int ohci_platform_probe(struct platform_device *dev)
+
+ return err;
+
+-err_put_hcd:
+- usb_put_hcd(hcd);
+ err_power:
+ if (pdata->power_off)
+ pdata->power_off(dev);
++err_put_clks:
++ while (--clk >= 0)
++ clk_put(priv->clks[clk]);
++err_put_hcd:
++ if (pdata == &ohci_platform_defaults)
++ dev->dev.platform_data = NULL;
++
++ usb_put_hcd(hcd);
+
+ return err;
+ }
+@@ -127,13 +229,22 @@ static int ohci_platform_remove(struct platform_device *dev)
+ {
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
++ int clk;
+
+ usb_remove_hcd(hcd);
+- usb_put_hcd(hcd);
+
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
++ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
++ clk_put(priv->clks[clk]);
++
++ usb_put_hcd(hcd);
++
++ if (pdata == &ohci_platform_defaults)
++ dev->dev.platform_data = NULL;
++
+ return 0;
+ }
+
+@@ -180,6 +291,12 @@ static int ohci_platform_resume(struct device *dev)
+ #define ohci_platform_resume NULL
+ #endif /* CONFIG_PM */
+
++static const struct of_device_id ohci_platform_ids[] = {
++ { .compatible = "usb-ohci", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ohci_platform_ids);
++
+ static const struct platform_device_id ohci_platform_table[] = {
+ { "ohci-platform", 0 },
+ { }
+@@ -200,6 +317,7 @@ static int ohci_platform_resume(struct device *dev)
+ .owner = THIS_MODULE,
+ .name = "ohci-platform",
+ .pm = &ohci_platform_pm_ops,
++ .of_match_table = ohci_platform_ids,
+ }
+ };
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch b/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch
new file mode 100644
index 0000000000..908d8410aa
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch
@@ -0,0 +1,392 @@
+From 543824fa2a8a592a6eec0e0053063284980dc378 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 5 Jan 2014 00:04:02 +0100
+Subject: [PATCH] ehci-platform: Add support for clks and phy passed through
+ devicetree
+
+Currently ehci-platform is only used in combination with devicetree when used
+with some Via socs. By extending it to (optionally) get clks and a phy from
+devicetree, and enabling / disabling those on power_on / off, it can be used
+more generically. Specifically after this commit it can be used for the
+ehci controller on Allwinner sunxi SoCs.
+
+Since ehci-platform is intended to handle any generic enough non pci ehci
+device, add a "usb-ehci" compatibility string.
+
+There already is a usb-ehci device-tree bindings document, update this
+with clks and phy bindings info.
+
+Although actually quite generic so far the via,vt8500 compatibilty string
+had its own bindings document. Somehow we even ended up with 2 of them. Since
+these provide no extra information over the generic usb-ehci documentation,
+this patch removes them.
+
+The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
+even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
+not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
+2 drivers claiming the same compatibility string getting build on ppc.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+---
+ Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
+ .../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
+ .../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
+ drivers/usb/host/Kconfig | 1 +
+ drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
+ 5 files changed, 142 insertions(+), 58 deletions(-)
+ delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+ delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
+index fa18612..2c1aeeb 100644
+--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
+@@ -7,13 +7,14 @@ Required properties:
+ (debug-port or other) can be also specified here, but only after
+ definition of standard EHCI registers.
+ - interrupts : one EHCI interrupt should be described here.
+-If device registers are implemented in big endian mode, the device
+-node should have "big-endian-regs" property.
+-If controller implementation operates with big endian descriptors,
+-"big-endian-desc" property should be specified.
+-If both big endian registers and descriptors are used by the controller
+-implementation, "big-endian" property can be specified instead of having
+-both "big-endian-regs" and "big-endian-desc".
++
++Optional properties:
++ - big-endian-regs : boolean, set this for hcds with big-endian registers
++ - big-endian-desc : boolean, set this for hcds with big-endian descriptors
++ - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
++ - clocks : a list of phandle + clock specifier pairs
++ - phys : phandle + phy specifier pair
++ - phy-names : "usb"
+
+ Example (Sequoia 440EPx):
+ ehci@e0000300 {
+@@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
+ reg = <0 e0000300 90 0 e0000390 70>;
+ big-endian;
+ };
++
++Example (Allwinner sun4i A10 SoC):
++ ehci0: usb@01c14000 {
++ compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
++ reg = <0x01c14000 0x100>;
++ interrupts = <39>;
++ clocks = <&ahb_gates 1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ };
+diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+deleted file mode 100644
+index 17b3ad1..0000000
+--- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
++++ /dev/null
+@@ -1,15 +0,0 @@
+-VIA/Wondermedia VT8500 EHCI Controller
+------------------------------------------------------
+-
+-Required properties:
+-- compatible : "via,vt8500-ehci"
+-- reg : Should contain 1 register ranges(address and length)
+-- interrupts : ehci controller interrupt
+-
+-Example:
+-
+- ehci@d8007900 {
+- compatible = "via,vt8500-ehci";
+- reg = <0xd8007900 0x200>;
+- interrupts = <43>;
+- };
+diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+deleted file mode 100644
+index 5fb8fd6..0000000
+--- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
++++ /dev/null
+@@ -1,12 +0,0 @@
+-VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
+-
+-Required properties:
+- - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
+- - reg: Address range of the ehci registers. size should be 0x200
+- - interrupts: Should contain the ehci interrupt.
+-
+-usb: ehci@D8007100 {
+- compatible = "wm,prizm-ehci", "usb-ehci";
+- reg = <0xD8007100 0x200>;
+- interrupts = <1>;
+-};
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index a9707da..e28cbe0 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -255,6 +255,7 @@ config USB_EHCI_ATH79
+
+ config USB_EHCI_HCD_PLATFORM
+ tristate "Generic EHCI driver for a platform device"
++ depends on !PPC_OF
+ default n
+ ---help---
+ Adds an EHCI host driver for a generic platform device, which
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 01536cf..5ebd0b7 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -3,6 +3,7 @@
+ *
+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
+ * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Derived from the ohci-ssb driver
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+@@ -18,6 +19,7 @@
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
++#include <linux/clk.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/err.h>
+ #include <linux/kernel.h>
+@@ -25,6 +27,7 @@
+ #include <linux/io.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
++#include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+ #include <linux/usb.h>
+ #include <linux/usb/hcd.h>
+@@ -33,6 +36,13 @@
+ #include "ehci.h"
+
+ #define DRIVER_DESC "EHCI generic platform driver"
++#define EHCI_MAX_CLKS 3
++#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
++
++struct ehci_platform_priv {
++ struct clk *clks[EHCI_MAX_CLKS];
++ struct phy *phy;
++};
+
+ static const char hcd_name[] = "ehci-platform";
+
+@@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+ return 0;
+ }
+
++static int ehci_platform_power_on(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
++ int clk, ret;
++
++ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
++ ret = clk_prepare_enable(priv->clks[clk]);
++ if (ret)
++ goto err_disable_clks;
++ }
++
++ if (priv->phy) {
++ ret = phy_init(priv->phy);
++ if (ret)
++ goto err_disable_clks;
++
++ ret = phy_power_on(priv->phy);
++ if (ret)
++ goto err_exit_phy;
++ }
++
++ return 0;
++
++err_exit_phy:
++ phy_exit(priv->phy);
++err_disable_clks:
++ while (--clk >= 0)
++ clk_disable_unprepare(priv->clks[clk]);
++
++ return ret;
++}
++
++static void ehci_platform_power_off(struct platform_device *dev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
++ int clk;
++
++ if (priv->phy) {
++ phy_power_off(priv->phy);
++ phy_exit(priv->phy);
++ }
++
++ for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
++ if (priv->clks[clk])
++ clk_disable_unprepare(priv->clks[clk]);
++}
++
+ static struct hc_driver __read_mostly ehci_platform_hc_driver;
+
+ static const struct ehci_driver_overrides platform_overrides __initconst = {
+- .reset = ehci_platform_reset,
++ .reset = ehci_platform_reset,
++ .extra_priv_size = sizeof(struct ehci_platform_priv),
+ };
+
+-static struct usb_ehci_pdata ehci_platform_defaults;
++static struct usb_ehci_pdata ehci_platform_defaults = {
++ .power_on = ehci_platform_power_on,
++ .power_suspend = ehci_platform_power_off,
++ .power_off = ehci_platform_power_off,
++};
+
+ static int ehci_platform_probe(struct platform_device *dev)
+ {
+ struct usb_hcd *hcd;
+ struct resource *res_mem;
+- struct usb_ehci_pdata *pdata;
+- int irq;
+- int err;
++ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
++ struct ehci_platform_priv *priv;
++ int err, irq, clk = 0;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ /*
+- * use reasonable defaults so platforms don't have to provide these.
+- * with DT probing on ARM, none of these are set.
++ * Use reasonable defaults so platforms don't have to provide these
++ * with DT probing on ARM.
+ */
+- if (!dev_get_platdata(&dev->dev))
+- dev->dev.platform_data = &ehci_platform_defaults;
++ if (!pdata)
++ pdata = &ehci_platform_defaults;
+
+ err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return err;
+
+- pdata = dev_get_platdata(&dev->dev);
+-
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0) {
+ dev_err(&dev->dev, "no irq provided");
+@@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev)
+ return -ENXIO;
+ }
+
++ hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
++ dev_name(&dev->dev));
++ if (!hcd)
++ return -ENOMEM;
++
++ platform_set_drvdata(dev, hcd);
++ dev->dev.platform_data = pdata;
++ priv = hcd_to_ehci_priv(hcd);
++
++ if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
++ priv->phy = devm_phy_get(&dev->dev, "usb");
++ if (IS_ERR(priv->phy)) {
++ err = PTR_ERR(priv->phy);
++ if (err == -EPROBE_DEFER)
++ goto err_put_hcd;
++ priv->phy = NULL;
++ }
++
++ for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
++ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
++ if (IS_ERR(priv->clks[clk])) {
++ err = PTR_ERR(priv->clks[clk]);
++ if (err == -EPROBE_DEFER)
++ goto err_put_clks;
++ priv->clks[clk] = NULL;
++ break;
++ }
++ }
++ }
++
+ if (pdata->power_on) {
+ err = pdata->power_on(dev);
+ if (err < 0)
+- return err;
+- }
+-
+- hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+- dev_name(&dev->dev));
+- if (!hcd) {
+- err = -ENOMEM;
+- goto err_power;
++ goto err_put_clks;
+ }
+
+ hcd->rsrc_start = res_mem->start;
+@@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev)
+ hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
+ if (IS_ERR(hcd->regs)) {
+ err = PTR_ERR(hcd->regs);
+- goto err_put_hcd;
++ goto err_power;
+ }
+ err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (err)
+- goto err_put_hcd;
++ goto err_power;
+
+ device_wakeup_enable(hcd->self.controller);
+ platform_set_drvdata(dev, hcd);
+
+ return err;
+
+-err_put_hcd:
+- usb_put_hcd(hcd);
+ err_power:
+ if (pdata->power_off)
+ pdata->power_off(dev);
++err_put_clks:
++ while (--clk >= 0)
++ clk_put(priv->clks[clk]);
++err_put_hcd:
++ if (pdata == &ehci_platform_defaults)
++ dev->dev.platform_data = NULL;
++
++ usb_put_hcd(hcd);
+
+ return err;
+ }
+@@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev)
+ {
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
++ int clk;
+
+ usb_remove_hcd(hcd);
+- usb_put_hcd(hcd);
+
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
++ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
++ clk_put(priv->clks[clk]);
++
++ usb_put_hcd(hcd);
++
+ if (pdata == &ehci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
+@@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev)
+ static const struct of_device_id vt8500_ehci_ids[] = {
+ { .compatible = "via,vt8500-ehci", },
+ { .compatible = "wm,prizm-ehci", },
++ { .compatible = "usb-ehci", },
+ {}
+ };
++MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
+
+ static const struct platform_device_id ehci_platform_table[] = {
+ { "ehci-platform", 0 },
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch b/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch
new file mode 100644
index 0000000000..178bf4590c
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch
@@ -0,0 +1,80 @@
+From 10d7c018269928db8487057c4c143dbd014d2262 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 21 Jan 2014 16:05:47 +0100
+Subject: [PATCH] ohci-platform: Add support for controllers with big-endian
+ regs / descriptors
+
+Note this commit uses the same devicetree booleans for this as the ones
+already existing in the usb-ehci bindings, see:
+Documentation/devicetree/bindings/usb/usb-ehci.txt
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/usb/usb-ohci.txt | 3 +++
+ drivers/usb/host/ohci-platform.c | 27 ++++++++++++++++++++++
+ 2 files changed, 30 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+index 6ba38d9..6933b0c 100644
+--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+@@ -6,6 +6,9 @@ Required properties:
+ - interrupts : ohci controller interrupt
+
+ Optional properties:
++- big-endian-regs : boolean, set this for hcds with big-endian registers
++- big-endian-desc : boolean, set this for hcds with big-endian descriptors
++- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - clocks : a list of phandle + clock specifier pairs
+ - phys : phandle + phy specifier pair
+ - phy-names : "usb"
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index 49304dd..e2c28fd 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -128,6 +128,7 @@ static int ohci_platform_probe(struct platform_device *dev)
+ struct resource *res_mem;
+ struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ohci_platform_priv *priv;
++ struct ohci_hcd *ohci;
+ int err, irq, clk = 0;
+
+ if (usb_disabled())
+@@ -164,8 +165,34 @@ static int ohci_platform_probe(struct platform_device *dev)
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ohci_priv(hcd);
++ ohci = hcd_to_ohci(hcd);
+
+ if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
++ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
++ ohci->flags |= OHCI_QUIRK_BE_MMIO;
++
++ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
++ ohci->flags |= OHCI_QUIRK_BE_DESC;
++
++ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
++ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
++
++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
++ if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
++ dev_err(&dev->dev,
++ "Error big-endian-regs not compiled in\n");
++ err = -EINVAL;
++ goto err_put_hcd;
++ }
++#endif
++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
++ if (ohci->flags & OHCI_QUIRK_BE_DESC) {
++ dev_err(&dev->dev,
++ "Error big-endian-desc not compiled in\n");
++ err = -EINVAL;
++ goto err_put_hcd;
++ }
++#endif
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch b/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch
new file mode 100644
index 0000000000..5f7043401d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch
@@ -0,0 +1,77 @@
+From 57b5e74a0d7ba5dbf77ee05a2693635faba5fe30 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 21 Jan 2014 16:20:53 +0100
+Subject: [PATCH] ehci-platform: Add support for controllers with big-endian
+ regs / descriptors
+
+This uses the already documented devicetree booleans for this, see:
+Documentation/devicetree/bindings/usb/usb-ehci.txt
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/usb/host/ehci-platform.c | 33 +++++++++++++++++++++++++++++++--
+ 1 file changed, 31 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 5ebd0b7..8fde649 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -55,8 +55,10 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
+
+ hcd->has_tt = pdata->has_tt;
+ ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+- ehci->big_endian_desc = pdata->big_endian_desc;
+- ehci->big_endian_mmio = pdata->big_endian_mmio;
++ if (pdata->big_endian_desc)
++ ehci->big_endian_desc = 1;
++ if (pdata->big_endian_mmio)
++ ehci->big_endian_mmio = 1;
+ ehci->ignore_oc = pdata->ignore_oc;
+
+ if (pdata->pre_setup) {
+@@ -142,6 +144,7 @@ static int ehci_platform_probe(struct platform_device *dev)
+ struct resource *res_mem;
+ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ehci_platform_priv *priv;
++ struct ehci_hcd *ehci;
+ int err, irq, clk = 0;
+
+ if (usb_disabled())
+@@ -177,8 +180,34 @@ static int ehci_platform_probe(struct platform_device *dev)
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ehci_priv(hcd);
++ ehci = hcd_to_ehci(hcd);
+
+ if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
++ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
++ ehci->big_endian_mmio = 1;
++
++ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
++ ehci->big_endian_desc = 1;
++
++ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
++ ehci->big_endian_mmio = ehci->big_endian_desc = 1;
++
++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
++ if (ehci->big_endian_mmio) {
++ dev_err(&dev->dev,
++ "Error big-endian-regs not compiled in\n");
++ err = -EINVAL;
++ goto err_put_hcd;
++ }
++#endif
++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
++ if (ehci->big_endian_desc) {
++ dev_err(&dev->dev,
++ "Error big-endian-desc not compiled in\n");
++ err = -EINVAL;
++ goto err_put_hcd;
++ }
++#endif
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch
new file mode 100644
index 0000000000..4255a34388
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch
@@ -0,0 +1,69 @@
+From abddd82743cc2c4acdfe66a6d5e63f2085d2269b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 11 Feb 2014 11:27:29 +0100
+Subject: [PATCH] ohci-platform: Change compatible string from usb-ohci to
+ generic-ohci
+
+The initial versions of the devicetree enablement patches for ohci-platform
+used "ohci-platform" as compatible string. However this was disliked by various
+reviewers because the platform bus is a Linux invention and devicetree is
+supposed to be OS agnostic. After much discussion I gave up and went with
+the generic usb-ohci as requested.
+
+In retro-spect I should have chosen something different, the dts files for many
+existing boards already claim to be compatible with "usb-ohci", ie they have:
+
+ compatible = "ti,ohci-omap3", "usb-ohci";
+
+In theory this should not be a problem since the "ti,ohci-omap3" entry takes
+presedence, but in practice using a conflicting compatible string is an issue,
+because it makes which driver gets used depend on driver registration order.
+
+This patch changes the compatible string claimed by ohci-platform to
+"generic-ohci", avoiding the driver registration / module loading ordering
+problems.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/usb/usb-ohci.txt | 4 ++--
+ drivers/usb/host/ohci-platform.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+index 6933b0c..45f67d9 100644
+--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
+@@ -1,7 +1,7 @@
+ USB OHCI controllers
+
+ Required properties:
+-- compatible : "usb-ohci"
++- compatible : "generic-ohci"
+ - reg : ohci controller register range (address and length)
+ - interrupts : ohci controller interrupt
+
+@@ -16,7 +16,7 @@ Optional properties:
+ Example:
+
+ ohci0: usb@01c14400 {
+- compatible = "allwinner,sun4i-a10-ohci", "usb-ohci";
++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <64>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index e2c28fd..b6ca0b2 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -319,7 +319,7 @@ static int ohci_platform_resume(struct device *dev)
+ #endif /* CONFIG_PM */
+
+ static const struct of_device_id ohci_platform_ids[] = {
+- { .compatible = "usb-ohci", },
++ { .compatible = "generic-ohci", },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, ohci_platform_ids);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch
new file mode 100644
index 0000000000..5222422a5f
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch
@@ -0,0 +1,83 @@
+From 80c544c77beeffee4e9484bf193ab391297688cd Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 11 Feb 2014 11:46:13 +0100
+Subject: [PATCH] ehci-platform: Change compatible string from usb-ehci to
+ generic-ehci
+
+The initial versions of the devicetree enablement patches for ehci-platform
+used "ehci-platform" as compatible string. However this was disliked by various
+reviewers because the platform bus is a Linux invention and devicetree is
+supposed to be OS agnostic. After much discussion I gave up, added a:
+"depends on !PPC_OF" to Kconfig to avoid a known conflict with PPC-OF platforms
+and went with the generic usb-ehci as requested.
+
+In retro-spect I should have chosen something different, the dts files for many
+existing boards already claim to be compatible with "usb-ehci", ie they have:
+
+ compatible = "ti,ehci-omap", "usb-ehci";
+
+In theory this should not be a problem since the "ti,ehci-omap" entry takes
+presedence, but in practice using a conflicting compatible string is an issue,
+because it makes which driver gets used depend on driver registration order.
+
+This patch changes the compatible string claimed by ehci-platform to
+"generic-ehci", avoiding the driver registration / module loading ordering
+problems, and removes the "depends on !PPC_OF" workaround.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/usb/usb-ehci.txt | 4 ++--
+ drivers/usb/host/Kconfig | 1 -
+ drivers/usb/host/ehci-platform.c | 2 +-
+ 3 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
+index 2c1aeeb..ff151ec 100644
+--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
+@@ -1,7 +1,7 @@
+ USB EHCI controllers
+
+ Required properties:
+- - compatible : should be "usb-ehci".
++ - compatible : should be "generic-ehci".
+ - reg : should contain at least address and length of the standard EHCI
+ register set for the device. Optional platform-dependent registers
+ (debug-port or other) can be also specified here, but only after
+@@ -27,7 +27,7 @@ Example (Sequoia 440EPx):
+
+ Example (Allwinner sun4i A10 SoC):
+ ehci0: usb@01c14000 {
+- compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <39>;
+ clocks = <&ahb_gates 1>;
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index e28cbe0..a9707da 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -255,7 +255,6 @@ config USB_EHCI_ATH79
+
+ config USB_EHCI_HCD_PLATFORM
+ tristate "Generic EHCI driver for a platform device"
+- depends on !PPC_OF
+ default n
+ ---help---
+ Adds an EHCI host driver for a generic platform device, which
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 8fde649..1178730 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -333,7 +333,7 @@ static int ehci_platform_resume(struct device *dev)
+ static const struct of_device_id vt8500_ehci_ids[] = {
+ { .compatible = "via,vt8500-ehci", },
+ { .compatible = "wm,prizm-ehci", },
+- { .compatible = "usb-ehci", },
++ { .compatible = "generic-ehci", },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch
new file mode 100644
index 0000000000..0b7695ac34
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch
@@ -0,0 +1,83 @@
+From 3aa1e8b65b7db768fade643e26f8995860596795 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 11 Feb 2014 17:41:48 +0100
+Subject: [PATCH] uhci-platform: Change compatible string from platform-uhci to
+ generic-uhci
+
+This brings the uhci-platform bindings in sync with what we've done for
+the ohci- and ehci-platform drivers. As discussed there using platform as a
+prefix is a bit weird as the platform bus is a Linux specific thing and
+the bindings are supposed to be OS agnostic.
+
+Note that the old platform-uhci compatible string is kept around for, well,
+compatibility reasons.
+
+While at it rename the bindings txt file to match the name of all the
+other ?hci-platform bindings docs.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/usb/platform-uhci.txt | 15 ---------------
+ Documentation/devicetree/bindings/usb/usb-uhci.txt | 15 +++++++++++++++
+ drivers/usb/host/uhci-platform.c | 1 +
+ 3 files changed, 16 insertions(+), 15 deletions(-)
+ delete mode 100644 Documentation/devicetree/bindings/usb/platform-uhci.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-uhci.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt
+deleted file mode 100644
+index a4fb071..0000000
+--- a/Documentation/devicetree/bindings/usb/platform-uhci.txt
++++ /dev/null
+@@ -1,15 +0,0 @@
+-Generic Platform UHCI Controller
+------------------------------------------------------
+-
+-Required properties:
+-- compatible : "platform-uhci"
+-- reg : Should contain 1 register ranges(address and length)
+-- interrupts : UHCI controller interrupt
+-
+-Example:
+-
+- uhci@d8007b00 {
+- compatible = "platform-uhci";
+- reg = <0xd8007b00 0x200>;
+- interrupts = <43>;
+- };
+diff --git a/Documentation/devicetree/bindings/usb/usb-uhci.txt b/Documentation/devicetree/bindings/usb/usb-uhci.txt
+new file mode 100644
+index 0000000..2981334
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt
+@@ -0,0 +1,15 @@
++Generic Platform UHCI Controller
++-----------------------------------------------------
++
++Required properties:
++- compatible : "generic-uhci" (deprecated: "platform-uhci")
++- reg : Should contain 1 register ranges(address and length)
++- interrupts : UHCI controller interrupt
++
++Example:
++
++ uhci@d8007b00 {
++ compatible = "generic-uhci";
++ reg = <0xd8007b00 0x200>;
++ interrupts = <43>;
++ };
+diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
+index 44e6c9d..01833ab 100644
+--- a/drivers/usb/host/uhci-platform.c
++++ b/drivers/usb/host/uhci-platform.c
+@@ -148,6 +148,7 @@ static void uhci_hcd_platform_shutdown(struct platform_device *op)
+ }
+
+ static const struct of_device_id platform_uhci_ids[] = {
++ { .compatible = "generic-uhci", },
+ { .compatible = "platform-uhci", },
+ {}
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch
new file mode 100644
index 0000000000..03f42f8483
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch
@@ -0,0 +1,56 @@
+From 1f5109503787538c4a5deb3be7da8336951b105b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 11 Feb 2014 17:50:51 +0100
+Subject: [PATCH] xhci-platform: Change compatible string from xhci-platform to
+ generic-xhci
+
+This brings the xhci-platform bindings in sync with what we've done for
+the ohci- and ehci-platform drivers. As discussed there using platform as a
+postfix is a bit weird as the platform bus is a Linux specific thing and
+the bindings are supposed to be OS agnostic.
+
+Note that the old xhci-platform compatible string is kept around for, well,
+compatibility reasons.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/usb/usb-xhci.txt | 4 ++--
+ drivers/usb/host/xhci-plat.c | 1 +
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
+index 5752df0..90f8f60 100644
+--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
+@@ -1,14 +1,14 @@
+ USB xHCI controllers
+
+ Required properties:
+- - compatible: should be "xhci-platform".
++ - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
+ - reg: should contain address and length of the standard XHCI
+ register set for the device.
+ - interrupts: one XHCI interrupt should be described here.
+
+ Example:
+ usb@f0931000 {
+- compatible = "xhci-platform";
++ compatible = "generic-xhci";
+ reg = <0xf0931000 0x8c8>;
+ interrupts = <0x0 0x4e 0x0>;
+ };
+diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
+index 8abda5c..8affef9 100644
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -226,6 +226,7 @@ static int xhci_plat_resume(struct device *dev)
+
+ #ifdef CONFIG_OF
+ static const struct of_device_id usb_xhci_of_match[] = {
++ { .compatible = "generic-xhci" },
+ { .compatible = "xhci-platform" },
+ { },
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch b/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch
new file mode 100644
index 0000000000..a31f16b8f8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch
@@ -0,0 +1,127 @@
+From edb7ebba49b6946e80dfac0d13ac15028952aa29 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 9 Jan 2014 19:33:04 +0100
+Subject: [PATCH] clk: sunxi: Add support for USB clock-register reset bits
+
+The usb-clk register is special in that it not only contains clk gate bits,
+but also has a few reset bits. This commit adds support for this by allowing
+gates type sunxi clks to also register a reset controller.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/clk/sunxi/clk-sunxi.c | 71 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 71 insertions(+)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 46a38b4..2dbaee7 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -18,6 +18,7 @@
+ #include <linux/clkdev.h>
+ #include <linux/of.h>
+ #include <linux/of_address.h>
++#include <linux/reset-controller.h>
+
+ #include "clk-factors.h"
+
+@@ -852,6 +853,59 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
+
+
+ /**
++ * sunxi_gates_reset... - reset bits in leaf gate clk registers handling
++ */
++
++struct gates_reset_data {
++ void __iomem *reg;
++ spinlock_t *lock;
++ struct reset_controller_dev rcdev;
++};
++
++static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct gates_reset_data *data = container_of(rcdev,
++ struct gates_reset_data,
++ rcdev);
++ unsigned long flags;
++ u32 reg;
++
++ spin_lock_irqsave(data->lock, flags);
++
++ reg = readl(data->reg);
++ writel(reg & ~BIT(id), data->reg);
++
++ spin_unlock_irqrestore(data->lock, flags);
++
++ return 0;
++}
++
++static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev,
++ unsigned long id)
++{
++ struct gates_reset_data *data = container_of(rcdev,
++ struct gates_reset_data,
++ rcdev);
++ unsigned long flags;
++ u32 reg;
++
++ spin_lock_irqsave(data->lock, flags);
++
++ reg = readl(data->reg);
++ writel(reg | BIT(id), data->reg);
++
++ spin_unlock_irqrestore(data->lock, flags);
++
++ return 0;
++}
++
++static struct reset_control_ops sunxi_gates_reset_ops = {
++ .assert = sunxi_gates_reset_assert,
++ .deassert = sunxi_gates_reset_deassert,
++};
++
++/**
+ * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
+ */
+
+@@ -859,6 +913,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
+
+ struct gates_data {
+ DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
++ u32 reset_mask;
+ };
+
+ static const struct gates_data sun4i_axi_gates_data __initconst = {
+@@ -929,6 +984,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
+ struct gates_data *data)
+ {
+ struct clk_onecell_data *clk_data;
++ struct gates_reset_data *reset_data;
+ const char *clk_parent;
+ const char *clk_name;
+ void *reg;
+@@ -972,6 +1028,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
+ clk_data->clk_num = i;
+
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++
++ /* Register a reset controler for gates with reset bits */
++ if (data->reset_mask == 0)
++ return;
++
++ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
++ if (!reset_data)
++ return;
++
++ reset_data->reg = reg;
++ reset_data->lock = &clk_lock;
++ reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
++ reset_data->rcdev.ops = &sunxi_gates_reset_ops;
++ reset_data->rcdev.of_node = node;
++ reset_controller_register(&reset_data->rcdev);
+ }
+
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch b/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch
new file mode 100644
index 0000000000..4302c0e5bb
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch
@@ -0,0 +1,50 @@
+From a6459be451bc7eb541aca2be3b36b06955d06622 Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Thu, 19 Sep 2013 21:59:32 +0200
+Subject: [PATCH] clk: sunxi: Add USB clock register defintions
+
+Add register definitions for the usb-clk register found on sun4i, sun5i and
+sun7i SoCs.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt | 5 +++++
+ drivers/clk/sunxi/clk-sunxi.c | 12 ++++++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index 0da774c..c77a5b8 100644
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 2dbaee7..9daa9b0 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -924,6 +924,16 @@ struct gates_data {
+ .mask = {0x7F77FFF, 0x14FB3F},
+ };
+
++static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
++ .mask = {0x1C0},
++ .reset_mask = 0x07,
++};
++
++static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
++ .mask = {0x140},
++ .reset_mask = 0x03,
++};
++
+ static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
+ .mask = {0x147667e7, 0x185915},
+ };
+@@ -1271,6 +1281,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+ {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
+ {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
+ {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
++ {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
++ {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
+ {}
+ };
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch b/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch
new file mode 100644
index 0000000000..c3693a7e8f
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch
@@ -0,0 +1,79 @@
+From c3593cc95c240663bd9c191c1029237e467575af Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 7 Feb 2014 18:08:03 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add sun4i-a10-usb-vbus-reg dts include file
+
+Almost all sun4i and sun7i boards have a gpio controlled vbus for usb1 and
+usb2, using gpio pin PH6 and PH3 as in the reference design. This commit adds
+an include file for this, avoiding the need to copy and paste the exact same
+dts code to almost all sun4i and sun7i dts files.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi | 54 +++++++++++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi
+new file mode 100644
+index 0000000..803be0c
+--- /dev/null
++++ b/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi
+@@ -0,0 +1,54 @@
++/*
++ * sun4i boards usb vbus supply common code
++ *
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/ {
++ soc@01c00000 {
++ pio: pinctrl@01c20800 {
++ usb1_vbus_pin_a: usb1_vbus_pin@0 {
++ allwinner,pins = "PH6";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++
++ usb2_vbus_pin_a: usb2_vbus_pin@0 {
++ allwinner,pins = "PH3";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++ };
++ };
++
++ reg_usb1_vbus: usb1-vbus {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ pinctrl-0 = <&usb1_vbus_pin_a>;
++ regulator-name = "usb1-vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ enable-active-high;
++ gpio = <&pio 7 6 0>;
++ };
++
++ reg_usb2_vbus: usb2-vbus {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ pinctrl-0 = <&usb2_vbus_pin_a>;
++ regulator-name = "usb2-vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ enable-active-high;
++ gpio = <&pio 7 3 0>;
++ };
++};
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch b/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch
new file mode 100644
index 0000000000..e6d4f27d73
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch
@@ -0,0 +1,95 @@
+From d11b47592e6af40fff595900c2af30774ee0b88e Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sun, 9 Feb 2014 14:17:28 +0100
+Subject: [PATCH] ARM: sun5i: dt: Add sun5i-a1*-usb-vbus-reg dts include files
+
+Almost all sun5i-a10s boards have a gpio controlled vbus for usb1 using gpio
+pin PB10 as in the reference design. This commit adds an include file for this,
+avoiding the need to copy and paste the dts code.
+
+For sun5i-a13 based board the reference design uses a gpio on the pmic, which
+we don't support yet. Still for consistency with all the other dts files also
+add a sun5i-a13-usb-vbus-reg.dtsi files, without a gpio reference for now.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi | 36 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi | 23 ++++++++++++++++
+ 2 files changed, 59 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi
+ create mode 100644 arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi
+new file mode 100644
+index 0000000..bb1a693
+--- /dev/null
++++ b/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi
+@@ -0,0 +1,36 @@
++/*
++ * sun5i a10s boards usb vbus supply common code
++ *
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/ {
++ soc@01c00000 {
++ pio: pinctrl@01c20800 {
++ usb1_vbus_pin_a: usb1_vbus_pin@0 {
++ allwinner,pins = "PB10";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++ };
++ };
++
++ reg_usb1_vbus: usb1-vbus {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ pinctrl-0 = <&usb1_vbus_pin_a>;
++ regulator-name = "usb1-vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ enable-active-high;
++ gpio = <&pio 1 10 0>;
++ };
++};
+diff --git a/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi
+new file mode 100644
+index 0000000..4d70b9a
+--- /dev/null
++++ b/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi
+@@ -0,0 +1,23 @@
++/*
++ * sun5i a13 boards usb vbus supply common code
++ *
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/ {
++ reg_usb1_vbus: usb1-vbus {
++ compatible = "regulator-fixed";
++ pinctrl-names = "default";
++ regulator-name = "usb1-vbus";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ enable-active-high;
++ };
++};
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch b/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch
new file mode 100644
index 0000000000..4c62640de4
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch
@@ -0,0 +1,420 @@
+From ac74dd1167924c412498a651edda63df49941f10 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 4 Jan 2014 23:56:17 +0100
+Subject: [PATCH] ARM: sunxi: Add driver for sunxi usb phy
+
+The Allwinner A1x / A2x SoCs have 2 or 3 usb phys which are all accessed
+through a single set of registers. Besides this there are also some other
+phy related bits which need poking, which are per phy, but shared between the
+ohci and ehci controllers, so these are also controlled from this new phy
+driver.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../devicetree/bindings/phy/sun4i-usb-phy.txt | 26 ++
+ drivers/phy/Kconfig | 11 +
+ drivers/phy/Makefile | 1 +
+ drivers/phy/phy-sun4i-usb.c | 329 +++++++++++++++++++++
+ 4 files changed, 367 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+ create mode 100644 drivers/phy/phy-sun4i-usb.c
+
+diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+new file mode 100644
+index 0000000..a82361b
+--- /dev/null
++++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+@@ -0,0 +1,26 @@
++Allwinner sun4i USB PHY
++-----------------------
++
++Required properties:
++- compatible : should be one of "allwinner,sun4i-a10-usb-phy",
++ "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy"
++- reg : a list of offset + length pairs
++- reg-names : "phy_ctrl", "pmu1" and for sun4i or sun7i "pmu2"
++- #phy-cells : from the generic phy bindings, must be 1
++- clocks : phandle + clock specifier for the phy clock
++- clock-names : "usb_phy"
++- resets : a list of phandle + reset specifier pairs
++- reset-names : "usb0_reset", "usb1_reset" and for sun4i or sun7i "usb2_reset"
++
++Example:
++ usbphy: phy@0x01c13400 {
++ #phy-cells = <1>;
++ compatible = "allwinner,sun4i-a10-usb-phy";
++ /* phy base regs, phy1 pmu reg, phy2 pmu reg */
++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
++ reg-names = "phy_ctrl", "pmu1", "pmu2";
++ clocks = <&usb_clk 8>;
++ clock-names = "usb_phy";
++ resets = <&usb_clk 1>, <&usb_clk 2>;
++ reset-names = "usb1_reset", "usb2_reset";
++ };
+diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
+index 4ef8755..6e336b4 100644
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -64,4 +64,15 @@ config BCM_KONA_USB2_PHY
+ help
+ Enable this to support the Broadcom Kona USB 2.0 PHY.
+
++config PHY_SUN4I_USB
++ tristate "Allwinner sunxi SoC USB PHY driver"
++ depends on ARCH_SUNXI
++ select GENERIC_PHY
++ help
++ Enable this to support the transceiver that is part of Allwinner
++ sunxi SoCs.
++
++ This driver controls the entire USB PHY block, both the USB OTG
++ parts, as well as the 2 regular USB 2 host PHYs.
++
+ endmenu
+diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
+index b57c253..9d4f8bb 100644
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -9,3 +9,4 @@ obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
+ obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
+ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
+ obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
++obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
+diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
+new file mode 100644
+index 0000000..31c4611
+--- /dev/null
++++ b/drivers/phy/phy-sun4i-usb.c
+@@ -0,0 +1,329 @@
++/*
++ * Allwinner sun4i USB phy driver
++ *
++ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
++ *
++ * Based on code from
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ *
++ * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
++ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
++ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/reset.h>
++
++#define REG_ISCR 0x00
++#define REG_PHYCTL 0x04
++#define REG_PHYBIST 0x08
++#define REG_PHYTUNE 0x0c
++
++#define SUNXI_AHB_ICHR8_EN BIT(10)
++#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
++#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
++#define SUNXI_ULPI_BYPASS_EN BIT(0)
++
++/* Common Control Bits for Both PHYs */
++#define PHY_PLL_BW 0x03
++#define PHY_RES45_CAL_EN 0x0c
++
++/* Private Control Bits for Each PHY */
++#define PHY_TX_AMPLITUDE_TUNE 0x20
++#define PHY_TX_SLEWRATE_TUNE 0x22
++#define PHY_VBUSVALID_TH_SEL 0x25
++#define PHY_PULLUP_RES_SEL 0x27
++#define PHY_OTG_FUNC_EN 0x28
++#define PHY_VBUS_DET_EN 0x29
++#define PHY_DISCON_TH_SEL 0x2a
++
++#define MAX_PHYS 3
++
++struct sun4i_usb_phy_data {
++ struct clk *clk;
++ void __iomem *base;
++ struct mutex mutex;
++ int num_phys;
++ u32 disc_thresh;
++ struct sun4i_usb_phy {
++ struct phy *phy;
++ void __iomem *pmu;
++ struct regulator *vbus;
++ struct reset_control *reset;
++ int index;
++ } phys[MAX_PHYS];
++};
++
++#define to_sun4i_usb_phy_data(phy) \
++ container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
++
++static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
++ int len)
++{
++ struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
++ u32 temp, usbc_bit = BIT(phy->index * 2);
++ int i;
++
++ mutex_lock(&phy_data->mutex);
++
++ for (i = 0; i < len; i++) {
++ temp = readl(phy_data->base + REG_PHYCTL);
++
++ /* clear the address portion */
++ temp &= ~(0xff << 8);
++
++ /* set the address */
++ temp |= ((addr + i) << 8);
++ writel(temp, phy_data->base + REG_PHYCTL);
++
++ /* set the data bit and clear usbc bit*/
++ temp = readb(phy_data->base + REG_PHYCTL);
++ if (data & 0x1)
++ temp |= BIT(7);
++ else
++ temp &= ~BIT(7);
++ temp &= ~usbc_bit;
++ writeb(temp, phy_data->base + REG_PHYCTL);
++
++ /* pulse usbc_bit */
++ temp = readb(phy_data->base + REG_PHYCTL);
++ temp |= usbc_bit;
++ writeb(temp, phy_data->base + REG_PHYCTL);
++
++ temp = readb(phy_data->base + REG_PHYCTL);
++ temp &= ~usbc_bit;
++ writeb(temp, phy_data->base + REG_PHYCTL);
++
++ data >>= 1;
++ }
++ mutex_unlock(&phy_data->mutex);
++}
++
++static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
++{
++ u32 bits, reg_value;
++
++ if (!phy->pmu)
++ return;
++
++ bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
++ SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
++
++ reg_value = readl(phy->pmu);
++
++ if (enable)
++ reg_value |= bits;
++ else
++ reg_value &= ~bits;
++
++ writel(reg_value, phy->pmu);
++}
++
++static int sun4i_usb_phy_init(struct phy *_phy)
++{
++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
++ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
++ int ret;
++
++ ret = clk_prepare_enable(data->clk);
++ if (ret)
++ return ret;
++
++ ret = reset_control_deassert(phy->reset);
++ if (ret) {
++ clk_disable_unprepare(data->clk);
++ return ret;
++ }
++
++ /* Adjust PHY's magnitude and rate */
++ sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
++
++ /* Disconnect threshold adjustment */
++ sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2);
++
++ sun4i_usb_phy_passby(phy, 1);
++
++ return 0;
++}
++
++static int sun4i_usb_phy_exit(struct phy *_phy)
++{
++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
++ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
++
++ sun4i_usb_phy_passby(phy, 0);
++ reset_control_assert(phy->reset);
++ clk_disable_unprepare(data->clk);
++
++ return 0;
++}
++
++static int sun4i_usb_phy_power_on(struct phy *_phy)
++{
++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
++ int ret = 0;
++
++ if (phy->vbus)
++ ret = regulator_enable(phy->vbus);
++
++ return ret;
++}
++
++static int sun4i_usb_phy_power_off(struct phy *_phy)
++{
++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
++
++ if (phy->vbus)
++ regulator_disable(phy->vbus);
++
++ return 0;
++}
++
++static struct phy_ops sun4i_usb_phy_ops = {
++ .init = sun4i_usb_phy_init,
++ .exit = sun4i_usb_phy_exit,
++ .power_on = sun4i_usb_phy_power_on,
++ .power_off = sun4i_usb_phy_power_off,
++ .owner = THIS_MODULE,
++};
++
++static struct phy *sun4i_usb_phy_xlate(struct device *dev,
++ struct of_phandle_args *args)
++{
++ struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
++
++ if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys))
++ return ERR_PTR(-ENODEV);
++
++ return data->phys[args->args[0]].phy;
++}
++
++static int sun4i_usb_phy_probe(struct platform_device *pdev)
++{
++ struct sun4i_usb_phy_data *data;
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ void __iomem *pmu = NULL;
++ struct phy_provider *phy_provider;
++ struct reset_control *reset;
++ struct regulator *vbus;
++ struct resource *res;
++ struct phy *phy;
++ char name[16];
++ int i;
++
++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ mutex_init(&data->mutex);
++
++ if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
++ data->num_phys = 2;
++ else
++ data->num_phys = 3;
++
++ if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy"))
++ data->disc_thresh = 3;
++ else
++ data->disc_thresh = 2;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
++ data->base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(data->base))
++ return PTR_ERR(data->base);
++
++ data->clk = devm_clk_get(dev, "usb_phy");
++ if (IS_ERR(data->clk)) {
++ dev_err(dev, "could not get usb_phy clock\n");
++ return PTR_ERR(data->clk);
++ }
++
++ /* Skip 0, 0 is the phy for otg which is not yet supported. */
++ for (i = 1; i < data->num_phys; i++) {
++ snprintf(name, sizeof(name), "usb%d_vbus", i);
++ vbus = devm_regulator_get_optional(dev, name);
++ if (IS_ERR(vbus)) {
++ if (PTR_ERR(vbus) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++ vbus = NULL;
++ }
++
++ snprintf(name, sizeof(name), "usb%d_reset", i);
++ reset = devm_reset_control_get(dev, name);
++ if (IS_ERR(reset)) {
++ dev_err(dev, "failed to get reset %s\n", name);
++ return PTR_ERR(phy);
++ }
++
++ if (i) { /* No pmu for usbc0 */
++ snprintf(name, sizeof(name), "pmu%d", i);
++ res = platform_get_resource_byname(pdev,
++ IORESOURCE_MEM, name);
++ pmu = devm_ioremap_resource(dev, res);
++ if (IS_ERR(pmu))
++ return PTR_ERR(pmu);
++ }
++
++ phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
++ if (IS_ERR(phy)) {
++ dev_err(dev, "failed to create PHY %d\n", i);
++ return PTR_ERR(phy);
++ }
++
++ data->phys[i].phy = phy;
++ data->phys[i].pmu = pmu;
++ data->phys[i].vbus = vbus;
++ data->phys[i].reset = reset;
++ data->phys[i].index = i;
++ phy_set_drvdata(phy, &data->phys[i]);
++ }
++
++ dev_set_drvdata(dev, data);
++ phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
++ if (IS_ERR(phy_provider))
++ return PTR_ERR(phy_provider);
++
++ return 0;
++}
++
++static const struct of_device_id sun4i_usb_phy_of_match[] = {
++ { .compatible = "allwinner,sun4i-a10-usb-phy" },
++ { .compatible = "allwinner,sun5i-a13-usb-phy" },
++ { .compatible = "allwinner,sun7i-a20-usb-phy" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
++
++static struct platform_driver sun4i_usb_phy_driver = {
++ .probe = sun4i_usb_phy_probe,
++ .driver = {
++ .of_match_table = sun4i_usb_phy_of_match,
++ .name = "sun4i-usb-phy",
++ .owner = THIS_MODULE,
++ }
++};
++module_platform_driver(sun4i_usb_phy_driver);
++
++MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_LICENSE("GPL v2");
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch
new file mode 100644
index 0000000000..f0f5b92b7d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch
@@ -0,0 +1,34 @@
+From a6ff9c88c09c81cb612f2588a5bfbde21bdcbf7b Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Thu, 19 Sep 2013 21:58:47 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 1a9ab7e..7550c4e 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -307,6 +307,15 @@
+ clock-output-names = "ir1";
+ };
+
++ usb_clk: clk@01c200cc {
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ compatible = "allwinner,sun4i-a10-usb-clk";
++ reg = <0x01c200cc 0x4>;
++ clocks = <&pll6 1>;
++ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
++ };
++
+ spi3_clk: clk@01c200d4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch
new file mode 100644
index 0000000000..6a0a1cfadc
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch
@@ -0,0 +1,86 @@
+From f1a981bd49f310775780c221fe92f6861c5e8f3f Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Wed, 18 Sep 2013 00:30:04 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add USB host bindings
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 7550c4e..80bbdeb 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -391,6 +391,38 @@
+ status = "disabled";
+ };
+
++ usbphy: phy@01c13400 {
++ #phy-cells = <1>;
++ compatible = "allwinner,sun4i-a10-usb-phy";
++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
++ reg-names = "phy_ctrl", "pmu1", "pmu2";
++ clocks = <&usb_clk 8>;
++ clock-names = "usb_phy";
++ resets = <&usb_clk 1>, <&usb_clk 2>;
++ reset-names = "usb1_reset", "usb2_reset";
++ status = "disabled";
++ };
++
++ ehci0: usb@01c14000 {
++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
++ reg = <0x01c14000 0x100>;
++ interrupts = <39>;
++ clocks = <&ahb_gates 1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci0: usb@01c14400 {
++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
++ reg = <0x01c14400 0x100>;
++ interrupts = <64>;
++ clocks = <&usb_clk 6>, <&ahb_gates 2>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -399,6 +431,26 @@
+ status = "disabled";
+ };
+
++ ehci1: usb@01c1c000 {
++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
++ reg = <0x01c1c000 0x100>;
++ interrupts = <40>;
++ clocks = <&ahb_gates 3>;
++ phys = <&usbphy 2>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci1: usb@01c1c400 {
++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
++ reg = <0x01c1c400 0x100>;
++ interrupts = <65>;
++ clocks = <&usb_clk 7>, <&ahb_gates 4>;
++ phys = <&usbphy 2>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch b/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch
new file mode 100644
index 0000000000..85483f280d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch
@@ -0,0 +1,62 @@
+From d2afb2629087ab17d87d605d4b7f49da3a85f1b1 Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Wed, 18 Sep 2013 22:45:06 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to cubieboard dts
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+index ef85b8e..57d2c9c 100644
+--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+@@ -13,6 +13,7 @@
+ /dts-v1/;
+ /include/ "sun4i-a10.dtsi"
+ /include/ "sunxi-ahci-reg.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
+
+ / {
+ model = "Cubietech Cubieboard";
+@@ -42,11 +43,33 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ led_pins_cubieboard: led_pins@0 {
+ allwinner,pins = "PH20", "PH21";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch b/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch
new file mode 100644
index 0000000000..bd85989ed3
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch
@@ -0,0 +1,61 @@
+From dee94e49177c0bac675d543b16de0f354b0f476a Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Wed, 18 Sep 2013 00:30:40 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to Mele A1000 dts
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-a1000.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+index 4b2a694..144b8e6 100644
+--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+@@ -13,6 +13,7 @@
+
+ /dts-v1/;
+ /include/ "sun4i-a10.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
+
+ / {
+ model = "Mele A1000";
+@@ -43,10 +44,32 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ status = "okay";
+ };
+
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ emac_power_pin_a1000: emac_power_pin@0 {
+ allwinner,pins = "PH15";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch
new file mode 100644
index 0000000000..2bb2a90df0
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch
@@ -0,0 +1,34 @@
+From ebac8eac9b49c914a975c04a62ea5cfc058d958d Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Thu, 19 Sep 2013 21:24:20 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index b58ce25..ed9b8cc 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -297,6 +297,15 @@
+ clock-output-names = "ir1";
+ };
+
++ usb_clk: clk@01c200cc {
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ compatible = "allwinner,sun4i-a10-usb-clk";
++ reg = <0x01c200cc 0x4>;
++ clocks = <&pll6 1>;
++ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
++ };
++
+ spi3_clk: clk@01c200d4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch
new file mode 100644
index 0000000000..1c5ef8b667
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch
@@ -0,0 +1,86 @@
+From bc68c927139d1cac9647c8bcd3e8cea1cac9eaef Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Thu, 19 Sep 2013 21:36:10 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add USB host bindings
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index ed9b8cc..bdfa594 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -453,6 +453,38 @@
+ status = "disabled";
+ };
+
++ usbphy: phy@01c13400 {
++ #phy-cells = <1>;
++ compatible = "allwinner,sun7i-a20-usb-phy";
++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
++ reg-names = "phy_ctrl", "pmu1", "pmu2";
++ clocks = <&usb_clk 8>;
++ clock-names = "usb_phy";
++ resets = <&usb_clk 1>, <&usb_clk 2>;
++ reset-names = "usb1_reset", "usb2_reset";
++ status = "disabled";
++ };
++
++ ehci0: usb@01c14000 {
++ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
++ reg = <0x01c14000 0x100>;
++ interrupts = <0 39 4>;
++ clocks = <&ahb_gates 1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci0: usb@01c14400 {
++ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci";
++ reg = <0x01c14400 0x100>;
++ interrupts = <0 64 4>;
++ clocks = <&usb_clk 6>, <&ahb_gates 2>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -461,6 +493,26 @@
+ status = "disabled";
+ };
+
++ ehci1: usb@01c1c000 {
++ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
++ reg = <0x01c1c000 0x100>;
++ interrupts = <0 40 4>;
++ clocks = <&ahb_gates 3>;
++ phys = <&usbphy 2>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci1: usb@01c1c400 {
++ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci";
++ reg = <0x01c1c400 0x100>;
++ interrupts = <0 65 4>;
++ clocks = <&usb_clk 7>, <&ahb_gates 4>;
++ phys = <&usbphy 2>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ pio: pinctrl@01c20800 {
+ compatible = "allwinner,sun7i-a20-pinctrl";
+ reg = <0x01c20800 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch b/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch
new file mode 100644
index 0000000000..7ca9d8ab26
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch
@@ -0,0 +1,62 @@
+From 5b820d3062a436cf36ddf2fecc88524b9adf7b6e Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Thu, 19 Sep 2013 21:29:45 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add USB host nodes to cubieboard2 dts
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+index a8186f5..9fa1d85 100644
+--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+@@ -14,6 +14,7 @@
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
+ /include/ "sunxi-ahci-reg.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
+
+ / {
+ model = "Cubietech Cubieboard2";
+@@ -28,11 +29,33 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ led_pins_cubieboard2: led_pins@0 {
+ allwinner,pins = "PH20", "PH21";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch b/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch
new file mode 100644
index 0000000000..11d093639f
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch
@@ -0,0 +1,61 @@
+From 2f2ffd5ea0174434c8214722127e5e977dcecf32 Mon Sep 17 00:00:00 2001
+From: Zalan Blenessy <zalan.blenessy@gmail.com>
+Date: Sun, 22 Dec 2013 17:08:10 +0100
+Subject: [PATCH] ARM: sun7i: dt: Add USB host nodes to a20-olinuxino-micro dts
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index aef289f..824ce0a 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -14,6 +14,7 @@
+ /dts-v1/;
+ /include/ "sun7i-a20.dtsi"
+ /include/ "sunxi-ahci-reg.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
+ #include <dt-bindings/input/input.h>
+
+ / {
+@@ -37,11 +38,33 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
+ allwinner,pins = "PH11";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch
new file mode 100644
index 0000000000..ef7323bbf1
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch
@@ -0,0 +1,55 @@
+From 84e5402d6755b0563cfbe1b6b930b13b1c10d56c Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Tue, 24 Sep 2013 20:02:39 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB clocks
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 9 +++++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi | 9 +++++++++
+ 2 files changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 95cb245..0565040 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -268,6 +268,15 @@
+ clock-output-names = "ir0";
+ };
+
++ usb_clk: clk@01c200cc {
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ compatible = "allwinner,sun5i-a13-usb-clk";
++ reg = <0x01c200cc 0x4>;
++ clocks = <&pll6 1>;
++ clock-output-names = "usb_ohci0", "usb_phy";
++ };
++
+ mbus_clk: clk@01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index bae0f5f..785dea5 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -266,6 +266,15 @@
+ clock-output-names = "ir0";
+ };
+
++ usb_clk: clk@01c200cc {
++ #clock-cells = <1>;
++ #reset-cells = <1>;
++ compatible = "allwinner,sun5i-a13-usb-clk";
++ reg = <0x01c200cc 0x4>;
++ clocks = <&pll6 1>;
++ clock-output-names = "usb_ohci0", "usb_phy";
++ };
++
+ mbus_clk: clk@01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch
new file mode 100644
index 0000000000..50dc201a9d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch
@@ -0,0 +1,103 @@
+From 22f661c548042565ffa32e468267f94cadafe144 Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Tue, 24 Sep 2013 20:03:40 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add USB host bindings
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 32 ++++++++++++++++++++++++++++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 64 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 0565040..a5431ed 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -341,6 +341,38 @@
+ status = "disabled";
+ };
+
++ usbphy: phy@01c13400 {
++ #phy-cells = <1>;
++ compatible = "allwinner,sun5i-a13-usb-phy";
++ reg = <0x01c13400 0x10 0x01c14800 0x4>;
++ reg-names = "phy_ctrl", "pmu1";
++ clocks = <&usb_clk 8>;
++ clock-names = "usb_phy";
++ resets = <&usb_clk 1>;
++ reset-names = "usb1_reset";
++ status = "disabled";
++ };
++
++ ehci0: usb@01c14000 {
++ compatible = "allwinner,sun5i-a10s-ehci", "generic-ehci";
++ reg = <0x01c14000 0x100>;
++ interrupts = <39>;
++ clocks = <&ahb_gates 1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci0: usb@01c14400 {
++ compatible = "allwinner,sun5i-a10s-ohci", "generic-ohci";
++ reg = <0x01c14400 0x100>;
++ interrupts = <40>;
++ clocks = <&usb_clk 6>, <&ahb_gates 2>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 785dea5..7fe9cdc 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -312,6 +312,38 @@
+ status = "disabled";
+ };
+
++ usbphy: phy@01c13400 {
++ #phy-cells = <1>;
++ compatible = "allwinner,sun5i-a13-usb-phy";
++ reg = <0x01c13400 0x10 0x01c14800 0x4>;
++ reg-names = "phy_ctrl", "pmu1";
++ clocks = <&usb_clk 8>;
++ clock-names = "usb_phy";
++ resets = <&usb_clk 1>;
++ reset-names = "usb1_reset";
++ status = "disabled";
++ };
++
++ ehci0: usb@01c14000 {
++ compatible = "allwinner,sun5i-a13-ehci", "generic-ehci";
++ reg = <0x01c14000 0x100>;
++ interrupts = <39>;
++ clocks = <&ahb_gates 1>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
++ ohci0: usb@01c14400 {
++ compatible = "allwinner,sun5i-a13-ohci", "generic-ohci";
++ reg = <0x01c14400 0x100>;
++ interrupts = <40>;
++ clocks = <&usb_clk 6>, <&ahb_gates 2>;
++ phys = <&usbphy 1>;
++ phy-names = "usb";
++ status = "disabled";
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch b/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch
new file mode 100644
index 0000000000..a664bc0b83
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch
@@ -0,0 +1,72 @@
+From 8bf60620f751f93157c81038527b03716c8aeede Mon Sep 17 00:00:00 2001
+From: Roman Byshko <rbyshko@gmail.com>
+Date: Tue, 24 Sep 2013 20:07:53 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add USB host nodes to A13-Olinuxino
+
+Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
+
+Signed-off-by: Roman Byshko <rbyshko@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+index ba32a41..39556d1 100644
+--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+@@ -13,6 +13,7 @@
+
+ /dts-v1/;
+ /include/ "sun5i-a13.dtsi"
++/include/ "sun5i-a13-usb-vbus-reg.dtsi"
+ #include <dt-bindings/input/input.h>
+
+ / {
+@@ -28,6 +29,19 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
+ pinctrl@01c20800 {
+ mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
+ allwinner,pins = "PG0";
+@@ -42,6 +56,13 @@
+ allwinner,drive = <1>;
+ allwinner,pull = <0>;
+ };
++
++ usb1_vbus_pin_olinuxino: usb1_vbus_pin@0 {
++ allwinner,pins = "PG11";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
+ };
+
+ lradc: lradc@01c22800 {
+@@ -86,4 +107,9 @@
+ default-state = "on";
+ };
+ };
++
++ reg_usb1_vbus: usb1-vbus {
++ pinctrl-0 = <&usb1_vbus_pin_olinuxino>;
++ gpio = <&pio 6 11 0>;
++ };
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch b/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch
deleted file mode 100644
index 3035a49ff9..0000000000
--- a/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-From 133a9b75e2b0c48cd1d8f93b0ee61089821c32d9 Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:34 +0800
-Subject: [PATCH] net: stmmac: Enable stmmac main clock when probing hardware
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 24 +++++++++++++----------
- 1 file changed, 14 insertions(+), 10 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -2680,10 +2680,17 @@ struct stmmac_priv *stmmac_dvr_probe(str
- if ((phyaddr >= 0) && (phyaddr <= 31))
- priv->plat->phy_addr = phyaddr;
-
-+ priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
-+ if (IS_ERR(priv->stmmac_clk)) {
-+ pr_warn("%s: warning: cannot get CSR clock\n", __func__);
-+ goto error_clk_get;
-+ }
-+ clk_prepare_enable(priv->stmmac_clk);
-+
- /* Init MAC and get the capabilities */
- ret = stmmac_hw_init(priv);
- if (ret)
-- goto error_free_netdev;
-+ goto error_hw_init;
-
- ndev->netdev_ops = &stmmac_netdev_ops;
-
-@@ -2721,12 +2728,6 @@ struct stmmac_priv *stmmac_dvr_probe(str
- goto error_netdev_register;
- }
-
-- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
-- if (IS_ERR(priv->stmmac_clk)) {
-- pr_warn("%s: warning: cannot get CSR clock\n", __func__);
-- goto error_clk_get;
-- }
--
- /* If a specific clk_csr value is passed from the platform
- * this means that the CSR Clock Range selection cannot be
- * changed at run-time and it is fixed. Viceversa the driver'll try to
-@@ -2751,15 +2752,18 @@ struct stmmac_priv *stmmac_dvr_probe(str
- }
- }
-
-+ clk_disable_unprepare(priv->stmmac_clk);
-+
- return priv;
-
- error_mdio_register:
-- clk_put(priv->stmmac_clk);
--error_clk_get:
- unregister_netdev(ndev);
- error_netdev_register:
- netif_napi_del(&priv->napi);
--error_free_netdev:
-+error_hw_init:
-+ clk_disable_unprepare(priv->stmmac_clk);
-+ clk_put(priv->stmmac_clk);
-+error_clk_get:
- free_netdev(ndev);
-
- return NULL;
diff --git a/target/linux/sunxi/patches-3.13/180-sunxi-select-PSCI.patch b/target/linux/sunxi/patches-3.13/190-sunxi-select-PSCI.patch
index a634240f49..a634240f49 100644
--- a/target/linux/sunxi/patches-3.13/180-sunxi-select-PSCI.patch
+++ b/target/linux/sunxi/patches-3.13/190-sunxi-select-PSCI.patch
diff --git a/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch b/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch
deleted file mode 100644
index 5c4f40d9a9..0000000000
--- a/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From a2acf761e37031737300c47284181a21b6bc0cc2 Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:35 +0800
-Subject: [PATCH] net: stmmac: Honor DT parameter to force DMA store and
- forward mode
-
-"snps,force_sf_dma_mode" is documented in stmmac device tree bindings,
-but is never handled by the driver.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -47,6 +47,7 @@ static int stmmac_probe_config_dt(struct
- plat->bus_id = 0;
-
- of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr);
-+ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
-
- plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
- sizeof(struct stmmac_mdio_bus_data),
diff --git a/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch b/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch
deleted file mode 100644
index 409f93afeb..0000000000
--- a/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 34722924d416c3521de2bc8d10dfcd07a55135ea Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:36 +0800
-Subject: [PATCH] net: stmmac: Use platform data tied with compatible strings
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 29 ++++++++++++++--------
- 1 file changed, 19 insertions(+), 10 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -26,8 +26,19 @@
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_net.h>
-+#include <linux/of_device.h>
- #include "stmmac.h"
-
-+static const struct of_device_id stmmac_dt_ids[] = {
-+ { .compatible = "st,spear600-gmac"},
-+ { .compatible = "snps,dwmac-3.610"},
-+ { .compatible = "snps,dwmac-3.70a"},
-+ { .compatible = "snps,dwmac-3.710"},
-+ { .compatible = "snps,dwmac"},
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-+
- #ifdef CONFIG_OF
- static int stmmac_probe_config_dt(struct platform_device *pdev,
- struct plat_stmmacenet_data *plat,
-@@ -35,10 +46,18 @@ static int stmmac_probe_config_dt(struct
- {
- struct device_node *np = pdev->dev.of_node;
- struct stmmac_dma_cfg *dma_cfg;
-+ const struct of_device_id *device;
-
- if (!np)
- return -ENODEV;
-
-+ device = of_match_device(stmmac_dt_ids, &pdev->dev);
-+ if (!device)
-+ return -ENODEV;
-+
-+ if (device->data)
-+ memcpy(plat, device->data, sizeof(*plat));
-+
- *mac = of_get_mac_address(np);
- plat->interface = of_get_phy_mode(np);
-
-@@ -257,16 +276,6 @@ static const struct dev_pm_ops stmmac_pl
- static const struct dev_pm_ops stmmac_pltfr_pm_ops;
- #endif /* CONFIG_PM */
-
--static const struct of_device_id stmmac_dt_ids[] = {
-- { .compatible = "st,spear600-gmac"},
-- { .compatible = "snps,dwmac-3.610"},
-- { .compatible = "snps,dwmac-3.70a"},
-- { .compatible = "snps,dwmac-3.710"},
-- { .compatible = "snps,dwmac"},
-- { /* sentinel */ }
--};
--MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
--
- struct platform_driver stmmac_pltfr_driver = {
- .probe = stmmac_pltfr_probe,
- .remove = stmmac_pltfr_remove,
diff --git a/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch b/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch
deleted file mode 100644
index 6bc409e33a..0000000000
--- a/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch
+++ /dev/null
@@ -1,187 +0,0 @@
-From 3c6560eccfeee3a93d57c3b2206abfbe06459015 Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:37 +0800
-Subject: [PATCH] net: stmmac: sunxi platfrom extensions for GMAC in Allwinner
- A20 SoC's
-
-The Allwinner A20 has an ethernet controller that seems to be
-an early version of Synopsys DesignWare MAC 10/100/1000 Universal,
-which is supported by the stmmac driver.
-
-Allwinner's GMAC requires setting additional registers in the SoC's
-clock control unit.
-
-The exact version of the DWMAC IP that Allwinner uses is unknown,
-thus the exact feature set is unknown.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- .../bindings/net/allwinner,sun7i-gmac.txt | 22 +++++++
- drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++++
- drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
- drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 76 ++++++++++++++++++++++
- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +
- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
- 6 files changed, 117 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-gmac.txt
- create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-gmac.txt
-@@ -0,0 +1,22 @@
-+* Allwinner GMAC ethernet controller
-+
-+This device is a platform glue layer for stmmac.
-+Please see stmmac.txt for the other unchanged properties.
-+
-+Required properties:
-+ - compatible: Should be "allwinner,sun7i-gmac"
-+ - reg: Address and length of register set for the device and corresponding
-+ clock control
-+
-+Examples:
-+
-+ gmac: ethernet@01c50000 {
-+ compatible = "allwinner,sun7i-gmac";
-+ reg = <0x01c50000 0x10000>,
-+ <0x01c20164 0x4>;
-+ interrupts = <0 85 1>;
-+ interrupt-names = "macirq";
-+ clocks = <&ahb_gates 49>;
-+ clock-names = "stmmaceth";
-+ phy-mode = "mii";
-+ };
---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
-+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
-@@ -25,6 +25,18 @@ config STMMAC_PLATFORM
-
- If unsure, say N.
-
-+config DWMAC_SUNXI
-+ bool "Allwinner GMAC support"
-+ depends on STMMAC_PLATFORM
-+ depends on ARCH_SUNXI
-+ default y
-+ ---help---
-+ Support for Allwinner A20 GMAC ethernet driver.
-+
-+ This selects Allwinner SoC glue layer support for the
-+ stmmac device driver. This driver is used for A20 GMAC
-+ ethernet controller.
-+
- config STMMAC_PCI
- bool "STMMAC PCI bus support"
- depends on STMMAC_ETH && PCI
---- a/drivers/net/ethernet/stmicro/stmmac/Makefile
-+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
-@@ -1,6 +1,7 @@
- obj-$(CONFIG_STMMAC_ETH) += stmmac.o
- stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
- stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
-+stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
- stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
- chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
- dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
-@@ -0,0 +1,76 @@
-+/**
-+ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
-+ *
-+ * Copyright (C) 2013 Chen-Yu Tsai
-+ *
-+ * Chen-Yu Tsai <wens@csie.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/phy.h>
-+#include <linux/stmmac.h>
-+
-+#define GMAC_IF_TYPE_RGMII 0x4
-+
-+#define GMAC_TX_CLK_MASK 0x3
-+#define GMAC_TX_CLK_MII 0x0
-+#define GMAC_TX_CLK_RGMII_INT 0x2
-+
-+static int sun7i_gmac_init(struct platform_device *pdev)
-+{
-+ struct resource *res;
-+ struct device *dev = &pdev->dev;
-+ void __iomem *addr = NULL;
-+ struct plat_stmmacenet_data *plat_dat = NULL;
-+ u32 priv_clk_reg;
-+
-+ plat_dat = dev_get_platdata(&pdev->dev);
-+ if (!plat_dat)
-+ return -EINVAL;
-+
-+ /* Get GMAC clock register in CCU */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ addr = devm_ioremap_resource(dev, res);
-+ if (IS_ERR(addr))
-+ return PTR_ERR(addr);
-+
-+ priv_clk_reg = readl(addr);
-+
-+ /* Set GMAC interface port mode */
-+ if (plat_dat->interface == PHY_INTERFACE_MODE_RGMII)
-+ priv_clk_reg |= GMAC_IF_TYPE_RGMII;
-+ else
-+ priv_clk_reg &= ~GMAC_IF_TYPE_RGMII;
-+
-+ /* Set GMAC transmit clock source. */
-+ priv_clk_reg &= ~GMAC_TX_CLK_MASK;
-+ if (plat_dat->interface == PHY_INTERFACE_MODE_RGMII
-+ || plat_dat->interface == PHY_INTERFACE_MODE_GMII)
-+ priv_clk_reg |= GMAC_TX_CLK_RGMII_INT;
-+ else
-+ priv_clk_reg |= GMAC_TX_CLK_MII;
-+
-+ writel(priv_clk_reg, addr);
-+
-+ /* mask out phy addr 0x0 */
-+ plat_dat->mdio_bus_data->phy_mask = 0x1;
-+
-+ return 0;
-+}
-+
-+const struct plat_stmmacenet_data sun7i_gmac_data = {
-+ .has_gmac = 1,
-+ .tx_coe = 1,
-+ .init = sun7i_gmac_init,
-+};
-+
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-@@ -130,6 +130,9 @@ void stmmac_disable_eee_mode(struct stmm
- bool stmmac_eee_init(struct stmmac_priv *priv);
-
- #ifdef CONFIG_STMMAC_PLATFORM
-+#ifdef CONFIG_DWMAC_SUNXI
-+extern const struct plat_stmmacenet_data sun7i_gmac_data;
-+#endif
- extern struct platform_driver stmmac_pltfr_driver;
- static inline int stmmac_register_platform(void)
- {
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -35,6 +35,9 @@ static const struct of_device_id stmmac_
- { .compatible = "snps,dwmac-3.70a"},
- { .compatible = "snps,dwmac-3.710"},
- { .compatible = "snps,dwmac"},
-+#ifdef CONFIG_DWMAC_SUNXI
-+ { .compatible = "allwinner,sun7i-gmac", .data = &sun7i_gmac_data},
-+#endif
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
diff --git a/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch b/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch
deleted file mode 100644
index 0b65dac0e4..0000000000
--- a/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From a07eeb627d300da0dee8cb39b59173332be8e4bb Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:38 +0800
-Subject: [PATCH] ARM: dts: sun7i: Add GMAC controller node to sun7i DTSI
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -605,6 +605,20 @@
- status = "disabled";
- };
-
-+ gmac: ethernet@01c50000 {
-+ compatible = "allwinner,sun7i-gmac", "snps,dwmac";
-+ reg = <0x01c50000 0x10000>,
-+ <0x01c20164 0x4>;
-+ interrupts = <0 85 1>;
-+ interrupt-names = "macirq";
-+ clocks = <&ahb_gates 49>;
-+ clock-names = "stmmaceth";
-+ snps,pbl = <2>;
-+ snps,fixed-burst;
-+ snps,force_sf_dma_mode;
-+ status = "disabled";
-+ };
-+
- hstimer@01c60000 {
- compatible = "allwinner,sun7i-a20-hstimer";
- reg = <0x01c60000 0x1000>;
diff --git a/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch b/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch
deleted file mode 100644
index e781d0f8fc..0000000000
--- a/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From a94741174cdc6bd29c56c5aa1a225ac6e7f4ebde Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:40 +0800
-Subject: [PATCH] ARM: dts: sun7i: cubietruck: Enable the GMAC
-
-The CubieTruck uses the GMAC with an RGMII phy.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-@@ -121,6 +121,14 @@
- pinctrl-0 = <&uart0_pins_a>;
- status = "okay";
- };
-+
-+ gmac: ethernet@01c50000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&gmac_pins_rgmii>;
-+ snps,phy-addr = <1>;
-+ phy-mode = "rgmii";
-+ status = "okay";
-+ };
- };
-
- leds {
diff --git a/target/linux/sunxi/patches-3.13/212-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch b/target/linux/sunxi/patches-3.13/211-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch
index feb736ad90..feb736ad90 100644
--- a/target/linux/sunxi/patches-3.13/212-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch
+++ b/target/linux/sunxi/patches-3.13/211-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch
diff --git a/target/linux/sunxi/patches-3.13/213-dt-sun7i-add-external-clk-outputs.patch b/target/linux/sunxi/patches-3.13/212-dt-sun7i-add-pinmuxing-for-extclocks.patch
index 3dda2946d2..3dda2946d2 100644
--- a/target/linux/sunxi/patches-3.13/213-dt-sun7i-add-external-clk-outputs.patch
+++ b/target/linux/sunxi/patches-3.13/212-dt-sun7i-add-pinmuxing-for-extclocks.patch
diff --git a/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch b/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch
new file mode 100644
index 0000000000..6dc1f1c66f
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch
@@ -0,0 +1,62 @@
+From 10b302a297aee952949423aaec0749b757f34950 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 17 Nov 2013 10:03:04 +0100
+Subject: [PATCH] ARM: sun4i: dt: Move the aliases to the DTSI
+
+The aliases are shared across boards are really belong to the DTSI.
+Move them there.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ----
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 5 -----
+ arch/arm/boot/dts/sun4i-a10.dtsi | 2 ++
+ 3 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+index eb4d73b..d4b081d 100644
+--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+@@ -18,10 +18,6 @@
+ model = "Mele A1000";
+ compatible = "mele,a1000", "allwinner,sun4i-a10";
+
+- aliases {
+- serial0 = &uart0;
+- };
+-
+ soc@01c00000 {
+ emac: ethernet@01c0b000 {
+ pinctrl-names = "default";
+diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+index 425a7db..f1c77e0 100644
+--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+@@ -17,11 +17,6 @@
+ model = "Cubietech Cubieboard";
+ compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10";
+
+- aliases {
+- serial0 = &uart0;
+- serial1 = &uart1;
+- };
+-
+ chosen {
+ bootargs = "earlyprintk console=ttyS0,115200";
+ };
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 3ba2b46..0adbbe3 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -17,6 +17,8 @@
+
+ aliases {
+ ethernet0 = &emac;
++ serial0 = &uart0;
++ serial1 = &uart1;
+ };
+
+ cpus {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch b/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch
deleted file mode 100644
index ee19c298fc..0000000000
--- a/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -253,6 +253,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
- sun4i-a10-cubieboard.dtb \
- sun4i-a10-mini-xplus.dtb \
- sun4i-a10-hackberry.dtb \
-+ sun4i-a10-pcduino.dtb \
- sun5i-a10s-olinuxino-micro.dtb \
- sun5i-a13-olinuxino.dtb \
- sun5i-a13-olinuxino-micro.dtb \
diff --git a/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch b/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch
new file mode 100644
index 0000000000..e54627d719
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch
@@ -0,0 +1,57 @@
+From 4dae1686782d52084893421b89ff1aa61e223aaf Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:49:11 +0100
+Subject: [PATCH] net: ethernet: sunxi: Add new compatibles
+
+The Allwinner A10 compatibles were following a slightly different compatible
+patterns than the rest of the SoCs for historical reasons. Add compatibles
+matching the other pattern to the ethernet driver for consistency, and keep the
+older one for backward compatibility.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt | 5 +++--
+ drivers/net/ethernet/allwinner/sun4i-emac.c | 3 +++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
+index b90bfcd..863d5b81 100644
+--- a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
++++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
+@@ -1,7 +1,8 @@
+ * Allwinner EMAC ethernet controller
+
+ Required properties:
+-- compatible: should be "allwinner,sun4i-emac".
++- compatible: should be "allwinner,sun4i-a10-emac" (Deprecated:
++ "allwinner,sun4i-emac")
+ - reg: address and length of the register set for the device.
+ - interrupts: interrupt for the device
+ - phy: A phandle to a phy node defining the PHY address (as the reg
+@@ -14,7 +15,7 @@ Optional properties:
+ Example:
+
+ emac: ethernet@01c0b000 {
+- compatible = "allwinner,sun4i-emac";
++ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <55>;
+ clocks = <&ahb_gates 17>;
+diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
+index 0cc2143..511f6ee 100644
+--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
++++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
+@@ -929,6 +929,9 @@ static int emac_resume(struct platform_device *dev)
+ }
+
+ static const struct of_device_id emac_of_match[] = {
++ {.compatible = "allwinner,sun4i-a10-emac",},
++
++ /* Deprecated */
+ {.compatible = "allwinner,sun4i-emac",},
+ {},
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch b/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch
deleted file mode 100644
index 8292840ab1..0000000000
--- a/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -254,6 +254,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
- sun4i-a10-mini-xplus.dtb \
- sun4i-a10-hackberry.dtb \
- sun4i-a10-pcduino.dtb \
-+ sun4i-a10-olinuxino-lime.dtb \
- sun5i-a10s-olinuxino-micro.dtb \
- sun5i-a13-olinuxino.dtb \
- sun5i-a13-olinuxino-micro.dtb \
diff --git a/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch b/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch
new file mode 100644
index 0000000000..fe1b436382
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch
@@ -0,0 +1,57 @@
+From efe205704fa8435b7bca495138dd2dbd973e0c28 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:49:12 +0100
+Subject: [PATCH] net: phy: sunxi: Add new compatibles
+
+The Allwinner A10 compatibles were following a slightly different compatible
+patterns than the rest of the SoCs for historical reasons. Add compatibles
+matching the other pattern to the mdio driver for consistency, and keep the
+older one for backward compatibility.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt | 5 +++--
+ drivers/net/phy/mdio-sun4i.c | 3 +++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt
+index 00b9f9a..4ec5641 100644
+--- a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt
++++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt
+@@ -1,7 +1,8 @@
+ * Allwinner A10 MDIO Ethernet Controller interface
+
+ Required properties:
+-- compatible: should be "allwinner,sun4i-mdio".
++- compatible: should be "allwinner,sun4i-a10-mdio"
++ (Deprecated: "allwinner,sun4i-mdio").
+ - reg: address and length of the register set for the device.
+
+ Optional properties:
+@@ -9,7 +10,7 @@ Optional properties:
+
+ Example at the SoC level:
+ mdio@01c0b080 {
+- compatible = "allwinner,sun4i-mdio";
++ compatible = "allwinner,sun4i-a10-mdio";
+ reg = <0x01c0b080 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c
+index bb88bc7..9367acc 100644
+--- a/drivers/net/phy/mdio-sun4i.c
++++ b/drivers/net/phy/mdio-sun4i.c
+@@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev)
+ }
+
+ static const struct of_device_id sun4i_mdio_dt_ids[] = {
++ { .compatible = "allwinner,sun4i-a10-mdio" },
++
++ /* Deprecated */
+ { .compatible = "allwinner,sun4i-mdio" },
+ { }
+ };
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch
deleted file mode 100644
index 358396674c..0000000000
--- a/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
-@@ -42,9 +42,9 @@
- };
- };
-
-- sdc0: sdc@01c0f000 {
-+ mmc0: mmc@01c0f000 {
- pinctrl-names = "default";
-- pinctrl-0 = <&sdc0_pins_a>;
-+ pinctrl-0 = <&mmc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_pcduino>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
diff --git a/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch b/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch
new file mode 100644
index 0000000000..83b6702357
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch
@@ -0,0 +1,85 @@
+From 1c70e099ac80ee779ffac66a6169ad936425fe41 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:49:13 +0100
+Subject: [PATCH] ARM: sunxi: dt: Convert to the new net compatibles
+
+Switch the device tree to the new compatibles introduced in the ethernet and
+mdio drivers to have a common pattern accross all Allwinner SoCs.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 4 ++--
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++--
+ arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++--
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 040bb0e..10666ca 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -315,7 +315,7 @@
+ ranges;
+
+ emac: ethernet@01c0b000 {
+- compatible = "allwinner,sun4i-emac";
++ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <55>;
+ clocks = <&ahb_gates 17>;
+@@ -323,7 +323,7 @@
+ };
+
+ mdio@01c0b080 {
+- compatible = "allwinner,sun4i-mdio";
++ compatible = "allwinner,sun4i-a10-mdio";
+ reg = <0x01c0b080 0x14>;
+ status = "disabled";
+ #address-cells = <1>;
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index ea16054..6496159 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -278,7 +278,7 @@
+ ranges;
+
+ emac: ethernet@01c0b000 {
+- compatible = "allwinner,sun4i-emac";
++ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <55>;
+ clocks = <&ahb_gates 17>;
+@@ -286,7 +286,7 @@
+ };
+
+ mdio@01c0b080 {
+- compatible = "allwinner,sun4i-mdio";
++ compatible = "allwinner,sun4i-a10-mdio";
+ reg = <0x01c0b080 0x14>;
+ status = "disabled";
+ #address-cells = <1>;
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 119f066..9ff0948 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -340,7 +340,7 @@
+ ranges;
+
+ emac: ethernet@01c0b000 {
+- compatible = "allwinner,sun4i-emac";
++ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+ interrupts = <0 55 4>;
+ clocks = <&ahb_gates 17>;
+@@ -348,7 +348,7 @@
+ };
+
+ mdio@01c0b080 {
+- compatible = "allwinner,sun4i-mdio";
++ compatible = "allwinner,sun4i-a10-mdio";
+ reg = <0x01c0b080 0x14>;
+ status = "disabled";
+ #address-cells = <1>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch
deleted file mode 100644
index 2812a22864..0000000000
--- a/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
-+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
-@@ -33,9 +33,9 @@
- };
- };
-
-- sdc0: sdc@01c0f000 {
-+ mmc0: mmc@01c0f000 {
- pinctrl-names = "default";
-- pinctrl-0 = <&sdc0_pins_a>;
-+ pinctrl-0 = <&mmc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
diff --git a/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch
deleted file mode 100644
index b998f11f56..0000000000
--- a/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-@@ -19,9 +19,9 @@
- compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
-
- soc@01c00000 {
-- sdc0: sdc@01c0f000 {
-+ mmc0: mmc@01c0f000 {
- pinctrl-names = "default";
-- pinctrl-0 = <&sdc0_pins_a>;
-+ pinctrl-0 = <&mmc0_pins_a>;
- pinctrl-1 = <&mmc0_cd_pin_cubietruck>;
- cd-gpios = <&pio 7 1 0>; /* PH1 */
- cd-mode = <1>;
diff --git a/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch
new file mode 100644
index 0000000000..b4bc637958
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch
@@ -0,0 +1,33 @@
+From 791f631bb8f3feb10871b82015a25a7f40ce68e7 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Thu, 2 Jan 2014 22:05:04 +0100
+Subject: [PATCH] ARM: sun4i: a10: Add missing serial aliases
+
+Some UART aliases have been defined, but not all of them. Add the remaining
+ones to be consistent and to ease the parsing of the DT by the bootloaders.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 10666ca..d9c097c 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -19,6 +19,12 @@
+ ethernet0 = &emac;
+ serial0 = &uart0;
+ serial1 = &uart1;
++ serial2 = &uart2;
++ serial3 = &uart3;
++ serial4 = &uart4;
++ serial5 = &uart5;
++ serial6 = &uart6;
++ serial7 = &uart7;
+ };
+
+ cpus {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch
new file mode 100644
index 0000000000..3f634850b6
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch
@@ -0,0 +1,31 @@
+From 64c3866d232e6b29862f4773ea97b16f4dad6950 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Thu, 2 Jan 2014 22:05:04 +0100
+Subject: [PATCH] ARM: sun5i: a10s: Add missing serial aliases
+
+Some UART aliases have been defined, but not all of them. Add the remaining
+ones to be consistent and to ease the parsing of the DT by the bootloaders.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 6496159..e00f292 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -18,6 +18,10 @@
+
+ aliases {
+ ethernet0 = &emac;
++ serial0 = &uart0;
++ serial1 = &uart1;
++ serial2 = &uart2;
++ serial3 = &uart3;
+ };
+
+ cpus {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch
new file mode 100644
index 0000000000..a60e497d7b
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch
@@ -0,0 +1,32 @@
+From 0cc774ef2524ec54e9d2db8771ba3739cb8ebc99 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Mon, 13 Jan 2014 11:08:47 +0100
+Subject: [PATCH] ARM: sun5i: a13: Add missing serial aliases
+
+Some UART aliases have been defined, but not all of them. Add the remaining
+ones to be consistent and to ease the parsing of the DT by the bootloaders.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a13.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 320335a..6de40b6 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -16,6 +16,11 @@
+ / {
+ interrupt-parent = <&intc>;
+
++ aliases {
++ serial0 = &uart1;
++ serial1 = &uart3;
++ };
++
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch
new file mode 100644
index 0000000000..5a1f25cba0
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch
@@ -0,0 +1,37 @@
+From 27fb9d199aa3d2f89b4d0b1930062bb1a5a69a57 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Thu, 2 Jan 2014 22:05:04 +0100
+Subject: [PATCH] ARM: sun6i: Add missing serial aliases
+
+Some UART aliases have been defined, but not all of them. Add the remaining
+ones to be consistent and to ease the parsing of the DT by the bootloaders.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun6i-a31.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
+index 5256ad9..092bf97 100644
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -16,6 +16,16 @@
+ / {
+ interrupt-parent = <&gic>;
+
++ aliases {
++ serial0 = &uart0;
++ serial1 = &uart1;
++ serial2 = &uart2;
++ serial3 = &uart3;
++ serial4 = &uart4;
++ serial5 = &uart5;
++ };
++
++
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch b/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch
new file mode 100644
index 0000000000..2e64dd88e1
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch
@@ -0,0 +1,35 @@
+From 4261ec43b199a214f6b0ae5fefefff2e524f8977 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Tue, 14 Jan 2014 22:49:50 +0800
+Subject: [PATCH] ARM: dts: sun7i: add pin muxing options for UART2
+
+UART2 is used on CubieTruck to connect to the Bluetooth module.
+Add the pin set used in this case.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index b476855..bfb2cf2 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -381,6 +381,13 @@
+ allwinner,pull = <0>;
+ };
+
++ uart2_pins_a: uart2@0 {
++ allwinner,pins = "PI16", "PI17", "PI18", "PI19";
++ allwinner,function = "uart2";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++
+ uart6_pins_a: uart6@0 {
+ allwinner,pins = "PI12", "PI13";
+ allwinner,function = "uart6";
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch b/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch
new file mode 100644
index 0000000000..4496437b8d
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch
@@ -0,0 +1,45 @@
+From 97e36b3ce3106988b82e1ca53b1d1c872bde855a Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:40 +0800
+Subject: [PATCH] clk: sunxi: get divs parent clock name from parent factor
+ clock
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Divs clocks consist of a parent factor clock with multiple outputs,
+and seperate clocks for each output. Get the name of the parent
+clock from the parent factor clock, instead of the DT node name.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Acked-by: Mike Turquette <mturquette@linaro.org>
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ drivers/clk/sunxi/clk-sunxi.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 7a2ed98..736fb60 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -869,7 +869,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+ struct divs_data *data)
+ {
+ struct clk_onecell_data *clk_data;
+- const char *parent = node->name;
++ const char *parent;
+ const char *clk_name;
+ struct clk **clks, *pclk;
+ struct clk_hw *gate_hw, *rate_hw;
+@@ -883,6 +883,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+
+ /* Set up factor clock that we will be dividing */
+ pclk = sunxi_factors_clk_setup(node, data->factors);
++ parent = __clk_get_name(pclk);
+
+ reg = of_iomap(node, 0);
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch b/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch
new file mode 100644
index 0000000000..7c49d0f792
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch
@@ -0,0 +1,55 @@
+From f64111ebaf6776558f0e60d0ea8c7a9c579b9436 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:37 +0800
+Subject: [PATCH] clk: sunxi: add clock-output-names dt property support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+sunxi clock drivers use dt node name as clock name, but clock
+nodes should be named clk@X, so the names would be the same.
+Let the drivers read clock names from dt clock-output-names
+property.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Acked-by: Mike Turquette <mturquette@linaro.org>
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ drivers/clk/sunxi/clk-sunxi.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index abb6c5a..0ed9794 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -51,6 +51,8 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
+ if (!gate)
+ goto err_free_fixed;
+
++ of_property_read_string(node, "clock-output-names", &clk_name);
++
+ /* set up gate and fixed rate properties */
+ gate->reg = of_iomap(node, 0);
+ gate->bit_idx = SUNXI_OSC24M_GATE;
+@@ -601,6 +603,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
++ of_property_read_string(node, "clock-output-names", &clk_name);
++
+ clk = clk_register_mux(NULL, clk_name, parents, i,
+ CLK_SET_RATE_NO_REPARENT, reg,
+ data->shift, SUNXI_MUX_GATE_WIDTH,
+@@ -660,6 +664,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
+
+ clk_parent = of_clk_get_parent_name(node, 0);
+
++ of_property_read_string(node, "clock-output-names", &clk_name);
++
+ clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
+ reg, data->shift, data->width,
+ data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch b/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch
new file mode 100644
index 0000000000..f89e97a92e
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch
@@ -0,0 +1,83 @@
+From 667f542db542fddc62d1299b17451d7cae84f6e1 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 3 Feb 2014 09:51:39 +0800
+Subject: [PATCH] clk: sunxi: add names for pll5, pll6 parent clocks to
+ factors_data
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Some factor clocks, such as the parent clock of pll5 and pll6, have
+multiple output names. Add the corresponding names to factors_data
+tied to compatible string.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Acked-by: Mike Turquette <mturquette@linaro.org>
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ drivers/clk/sunxi/clk-sunxi.c | 27 ++++++++++++++++++---------
+ 1 file changed, 18 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 0ed9794..7a2ed98 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -389,6 +389,7 @@ struct factors_data {
+ int mux;
+ struct clk_factors_config *table;
+ void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
++ const char *name;
+ };
+
+ static struct clk_factors_config sun4i_pll1_config = {
+@@ -457,6 +458,14 @@ struct factors_data {
+ .enable = 31,
+ .table = &sun4i_pll5_config,
+ .getter = sun4i_get_pll5_factors,
++ .name = "pll5",
++};
++
++static const struct factors_data sun4i_pll6_data __initconst = {
++ .enable = 31,
++ .table = &sun4i_pll5_config,
++ .getter = sun4i_get_pll5_factors,
++ .name = "pll6",
+ };
+
+ static const struct factors_data sun4i_apb1_data __initconst = {
+@@ -499,14 +508,14 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+- /* Nodes should be providing the name via clock-output-names
+- * but originally our dts didn't, and so we used node->name.
+- * The new, better nodes look like clk@deadbeef, so we pull the
+- * name just in this case */
+- if (!strcmp("clk", clk_name)) {
+- of_property_read_string_index(node, "clock-output-names",
+- 0, &clk_name);
+- }
++ /*
++ * some factor clocks, such as pll5 and pll6, may have multiple
++ * outputs, and have their name designated in factors_data
++ */
++ if (data->name)
++ clk_name = data->name;
++ else
++ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+ if (!factors)
+@@ -838,7 +847,7 @@ struct divs_data {
+ };
+
+ static const struct divs_data pll6_divs_data __initconst = {
+- .factors = &sun4i_pll5_data,
++ .factors = &sun4i_pll6_data,
+ .div = {
+ { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
+ { .fixed = 2 }, /* P, other */
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch b/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch
new file mode 100644
index 0000000000..ce5a0705c1
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch
@@ -0,0 +1,177 @@
+From 967f938d4b16233fd7596e94803a36161847c6a8 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Mon, 10 Feb 2014 18:35:47 +0800
+Subject: [PATCH] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
+
+The Allwinner A20/A31 clock module controls the transmit clock source
+and interface type of the GMAC ethernet controller. Model this as
+a single clock for GMAC drivers to use.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++
+ drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++
+ 2 files changed, 126 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index 93d003c..0da774c 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -37,6 +37,7 @@ Required properties:
+ "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
+ "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
+ "allwinner,sun7i-a20-out-clk" - for the external output clocks
++ "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
+
+ Required properties for all clocks:
+ - reg : shall be the control register address for the clock.
+@@ -50,6 +51,9 @@ Required properties for all clocks:
+ If the clock module only has one output, the name shall be the
+ module name.
+
++For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
++dummy clocks at 25 MHz and 125 MHz, respectively. See example.
++
+ Clock consumers should specify the desired clocks they use with a
+ "clocks" phandle cell. Consumers that are using a gated clock should
+ provide an additional ID in their clock property. This ID is the
+@@ -96,3 +100,29 @@ mmc0_clk: clk@01c20088 {
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ clock-output-names = "mmc0";
+ };
++
++mii_phy_tx_clk: clk@2 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <25000000>;
++ clock-output-names = "mii_phy_tx";
++};
++
++gmac_int_tx_clk: clk@3 {
++ #clock-cells = <0>;
++ compatible = "fixed-clock";
++ clock-frequency = <125000000>;
++ clock-output-names = "gmac_int_tx";
++};
++
++gmac_clk: clk@01c20164 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun7i-a20-gmac-clk";
++ reg = <0x01c20164 0x4>;
++ /*
++ * The first clock must be fixed at 25MHz;
++ * the second clock must be fixed at 125MHz
++ */
++ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
++ clock-output-names = "gmac";
++};
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 0dce6fd..3283179 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -404,6 +404,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
+
+
+ /**
++ * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
++ *
++ * This clock looks something like this
++ * ________________________
++ * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
++ * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
++ * Ext. 125MHz RGMII TX clk >--|__divider__/ |
++ * |________________________|
++ *
++ * The external 125 MHz reference is optional, i.e. GMAC can use its
++ * internal TX clock just fine. The A31 GMAC clock module does not have
++ * the divider controls for the external reference.
++ *
++ * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
++ * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
++ * select the appropriate source and gate/ungate the output to the PHY.
++ *
++ * Only the GMAC should use this clock. Altering the clock so that it doesn't
++ * match the GMAC's operation parameters will result in the GMAC not being
++ * able to send traffic out. The GMAC driver should set the clock rate and
++ * enable/disable this clock to configure the required state. The clock
++ * driver then responds by auto-reparenting the clock.
++ */
++
++#define SUN7I_A20_GMAC_GPIT 2
++#define SUN7I_A20_GMAC_MASK 0x3
++#define SUN7I_A20_GMAC_PARENTS 2
++
++static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
++{
++ struct clk *clk;
++ struct clk_mux *mux;
++ struct clk_gate *gate;
++ const char *clk_name = node->name;
++ const char *parents[SUN7I_A20_GMAC_PARENTS];
++ void *reg;
++
++ if (of_property_read_string(node, "clock-output-names", &clk_name))
++ return;
++
++ /* allocate mux and gate clock structs */
++ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
++ if (!mux)
++ return;
++
++ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
++ if (!gate)
++ goto free_mux;
++
++ /* gmac clock requires exactly 2 parents */
++ parents[0] = of_clk_get_parent_name(node, 0);
++ parents[1] = of_clk_get_parent_name(node, 1);
++ if (!parents[0] || !parents[1])
++ goto free_gate;
++
++ reg = of_iomap(node, 0);
++ if (!reg)
++ goto free_gate;
++
++ /* set up gate and fixed rate properties */
++ gate->reg = reg;
++ gate->bit_idx = SUN7I_A20_GMAC_GPIT;
++ gate->lock = &clk_lock;
++ mux->reg = reg;
++ mux->mask = SUN7I_A20_GMAC_MASK;
++ mux->flags = CLK_MUX_INDEX_BIT;
++ mux->lock = &clk_lock;
++
++ clk = clk_register_composite(NULL, clk_name,
++ parents, SUN7I_A20_GMAC_PARENTS,
++ &mux->hw, &clk_mux_ops,
++ NULL, NULL,
++ &gate->hw, &clk_gate_ops,
++ 0);
++
++ if (IS_ERR(clk))
++ goto iounmap_reg;
++
++ of_clk_add_provider(node, of_clk_src_simple_get, clk);
++ clk_register_clkdev(clk, clk_name, NULL);
++
++ return;
++
++iounmap_reg:
++ iounmap(reg);
++free_gate:
++ kfree(gate);
++free_mux:
++ kfree(mux);
++}
++CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
++ sun7i_a20_gmac_clk_setup);
++
++
++
++/**
+ * sunxi_factors_clk_setup() - Setup function for factor clocks
+ */
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch b/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch
new file mode 100644
index 0000000000..5238534ff1
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch
@@ -0,0 +1,36 @@
+From 673fac742946bcb7cc43b9e67459862d6c4a8a6c Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Wed, 1 Jan 2014 10:30:47 +0800
+Subject: [PATCH] ARM: dts: sun7i: Change 32768 Hz oscillator node name to
+ clk@N style
+
+Device tree naming conventions state that node names should match
+the nodes function. Change external low speed oscillator node name
+to match.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 898b021..edad6f1 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -53,10 +53,11 @@
+ clock-frequency = <24000000>;
+ };
+
+- osc32k: osc32k {
++ osc32k: clk@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
++ clock-output-names = "osc32k";
+ };
+
+ pll1: pll1@01c20000 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch b/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch
new file mode 100644
index 0000000000..6e220e97e0
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch
@@ -0,0 +1,111 @@
+From 92ef67c53ad92487c3c8de75e7940384c2edd793 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Wed, 5 Feb 2014 14:05:03 +0100
+Subject: [PATCH] clk: sunxi: Add support for PLL6 on the A31
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The A31 has a slightly different PLL6 clock. Add support for this new clock in
+our driver.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
+ drivers/clk/sunxi/clk-sunxi.c | 45 +++++++++++++++++++++++
+ 2 files changed, 46 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index ca2b692..c37c764 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -11,6 +11,7 @@ Required properties:
+ "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
+ "allwinner,sun4i-pll5-clk" - for the PLL5 clock
+ "allwinner,sun4i-pll6-clk" - for the PLL6 clock
++ "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
+ "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
+ "allwinner,sun4i-axi-clk" - for the AXI clock
+ "allwinner,sun4i-axi-gates-clk" - for the AXI gates
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index a779c31..d4cf297 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -252,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
+ *n = DIV_ROUND_UP(div, (*k+1));
+ }
+
++/**
++ * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
++ * PLL6 rate is calculated as follows
++ * rate = parent_rate * n * (k + 1) / 2
++ * parent_rate is always 24Mhz
++ */
++
++static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
++ u8 *n, u8 *k, u8 *m, u8 *p)
++{
++ u8 div;
++
++ /*
++ * We always have 24MHz / 2, so we can just say that our
++ * parent clock is 12MHz.
++ */
++ parent_rate = parent_rate / 2;
++
++ /* Normalize value to a parent_rate multiple (24M / 2) */
++ div = *freq / parent_rate;
++ *freq = parent_rate * div;
++
++ /* we were called to round the frequency, we can now return */
++ if (n == NULL)
++ return;
++
++ *k = div / 32;
++ if (*k > 3)
++ *k = 3;
+
++ *n = DIV_ROUND_UP(div, (*k+1));
++}
+
+ /**
+ * sun4i_get_apb1_factors() - calculates m, p factors for APB1
+@@ -420,6 +451,13 @@ struct factors_data {
+ .kwidth = 2,
+ };
+
++static struct clk_factors_config sun6i_a31_pll6_config = {
++ .nshift = 8,
++ .nwidth = 5,
++ .kshift = 4,
++ .kwidth = 2,
++};
++
+ static struct clk_factors_config sun4i_apb1_config = {
+ .mshift = 0,
+ .mwidth = 5,
+@@ -469,6 +507,12 @@ struct factors_data {
+ .name = "pll6",
+ };
+
++static const struct factors_data sun6i_a31_pll6_data __initconst = {
++ .enable = 31,
++ .table = &sun6i_a31_pll6_config,
++ .getter = sun6i_a31_get_pll6_factors,
++};
++
+ static const struct factors_data sun4i_apb1_data __initconst = {
+ .table = &sun4i_apb1_config,
+ .getter = sun4i_get_apb1_factors,
+@@ -1069,6 +1113,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+ static const struct of_device_id clk_factors_match[] __initconst = {
+ {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
+ {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
++ {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
+ {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
+ {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
+ {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch b/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch
new file mode 100644
index 0000000000..8941125a60
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch
@@ -0,0 +1,599 @@
+From 3558fe900e8af6c3bfadeff24a12ffb19ac9b108 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Wed, 5 Feb 2014 14:05:05 +0100
+Subject: [PATCH 1/2] spi: sunxi: Add Allwinner A31 SPI controller driver
+
+The Allwinner A31 has a new SPI controller IP compared to the older Allwinner
+SoCs.
+
+It supports DMA, but the driver only does PIO for now, and DMA will be
+supported eventually.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Mark Brown <broonie@linaro.org>
+---
+ .../devicetree/bindings/spi/spi-sun6i.txt | 24 +
+ drivers/spi/Kconfig | 6 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-sun6i.c | 483 +++++++++++++++++++++
+ 4 files changed, 514 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
+ create mode 100644 drivers/spi/spi-sun6i.c
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
+new file mode 100644
+index 0000000..21de73d
+--- /dev/null
++++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
+@@ -0,0 +1,24 @@
++Allwinner A31 SPI controller
++
++Required properties:
++- compatible: Should be "allwinner,sun6i-a31-spi".
++- reg: Should contain register location and length.
++- interrupts: Should contain interrupt.
++- clocks: phandle to the clocks feeding the SPI controller. Two are
++ needed:
++ - "ahb": the gated AHB parent clock
++ - "mod": the parent module clock
++- clock-names: Must contain the clock names described just above
++- resets: phandle to the reset controller asserting this device in
++ reset
++
++Example:
++
++spi1: spi@01c69000 {
++ compatible = "allwinner,sun6i-a31-spi";
++ reg = <0x01c69000 0x1000>;
++ interrupts = <0 66 4>;
++ clocks = <&ahb1_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ resets = <&ahb1_rst 21>;
++};
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index ba9310b..7cfe0ee 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -446,6 +446,12 @@ config SPI_SIRF
+ help
+ SPI driver for CSR SiRFprimaII SoCs
+
++config SPI_SUN6I
++ tristate "Allwinner A31 SPI controller"
++ depends on ARCH_SUNXI || COMPILE_TEST
++ help
++ This enables using the SPI controller on the Allwinner A31 SoCs.
++
+ config SPI_MXS
+ tristate "Freescale MXS SPI controller"
+ depends on ARCH_MXS
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 95af48d..13b6ccf 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -70,6 +70,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
+ obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
+ obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
+ obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
++obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
+ obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
+ obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
+ obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
+diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
+new file mode 100644
+index 0000000..94d38d0
+--- /dev/null
++++ b/drivers/spi/spi-sun6i.c
+@@ -0,0 +1,483 @@
++/*
++ * Copyright (C) 2012 - 2014 Allwinner Tech
++ * Pan Nan <pannan@allwinnertech.com>
++ *
++ * Copyright (C) 2014 Maxime Ripard
++ * Maxime Ripard <maxime.ripard@free-electrons.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++#include <linux/workqueue.h>
++
++#include <linux/spi/spi.h>
++
++#define SUN6I_FIFO_DEPTH 128
++
++#define SUN6I_GBL_CTL_REG 0x04
++#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
++#define SUN6I_GBL_CTL_MASTER BIT(1)
++#define SUN6I_GBL_CTL_TP BIT(7)
++#define SUN6I_GBL_CTL_RST BIT(31)
++
++#define SUN6I_TFR_CTL_REG 0x08
++#define SUN6I_TFR_CTL_CPHA BIT(0)
++#define SUN6I_TFR_CTL_CPOL BIT(1)
++#define SUN6I_TFR_CTL_SPOL BIT(2)
++#define SUN6I_TFR_CTL_CS_MASK 0x3
++#define SUN6I_TFR_CTL_CS(cs) (((cs) & SUN6I_TFR_CTL_CS_MASK) << 4)
++#define SUN6I_TFR_CTL_CS_MANUAL BIT(6)
++#define SUN6I_TFR_CTL_CS_LEVEL BIT(7)
++#define SUN6I_TFR_CTL_DHB BIT(8)
++#define SUN6I_TFR_CTL_FBS BIT(12)
++#define SUN6I_TFR_CTL_XCH BIT(31)
++
++#define SUN6I_INT_CTL_REG 0x10
++#define SUN6I_INT_CTL_RF_OVF BIT(8)
++#define SUN6I_INT_CTL_TC BIT(12)
++
++#define SUN6I_INT_STA_REG 0x14
++
++#define SUN6I_FIFO_CTL_REG 0x18
++#define SUN6I_FIFO_CTL_RF_RST BIT(15)
++#define SUN6I_FIFO_CTL_TF_RST BIT(31)
++
++#define SUN6I_FIFO_STA_REG 0x1c
++#define SUN6I_FIFO_STA_RF_CNT_MASK 0x7f
++#define SUN6I_FIFO_STA_RF_CNT_BITS 0
++#define SUN6I_FIFO_STA_TF_CNT_MASK 0x7f
++#define SUN6I_FIFO_STA_TF_CNT_BITS 16
++
++#define SUN6I_CLK_CTL_REG 0x24
++#define SUN6I_CLK_CTL_CDR2_MASK 0xff
++#define SUN6I_CLK_CTL_CDR2(div) (((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
++#define SUN6I_CLK_CTL_CDR1_MASK 0xf
++#define SUN6I_CLK_CTL_CDR1(div) (((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
++#define SUN6I_CLK_CTL_DRS BIT(12)
++
++#define SUN6I_BURST_CNT_REG 0x30
++#define SUN6I_BURST_CNT(cnt) ((cnt) & 0xffffff)
++
++#define SUN6I_XMIT_CNT_REG 0x34
++#define SUN6I_XMIT_CNT(cnt) ((cnt) & 0xffffff)
++
++#define SUN6I_BURST_CTL_CNT_REG 0x38
++#define SUN6I_BURST_CTL_CNT_STC(cnt) ((cnt) & 0xffffff)
++
++#define SUN6I_TXDATA_REG 0x200
++#define SUN6I_RXDATA_REG 0x300
++
++struct sun6i_spi {
++ struct spi_master *master;
++ void __iomem *base_addr;
++ struct clk *hclk;
++ struct clk *mclk;
++ struct reset_control *rstc;
++
++ struct completion done;
++
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ int len;
++};
++
++static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
++{
++ return readl(sspi->base_addr + reg);
++}
++
++static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
++{
++ writel(value, sspi->base_addr + reg);
++}
++
++static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
++{
++ u32 reg, cnt;
++ u8 byte;
++
++ /* See how much data is available */
++ reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
++ reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
++ cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
++
++ if (len > cnt)
++ len = cnt;
++
++ while (len--) {
++ byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
++ if (sspi->rx_buf)
++ *sspi->rx_buf++ = byte;
++ }
++}
++
++static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
++{
++ u8 byte;
++
++ if (len > sspi->len)
++ len = sspi->len;
++
++ while (len--) {
++ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
++ writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
++ sspi->len--;
++ }
++}
++
++static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
++{
++ struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
++ u32 reg;
++
++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
++ reg &= ~SUN6I_TFR_CTL_CS_MASK;
++ reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
++
++ if (enable)
++ reg |= SUN6I_TFR_CTL_CS_LEVEL;
++ else
++ reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
++
++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
++}
++
++
++static int sun6i_spi_transfer_one(struct spi_master *master,
++ struct spi_device *spi,
++ struct spi_transfer *tfr)
++{
++ struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ unsigned int mclk_rate, div, timeout;
++ unsigned int tx_len = 0;
++ int ret = 0;
++ u32 reg;
++
++ /* We don't support transfer larger than the FIFO */
++ if (tfr->len > SUN6I_FIFO_DEPTH)
++ return -EINVAL;
++
++ reinit_completion(&sspi->done);
++ sspi->tx_buf = tfr->tx_buf;
++ sspi->rx_buf = tfr->rx_buf;
++ sspi->len = tfr->len;
++
++ /* Clear pending interrupts */
++ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
++
++ /* Reset FIFO */
++ sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
++ SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
++
++ /*
++ * Setup the transfer control register: Chip Select,
++ * polarities, etc.
++ */
++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
++
++ if (spi->mode & SPI_CPOL)
++ reg |= SUN6I_TFR_CTL_CPOL;
++ else
++ reg &= ~SUN6I_TFR_CTL_CPOL;
++
++ if (spi->mode & SPI_CPHA)
++ reg |= SUN6I_TFR_CTL_CPHA;
++ else
++ reg &= ~SUN6I_TFR_CTL_CPHA;
++
++ if (spi->mode & SPI_LSB_FIRST)
++ reg |= SUN6I_TFR_CTL_FBS;
++ else
++ reg &= ~SUN6I_TFR_CTL_FBS;
++
++ /*
++ * If it's a TX only transfer, we don't want to fill the RX
++ * FIFO with bogus data
++ */
++ if (sspi->rx_buf)
++ reg &= ~SUN6I_TFR_CTL_DHB;
++ else
++ reg |= SUN6I_TFR_CTL_DHB;
++
++ /* We want to control the chip select manually */
++ reg |= SUN6I_TFR_CTL_CS_MANUAL;
++
++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
++
++ /* Ensure that we have a parent clock fast enough */
++ mclk_rate = clk_get_rate(sspi->mclk);
++ if (mclk_rate < (2 * spi->max_speed_hz)) {
++ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
++ mclk_rate = clk_get_rate(sspi->mclk);
++ }
++
++ /*
++ * Setup clock divider.
++ *
++ * We have two choices there. Either we can use the clock
++ * divide rate 1, which is calculated thanks to this formula:
++ * SPI_CLK = MOD_CLK / (2 ^ cdr)
++ * Or we can use CDR2, which is calculated with the formula:
++ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
++ * Wether we use the former or the latter is set through the
++ * DRS bit.
++ *
++ * First try CDR2, and if we can't reach the expected
++ * frequency, fall back to CDR1.
++ */
++ div = mclk_rate / (2 * spi->max_speed_hz);
++ if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
++ if (div > 0)
++ div--;
++
++ reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
++ } else {
++ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
++ reg = SUN6I_CLK_CTL_CDR1(div);
++ }
++
++ sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
++
++ /* Setup the transfer now... */
++ if (sspi->tx_buf)
++ tx_len = tfr->len;
++
++ /* Setup the counters */
++ sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len));
++ sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len));
++ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG,
++ SUN6I_BURST_CTL_CNT_STC(tx_len));
++
++ /* Fill the TX FIFO */
++ sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
++
++ /* Enable the interrupts */
++ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
++
++ /* Start the transfer */
++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
++
++ timeout = wait_for_completion_timeout(&sspi->done,
++ msecs_to_jiffies(1000));
++ if (!timeout) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
++
++out:
++ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
++
++ return ret;
++}
++
++static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
++{
++ struct sun6i_spi *sspi = dev_id;
++ u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
++
++ /* Transfer complete */
++ if (status & SUN6I_INT_CTL_TC) {
++ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
++ complete(&sspi->done);
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static int sun6i_spi_runtime_resume(struct device *dev)
++{
++ struct spi_master *master = dev_get_drvdata(dev);
++ struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ int ret;
++
++ ret = clk_prepare_enable(sspi->hclk);
++ if (ret) {
++ dev_err(dev, "Couldn't enable AHB clock\n");
++ goto out;
++ }
++
++ ret = clk_prepare_enable(sspi->mclk);
++ if (ret) {
++ dev_err(dev, "Couldn't enable module clock\n");
++ goto err;
++ }
++
++ ret = reset_control_deassert(sspi->rstc);
++ if (ret) {
++ dev_err(dev, "Couldn't deassert the device from reset\n");
++ goto err2;
++ }
++
++ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
++ SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
++
++ return 0;
++
++err2:
++ clk_disable_unprepare(sspi->mclk);
++err:
++ clk_disable_unprepare(sspi->hclk);
++out:
++ return ret;
++}
++
++static int sun6i_spi_runtime_suspend(struct device *dev)
++{
++ struct spi_master *master = dev_get_drvdata(dev);
++ struct sun6i_spi *sspi = spi_master_get_devdata(master);
++
++ reset_control_assert(sspi->rstc);
++ clk_disable_unprepare(sspi->mclk);
++ clk_disable_unprepare(sspi->hclk);
++
++ return 0;
++}
++
++static int sun6i_spi_probe(struct platform_device *pdev)
++{
++ struct spi_master *master;
++ struct sun6i_spi *sspi;
++ struct resource *res;
++ int ret = 0, irq;
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
++ if (!master) {
++ dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
++ return -ENOMEM;
++ }
++
++ platform_set_drvdata(pdev, master);
++ sspi = spi_master_get_devdata(master);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(sspi->base_addr)) {
++ ret = PTR_ERR(sspi->base_addr);
++ goto err_free_master;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "No spi IRQ specified\n");
++ ret = -ENXIO;
++ goto err_free_master;
++ }
++
++ ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
++ 0, "sun6i-spi", sspi);
++ if (ret) {
++ dev_err(&pdev->dev, "Cannot request IRQ\n");
++ goto err_free_master;
++ }
++
++ sspi->master = master;
++ master->set_cs = sun6i_spi_set_cs;
++ master->transfer_one = sun6i_spi_transfer_one;
++ master->num_chipselect = 4;
++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++ master->dev.of_node = pdev->dev.of_node;
++ master->auto_runtime_pm = true;
++
++ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
++ if (IS_ERR(sspi->hclk)) {
++ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
++ ret = PTR_ERR(sspi->hclk);
++ goto err_free_master;
++ }
++
++ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
++ if (IS_ERR(sspi->mclk)) {
++ dev_err(&pdev->dev, "Unable to acquire module clock\n");
++ ret = PTR_ERR(sspi->mclk);
++ goto err_free_master;
++ }
++
++ init_completion(&sspi->done);
++
++ sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(sspi->rstc)) {
++ dev_err(&pdev->dev, "Couldn't get reset controller\n");
++ ret = PTR_ERR(sspi->rstc);
++ goto err_free_master;
++ }
++
++ /*
++ * This wake-up/shutdown pattern is to be able to have the
++ * device woken up, even if runtime_pm is disabled
++ */
++ ret = sun6i_spi_runtime_resume(&pdev->dev);
++ if (ret) {
++ dev_err(&pdev->dev, "Couldn't resume the device\n");
++ goto err_free_master;
++ }
++
++ pm_runtime_set_active(&pdev->dev);
++ pm_runtime_enable(&pdev->dev);
++ pm_runtime_idle(&pdev->dev);
++
++ ret = devm_spi_register_master(&pdev->dev, master);
++ if (ret) {
++ dev_err(&pdev->dev, "cannot register SPI master\n");
++ goto err_pm_disable;
++ }
++
++ return 0;
++
++err_pm_disable:
++ pm_runtime_disable(&pdev->dev);
++ sun6i_spi_runtime_suspend(&pdev->dev);
++err_free_master:
++ spi_master_put(master);
++ return ret;
++}
++
++static int sun6i_spi_remove(struct platform_device *pdev)
++{
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++static const struct of_device_id sun6i_spi_match[] = {
++ { .compatible = "allwinner,sun6i-a31-spi", },
++ {}
++};
++MODULE_DEVICE_TABLE(of, sun6i_spi_match);
++
++static const struct dev_pm_ops sun6i_spi_pm_ops = {
++ .runtime_resume = sun6i_spi_runtime_resume,
++ .runtime_suspend = sun6i_spi_runtime_suspend,
++};
++
++static struct platform_driver sun6i_spi_driver = {
++ .probe = sun6i_spi_probe,
++ .remove = sun6i_spi_remove,
++ .driver = {
++ .name = "sun6i-spi",
++ .owner = THIS_MODULE,
++ .of_match_table = sun6i_spi_match,
++ .pm = &sun6i_spi_pm_ops,
++ },
++};
++module_platform_driver(sun6i_spi_driver);
++
++MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
++MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
++MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
++MODULE_LICENSE("GPL");
+--
+1.8.5.5
+
+
+From 7961656a6f11b69966500d7bd25273203fd930da Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@linaro.org>
+Date: Thu, 6 Feb 2014 10:53:51 +0000
+Subject: [PATCH 2/2] spi/sunxi: Add missing dependency on RESET_CONTROLLER
+
+Signed-off-by: Mark Brown <broonie@linaro.org>
+---
+ drivers/spi/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 7cfe0ee..0ec4641 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -449,6 +449,7 @@ config SPI_SIRF
+ config SPI_SUN6I
+ tristate "Allwinner A31 SPI controller"
+ depends on ARCH_SUNXI || COMPILE_TEST
++ depends on RESET_CONTROLLER
+ help
+ This enables using the SPI controller on the Allwinner A31 SoCs.
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch b/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch
new file mode 100644
index 0000000000..78475fccae
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch
@@ -0,0 +1,82 @@
+From b0a09c756bf6e0b89d6b88a7620ba4cd86b1895b Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Wed, 5 Feb 2014 14:05:04 +0100
+Subject: [PATCH] ARM: sun6i: dt: Add PLL6 and SPI module clocks
+
+The module clocks in the A31 are still compatible with the A10 one. Add the SPI
+module clocks and the PLL6 in the device tree to allow their use by the SPI
+controllers.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun6i-a31.dtsi | 46 ++++++++++++++++++++++++++++++++--------
+ 1 file changed, 37 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
+index 092bf97..93d7bb6 100644
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -83,16 +83,12 @@
+ clocks = <&osc24M>;
+ };
+
+- /*
+- * This is a dummy clock, to be used as placeholder on
+- * other mux clocks when a specific parent clock is not
+- * yet implemented. It should be dropped when the driver
+- * is complete.
+- */
+- pll6: pll6 {
++ pll6: clk@01c20028 {
+ #clock-cells = <0>;
+- compatible = "fixed-clock";
+- clock-frequency = <0>;
++ compatible = "allwinner,sun6i-a31-pll6-clk";
++ reg = <0x01c20028 0x4>;
++ clocks = <&osc24M>;
++ clock-output-names = "pll6";
+ };
+
+ cpu: cpu@01c20050 {
+@@ -192,6 +188,38 @@
+ "apb2_uart1", "apb2_uart2", "apb2_uart3",
+ "apb2_uart4", "apb2_uart5";
+ };
++
++ spi0_clk: clk@01c200a0 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c200a0 0x4>;
++ clocks = <&osc24M>, <&pll6>;
++ clock-output-names = "spi0";
++ };
++
++ spi1_clk: clk@01c200a4 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c200a4 0x4>;
++ clocks = <&osc24M>, <&pll6>;
++ clock-output-names = "spi1";
++ };
++
++ spi2_clk: clk@01c200a8 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c200a8 0x4>;
++ clocks = <&osc24M>, <&pll6>;
++ clock-output-names = "spi2";
++ };
++
++ spi3_clk: clk@01c200ac {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c200ac 0x4>;
++ clocks = <&osc24M>, <&pll6>;
++ clock-output-names = "spi3";
++ };
+ };
+
+ soc@01c00000 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch b/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch
new file mode 100644
index 0000000000..be2cce5f11
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch
@@ -0,0 +1,571 @@
+From 67e7ba38902a28679bf6ee8fd82952ae6795f5f5 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:53 +0100
+Subject: [PATCH] spi: sunxi: Add Allwinner A10 SPI controller driver
+
+The older Allwinner SoCs (A10, A13, A10s and A20) all have the same SPI
+controller.
+
+Unfortunately, this SPI controller, even though quite similar, is significantly
+different from the recently supported A31 SPI controller (different registers
+offset, split/merged registers, etc.). Supporting both controllers in a single
+driver would be unreasonable, hence the addition of a new driver.
+
+Like its more recent counterpart, it supports DMA, but the driver only does PIO
+until we have a dmaengine driver for this platform.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ .../devicetree/bindings/spi/spi-sun4i.txt | 24 ++
+ drivers/spi/Kconfig | 6 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-sun4i.c | 477 +++++++++++++++++++++
+ 4 files changed, 508 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-sun4i.txt
+ create mode 100644 drivers/spi/spi-sun4i.c
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-sun4i.txt b/Documentation/devicetree/bindings/spi/spi-sun4i.txt
+new file mode 100644
+index 0000000..de827f5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/spi/spi-sun4i.txt
+@@ -0,0 +1,24 @@
++Allwinner A10 SPI controller
++
++Required properties:
++- compatible: Should be "allwinner,sun4-a10-spi".
++- reg: Should contain register location and length.
++- interrupts: Should contain interrupt.
++- clocks: phandle to the clocks feeding the SPI controller. Two are
++ needed:
++ - "ahb": the gated AHB parent clock
++ - "mod": the parent module clock
++- clock-names: Must contain the clock names described just above
++
++Example:
++
++spi1: spi@01c06000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c06000 0x1000>;
++ interrupts = <11>;
++ clocks = <&ahb_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++};
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 58530d3..78adfae 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -446,6 +446,12 @@ config SPI_SIRF
+ help
+ SPI driver for CSR SiRFprimaII SoCs
+
++config SPI_SUN4I
++ tristate "Allwinner A10 SoCs SPI controller"
++ depends on ARCH_SUNXI || COMPILE_TEST
++ help
++ SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
++
+ config SPI_SUN6I
+ tristate "Allwinner A31 SPI controller"
+ depends on ARCH_SUNXI || COMPILE_TEST
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 13b6ccf..65f4993 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -70,6 +70,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o
+ obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
+ obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
+ obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
++obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
+ obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
+ obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
+ obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
+diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
+new file mode 100644
+index 0000000..3f82705
+--- /dev/null
++++ b/drivers/spi/spi-sun4i.c
+@@ -0,0 +1,477 @@
++/*
++ * Copyright (C) 2012 - 2014 Allwinner Tech
++ * Pan Nan <pannan@allwinnertech.com>
++ *
++ * Copyright (C) 2014 Maxime Ripard
++ * Maxime Ripard <maxime.ripard@free-electrons.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/workqueue.h>
++
++#include <linux/spi/spi.h>
++
++#define SUN4I_FIFO_DEPTH 64
++
++#define SUN4I_RXDATA_REG 0x00
++
++#define SUN4I_TXDATA_REG 0x04
++
++#define SUN4I_CTL_REG 0x08
++#define SUN4I_CTL_ENABLE BIT(0)
++#define SUN4I_CTL_MASTER BIT(1)
++#define SUN4I_CTL_CPHA BIT(2)
++#define SUN4I_CTL_CPOL BIT(3)
++#define SUN4I_CTL_CS_ACTIVE_LOW BIT(4)
++#define SUN4I_CTL_LMTF BIT(6)
++#define SUN4I_CTL_TF_RST BIT(8)
++#define SUN4I_CTL_RF_RST BIT(9)
++#define SUN4I_CTL_XCH BIT(10)
++#define SUN4I_CTL_CS_MASK 0x3000
++#define SUN4I_CTL_CS(cs) (((cs) << 12) & SUN4I_CTL_CS_MASK)
++#define SUN4I_CTL_DHB BIT(15)
++#define SUN4I_CTL_CS_MANUAL BIT(16)
++#define SUN4I_CTL_CS_LEVEL BIT(17)
++#define SUN4I_CTL_TP BIT(18)
++
++#define SUN4I_INT_CTL_REG 0x0c
++#define SUN4I_INT_CTL_TC BIT(16)
++
++#define SUN4I_INT_STA_REG 0x10
++
++#define SUN4I_DMA_CTL_REG 0x14
++
++#define SUN4I_WAIT_REG 0x18
++
++#define SUN4I_CLK_CTL_REG 0x1c
++#define SUN4I_CLK_CTL_CDR2_MASK 0xff
++#define SUN4I_CLK_CTL_CDR2(div) ((div) & SUN4I_CLK_CTL_CDR2_MASK)
++#define SUN4I_CLK_CTL_CDR1_MASK 0xf
++#define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
++#define SUN4I_CLK_CTL_DRS BIT(12)
++
++#define SUN4I_BURST_CNT_REG 0x20
++#define SUN4I_BURST_CNT(cnt) ((cnt) & 0xffffff)
++
++#define SUN4I_XMIT_CNT_REG 0x24
++#define SUN4I_XMIT_CNT(cnt) ((cnt) & 0xffffff)
++
++#define SUN4I_FIFO_STA_REG 0x28
++#define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f
++#define SUN4I_FIFO_STA_RF_CNT_BITS 0
++#define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f
++#define SUN4I_FIFO_STA_TF_CNT_BITS 16
++
++struct sun4i_spi {
++ struct spi_master *master;
++ void __iomem *base_addr;
++ struct clk *hclk;
++ struct clk *mclk;
++
++ struct completion done;
++
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ int len;
++};
++
++static inline u32 sun4i_spi_read(struct sun4i_spi *sspi, u32 reg)
++{
++ return readl(sspi->base_addr + reg);
++}
++
++static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value)
++{
++ writel(value, sspi->base_addr + reg);
++}
++
++static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
++{
++ u32 reg, cnt;
++ u8 byte;
++
++ /* See how much data is available */
++ reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
++ reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
++ cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
++
++ if (len > cnt)
++ len = cnt;
++
++ while (len--) {
++ byte = readb(sspi->base_addr + SUN4I_RXDATA_REG);
++ if (sspi->rx_buf)
++ *sspi->rx_buf++ = byte;
++ }
++}
++
++static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len)
++{
++ u8 byte;
++
++ if (len > sspi->len)
++ len = sspi->len;
++
++ while (len--) {
++ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
++ writeb(byte, sspi->base_addr + SUN4I_TXDATA_REG);
++ sspi->len--;
++ }
++}
++
++static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
++{
++ struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
++ u32 reg;
++
++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
++
++ reg &= ~SUN4I_CTL_CS_MASK;
++ reg |= SUN4I_CTL_CS(spi->chip_select);
++
++ if (enable)
++ reg |= SUN4I_CTL_CS_LEVEL;
++ else
++ reg &= ~SUN4I_CTL_CS_LEVEL;
++
++ /*
++ * Even though this looks irrelevant since we are supposed to
++ * be controlling the chip select manually, this bit also
++ * controls the levels of the chip select for inactive
++ * devices.
++ *
++ * If we don't set it, the chip select level will go low by
++ * default when the device is idle, which is not really
++ * expected in the common case where the chip select is active
++ * low.
++ */
++ if (spi->mode & SPI_CS_HIGH)
++ reg &= ~SUN4I_CTL_CS_ACTIVE_LOW;
++ else
++ reg |= SUN4I_CTL_CS_ACTIVE_LOW;
++
++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
++}
++
++static int sun4i_spi_transfer_one(struct spi_master *master,
++ struct spi_device *spi,
++ struct spi_transfer *tfr)
++{
++ struct sun4i_spi *sspi = spi_master_get_devdata(master);
++ unsigned int mclk_rate, div, timeout;
++ unsigned int tx_len = 0;
++ int ret = 0;
++ u32 reg;
++
++ /* We don't support transfer larger than the FIFO */
++ if (tfr->len > SUN4I_FIFO_DEPTH)
++ return -EINVAL;
++
++ reinit_completion(&sspi->done);
++ sspi->tx_buf = tfr->tx_buf;
++ sspi->rx_buf = tfr->rx_buf;
++ sspi->len = tfr->len;
++
++ /* Clear pending interrupts */
++ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0);
++
++
++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
++
++ /* Reset FIFOs */
++ sun4i_spi_write(sspi, SUN4I_CTL_REG,
++ reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
++
++ /*
++ * Setup the transfer control register: Chip Select,
++ * polarities, etc.
++ */
++ if (spi->mode & SPI_CPOL)
++ reg |= SUN4I_CTL_CPOL;
++ else
++ reg &= ~SUN4I_CTL_CPOL;
++
++ if (spi->mode & SPI_CPHA)
++ reg |= SUN4I_CTL_CPHA;
++ else
++ reg &= ~SUN4I_CTL_CPHA;
++
++ if (spi->mode & SPI_LSB_FIRST)
++ reg |= SUN4I_CTL_LMTF;
++ else
++ reg &= ~SUN4I_CTL_LMTF;
++
++
++ /*
++ * If it's a TX only transfer, we don't want to fill the RX
++ * FIFO with bogus data
++ */
++ if (sspi->rx_buf)
++ reg &= ~SUN4I_CTL_DHB;
++ else
++ reg |= SUN4I_CTL_DHB;
++
++ /* We want to control the chip select manually */
++ reg |= SUN4I_CTL_CS_MANUAL;
++
++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
++
++ /* Ensure that we have a parent clock fast enough */
++ mclk_rate = clk_get_rate(sspi->mclk);
++ if (mclk_rate < (2 * spi->max_speed_hz)) {
++ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
++ mclk_rate = clk_get_rate(sspi->mclk);
++ }
++
++ /*
++ * Setup clock divider.
++ *
++ * We have two choices there. Either we can use the clock
++ * divide rate 1, which is calculated thanks to this formula:
++ * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
++ * Or we can use CDR2, which is calculated with the formula:
++ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
++ * Wether we use the former or the latter is set through the
++ * DRS bit.
++ *
++ * First try CDR2, and if we can't reach the expected
++ * frequency, fall back to CDR1.
++ */
++ div = mclk_rate / (2 * spi->max_speed_hz);
++ if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
++ if (div > 0)
++ div--;
++
++ reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
++ } else {
++ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
++ reg = SUN4I_CLK_CTL_CDR1(div);
++ }
++
++ sun4i_spi_write(sspi, SUN4I_CLK_CTL_REG, reg);
++
++ /* Setup the transfer now... */
++ if (sspi->tx_buf)
++ tx_len = tfr->len;
++
++ /* Setup the counters */
++ sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
++ sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
++
++ /* Fill the TX FIFO */
++ sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
++
++ /* Enable the interrupts */
++ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
++
++ /* Start the transfer */
++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
++
++ timeout = wait_for_completion_timeout(&sspi->done,
++ msecs_to_jiffies(1000));
++ if (!timeout) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
++
++out:
++ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
++
++ return ret;
++}
++
++static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
++{
++ struct sun4i_spi *sspi = dev_id;
++ u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
++
++ /* Transfer complete */
++ if (status & SUN4I_INT_CTL_TC) {
++ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
++ complete(&sspi->done);
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static int sun4i_spi_runtime_resume(struct device *dev)
++{
++ struct spi_master *master = dev_get_drvdata(dev);
++ struct sun4i_spi *sspi = spi_master_get_devdata(master);
++ int ret;
++
++ ret = clk_prepare_enable(sspi->hclk);
++ if (ret) {
++ dev_err(dev, "Couldn't enable AHB clock\n");
++ goto out;
++ }
++
++ ret = clk_prepare_enable(sspi->mclk);
++ if (ret) {
++ dev_err(dev, "Couldn't enable module clock\n");
++ goto err;
++ }
++
++ sun4i_spi_write(sspi, SUN4I_CTL_REG,
++ SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP);
++
++ return 0;
++
++err:
++ clk_disable_unprepare(sspi->hclk);
++out:
++ return ret;
++}
++
++static int sun4i_spi_runtime_suspend(struct device *dev)
++{
++ struct spi_master *master = dev_get_drvdata(dev);
++ struct sun4i_spi *sspi = spi_master_get_devdata(master);
++
++ clk_disable_unprepare(sspi->mclk);
++ clk_disable_unprepare(sspi->hclk);
++
++ return 0;
++}
++
++static int sun4i_spi_probe(struct platform_device *pdev)
++{
++ struct spi_master *master;
++ struct sun4i_spi *sspi;
++ struct resource *res;
++ int ret = 0, irq;
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
++ if (!master) {
++ dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
++ return -ENOMEM;
++ }
++
++ platform_set_drvdata(pdev, master);
++ sspi = spi_master_get_devdata(master);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(sspi->base_addr)) {
++ ret = PTR_ERR(sspi->base_addr);
++ goto err_free_master;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "No spi IRQ specified\n");
++ ret = -ENXIO;
++ goto err_free_master;
++ }
++
++ ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler,
++ 0, "sun4i-spi", sspi);
++ if (ret) {
++ dev_err(&pdev->dev, "Cannot request IRQ\n");
++ goto err_free_master;
++ }
++
++ sspi->master = master;
++ master->set_cs = sun4i_spi_set_cs;
++ master->transfer_one = sun4i_spi_transfer_one;
++ master->num_chipselect = 4;
++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++ master->dev.of_node = pdev->dev.of_node;
++ master->auto_runtime_pm = true;
++
++ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
++ if (IS_ERR(sspi->hclk)) {
++ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
++ ret = PTR_ERR(sspi->hclk);
++ goto err_free_master;
++ }
++
++ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
++ if (IS_ERR(sspi->mclk)) {
++ dev_err(&pdev->dev, "Unable to acquire module clock\n");
++ ret = PTR_ERR(sspi->mclk);
++ goto err_free_master;
++ }
++
++ init_completion(&sspi->done);
++
++ /*
++ * This wake-up/shutdown pattern is to be able to have the
++ * device woken up, even if runtime_pm is disabled
++ */
++ ret = sun4i_spi_runtime_resume(&pdev->dev);
++ if (ret) {
++ dev_err(&pdev->dev, "Couldn't resume the device\n");
++ goto err_free_master;
++ }
++
++ pm_runtime_set_active(&pdev->dev);
++ pm_runtime_enable(&pdev->dev);
++ pm_runtime_idle(&pdev->dev);
++
++ ret = devm_spi_register_master(&pdev->dev, master);
++ if (ret) {
++ dev_err(&pdev->dev, "cannot register SPI master\n");
++ goto err_pm_disable;
++ }
++
++ return 0;
++
++err_pm_disable:
++ pm_runtime_disable(&pdev->dev);
++ sun4i_spi_runtime_suspend(&pdev->dev);
++err_free_master:
++ spi_master_put(master);
++ return ret;
++}
++
++static int sun4i_spi_remove(struct platform_device *pdev)
++{
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++static const struct of_device_id sun4i_spi_match[] = {
++ { .compatible = "allwinner,sun4i-a10-spi", },
++ {}
++};
++MODULE_DEVICE_TABLE(of, sun4i_spi_match);
++
++static const struct dev_pm_ops sun4i_spi_pm_ops = {
++ .runtime_resume = sun4i_spi_runtime_resume,
++ .runtime_suspend = sun4i_spi_runtime_suspend,
++};
++
++static struct platform_driver sun4i_spi_driver = {
++ .probe = sun4i_spi_probe,
++ .remove = sun4i_spi_remove,
++ .driver = {
++ .name = "sun4i-spi",
++ .owner = THIS_MODULE,
++ .of_match_table = sun4i_spi_match,
++ .pm = &sun4i_spi_pm_ops,
++ },
++};
++module_platform_driver(sun4i_spi_driver);
++
++MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
++MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
++MODULE_DESCRIPTION("Allwinner A1X/A20 SPI controller driver");
++MODULE_LICENSE("GPL");
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch b/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch
new file mode 100644
index 0000000000..8d43f621ee
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch
@@ -0,0 +1,85 @@
+From 3fff6e0d2bdd3b3f999a9dfcc8432ecba56eaad8 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:54 +0100
+Subject: [PATCH] ARM: dt: sun7i: Add A20 SPI controller nodes
+
+The A20 has 4 SPI controllers compatible with the one found in the A10. Add
+them in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 1961751..bcea04a 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -393,6 +393,28 @@
+ #size-cells = <1>;
+ ranges;
+
++ spi0: spi@01c05000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c05000 0x1000>;
++ interrupts = <0 10 4>;
++ clocks = <&ahb_gates 20>, <&spi0_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ spi1: spi@01c06000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c06000 0x1000>;
++ interrupts = <0 11 4>;
++ clocks = <&ahb_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ emac: ethernet@01c0b000 {
+ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+@@ -485,6 +507,17 @@
+ status = "disabled";
+ };
+
++ spi2: spi@01c17000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c17000 0x1000>;
++ interrupts = <0 12 4>;
++ clocks = <&ahb_gates 22>, <&spi2_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -513,6 +546,17 @@
+ status = "disabled";
+ };
+
++ spi3: spi@01c1f000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c1f000 0x1000>;
++ interrupts = <0 50 4>;
++ clocks = <&ahb_gates 23>, <&spi3_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ pio: pinctrl@01c20800 {
+ compatible = "allwinner,sun7i-a20-pinctrl";
+ reg = <0x01c20800 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch
new file mode 100644
index 0000000000..4848688ba2
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch
@@ -0,0 +1,84 @@
+From f21f034bd5b288068e1fa35c28d5e48e9ae8cbf5 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:55 +0100
+Subject: [PATCH] ARM: dt: sun4i: Add A10 SPI controller nodes
+
+The A10 has 4 SPI controllers that are now supported. Add them in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 3a5775c..cdd5b72 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -331,6 +331,28 @@
+ #size-cells = <1>;
+ ranges;
+
++ spi0: spi@01c05000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c05000 0x1000>;
++ interrupts = <10>;
++ clocks = <&ahb_gates 20>, <&spi0_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ spi1: spi@01c06000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c06000 0x1000>;
++ interrupts = <11>;
++ clocks = <&ahb_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ emac: ethernet@01c0b000 {
+ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+@@ -423,6 +445,17 @@
+ status = "disabled";
+ };
+
++ spi2: spi@01c17000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c17000 0x1000>;
++ interrupts = <12>;
++ clocks = <&ahb_gates 22>, <&spi2_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+@@ -451,6 +484,17 @@
+ status = "disabled";
+ };
+
++ spi3: spi@01c1f000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c1f000 0x1000>;
++ interrupts = <50>;
++ clocks = <&ahb_gates 23>, <&spi3_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch
new file mode 100644
index 0000000000..46ee7d2107
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch
@@ -0,0 +1,67 @@
+From f76e72a20510fa17934c82bed5e23f7c4a4f2931 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:56 +0100
+Subject: [PATCH] ARM: dt: sun5i: Add A10s SPI controller nodes
+
+The A10s has 3 SPI controllers compatible with the one found in the A10. Add
+them in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index e5064dc..2dedb7c 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -292,6 +292,28 @@
+ #size-cells = <1>;
+ ranges;
+
++ spi0: spi@01c05000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c05000 0x1000>;
++ interrupts = <10>;
++ clocks = <&ahb_gates 20>, <&spi0_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ spi1: spi@01c06000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c06000 0x1000>;
++ interrupts = <11>;
++ clocks = <&ahb_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ emac: ethernet@01c0b000 {
+ compatible = "allwinner,sun4i-a10-emac";
+ reg = <0x01c0b000 0x1000>;
+@@ -373,6 +395,17 @@
+ status = "disabled";
+ };
+
++ spi2: spi@01c17000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c17000 0x1000>;
++ interrupts = <12>;
++ clocks = <&ahb_gates 22>, <&spi2_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch
new file mode 100644
index 0000000000..30bec686a8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch
@@ -0,0 +1,67 @@
+From a02b2ef06a3f11d2e6c20c2cdcdd6f0b4217d234 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:57 +0100
+Subject: [PATCH] ARM: dt: sun5i: Add A13 SPI controller nodes
+
+The A13 has 3 SPI controllers compatible with the one found in the A10. Add
+them in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a13.dtsi | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index b0cc56c..1ff406b 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -290,6 +290,28 @@
+ #size-cells = <1>;
+ ranges;
+
++ spi0: spi@01c05000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c05000 0x1000>;
++ interrupts = <10>;
++ clocks = <&ahb_gates 20>, <&spi0_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ spi1: spi@01c06000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c06000 0x1000>;
++ interrupts = <11>;
++ clocks = <&ahb_gates 21>, <&spi1_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+@@ -344,6 +366,17 @@
+ status = "disabled";
+ };
+
++ spi2: spi@01c17000 {
++ compatible = "allwinner,sun4i-a10-spi";
++ reg = <0x01c17000 0x1000>;
++ interrupts = <12>;
++ clocks = <&ahb_gates 22>, <&spi2_clk>;
++ clock-names = "ahb", "mod";
++ status = "disabled";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
+ intc: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ reg = <0x01c20400 0x400>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch b/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch
new file mode 100644
index 0000000000..9d2543cbd2
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch
@@ -0,0 +1,38 @@
+From eb9180f426a7da1da5ed0f3aa13b92609c869fc0 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:58 +0100
+Subject: [PATCH] ARM: dt: sun7i: Add SPI muxing options
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index bcea04a..9f57035 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -688,6 +688,20 @@
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
++
++ spi1_pins_a: spi1@0 {
++ allwinner,pins = "PI16", "PI17", "PI18", "PI19";
++ allwinner,function = "spi1";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++
++ spi2_pins_a: spi2@0 {
++ allwinner,pins = "PC19", "PC20", "PC21", "PC22";
++ allwinner,function = "spi2";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
+ };
+
+ timer@01c20c00 {
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch b/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch
new file mode 100644
index 0000000000..bebcbd0849
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch
@@ -0,0 +1,46 @@
+From 5c5ac3fb749c64e7c1e6e3208fcabab065359f56 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 22 Feb 2014 22:35:59 +0100
+Subject: [PATCH] ARM: dts: sun7i: Enable the SPI controllers of the
+ A20-olinuxino-micro
+
+The A20-Olinuxino-micro has two SPI bus exposed on its UEXT connectors, enable
+them.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index 824ce0a..68cedf3 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -21,7 +21,24 @@
+ model = "Olimex A20-Olinuxino Micro";
+ compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
+
++ aliases {
++ spi0 = &spi1;
++ spi1 = &spi2;
++ };
++
+ soc@01c00000 {
++ spi1: spi@01c06000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins_a>;
++ status = "okay";
++ };
++
++ spi2: spi@01c17000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi2_pins_a>;
++ status = "okay";
++ };
++
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch b/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch
new file mode 100644
index 0000000000..7a4498b920
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch
@@ -0,0 +1,53 @@
+From 111579574584c73a91c2b1bf8657c3691cc22409 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:55:23 +0100
+Subject: [PATCH] wdt: sunxi: Introduce a new compatible for the A10 and A31
+
+For historical reasons, the Allwinner A10 compatibles are not following the
+patterns used for this other Allwinner SoCs.
+
+Introduce a new compatible following the usual pattern, and deprecate the olders.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt | 7 ++++---
+ drivers/watchdog/sunxi_wdt.c | 1 +
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
+index e39cb26..6e8c937 100644
+--- a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
++++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
+@@ -2,13 +2,14 @@ Allwinner SoCs Watchdog timer
+
+ Required properties:
+
+-- compatible : should be "allwinner,<soc-family>-wdt", the currently supported
+- SoC families being sun4i and sun6i
++- compatible : should be either "allwinner,sun4i-a10-wdt" or
++ "allwinner,sun6i-a31-wdt" (deprecated:
++ "allwinner,sun4i-wdt", "allwinner,sun6i-wdt")
+ - reg : Specifies base physical address and size of the registers.
+
+ Example:
+
+ wdt: watchdog@01c20c90 {
+- compatible = "allwinner,sun4i-wdt";
++ compatible = "allwinner,sun4i-a10-wdt";
+ reg = <0x01c20c90 0x10>;
+ };
+diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
+index 76332d89..7c8923d 100644
+--- a/drivers/watchdog/sunxi_wdt.c
++++ b/drivers/watchdog/sunxi_wdt.c
+@@ -206,6 +206,7 @@ static void sunxi_wdt_shutdown(struct platform_device *pdev)
+
+ static const struct of_device_id sunxi_wdt_dt_ids[] = {
+ { .compatible = "allwinner,sun4i-wdt" },
++ { .compatible = "allwinner,sun4i-a10-wdt" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch b/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch
new file mode 100644
index 0000000000..0150dfa114
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch
@@ -0,0 +1,31 @@
+From b50ff681c8e3e9e408ee1fb6c6317bc8da653a01 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:55:24 +0100
+Subject: [PATCH] ARM: sunxi: Add the new watchog compatibles to the reboot
+ code
+
+Now that the watchdog driver has new compatibles, we need to support them in
+the machine reboot code too.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/mach-sunxi/sunxi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
+index aeea6ce..c310df6 100644
+--- a/arch/arm/mach-sunxi/sunxi.c
++++ b/arch/arm/mach-sunxi/sunxi.c
+@@ -95,7 +95,9 @@ static void sun6i_restart(enum reboot_mode mode, const char *cmd)
+
+ static struct of_device_id sunxi_restart_ids[] = {
+ { .compatible = "allwinner,sun4i-wdt" },
++ { .compatible = "allwinner,sun4i-a10-wdt" },
+ { .compatible = "allwinner,sun6i-wdt" },
++ { .compatible = "allwinner,sun6i-a31-wdt" },
+ { /*sentinel*/ }
+ };
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch b/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch
new file mode 100644
index 0000000000..843d0d69b8
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch
@@ -0,0 +1,86 @@
+From 0dba36162dffdee935287645d515f53057de3537 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 2 Feb 2014 14:55:25 +0100
+Subject: [PATCH] ARM: sunxi: dt: Update the watchdog compatibles
+
+The watchdog compatibles were following a different pattern than the one found
+in the other devices. Now that the driver supports the right pattern, switch to
+it in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 2 +-
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +-
+ arch/arm/boot/dts/sun5i-a13.dtsi | 2 +-
+ arch/arm/boot/dts/sun6i-a31.dtsi | 2 +-
+ arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
+ 5 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 80bbdeb..3a5775c 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -545,7 +545,7 @@
+ };
+
+ wdt: watchdog@01c20c90 {
+- compatible = "allwinner,sun4i-wdt";
++ compatible = "allwinner,sun4i-a10-wdt";
+ reg = <0x01c20c90 0x10>;
+ };
+
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index a5431ed..e5064dc 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -467,7 +467,7 @@
+ };
+
+ wdt: watchdog@01c20c90 {
+- compatible = "allwinner,sun4i-wdt";
++ compatible = "allwinner,sun4i-a10-wdt";
+ reg = <0x01c20c90 0x10>;
+ };
+
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 7fe9cdc..b0cc56c 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -413,7 +413,7 @@
+ };
+
+ wdt: watchdog@01c20c90 {
+- compatible = "allwinner,sun4i-wdt";
++ compatible = "allwinner,sun4i-a10-wdt";
+ reg = <0x01c20c90 0x10>;
+ };
+
+diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
+index b4407f17..c15f30e 100644
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -289,7 +289,7 @@
+ };
+
+ wdt1: watchdog@01c20ca0 {
+- compatible = "allwinner,sun6i-wdt";
++ compatible = "allwinner,sun6i-a31-wdt";
+ reg = <0x01c20ca0 0x20>;
+ };
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index e67924a..1961751 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -659,7 +659,7 @@
+ };
+
+ wdt: watchdog@01c20c90 {
+- compatible = "allwinner,sun4i-wdt";
++ compatible = "allwinner,sun4i-a10-wdt";
+ reg = <0x01c20c90 0x10>;
+ };
+
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch b/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch
new file mode 100644
index 0000000000..e42f0feeb7
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch
@@ -0,0 +1,354 @@
+From 328d21d9c56ddca56ed80b1595066b1621f6926b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 23 Dec 2013 16:21:02 +0100
+Subject: [PATCH] input: Add new sun4i-ts driver for Allwinner sunxi SoC's rtp
+ controller
+
+Note the sun4i-ts controller is capable of detecting a second touch, but when
+a second touch is present then the accuracy becomes so bad the reported touch
+location is not useable.
+
+The original android driver contains some complicated heuristics using the
+aprox. distance between the 2 touches to see if the user is making a pinch
+open / close movement, and then reports emulated multi-touch events around
+the last touch coordinate (as the dual-touch coordinates are worthless).
+
+These kinds of heuristics are just asking for trouble (and don't belong
+in the kernel). So this driver offers straight forward, reliable single
+touch functionality only.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ .../bindings/input/touchscreen/sun4i.txt | 15 ++
+ drivers/input/touchscreen/Kconfig | 10 +
+ drivers/input/touchscreen/Makefile | 1 +
+ drivers/input/touchscreen/sun4i-ts.c | 262 +++++++++++++++++++++
+ 4 files changed, 288 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
+ create mode 100644 drivers/input/touchscreen/sun4i-ts.c
+
+diff --git a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
+new file mode 100644
+index 0000000..e45927e
+--- /dev/null
++++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
+@@ -0,0 +1,15 @@
++sun4i resistive touchscreen controller
++--------------------------------------
++
++Required properties:
++ - compatible: "allwinner,sun4i-ts"
++ - reg: mmio address range of the chip
++ - interrupts: interrupt to which the chip is connected
++
++Example:
++
++ rtp: rtp@01c25000 {
++ compatible = "allwinner,sun4i-ts";
++ reg = <0x01c25000 0x100>;
++ interrupts = <29>;
++ };
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 07e9e82..f4c5ca3 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -906,6 +906,16 @@ config TOUCHSCREEN_STMPE
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
++config TOUCHSCREEN_SUN4I
++ tristate "Allwinner sun4i resistive touchscreen controller support"
++ depends on ARCH_SUNXI
++ help
++ This selects support for the resistive touchscreen controller
++ found on Allwinner sunxi SoCs.
++
++ To compile this driver as a module, choose M here: the
++ module will be called sun4i-ts.
++
+ config TOUCHSCREEN_SUR40
+ tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
+ depends on USB
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 62801f2..c8f7375 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
+ obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
++obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
+ obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
+ obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
+ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
+diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
+new file mode 100644
+index 0000000..5945219
+--- /dev/null
++++ b/drivers/input/touchscreen/sun4i-ts.c
+@@ -0,0 +1,262 @@
++/*
++ * Allwinner sunxi resistive touchscreen controller driver
++ *
++ * Copyright (C) 2013 - 2014 Hans de Goede <hdegoede@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++/*
++ * The sun4i-ts controller is capable of detecting a second touch, but when a
++ * second touch is present then the accuracy becomes so bad the reported touch
++ * location is not useable.
++ *
++ * The original android driver contains some complicated heuristics using the
++ * aprox. distance between the 2 touches to see if the user is making a pinch
++ * open / close movement, and then reports emulated multi-touch events around
++ * the last touch coordinate (as the dual-touch coordinates are worthless).
++ *
++ * These kinds of heuristics are just asking for trouble (and don't belong
++ * in the kernel). So this driver offers straight forward, reliable single
++ * touch functionality only.
++ */
++
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define TP_CTRL0 0x00
++#define TP_CTRL1 0x04
++#define TP_CTRL2 0x08
++#define TP_CTRL3 0x0c
++#define TP_INT_FIFOC 0x10
++#define TP_INT_FIFOS 0x14
++#define TP_TPR 0x18
++#define TP_CDAT 0x1c
++#define TEMP_DATA 0x20
++#define TP_DATA 0x24
++
++/* TP_CTRL0 bits */
++#define ADC_FIRST_DLY(x) ((x) << 24) /* 8 bits */
++#define ADC_FIRST_DLY_MODE(x) ((x) << 23)
++#define ADC_CLK_SEL(x) ((x) << 22)
++#define ADC_CLK_DIV(x) ((x) << 20) /* 3 bits */
++#define FS_DIV(x) ((x) << 16) /* 4 bits */
++#define T_ACQ(x) ((x) << 0) /* 16 bits */
++
++/* TP_CTRL1 bits */
++#define STYLUS_UP_DEBOUN(x) ((x) << 12) /* 8 bits */
++#define STYLUS_UP_DEBOUN_EN(x) ((x) << 9)
++#define TOUCH_PAN_CALI_EN(x) ((x) << 6)
++#define TP_DUAL_EN(x) ((x) << 5)
++#define TP_MODE_EN(x) ((x) << 4)
++#define TP_ADC_SELECT(x) ((x) << 3)
++#define ADC_CHAN_SELECT(x) ((x) << 0) /* 3 bits */
++
++/* TP_CTRL2 bits */
++#define TP_SENSITIVE_ADJUST(x) ((x) << 28) /* 4 bits */
++#define TP_MODE_SELECT(x) ((x) << 26) /* 2 bits */
++#define PRE_MEA_EN(x) ((x) << 24)
++#define PRE_MEA_THRE_CNT(x) ((x) << 0) /* 24 bits */
++
++/* TP_CTRL3 bits */
++#define FILTER_EN(x) ((x) << 2)
++#define FILTER_TYPE(x) ((x) << 0) /* 2 bits */
++
++/* TP_INT_FIFOC irq and fifo mask / control bits */
++#define TEMP_IRQ_EN(x) ((x) << 18)
++#define OVERRUN_IRQ_EN(x) ((x) << 17)
++#define DATA_IRQ_EN(x) ((x) << 16)
++#define TP_DATA_XY_CHANGE(x) ((x) << 13)
++#define FIFO_TRIG(x) ((x) << 8) /* 5 bits */
++#define DATA_DRQ_EN(x) ((x) << 7)
++#define FIFO_FLUSH(x) ((x) << 4)
++#define TP_UP_IRQ_EN(x) ((x) << 1)
++#define TP_DOWN_IRQ_EN(x) ((x) << 0)
++
++/* TP_INT_FIFOS irq and fifo status bits */
++#define TEMP_DATA_PENDING BIT(18)
++#define FIFO_OVERRUN_PENDING BIT(17)
++#define FIFO_DATA_PENDING BIT(16)
++#define TP_IDLE_FLG BIT(2)
++#define TP_UP_PENDING BIT(1)
++#define TP_DOWN_PENDING BIT(0)
++
++/* TP_TPR bits */
++#define TEMP_ENABLE(x) ((x) << 16)
++#define TEMP_PERIOD(x) ((x) << 0) /* t = x * 256 * 16 / clkin */
++
++struct sun4i_ts_data {
++ struct device *dev;
++ struct input_dev *input;
++ void __iomem *base;
++ unsigned int irq;
++ bool ignore_fifo_data;
++};
++
++static irqreturn_t sun4i_ts_irq(int irq, void *dev_id)
++{
++ struct sun4i_ts_data *ts = dev_id;
++ u32 reg_val, x, y;
++
++ reg_val = readl(ts->base + TP_INT_FIFOS);
++
++ if (reg_val & FIFO_DATA_PENDING) {
++ x = readl(ts->base + TP_DATA);
++ y = readl(ts->base + TP_DATA);
++ /* The 1st location reported after an up event is unreliable */
++ if (!ts->ignore_fifo_data) {
++ input_report_abs(ts->input, ABS_X, x);
++ input_report_abs(ts->input, ABS_Y, y);
++ /*
++ * The hardware has a separate down status bit, but
++ * that gets set before we get the first location,
++ * resulting in reporting a click on the old location.
++ */
++ input_report_key(ts->input, BTN_TOUCH, 1);
++ input_sync(ts->input);
++ } else {
++ ts->ignore_fifo_data = false;
++ }
++ }
++
++ if (reg_val & TP_UP_PENDING) {
++ ts->ignore_fifo_data = true;
++ input_report_key(ts->input, BTN_TOUCH, 0);
++ input_sync(ts->input);
++ }
++
++ writel(reg_val, ts->base + TP_INT_FIFOS);
++
++ return IRQ_HANDLED;
++}
++
++static int sun4i_ts_open(struct input_dev *dev)
++{
++ struct sun4i_ts_data *ts = input_get_drvdata(dev);
++
++ /* Flush, set trig level to 1, enable data and up irqs */
++ writel(DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) | TP_UP_IRQ_EN(1),
++ ts->base + TP_INT_FIFOC);
++
++ return 0;
++}
++
++static void sun4i_ts_close(struct input_dev *dev)
++{
++ struct sun4i_ts_data *ts = input_get_drvdata(dev);
++
++ /* Deactivate all IRQs */
++ writel(0, ts->base + TP_INT_FIFOC);
++}
++
++static int sun4i_ts_probe(struct platform_device *pdev)
++{
++ struct sun4i_ts_data *ts;
++ struct device *dev = &pdev->dev;
++ int ret;
++
++ ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL);
++ if (!ts)
++ return -ENOMEM;
++
++ ts->dev = dev;
++ ts->ignore_fifo_data = true;
++
++ ts->input = devm_input_allocate_device(dev);
++ if (!ts->input)
++ return -ENOMEM;
++
++ ts->input->name = pdev->name;
++ ts->input->phys = "sun4i_ts/input0";
++ ts->input->open = sun4i_ts_open;
++ ts->input->close = sun4i_ts_close;
++ ts->input->id.bustype = BUS_HOST;
++ ts->input->id.vendor = 0x0001;
++ ts->input->id.product = 0x0001;
++ ts->input->id.version = 0x0100;
++ ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
++ set_bit(BTN_TOUCH, ts->input->keybit);
++ input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0);
++ input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0);
++ input_set_drvdata(ts->input, ts);
++
++ ts->base = devm_ioremap_resource(dev,
++ platform_get_resource(pdev, IORESOURCE_MEM, 0));
++ if (IS_ERR(ts->base))
++ return PTR_ERR(ts->base);
++
++ ts->irq = platform_get_irq(pdev, 0);
++ ret = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts);
++ if (ret)
++ return ret;
++
++ /*
++ * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192,
++ * t_acq = clkin / (16 * 64)
++ */
++ writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63),
++ ts->base + TP_CTRL0);
++
++ /*
++ * sensitive_adjust = 15 : max, which is not all that sensitive,
++ * tp_mode = 0 : only x and y coordinates, as we don't use dual touch
++ */
++ writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0),
++ ts->base + TP_CTRL2);
++
++ /* Enable median filter, type 1 : 5/3 */
++ writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3);
++
++ /* Enable temperature measurement, period 1953 (2 seconds) */
++ writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR);
++
++ /*
++ * Set stylus up debounce to aprox 10 ms, enable debounce, and
++ * finally enable tp mode.
++ */
++ writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1),
++ ts->base + TP_CTRL1);
++
++ ret = input_register_device(ts->input);
++ if (ret)
++ return ret;
++
++ platform_set_drvdata(pdev, ts);
++ return 0;
++}
++
++static const struct of_device_id sun4i_ts_of_match[] = {
++ { .compatible = "allwinner,sun4i-ts", },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, sun4i_ts_of_match);
++
++static struct platform_driver sun4i_ts_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "sun4i-ts",
++ .of_match_table = of_match_ptr(sun4i_ts_of_match),
++ },
++ .probe = sun4i_ts_probe,
++};
++
++module_platform_driver(sun4i_ts_driver);
++
++MODULE_DESCRIPTION("Allwinner sun4i resistive touchscreen controller driver");
++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
++MODULE_LICENSE("GPL");
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch b/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch
new file mode 100644
index 0000000000..cca20c3e3c
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch
@@ -0,0 +1,86 @@
+From 248529e6c78ba746988f1313f7bfb7ae74eae785 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Mon, 13 Jan 2014 14:15:01 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add basic board support for LinkSprite
+ pcDuino
+
+This patch will add a basic board support DT for the
+LinkSprite pcDuino board.
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/sun4i-a10-pcduino.dts | 48 +++++++++++++++++++++++++++++++++
+ 2 files changed, 49 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sun4i-a10-pcduino.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 6d1e43d..0b127db 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -283,6 +283,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
+ sun4i-a10-cubieboard.dtb \
+ sun4i-a10-mini-xplus.dtb \
+ sun4i-a10-hackberry.dtb \
++ sun4i-a10-pcduino.dtb \
+ sun5i-a10s-olinuxino-micro.dtb \
+ sun5i-a13-olinuxino.dtb \
+ sun5i-a13-olinuxino-micro.dtb \
+diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+new file mode 100644
+index 0000000..f5692a3
+--- /dev/null
++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+@@ -0,0 +1,48 @@
++/*
++ * Copyright 2014 Zoltan HERPAI
++ * Zoltan HERPAI <wigyori@uid0.hu>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/dts-v1/;
++/include/ "sun4i-a10.dtsi"
++
++/ {
++ model = "LinkSprite pcDuino";
++ compatible = "linksprite,a10-pcduino", "allwinner,sun4i-a10";
++
++ soc@01c00000 {
++ emac: ethernet@01c0b000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emac_pins_a>;
++ phy = <&phy1>;
++ status = "okay";
++ };
++
++ mdio@01c0b080 {
++ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
++ };
++
++ uart0: serial@01c28000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins_a>;
++ status = "okay";
++ };
++
++ i2c0: i2c@01c2ac00 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c0_pins_a>;
++ status = "okay";
++ };
++ };
++};
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch b/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch
new file mode 100644
index 0000000000..e028d120fa
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch
@@ -0,0 +1,73 @@
+From 54b9b9ab635ed8e643784402096524768f490f5d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 11 Jan 2014 04:33:23 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add mmc node to a few more boards
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-hackberry.dts | 9 +++++++++
+ arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 8 ++++++++
+ arch/arm/boot/dts/sun4i-a10-pcduino.dts | 8 ++++++++
+ 3 files changed, 25 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+index 6692d336..2eb30d0 100644
+--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
++++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+@@ -35,6 +35,15 @@
+ };
+ };
+
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ cd-mode = <1>;
++ status = "okay";
++ };
++
+ pio: pinctrl@01c20800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hackberry_hogs>;
+diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+index 70b3323..6dbe53c 100644
+--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
++++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+@@ -19,6 +19,14 @@
+ compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10";
+
+ soc@01c00000 {
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+index f5692a3..87f7742 100644
+--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+@@ -33,6 +33,14 @@
+ };
+ };
+
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ status = "okay";
++ };
++
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch b/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch
new file mode 100644
index 0000000000..c81008fa1a
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch
@@ -0,0 +1,58 @@
+From 713c2957f8b9e49b2170c9e546d705c9c358faee Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 17 Feb 2014 20:41:04 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to pcduino.dts
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/sun4i-a10-pcduino.dts | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+index 87f7742..3ccd357 100644
+--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+@@ -12,6 +12,7 @@
+
+ /dts-v1/;
+ /include/ "sun4i-a10.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
+
+ / {
+ model = "LinkSprite pcDuino";
+@@ -41,6 +42,32 @@
+ status = "okay";
+ };
+
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
++ ahci: sata@01c18000 {
++ status = "okay";
++ };
++
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+--
+1.8.5.5
+
diff --git a/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch b/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch
new file mode 100644
index 0000000000..f6cbf1becd
--- /dev/null
+++ b/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch
@@ -0,0 +1,150 @@
+From 75e7218e107016a4baae26c70a81b1111fc8c70b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 10 Jan 2014 23:23:06 +0100
+Subject: [PATCH] ARM: sun4i: dt: Add sun4i-a10-olinuxino-lime.dtb
+
+This add support for the A10-OLinuXino-LIME:
+https://www.olimex.com/Products/OLinuXino/A10/A10-OLinuXino-LIME
+
+A low cost Allwinner A10 based dev-board, with sata, ethernet, hdmi and 2x USB.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 112 +++++++++++++++++++++++++
+ 2 files changed, 113 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 0b127db..c576de8 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -283,6 +283,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
+ sun4i-a10-cubieboard.dtb \
+ sun4i-a10-mini-xplus.dtb \
+ sun4i-a10-hackberry.dtb \
++ sun4i-a10-olinuxino-lime.dtb \
+ sun4i-a10-pcduino.dtb \
+ sun5i-a10s-olinuxino-micro.dtb \
+ sun5i-a13-olinuxino.dtb \
+diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+new file mode 100644
+index 0000000..3c076f2
+--- /dev/null
++++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+@@ -0,0 +1,112 @@
++/*
++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
++ *
++ * The code contained herein is licensed under the GNU General Public
++ * License. You may obtain a copy of the GNU General Public License
++ * Version 2 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/gpl-license.html
++ * http://www.gnu.org/copyleft/gpl.html
++ */
++
++/dts-v1/;
++/include/ "sun4i-a10.dtsi"
++/include/ "sunxi-ahci-reg.dtsi"
++/include/ "sun4i-a10-usb-vbus-reg.dtsi"
++
++/ {
++ model = "Olimex A10-OLinuXino-LIME";
++ compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10";
++
++ soc@01c00000 {
++ emac: ethernet@01c0b000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emac_pins_a>;
++ phy = <&phy1>;
++ status = "okay";
++ };
++
++ mdio@01c0b080 {
++ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
++ };
++
++ mmc0: mmc@01c0f000 {
++ pinctrl-names = "default", "default";
++ pinctrl-0 = <&mmc0_pins_a>;
++ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
++ cd-gpios = <&pio 7 1 0>; /* PH1 */
++ cd-mode = <1>;
++ status = "okay";
++ };
++
++ usbphy: phy@01c13400 {
++ usb1_vbus-supply = <&reg_usb1_vbus>;
++ usb2_vbus-supply = <&reg_usb2_vbus>;
++ status = "okay";
++ };
++
++ ehci0: usb@01c14000 {
++ status = "okay";
++ };
++
++ ohci0: usb@01c14400 {
++ status = "okay";
++ };
++
++ ahci: sata@01c18000 {
++ target-supply = <&reg_ahci_5v>;
++ status = "okay";
++ };
++
++ ehci1: usb@01c1c000 {
++ status = "okay";
++ };
++
++ ohci1: usb@01c1c400 {
++ status = "okay";
++ };
++
++ pinctrl@01c20800 {
++ ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 {
++ allwinner,pins = "PC3";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <0>;
++ allwinner,pull = <0>;
++ };
++
++ led_pins_olinuxinolime: led_pins@0 {
++ allwinner,pins = "PH2";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <1>;
++ allwinner,pull = <0>;
++ };
++ };
++
++ uart0: serial@01c28000 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart0_pins_a>;
++ status = "okay";
++ };
++ };
++
++ leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&led_pins_olinuxinolime>;
++
++ green {
++ label = "a10-olinuxino-lime:green:usr";
++ gpios = <&pio 7 2 0>;
++ default-state = "on";
++ };
++ };
++
++ reg_ahci_5v: ahci-5v {
++ pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>;
++ gpio = <&pio 2 3 0>;
++ };
++};
+--
+1.8.5.5
+