Sfoglia il codice sorgente

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 <[email protected]>

SVN-Revision: 39782
Zoltan Herpai 11 anni fa
parent
commit
ac4b9dbb3c
100 ha cambiato i file con 7297 aggiunte e 4042 eliminazioni
  1. 14 6
      target/linux/sunxi/config-3.13
  2. 0 168
      target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
  3. 0 168
      target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts
  4. 0 75
      target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
  5. 0 908
      target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c
  6. 0 246
      target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h
  7. 0 95
      target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch
  8. 0 0
      target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch
  9. 0 0
      target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch
  10. 0 60
      target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch
  11. 14 7
      target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch
  12. 139 0
      target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch
  13. 261 0
      target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch
  14. 112 0
      target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch
  15. 132 0
      target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch
  16. 0 0
      target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch
  17. 0 0
      target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch
  18. 0 0
      target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch
  19. 7 2
      target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch
  20. 0 0
      target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch
  21. 56 0
      target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch
  22. 39 0
      target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch
  23. 22 13
      target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch
  24. 50 0
      target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch
  25. 77 0
      target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch
  26. 31 0
      target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch
  27. 223 0
      target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch
  28. 214 0
      target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch
  29. 45 0
      target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch
  30. 57 0
      target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch
  31. 146 0
      target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch
  32. 50 0
      target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch
  33. 73 0
      target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch
  34. 38 0
      target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch
  35. 20 11
      target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch
  36. 22 12
      target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch
  37. 0 41
      target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch
  38. 0 97
      target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch
  39. 96 0
      target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch
  40. 158 0
      target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch
  41. 0 131
      target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch
  42. 124 0
      target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch
  43. 31 0
      target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch
  44. 55 0
      target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch
  45. 123 0
      target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch
  46. 273 0
      target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch
  47. 0 22
      target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch
  48. 45 0
      target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch
  49. 40 0
      target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch
  50. 48 0
      target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch
  51. 222 0
      target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch
  52. 255 0
      target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch
  53. 141 0
      target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch
  54. 211 0
      target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch
  55. 344 0
      target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch
  56. 188 0
      target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch
  57. 0 46
      target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch
  58. 352 0
      target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch
  59. 0 436
      target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch
  60. 31 0
      target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch
  61. 0 90
      target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch
  62. 142 0
      target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch
  63. 0 167
      target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch
  64. 85 0
      target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch
  65. 47 0
      target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch
  66. 122 0
      target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch
  67. 127 0
      target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch
  68. 1187 0
      target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch
  69. 56 0
      target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch
  70. 49 0
      target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch
  71. 32 0
      target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch
  72. 34 0
      target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch
  73. 45 0
      target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch
  74. 7 1
      target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch
  75. 7 2
      target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch
  76. 44 0
      target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch
  77. 0 31
      target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch
  78. 8 3
      target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch
  79. 49 0
      target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch
  80. 26 0
      target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch
  81. 46 0
      target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch
  82. 0 31
      target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch
  83. 0 493
      target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch
  84. 129 0
      target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch
  85. 0 27
      target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch
  86. 0 58
      target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch
  87. 72 29
      target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch
  88. 0 81
      target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch
  89. 160 0
      target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch
  90. 0 78
      target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch
  91. 64 0
      target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch
  92. 107 0
      target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch
  93. 73 0
      target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch
  94. 0 27
      target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch
  95. 0 58
      target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch
  96. 0 80
      target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch
  97. 0 86
      target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch
  98. 0 83
      target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch
  99. 0 27
      target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch
  100. 0 46
      target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch

+ 14 - 6
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

+ 0 - 168
target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts

@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <[email protected]>
- *
- * 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;
-		};
-	};
-};

+ 0 - 168
target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts

@@ -1,168 +0,0 @@
-/*
- * Copyright 2012 Stefan Roese
- * Stefan Roese <[email protected]>
- *
- * 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;
-		};
-	};
-};

+ 0 - 75
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>;
-		};
-	};
 };

+ 0 - 908
target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c

@@ -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 <[email protected]>
- * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
- * (C) Copyright 2013-2013 David Lanzendörfer <[email protected]>
- * (C) Copyright 2013-2013 Hans de Goede <[email protected]>
- *
- * 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 <[email protected]>");
-MODULE_ALIAS("platform:sunxi-mmc");

+ 0 - 246
target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h

@@ -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 <[email protected]>
- * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
- * (C) Copyright 2013-2013 David Lanzendörfer <[email protected]>
- * (C) Copyright 2013-2013 Hans de Goede <[email protected]>
- *
- * 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

+ 0 - 95
target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch

@@ -1,95 +0,0 @@
-From 9490107c16c8eaa35b07794e19d5d2eddea8e44b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <[email protected]>
-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 <[email protected]>
----
- 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,},
- 	{}

+ 0 - 0
target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch → target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch


+ 0 - 0
target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch → target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch


+ 0 - 60
target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch

@@ -1,60 +0,0 @@
-From c8fe5648aff581545ce5744f73ee1312080b8ef4 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <[email protected]>
-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 <[email protected]>
----
- 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 {

+ 14 - 7
target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch → 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 <[email protected]>
-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 <[email protected]>
+Signed-off-by: Maxime Ripard <[email protected]>
 ---
- 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 <[email protected]>
 +		/*
 +		 * 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 <[email protected]>
 +		};
  	};
  
- 	timer {
+ 	soc@01c00000 {
+-- 
+1.8.5.5
+

+ 139 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Maxime Ripard <[email protected]>
+---
+ 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
+

+ 261 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Maxime Ripard <[email protected]>
+---
+ 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
+

+ 112 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Maxime Ripard <[email protected]>
+---
+ 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
+

+ 132 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Maxime Ripard <[email protected]>
+---
+ 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
+

+ 0 - 0
target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch → target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch


+ 0 - 0
target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch → target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch


+ 0 - 0
target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch → target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch


+ 7 - 2
target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch → 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 <[email protected]>
 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 <[email protected]>
  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 <[email protected]>
  	soc@01c00000 {
  		compatible = "simple-bus";
  		#address-cells = <1>;
+-- 
+1.8.5.5
+

+ 0 - 0
target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch → target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch


+ 56 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 39 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 22 - 13
target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch → 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 <[email protected]>
-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 <[email protected]>
 ---
- 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
+

+ 50 - 0
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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Josh Triplett <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 77 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 31 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 223 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 214 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 45 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 57 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 146 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 50 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 73 - 0
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 <[email protected]>
+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 <[email protected]>
+Acked-by: Giuseppe Cavallaro <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 38 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 20 - 11
target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch → 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 <[email protected]>
-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 <[email protected]>
 ---
- 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 <[email protected]>
 -			};
 -		};
 -
- 		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
+

+ 22 - 12
target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch → 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 <[email protected]>
-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 <[email protected]>
 ---
- 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 <[email protected]>
 -			};
 -		};
 -
- 		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
+

+ 0 - 41
target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch

@@ -1,41 +0,0 @@
-From 447675f817b95881e9922f002de3fc7f6d6e9207 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <[email protected]>
-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 <[email protected]>
----
- 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

+ 0 - 97
target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch

@@ -1,97 +0,0 @@
-From 677631fa522e4ac24f636535e3abb5cd1a5ef40e Mon Sep 17 00:00:00 2001
-From: Hans de Goede <[email protected]>
-Date: Sat, 14 Dec 2013 22:58:12 +0100
-Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
-
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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 {

+ 96 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 158 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 0 - 131
target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch

@@ -1,131 +0,0 @@
-From 3cce544eb5964c14653dddde731cac4cbff97d90 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <[email protected]>
-Date: Sat, 14 Dec 2013 22:58:15 +0100
-Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
-
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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 {

+ 124 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 31 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 55 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ 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
+

+ 123 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ .../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
+

+ 273 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ .../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  <[email protected]>
++ *
++ * 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
+

+ 0 - 22
target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch

@@ -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;

+ 45 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 40 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 48 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 222 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 255 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ .../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
+

+ 141 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ .../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
+

+ 211 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 344 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 188 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 0 - 46
target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch

@@ -1,46 +0,0 @@
-From 3eec76bc21d78e56ac8404b59f29dd9dbbd1528a Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <[email protected]>
-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 <[email protected]>
----
- 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;

+ 352 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ .../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 <[email protected]>
++ * Copyright 2014 Hans de Goede <[email protected]>
++ *
++ * 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 <[email protected]>
++ *
++ * 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 <[email protected]>");
++MODULE_LICENSE("GPL");
+-- 
+1.8.5.5
+

+ 0 - 436
target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch

@@ -1,436 +0,0 @@
-From 22345cc059de4a6ea1dc7657dd6ad86ca16a8814 Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <[email protected]>
-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 <[email protected]>
-Signed-off-by: Hans de Goede <[email protected]>
----
- .../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 <[email protected]>
-+ * Copyright 2014 Hans de Goede <[email protected]>
-+ *
-+ * 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 <[email protected]>
-+ *
-+ * 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 <[email protected]>");
-+MODULE_LICENSE("GPL");

+ 31 - 0
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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Bartlomiej Zolnierkiewicz <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 0 - 90
target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch

@@ -1,90 +0,0 @@
-From 23af610e09f78822ade4067a400ff9ceb5b020ea Mon Sep 17 00:00:00 2001
-From: Oliver Schinagl <[email protected]>
-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 <[email protected]>
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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>;

+ 142 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Roger Quadros <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 0 - 167
target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch

@@ -1,167 +0,0 @@
-From 4ce1f4c3ab04a697e9861b77582077b905b3f8a0 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <[email protected]>
-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 <[email protected]>
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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>;

+ 85 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Roger Quadros <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 47 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 122 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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
+

+ 127 - 0
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 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 1187 - 0
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?= <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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 <[email protected]>
++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch>
++ * (C) Copyright 2014-2015 David Lanzendörfer <[email protected]>
++ * (C) Copyright 2014-2015 Hans de Goede <[email protected]>
++ *
++ * 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 <[email protected]>");
++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 <[email protected]>
++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch>
++ * (C) Copyright 2014-2015 David Lanzendörfer <[email protected]>
++ * (C) Copyright 2014-2015 Hans de Goede <[email protected]>
++ *
++ * 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
+

+ 56 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 49 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 32 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 34 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 45 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 7 - 1
target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch → 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 <[email protected]>
 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 <[email protected]>
  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 <[email protected]>
 +void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
 +
 +#endif
+-- 
+1.8.5.5
+

+ 7 - 2
target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch → 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?= <[email protected]>
 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 <[email protected]>
  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 <[email protected]>
   * sunxi_factors_clk_setup() - Setup function for factor clocks
   */
  
+-- 
+1.8.5.5
+

+ 44 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 0 - 31
target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch

@@ -1,31 +0,0 @@
-From 109e7dc17a77f84d56e76dea873363a8262bc806 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-Date: Thu, 19 Sep 2013 21:59:32 +0200
-Subject: [PATCH] clk: sunxi: Add support for USB clocks
-
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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,},

+ 8 - 3
target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch → 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 <[email protected]>
 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 <[email protected]>
  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 <[email protected]>
  	/* Hole */
  	SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
  		  SUNXI_FUNCTION(0x0, "gpio_in"),
+-- 
+1.8.5.5
+

+ 49 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 26 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 46 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 0 - 31
target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch

@@ -1,31 +0,0 @@
-From 6b5cb5cada555c90562aed82e8891439a35009ab Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-Date: Sun, 6 Oct 2013 14:04:50 +0200
-Subject: [PATCH] clk: sun5i: Add support for USB clocks
-
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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,},

+ 0 - 493
target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch

@@ -1,493 +0,0 @@
-From 825ce97e1faa39bfd30c3dca95fba5eb021cb534 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
-
-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 <[email protected]>
-+ *
-+ * 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 <[email protected]>");

+ 129 - 0
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?= <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 0 - 27
target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch

@@ -1,27 +0,0 @@
-From 04f41bafdff26bd895f2a1f894fd427779d7ed51 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
----
- 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>;

+ 0 - 58
target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch

@@ -1,58 +0,0 @@
-From ec53e86224acaa3891148fa298bb1504f3579d6b Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-Date: Wed, 18 Sep 2013 00:30:04 +0200
-Subject: [PATCH] ARM: sun4i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <[email protected]>
-
-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";
-+		};
- 	};
- };

+ 72 - 29
target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch → 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 <[email protected]>
-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?= <[email protected]>
+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 <[email protected]>
 Signed-off-by: Hans de Goede <[email protected]>
 ---
- 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 <[email protected]>
 +				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>;
  		};
  
@@ -79,11 +85,21 @@ Signed-off-by: Hans de Goede <[email protected]>
 +			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>;
-@@ -363,6 +383,20 @@
+@@ -369,6 +399,20 @@
  				allwinner,drive = <0>;
  				allwinner,pull = <0>;
  			};
@@ -104,18 +120,19 @@ Signed-off-by: Hans de Goede <[email protected]>
  		};
  
  		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 <[email protected]>
 +				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 <[email protected]>
 +				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;
  
@@ -171,11 +191,31 @@ Signed-off-by: Hans de Goede <[email protected]>
 +			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";
++		};
 +
  		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 <[email protected]>
  		};
  
  		timer@01c20c00 {
+-- 
+1.8.5.5
+

+ 0 - 81
target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch

@@ -1,81 +0,0 @@
-From 875bbd46c296e4b9ed130848bc64be5cf39669c8 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
-
-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>;
-+		};
- 	};
- };

+ 160 - 0
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?= <[email protected]>
+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 <[email protected]>
+Signed-off-by: Hans de Goede <[email protected]>
+---
+ 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
+

+ 0 - 78
target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch

@@ -1,78 +0,0 @@
-From 9a86b6c16abc11b1090fbf4e102b4eed1d474d96 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
----
- 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>;
-+		};
- 	};
- };

+ 64 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 107 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 73 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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
+

+ 0 - 27
target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch

@@ -1,27 +0,0 @@
-From b7739d837e1176b2206ee541075c9eba0a263695 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
----
- 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";

+ 0 - 58
target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch

@@ -1,58 +0,0 @@
-From a82eb088ea3fa4c25b256400690a30f4b0392e91 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-Date: Thu, 19 Sep 2013 21:36:10 +0200
-Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <[email protected]>
-
-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";
-+		};
- 	};
- };

+ 0 - 80
target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch

@@ -1,80 +0,0 @@
-From 8ba068f40cce9612d2ac0879b6978274ab497d31 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
-
-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>;
-+		};
- 	};
- };

+ 0 - 86
target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch

@@ -1,86 +0,0 @@
-From 5031cb9d88fe9ea4a37fe342ec5f8e2f0f930e00 Mon Sep 17 00:00:00 2001
-From: Zalan Blenessy <[email protected]>
-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 <[email protected]>
----
- 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>;
-+		};
- 	};
- };

+ 0 - 83
target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch

@@ -1,83 +0,0 @@
-From 90cab9a5e7c43bfbda25dd114a838f4e4b50b6ff Mon Sep 17 00:00:00 2001
-From: Hans de Goede <[email protected]>
-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 <[email protected]>
----
- 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>;
-+		};
- 	};
- };

+ 0 - 27
target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch

@@ -1,27 +0,0 @@
-From f017ea35bd87e7935fbf5a03bc016d8b1efa03c0 Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-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 <[email protected]>
----
- 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>;

+ 0 - 46
target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch

@@ -1,46 +0,0 @@
-From 3d3aa5f5c67d3f860b68def6a0ffce5e7175f85e Mon Sep 17 00:00:00 2001
-From: arokux <[email protected]>
-Date: Tue, 24 Sep 2013 20:03:40 +0200
-Subject: [PATCH] ARM: sun5i: dt: Add USB EHCI bindings
-
-Signed-off-by: Hans de Goede <[email protected]>
----
- 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";
-+		};
- 	};
- };

Some files were not shown because too many files changed in this diff