From ffab96be3482abc580ff3d5558193114a3e4e02e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sun, 1 Jun 2014 19:15:32 +0000 Subject: [PATCH] [armhf] Backport and enable sunxi MMC driver (Closes: #749484) svn path=/dists/trunk/linux/; revision=21369 --- debian/changelog | 4 +- debian/config/armhf/config.armmp | 1 + ...M-dts-sun4i-Add-mmc-controller-nodes.patch | 68 + ...d-pin-muxing-info-for-the-mmc0-contr.patch | 43 + ...d-reg_vcc3v3-to-sun4i-board-mmc-node.patch | 104 ++ ...able-mmc-controller-on-various-A10-b.patch | 164 +++ ...M-dts-sun5i-Add-mmc-controller-nodes.patch | 89 ++ ...d-pin-muxing-info-for-the-mmc-contro.patch | 61 + ...d-reg_vcc3v3-to-sun5i-board-mmc-node.patch | 60 + ...able-mmc-controller-on-various-A10s-.patch | 138 ++ .../arm/ARM-dts-sun6i-Add-mmc-clocks.patch | 54 + ...M-dts-sun6i-Add-mmc-controller-nodes.patch | 67 + ...d-new-sun6i-a31-m9-dts-file-for-Mele.patch | 79 ++ ...d-pin-muxing-info-for-the-mmc-contro.patch | 35 + ...d-reg_vcc3v3-to-sun6i-board-mmc-node.patch | 34 + ...d-basic-support-for-the-Cubietruck-W.patch | 72 + ...M-dts-sun7i-Add-mmc-controller-nodes.patch | 63 + ...d-pin-muxing-info-for-the-mmc-contro.patch | 45 + ...d-reg_vcc3v3-to-sun7i-board-mmc-node.patch | 60 + ...able-mmc-controller-on-various-A20-b.patch | 94 ++ ...bietruck-set-mmc3-bus-width-property.patch | 29 + ...d-reg_vcc3v3-supply-to-sunxi-common-.patch | 31 + ...clk_sunxi_mmc_phase_control-to-take-.patch | 49 + ...lk-sunxi-Implement-MMC-phase-control.patch | 97 ++ ...actors-automatic-reparenting-support.patch | 76 ++ ...iver-for-SD-MMC-hosts-found-on-Allwi.patch | 1153 +++++++++++++++++ debian/patches/series | 25 + 27 files changed, 2794 insertions(+), 1 deletion(-) create mode 100644 debian/patches/features/arm/ARM-dts-sun4i-Add-mmc-controller-nodes.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun4i-Add-pin-muxing-info-for-the-mmc0-contr.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun4i-Add-reg_vcc3v3-to-sun4i-board-mmc-node.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun4i-Enable-mmc-controller-on-various-A10-b.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun5i-Add-mmc-controller-nodes.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun5i-Add-pin-muxing-info-for-the-mmc-contro.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun5i-Add-reg_vcc3v3-to-sun5i-board-mmc-node.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun5i-Enable-mmc-controller-on-various-A10s-.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-clocks.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-controller-nodes.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun6i-Add-new-sun6i-a31-m9-dts-file-for-Mele.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun6i-Add-pin-muxing-info-for-the-mmc-contro.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun6i-Add-reg_vcc3v3-to-sun6i-board-mmc-node.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-Add-basic-support-for-the-Cubietruck-W.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-Add-mmc-controller-nodes.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-Add-pin-muxing-info-for-the-mmc-contro.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-Add-reg_vcc3v3-to-sun7i-board-mmc-node.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-Enable-mmc-controller-on-various-A20-b.patch create mode 100644 debian/patches/features/arm/ARM-dts-sun7i-cubietruck-set-mmc3-bus-width-property.patch create mode 100644 debian/patches/features/arm/ARM-dts-sunxi-Add-reg_vcc3v3-supply-to-sunxi-common-.patch create mode 100644 debian/patches/features/arm/clk-sunxi-Fixup-clk_sunxi_mmc_phase_control-to-take-.patch create mode 100644 debian/patches/features/arm/clk-sunxi-Implement-MMC-phase-control.patch create mode 100644 debian/patches/features/arm/clk-sunxi-factors-automatic-reparenting-support.patch create mode 100644 debian/patches/features/arm/mmc-sunxi-Add-driver-for-SD-MMC-hosts-found-on-Allwi.patch diff --git a/debian/changelog b/debian/changelog index 7f8761ec0..7d0476598 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,9 @@ linux (3.15~rc7-1~exp2) UNRELEASED; urgency=medium [ Ian Campbell ] - * [armhf] Enable Broadcom IEEE802.11n embedded FullMAC WLAN driver (Closes: #734430) + * [armhf] Enable Broadcom IEEE802.11n embedded FullMAC WLAN driver + (Closes: #734430) + * [armhf] Backport and enable sunxi MMC driver (Closes: #749484) -- maximilian attems Tue, 27 May 2014 13:59:47 +0200 diff --git a/debian/config/armhf/config.armmp b/debian/config/armhf/config.armmp index bb7646c2c..8a704d353 100644 --- a/debian/config/armhf/config.armmp +++ b/debian/config/armhf/config.armmp @@ -357,6 +357,7 @@ CONFIG_MMC_OMAP_HS=m CONFIG_MMC_MVSDIO=m CONFIG_MMC_SPI=m CONFIG_MMC_WMT=m +CONFIG_MMC_SUNXI=m ## ## file: drivers/mtd/Kconfig diff --git a/debian/patches/features/arm/ARM-dts-sun4i-Add-mmc-controller-nodes.patch b/debian/patches/features/arm/ARM-dts-sun4i-Add-mmc-controller-nodes.patch new file mode 100644 index 000000000..9edbd335f --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun4i-Add-mmc-controller-nodes.patch @@ -0,0 +1,68 @@ +From b258b369e8ec4b6f544265aea52bb74476185b12 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= +Date: Fri, 2 May 2014 17:57:18 +0200 +Subject: [PATCH 01/12] ARM: dts: sun4i: Add mmc controller nodes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add nodes for the 4 mmc controllers found on A10 SoCs to +arch/arm/boot/dts/sun4i-a10.dtsi. + +Signed-off-by: David Lanzendörfer +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 4dc3761..aa7fced 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -377,6 +377,42 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun4i-a10-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <32>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun4i-a10-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <33>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun4i-a10-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <34>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ compatible = "allwinner,sun4i-a10-mmc"; ++ reg = <0x01c12000 0x1000>; ++ clocks = <&ahb_gates 11>, <&mmc3_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <35>; ++ status = "disabled"; ++ }; ++ + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun4i-a10-usb-phy"; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun4i-Add-pin-muxing-info-for-the-mmc0-contr.patch b/debian/patches/features/arm/ARM-dts-sun4i-Add-pin-muxing-info-for-the-mmc0-contr.patch new file mode 100644 index 000000000..884affa0f --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun4i-Add-pin-muxing-info-for-the-mmc0-contr.patch @@ -0,0 +1,43 @@ +From b5f86a3a719d2defb6b4144f75bfd92342f01aaa Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:19 +0200 +Subject: [PATCH 02/12] ARM: dts: sun4i: Add pin-muxing info for the mmc0 + controller + +mmc0 is the only controller actually being used on boards, so limit the +pin-muxing options to that. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index aa7fced..c7b794e 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -579,6 +579,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 = <2>; ++ 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.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun4i-Add-reg_vcc3v3-to-sun4i-board-mmc-node.patch b/debian/patches/features/arm/ARM-dts-sun4i-Add-reg_vcc3v3-to-sun4i-board-mmc-node.patch new file mode 100644 index 000000000..ac0846eb6 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun4i-Add-reg_vcc3v3-to-sun4i-board-mmc-node.patch @@ -0,0 +1,104 @@ +From a4da476b6c712bce10beddd342111d346a526caa Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 May 2014 09:46:54 +0200 +Subject: [PATCH 2/5] ARM: dts: sun4i: Add reg_vcc3v3 to sun4i board mmc nodes + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 1 + + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 1 + + arch/arm/boot/dts/sun4i-a10-hackberry.dts | 1 + + arch/arm/boot/dts/sun4i-a10-inet97fv2.dts | 1 + + arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 1 + + arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 1 + + arch/arm/boot/dts/sun4i-a10-pcduino.dts | 1 + + 7 files changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index 93af306..0b97c07 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -39,6 +39,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index 8581385..c200eac 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -37,6 +37,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +index 9dc7b1c..547fadc 100644 +--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts ++++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +@@ -39,6 +39,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +index 297b8f6..f13723e 100644 +--- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts ++++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +@@ -27,6 +27,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +index b7a4218..c01cea5 100644 +--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts ++++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +@@ -23,6 +23,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +index 4b7fd04..d46a7db 100644 +--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts ++++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +@@ -36,6 +36,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +index 4d9c3cd..fb03bcc 100644 +--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts ++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +@@ -37,6 +37,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun4i-Enable-mmc-controller-on-various-A10-b.patch b/debian/patches/features/arm/ARM-dts-sun4i-Enable-mmc-controller-on-various-A10-b.patch new file mode 100644 index 000000000..e2ed25443 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun4i-Enable-mmc-controller-on-various-A10-b.patch @@ -0,0 +1,164 @@ +From c0955a86f4af4fef7965bfcd41a9642a3f67486b Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:20 +0200 +Subject: [PATCH 03/12] ARM: dts: sun4i: Enable mmc controller on various A10 + boards + +Tested on a subset of these boards, for the others boards the settings match +the ones of the tested boards according to the original firmware fex files. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-hackberry.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-inet97fv2.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-pcduino.dts | 9 +++++++++ + 7 files changed, 63 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index fa746aea..93af306 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -36,6 +36,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index 4684cbe..8581385 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -34,6 +34,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +index d7c17e4..9dc7b1c 100644 +--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts ++++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +@@ -36,6 +36,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +index fe9272e..297b8f6 100644 +--- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts ++++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts +@@ -24,6 +24,15 @@ + }; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +index dd84a9e..b7a4218 100644 +--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts ++++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +@@ -20,6 +20,15 @@ + compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +index 66cf0c7..4b7fd04 100644 +--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts ++++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +@@ -33,6 +33,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +index 255b47e..4d9c3cd 100644 +--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts ++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +@@ -34,6 +34,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun5i-Add-mmc-controller-nodes.patch b/debian/patches/features/arm/ARM-dts-sun5i-Add-mmc-controller-nodes.patch new file mode 100644 index 000000000..28f00f61d --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun5i-Add-mmc-controller-nodes.patch @@ -0,0 +1,89 @@ +From d3aed1dfbd2e66ff2eca14897fa141a989a36fb0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= +Date: Fri, 2 May 2014 17:57:21 +0200 +Subject: [PATCH 04/12] ARM: dts: sun5i: Add mmc controller nodes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add nodes for the 3 mmc controllers found on A10s SoCs and for the 2 mmc +controllers found on A13 SoCs. + +Signed-off-by: David Lanzendörfer +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 27 +++++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 18 ++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 9493b21..aa1dd59 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -338,6 +338,33 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <32>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <33>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <34>; ++ status = "disabled"; ++ }; ++ + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-phy"; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index dda9df6..c9fdb7b 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -320,6 +320,24 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <32>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <34>; ++ status = "disabled"; ++ }; ++ + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-phy"; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun5i-Add-pin-muxing-info-for-the-mmc-contro.patch b/debian/patches/features/arm/ARM-dts-sun5i-Add-pin-muxing-info-for-the-mmc-contro.patch new file mode 100644 index 000000000..80bd976d7 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun5i-Add-pin-muxing-info-for-the-mmc-contro.patch @@ -0,0 +1,61 @@ +From 6da50f13a7153c4d55ee8e3ab9d5f7248ff8e3fc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 26 Apr 2014 12:16:12 +0200 +Subject: [PATCH] ARM: dts: sun5i: Add pin-muxing info for the mmc controllers + +This adds pin-muxing info for the mmc controller / port combinations which +are known to be used on actual boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 14 ++++++++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++ + 2 files changed, 21 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 79989ed..9493b21 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -451,6 +451,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 = <2>; ++ allwinner,pull = <0>; ++ }; ++ ++ mmc1_pins_a: mmc1@0 { ++ allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8"; ++ allwinner,function = "mmc1"; ++ allwinner,drive = <2>; ++ allwinner,pull = <0>; ++ }; + }; + + timer@01c20c00 { +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index d0836d4..dda9df6 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -415,6 +415,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 = <2>; ++ allwinner,pull = <0>; ++ }; + }; + + timer@01c20c00 { +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun5i-Add-reg_vcc3v3-to-sun5i-board-mmc-node.patch b/debian/patches/features/arm/ARM-dts-sun5i-Add-reg_vcc3v3-to-sun5i-board-mmc-node.patch new file mode 100644 index 000000000..3059bef99 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun5i-Add-reg_vcc3v3-to-sun5i-board-mmc-node.patch @@ -0,0 +1,60 @@ +From b4d6c77e3c64c1d1c097db1baa9c12126a4f583d Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 May 2014 09:46:55 +0200 +Subject: [PATCH 3/5] ARM: dts: sun5i: Add reg_vcc3v3 to sun5i board mmc nodes + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 2 ++ + arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 1 + + arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 1 + + 3 files changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +index de91308..ea9519d 100644 +--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +@@ -38,6 +38,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino_micro>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 1 0>; /* PG1 */ + cd-inverted; +@@ -47,6 +48,7 @@ + mmc1: mmc@01c10000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>, <&mmc1_cd_pin_olinuxino_micro>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 13 0>; /* PG13 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +index 8515f19..fa44b02 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +@@ -24,6 +24,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxinom>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +index 51a9438..429994e 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +@@ -23,6 +23,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ + cd-inverted; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun5i-Enable-mmc-controller-on-various-A10s-.patch b/debian/patches/features/arm/ARM-dts-sun5i-Enable-mmc-controller-on-various-A10s-.patch new file mode 100644 index 000000000..c41034736 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun5i-Enable-mmc-controller-on-various-A10s-.patch @@ -0,0 +1,138 @@ +From 31064bbd6dc3d49fe18f97d81e6ef2cb0358c9c8 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:22 +0200 +Subject: [PATCH 05/12] ARM: dts: sun5i: Enable mmc controller on various A10s + and A13 boards + +The cd pin settings have been taken from the original firmware fex files, +and have been confirmed to work on the actual boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 32 ++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 16 ++++++++++++ + arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 16 ++++++++++++ + 3 files changed, 64 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +index 23611b7..de91308 100644 +--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +@@ -35,6 +35,24 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino_micro>; ++ bus-width = <4>; ++ cd-gpios = <&pio 6 1 0>; /* PG1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins_a>, <&mmc1_cd_pin_olinuxino_micro>; ++ bus-width = <4>; ++ cd-gpios = <&pio 6 13 0>; /* PG13 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +@@ -49,6 +67,20 @@ + }; + + pinctrl@01c20800 { ++ mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin@0 { ++ allwinner,pins = "PG1"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <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 = <1>; ++ }; ++ + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PE3"; + allwinner,function = "gpio_out"; +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +index 11169d5..8515f19 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +@@ -21,6 +21,15 @@ + compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxinom>; ++ bus-width = <4>; ++ cd-gpios = <&pio 6 0 0>; /* PG0 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +@@ -35,6 +44,13 @@ + }; + + pinctrl@01c20800 { ++ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { ++ allwinner,pins = "PG0"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <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 7a9187b..51a9438 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +@@ -20,6 +20,15 @@ + compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_olinuxino>; ++ bus-width = <4>; ++ cd-gpios = <&pio 6 0 0>; /* PG0 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +@@ -34,6 +43,13 @@ + }; + + pinctrl@01c20800 { ++ mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { ++ allwinner,pins = "PG0"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <0>; ++ allwinner,pull = <1>; ++ }; ++ + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PG9"; + allwinner,function = "gpio_out"; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-clocks.patch b/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-clocks.patch new file mode 100644 index 000000000..330f089e5 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-clocks.patch @@ -0,0 +1,54 @@ +From adc54c858499436f049cc7252de617314e7bacf2 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:23 +0200 +Subject: [PATCH 06/12] ARM: dts: sun6i: Add mmc clocks + +Add clk-nodes for the mmc clocks. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -198,6 +198,38 @@ + "apb2_uart4", "apb2_uart5"; + }; + ++ mmc0_clk: clk@01c20088 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-mod0-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "mmc0"; ++ }; ++ ++ mmc1_clk: clk@01c2008c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-mod0-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "mmc1"; ++ }; ++ ++ mmc2_clk: clk@01c20090 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-mod0-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "mmc2"; ++ }; ++ ++ mmc3_clk: clk@01c20094 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-mod0-clk"; ++ reg = <0x01c20094 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "mmc3"; ++ }; ++ + spi0_clk: clk@01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; diff --git a/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-controller-nodes.patch b/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-controller-nodes.patch new file mode 100644 index 000000000..7fcd4adea --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun6i-Add-mmc-controller-nodes.patch @@ -0,0 +1,67 @@ +From 5b753f0e27da2b0a29142be0833784475bc29366 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:24 +0200 +Subject: [PATCH 07/12] ARM: dts: sun6i: Add mmc controller nodes + +Add nodes for the 4 mmc controllers found on A31 SoCs to +arch/arm/boot/dts/sun6i-a31.dtsi. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -277,6 +277,50 @@ + interrupts = <0 32 4>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb1_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mmc"; ++ resets = <&ahb1_rst 8>; ++ reset-names = "ahb"; ++ interrupts = <0 60 4>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb1_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mmc"; ++ resets = <&ahb1_rst 9>; ++ reset-names = "ahb"; ++ interrupts = <0 61 4>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb1_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mmc"; ++ resets = <&ahb1_rst 10>; ++ reset-names = "ahb"; ++ interrupts = <0 62 4>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c12000 0x1000>; ++ clocks = <&ahb1_gates 11>, <&mmc3_clk>; ++ clock-names = "ahb", "mmc"; ++ resets = <&ahb1_rst 11>; ++ reset-names = "ahb"; ++ interrupts = <0 63 4>; ++ status = "disabled"; ++ }; ++ + pio: pinctrl@01c20800 { + compatible = "allwinner,sun6i-a31-pinctrl"; + reg = <0x01c20800 0x400>; diff --git a/debian/patches/features/arm/ARM-dts-sun6i-Add-new-sun6i-a31-m9-dts-file-for-Mele.patch b/debian/patches/features/arm/ARM-dts-sun6i-Add-new-sun6i-a31-m9-dts-file-for-Mele.patch new file mode 100644 index 000000000..682162dd9 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun6i-Add-new-sun6i-a31-m9-dts-file-for-Mele.patch @@ -0,0 +1,79 @@ +From 0ff1ffd3fe86840c80458ea45c2379014c86b660 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:25 +0200 +Subject: [PATCH 08/12] ARM: dts: sun6i: Add new sun6i-a31-m9 dts file for Mele + M9 + +Add a new sun6i-a31-m9 dts file for the Mele M9 / Mele A1000G Quad. These +HTPCs use the same board in a different case, for more details see: +http://linux-sunxi.org/Mele_M9 + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/sun6i-a31-m9.dts | 48 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+) + create mode 100644 arch/arm/boot/dts/sun6i-a31-m9.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -344,6 +344,7 @@ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ + sun6i-a31-colombus.dtb \ ++ sun6i-a31-m9.dtb \ + sun7i-a20-cubieboard2.dtb \ + sun7i-a20-cubietruck.dtb \ + sun7i-a20-olinuxino-micro.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/sun6i-a31-m9.dts +@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2014 Hans de Goede ++ * ++ * 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/ "sun6i-a31.dtsi" ++ ++/ { ++ model = "Mele M9 / A1000G Quad top set box"; ++ compatible = "mele,m9", "allwinner,sun6i-a31"; ++ ++ chosen { ++ bootargs = "earlyprintk console=ttyS0,115200"; ++ }; ++ ++ soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_m9>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 22 0>; /* PH22 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ ++ pio: pinctrl@01c20800 { ++ mmc0_cd_pin_m9: mmc0_cd_pin@0 { ++ allwinner,pins = "PH22"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <0>; ++ allwinner,pull = <1>; ++ }; ++ }; ++ ++ uart0: serial@01c28000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++ }; ++ }; ++}; diff --git a/debian/patches/features/arm/ARM-dts-sun6i-Add-pin-muxing-info-for-the-mmc-contro.patch b/debian/patches/features/arm/ARM-dts-sun6i-Add-pin-muxing-info-for-the-mmc-contro.patch new file mode 100644 index 000000000..4433e5c21 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun6i-Add-pin-muxing-info-for-the-mmc-contro.patch @@ -0,0 +1,35 @@ +From 9797eb83c85d553dbc062b2953597fb1086649e9 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 26 Apr 2014 12:16:16 +0200 +Subject: [PATCH] ARM: dts: sun6i: Add pin-muxing info for the mmc controllers + +This adds pin-muxing info for the mmc controller / port combinations which +are known to be used on actual boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index 22f63e0..30138cd 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -295,6 +295,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 = <2>; ++ allwinner,pull = <0>; ++ }; + }; + + ahb1_rst: reset@01c202c0 { +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun6i-Add-reg_vcc3v3-to-sun6i-board-mmc-node.patch b/debian/patches/features/arm/ARM-dts-sun6i-Add-reg_vcc3v3-to-sun6i-board-mmc-node.patch new file mode 100644 index 000000000..0138f31fc --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun6i-Add-reg_vcc3v3-to-sun6i-board-mmc-node.patch @@ -0,0 +1,34 @@ +From e6879d190d0ccd02d60b24ff9e49c0e105d135a6 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 May 2014 09:46:56 +0200 +Subject: [PATCH 4/5] ARM: dts: sun6i: Add reg_vcc3v3 to sun6i board mmc nodes + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun6i-a31-m9.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/dts/sun6i-a31-m9.dts b/arch/arm/boot/dts/sun6i-a31-m9.dts +index 22eacf8..bc6115d 100644 +--- a/arch/arm/boot/dts/sun6i-a31-m9.dts ++++ b/arch/arm/boot/dts/sun6i-a31-m9.dts +@@ -11,6 +11,7 @@ + + /dts-v1/; + /include/ "sun6i-a31.dtsi" ++/include/ "sunxi-common-regulators.dtsi" + + / { + model = "Mele M9 / A1000G Quad top set box"; +@@ -24,6 +25,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_m9>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 22 0>; /* PH22 */ + cd-inverted; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun7i-Add-basic-support-for-the-Cubietruck-W.patch b/debian/patches/features/arm/ARM-dts-sun7i-Add-basic-support-for-the-Cubietruck-W.patch new file mode 100644 index 000000000..fd810cb7b --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-Add-basic-support-for-the-Cubietruck-W.patch @@ -0,0 +1,72 @@ +From 3906c0a688587408fa37a411d5e79778039e9dc3 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 2 May 2014 17:57:29 +0200 +Subject: [PATCH 12/12] ARM: dts: sun7i: Add basic support for the Cubietruck + WiFi module + +The CubieTruck has an AMPAK AP6210 WiFi+Bluetooth module. The WiFi +part is a BCM43362 IC connected to MMC3 in the A20 SoC via SDIO. +The IC also takes a power enable signal via GPIO. + +The WiFi module supports out-of-band interrupt signaling via GPIO, +but this is not supported in this patch. + +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 31 ++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -29,6 +29,14 @@ + status = "okay"; + }; + ++ mmc3: mmc@01c12000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins_a>; ++ vmmc-supply = <®_vmmc3>; ++ non-removable; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +@@ -57,6 +65,18 @@ + }; + + pinctrl@01c20800 { ++ mmc3_pins_a: mmc3@0 { ++ /* AP6210 requires pull-up */ ++ allwinner,pull = <1>; ++ }; ++ ++ vmmc3_pin_cubietruck: vmmc3_pin@0 { ++ allwinner,pins = "PH9"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 { + allwinner,pins = "PH12"; + allwinner,function = "gpio_out"; +@@ -148,4 +168,15 @@ + reg_usb2_vbus: usb2-vbus { + status = "okay"; + }; ++ ++ reg_vmmc3: vmmc3 { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vmmc3_pin_cubietruck>; ++ regulator-name = "vmmc3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ gpio = <&pio 7 9 0>; ++ }; + }; diff --git a/debian/patches/features/arm/ARM-dts-sun7i-Add-mmc-controller-nodes.patch b/debian/patches/features/arm/ARM-dts-sun7i-Add-mmc-controller-nodes.patch new file mode 100644 index 000000000..5f5dd6cdd --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-Add-mmc-controller-nodes.patch @@ -0,0 +1,63 @@ +From dd29ce53b2a48bbb29eaa4a0c86a7a5f36c3d9c0 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:26 +0200 +Subject: [PATCH 09/12] ARM: dts: sun7i: Add mmc controller nodes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add nodes for the 4 mmc controllers found on A20 SoCs to +arch/arm/boot/dts/sun7i-a20.dtsi. + +Signed-off-by: David Lanzendörfer +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -447,6 +447,42 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <0 32 4>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <0 33 4>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <0 34 4>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c12000 0x1000>; ++ clocks = <&ahb_gates 11>, <&mmc3_clk>; ++ clock-names = "ahb", "mmc"; ++ interrupts = <0 35 4>; ++ status = "disabled"; ++ }; ++ + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun7i-a20-usb-phy"; diff --git a/debian/patches/features/arm/ARM-dts-sun7i-Add-pin-muxing-info-for-the-mmc-contro.patch b/debian/patches/features/arm/ARM-dts-sun7i-Add-pin-muxing-info-for-the-mmc-contro.patch new file mode 100644 index 000000000..b10e776fa --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-Add-pin-muxing-info-for-the-mmc-contro.patch @@ -0,0 +1,45 @@ +From 11fbedf4dd960db39b40aa59253bb7375df54241 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:27 +0200 +Subject: [PATCH 10/12] ARM: dts: sun7i: Add pin-muxing info for the mmc + controllers + +This adds pin-muxing info for the mmc controller / port combinations which +are known to be used on actual boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -689,6 +689,27 @@ + allwinner,drive = <0>; + allwinner,pull = <0>; + }; ++ ++ mmc0_pins_a: mmc0@0 { ++ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; ++ allwinner,function = "mmc0"; ++ allwinner,drive = <2>; ++ 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 = <2>; ++ allwinner,pull = <0>; ++ }; + }; + + timer@01c20c00 { diff --git a/debian/patches/features/arm/ARM-dts-sun7i-Add-reg_vcc3v3-to-sun7i-board-mmc-node.patch b/debian/patches/features/arm/ARM-dts-sun7i-Add-reg_vcc3v3-to-sun7i-board-mmc-node.patch new file mode 100644 index 000000000..2f7d16b73 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-Add-reg_vcc3v3-to-sun7i-board-mmc-node.patch @@ -0,0 +1,60 @@ +From 0ed9eab3030a337d803a0eaefd70fc254a1ae1c8 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 May 2014 09:46:57 +0200 +Subject: [PATCH 5/5] ARM: dts: sun7i: Add reg_vcc3v3 to sun7i board mmc nodes + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 1 + + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 1 + + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 2 ++ + 3 files changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index 3918e2f..a5ad945 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -23,6 +23,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index 9dbb763c..b7e79d0 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -23,6 +23,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index 1bfef12..b759630 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -34,6 +34,7 @@ + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; /* PH1 */ + cd-inverted; +@@ -43,6 +44,7 @@ + mmc3: mmc@01c12000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_olinuxinom>; ++ vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 11 0>; /* PH11 */ + cd-inverted; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sun7i-Enable-mmc-controller-on-various-A20-b.patch b/debian/patches/features/arm/ARM-dts-sun7i-Enable-mmc-controller-on-various-A20-b.patch new file mode 100644 index 000000000..dd769b37e --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-Enable-mmc-controller-on-various-A20-b.patch @@ -0,0 +1,94 @@ +From c621183c203affa526c15e46432c24f31afed997 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 2 May 2014 17:57:28 +0200 +Subject: [PATCH 11/12] ARM: dts: sun7i: Enable mmc controller on various A20 + boards + +The cd pin settings have been taken from the original firmware fex files, +and have been confirmed to work on the actual boards. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 9 +++++++++ + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 9 +++++++++ + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 25 +++++++++++++++++++++++++ + 3 files changed, 43 insertions(+) + +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -20,6 +20,15 @@ + compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -20,6 +20,15 @@ + compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -31,6 +31,24 @@ + status = "okay"; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_olinuxinom>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 11 0>; /* PH11 */ ++ cd-inverted; ++ status = "okay"; ++ }; ++ + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; +@@ -65,6 +83,13 @@ + }; + + 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/debian/patches/features/arm/ARM-dts-sun7i-cubietruck-set-mmc3-bus-width-property.patch b/debian/patches/features/arm/ARM-dts-sun7i-cubietruck-set-mmc3-bus-width-property.patch new file mode 100644 index 000000000..68377b477 --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sun7i-cubietruck-set-mmc3-bus-width-property.patch @@ -0,0 +1,29 @@ +From c5b7261cae14ada86f5823659664fade0bcefa20 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 21 May 2014 19:43:30 +0200 +Subject: [PATCH] ARM: dts: sun7i: cubietruck: set mmc3 bus-width property + +bus-width defaults to 1, and all 4 lines are hooked up at the cubietruck, +properly set bus-width to 4. + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index b7e79d0..b87fea9 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -34,6 +34,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vmmc3>; ++ bus-width = <4>; + non-removable; + status = "okay"; + }; +-- +1.9.0 + diff --git a/debian/patches/features/arm/ARM-dts-sunxi-Add-reg_vcc3v3-supply-to-sunxi-common-.patch b/debian/patches/features/arm/ARM-dts-sunxi-Add-reg_vcc3v3-supply-to-sunxi-common-.patch new file mode 100644 index 000000000..beaf353de --- /dev/null +++ b/debian/patches/features/arm/ARM-dts-sunxi-Add-reg_vcc3v3-supply-to-sunxi-common-.patch @@ -0,0 +1,31 @@ +From e509e4044b1c2d44abead8ccd152c956890bf5dd Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 May 2014 09:46:53 +0200 +Subject: [PATCH 1/5] ARM: dts: sunxi: Add reg_vcc3v3 supply to + sunxi-common-regulators.dtsi + +Signed-off-by: Hans de Goede +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/sunxi-common-regulators.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sunxi-common-regulators.dtsi b/arch/arm/boot/dts/sunxi-common-regulators.dtsi +index 18eeac0..026bd83 100644 +--- a/arch/arm/boot/dts/sunxi-common-regulators.dtsi ++++ b/arch/arm/boot/dts/sunxi-common-regulators.dtsi +@@ -72,4 +72,11 @@ + gpio = <&pio 7 3 0>; + status = "disabled"; + }; ++ ++ reg_vcc3v3: vcc3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; + }; +-- +1.9.0 + diff --git a/debian/patches/features/arm/clk-sunxi-Fixup-clk_sunxi_mmc_phase_control-to-take-.patch b/debian/patches/features/arm/clk-sunxi-Fixup-clk_sunxi_mmc_phase_control-to-take-.patch new file mode 100644 index 000000000..91ebd650b --- /dev/null +++ b/debian/patches/features/arm/clk-sunxi-Fixup-clk_sunxi_mmc_phase_control-to-take-.patch @@ -0,0 +1,49 @@ +From a97181adf1502128e2945b4fef2591249c565467 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 12 May 2014 14:04:47 +0200 +Subject: [PATCH] clk: sunxi: Fixup clk_sunxi_mmc_phase_control to take a clk + rather then a hw_clk + +__clk_get_hw is supposed to be used by clk providers, not clk consumers. + +Signed-off-by: Hans de Goede +Reviewed-by: Ulf Hansson +Signed-off-by: Mike Turquette +--- + drivers/clk/sunxi/clk-sunxi.c | 3 ++- + include/linux/clk/sunxi.h | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 59f9040..4cc2b2a 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -510,11 +510,12 @@ CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", + * clk_sunxi_mmc_phase_control() - configures MMC clock phase control + */ + +-void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output) ++void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output) + { + #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) + #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) + ++ struct clk_hw *hw = __clk_get_hw(clk); + struct clk_composite *composite = to_clk_composite(hw); + struct clk_hw *rate_hw = composite->rate_hw; + struct clk_factors *factors = to_clk_factors(rate_hw); +diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h +index 1ef5c89..aed28c4 100644 +--- a/include/linux/clk/sunxi.h ++++ b/include/linux/clk/sunxi.h +@@ -17,6 +17,6 @@ + + #include + +-void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); ++void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output); + + #endif +-- +1.9.0 + diff --git a/debian/patches/features/arm/clk-sunxi-Implement-MMC-phase-control.patch b/debian/patches/features/arm/clk-sunxi-Implement-MMC-phase-control.patch new file mode 100644 index 000000000..7b2638e0f --- /dev/null +++ b/debian/patches/features/arm/clk-sunxi-Implement-MMC-phase-control.patch @@ -0,0 +1,97 @@ +From 95713978b0a2929b72933235bb07c0a793e71afa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Fri, 2 May 2014 17:57:16 +0200 +Subject: [PATCH 2/2] clk: sunxi: Implement MMC phase control +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +HdG: add header exporting clk_sunxi_mmc_phase_control + +Signed-off-by: Emilio López +Signed-off-by: Hans de Goede +Signed-off-by: Mike Turquette +--- + drivers/clk/sunxi/clk-sunxi.c | 36 ++++++++++++++++++++++++++++++++++++ + include/linux/clk/sunxi.h | 22 ++++++++++++++++++++++ + 2 files changed, 58 insertions(+) + create mode 100644 include/linux/clk/sunxi.h + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index bd7dc73..59f9040 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -507,6 +507,42 @@ CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", + + + /** ++ * clk_sunxi_mmc_phase_control() - configures MMC clock phase control ++ */ ++ ++void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output) ++{ ++ #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) ++ #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) ++ ++ struct clk_composite *composite = to_clk_composite(hw); ++ struct clk_hw *rate_hw = composite->rate_hw; ++ struct clk_factors *factors = to_clk_factors(rate_hw); ++ unsigned long flags = 0; ++ u32 reg; ++ ++ if (factors->lock) ++ spin_lock_irqsave(factors->lock, flags); ++ ++ reg = readl(factors->reg); ++ ++ /* set sample clock phase control */ ++ reg &= ~(0x7 << 20); ++ reg |= ((sample & 0x7) << 20); ++ ++ /* set output clock phase control */ ++ reg &= ~(0x7 << 8); ++ reg |= ((output & 0x7) << 8); ++ ++ writel(reg, factors->reg); ++ ++ if (factors->lock) ++ spin_unlock_irqrestore(factors->lock, flags); ++} ++EXPORT_SYMBOL(clk_sunxi_mmc_phase_control); ++ ++ ++/** + * sunxi_factors_clk_setup() - Setup function for factor clocks + */ + +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 @@ ++/* ++ * Copyright 2013 - Hans de Goede ++ * ++ * 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. ++ */ ++ ++#ifndef __LINUX_CLK_SUNXI_H_ ++#define __LINUX_CLK_SUNXI_H_ ++ ++#include ++ ++void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); ++ ++#endif +-- +1.9.0 + diff --git a/debian/patches/features/arm/clk-sunxi-factors-automatic-reparenting-support.patch b/debian/patches/features/arm/clk-sunxi-factors-automatic-reparenting-support.patch new file mode 100644 index 000000000..90ad0ae2d --- /dev/null +++ b/debian/patches/features/arm/clk-sunxi-factors-automatic-reparenting-support.patch @@ -0,0 +1,76 @@ +From 862b728387aef3a3776ad2a261e484aff36c5e67 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Emilio=20L=C3=B3pez?= +Date: Fri, 2 May 2014 17:57:15 +0200 +Subject: [PATCH 1/2] clk: sunxi: factors: automatic reparenting support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit implements .determine_rate, so that our factor clocks can be +reparented when needed. + +Signed-off-by: Emilio López +Signed-off-by: Hans de Goede +Acked-by: Maxime Ripard +Signed-off-by: Mike Turquette +--- + drivers/clk/sunxi/clk-factors.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 9e23264..3806d97 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -77,6 +77,41 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, + return rate; + } + ++static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ struct clk *clk = hw->clk, *parent, *best_parent = NULL; ++ int i, num_parents; ++ unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; ++ ++ /* find the parent that can help provide the fastest rate <= rate */ ++ num_parents = __clk_get_num_parents(clk); ++ for (i = 0; i < num_parents; i++) { ++ parent = clk_get_parent_by_index(clk, i); ++ if (!parent) ++ continue; ++ if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT) ++ parent_rate = __clk_round_rate(parent, rate); ++ else ++ parent_rate = __clk_get_rate(parent); ++ ++ child_rate = clk_factors_round_rate(hw, rate, &parent_rate); ++ ++ if (child_rate <= rate && child_rate > best_child_rate) { ++ best_parent = parent; ++ best = parent_rate; ++ best_child_rate = child_rate; ++ } ++ } ++ ++ if (best_parent) ++ *best_parent_p = best_parent; ++ *best_parent_rate = best; ++ ++ return best_child_rate; ++} ++ + static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) + { +@@ -113,6 +148,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, + } + + const struct clk_ops clk_factors_ops = { ++ .determine_rate = clk_factors_determine_rate, + .recalc_rate = clk_factors_recalc_rate, + .round_rate = clk_factors_round_rate, + .set_rate = clk_factors_set_rate, +-- +1.9.0 + diff --git a/debian/patches/features/arm/mmc-sunxi-Add-driver-for-SD-MMC-hosts-found-on-Allwi.patch b/debian/patches/features/arm/mmc-sunxi-Add-driver-for-SD-MMC-hosts-found-on-Allwi.patch new file mode 100644 index 000000000..63826874d --- /dev/null +++ b/debian/patches/features/arm/mmc-sunxi-Add-driver-for-SD-MMC-hosts-found-on-Allwi.patch @@ -0,0 +1,1153 @@ +From 19b7f796c375a8098924717b171ac5058129d2c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= +Date: Mon, 12 May 2014 14:04:48 +0200 +Subject: [PATCH] mmc: 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 + +The Allwinner sunxi mmc host 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. However the rest of the host is not identical to mmc-dw, it +deals with sending stop commands in hardware which makes it significantly +different from the mmc-dw devices. + +Signed-off-by: David Lanzendörfer +[hdegoede@redhat.com: various cleanups and fixes] +Signed-off-by: Hans de Goede +Acked-by: Maxime Ripard +Acked-by: Arnd Bergmann +Signed-off-by: Ulf Hansson +Signed-off-by: Chris Ball +[ ijc -- backported, trivial conflicts in drivers/mmc/{Kconfig,Makefile} ] +--- + .../devicetree/bindings/mmc/sunxi-mmc.txt | 43 + + drivers/mmc/host/Kconfig | 7 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/sunxi-mmc.c | 1049 ++++++++++++++++++++ + 4 files changed, 1100 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mmc/sunxi-mmc.txt + create mode 100644 drivers/mmc/host/sunxi-mmc.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +@@ -0,0 +1,43 @@ ++* Allwinner sunxi MMC controller ++ ++The highspeed MMC host controller on Allwinner SoCs provides an interface ++for MMC, SD and SDIO types of memory cards. ++ ++Supported maximum speeds are the ones of the eMMC standard 4.5 as well ++as the speed of SD standard 3.0. ++Absolute maximum transfer rate is 200MB/s ++ ++Required properties: ++ - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc" ++ - reg : mmc controller base registers ++ - clocks : a list with 2 phandle + clock specifier pairs ++ - clock-names : must contain "ahb" and "mmc" ++ - interrupts : mmc controller interrupt ++ ++Optional properties: ++ - resets : phandle + reset specifier pair ++ - reset-names : must contain "ahb" ++ - for cd, bus-width and additional generic mmc parameters ++ please refer to mmc.txt within this directory ++ ++Examples: ++ - Within .dtsi: ++ 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>; ++ status = "disabled"; ++ }; ++ ++ - Within dts: ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++ }; +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -694,3 +694,10 @@ + 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. +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -50,6 +50,7 @@ + obj-$(CONFIG_MMC_VUB300) += vub300.o + obj-$(CONFIG_MMC_USHC) += ushc.o + obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o ++obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o + + obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o + +--- /dev/null ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -0,0 +1,1049 @@ ++/* ++ * Driver for sunxi SD/MMC host controllers ++ * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. ++ * (C) Copyright 2007-2011 Aaron Maoye ++ * (C) Copyright 2013-2014 O2S GmbH ++ * (C) Copyright 2013-2014 David Lanzend�rfer ++ * (C) Copyright 2013-2014 Hans de Goede ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* register offset definitions */ ++#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 mmc_readl(host, reg) \ ++ readl((host)->reg_base + SDXC_##reg) ++#define mmc_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_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 (0 << 31) ++#define SDXC_HARDWARE_RESET \ ++ (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET) ++ ++/* 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_RESP_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_RESP_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_RESP_CRC_ERROR BIT(6) ++#define SDXC_DATA_CRC_ERROR BIT(7) ++#define SDXC_RESP_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_RESP_ERROR | SDXC_RESP_CRC_ERROR | SDXC_DATA_CRC_ERROR | \ ++ SDXC_RESP_TIMEOUT | SDXC_DATA_TIMEOUT | SDXC_FIFO_RUN_ERROR | \ ++ SDXC_HARD_WARE_LOCKED | SDXC_START_BIT_ERROR | SDXC_END_BIT_ERROR) ++#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 (0xceaa << 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_IRQ_ENABLE 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 BIT(10) ++#define SDXC_IDMAC_IDLE (0 << 13) ++#define SDXC_IDMAC_SUSPEND (1 << 13) ++#define SDXC_IDMAC_DESC_READ (2 << 13) ++#define SDXC_IDMAC_DESC_CHECK (3 << 13) ++#define SDXC_IDMAC_READ_REQUEST_WAIT (4 << 13) ++#define SDXC_IDMAC_WRITE_REQUEST_WAIT (5 << 13) ++#define SDXC_IDMAC_READ (6 << 13) ++#define SDXC_IDMAC_WRITE (7 << 13) ++#define SDXC_IDMAC_DESC_CLOSE (8 << 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 reset_control *reset; ++ ++ /* IO mapping base */ ++ void __iomem *reg_base; ++ ++ /* clock management */ ++ struct clk *clk_ahb; ++ struct clk *clk_mmc; ++ ++ /* irq */ ++ spinlock_t lock; ++ int irq; ++ u32 int_sum; ++ u32 sdio_imask; ++ ++ /* dma */ ++ u32 idma_des_size_bits; ++ dma_addr_t sg_dma; ++ void *sg_cpu; ++ bool wait_dma; ++ ++ struct mmc_request *mrq; ++ struct mmc_request *manual_stop_mrq; ++ int ferror; ++}; ++ ++static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) ++{ ++ unsigned long expire = jiffies + msecs_to_jiffies(250); ++ u32 rval; ++ ++ mmc_writel(host, REG_CMDR, SDXC_HARDWARE_RESET); ++ do { ++ rval = mmc_readl(host, REG_GCTRL); ++ } while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET)); ++ ++ if (rval & SDXC_HARDWARE_RESET) { ++ dev_err(mmc_dev(host->mmc), "fatal err reset timeout\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sunxi_mmc_init_host(struct mmc_host *mmc) ++{ ++ u32 rval; ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ ++ if (sunxi_mmc_reset_host(host)) ++ return -EIO; ++ ++ mmc_writel(host, REG_FTRGL, 0x20070008); ++ mmc_writel(host, REG_TMOUT, 0xffffffff); ++ mmc_writel(host, REG_IMASK, host->sdio_imask); ++ mmc_writel(host, REG_RINTR, 0xffffffff); ++ mmc_writel(host, REG_DBGC, 0xdeb); ++ mmc_writel(host, REG_FUNS, SDXC_CEATA_ON); ++ mmc_writel(host, REG_DLBA, host->sg_dma); ++ ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_INTERRUPT_ENABLE_BIT; ++ rval &= ~SDXC_ACCESS_DONE_DIRECT; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ return 0; ++} ++ ++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; ++ ++ /* ++ * Avoid the io-store starting the idmac hitting io-mem before the ++ * descriptors hit the main-mem. ++ */ ++ wmb(); ++} ++ ++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_map_dma(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ u32 i, dma_len; ++ struct scatterlist *sg; ++ ++ dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ if (dma_len == 0) { ++ dev_err(mmc_dev(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(host->mmc), ++ "unaligned scatterlist: os %x length %d\n", ++ sg->offset, sg->length); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static void sunxi_mmc_start_dma(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ u32 rval; ++ ++ sunxi_mmc_init_idma_des(host, data); ++ ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_DMA_ENABLE_BIT; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval |= SDXC_DMA_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ mmc_writel(host, REG_DMAC, SDXC_IDMAC_SOFT_RESET); ++ ++ if (!(data->flags & MMC_DATA_WRITE)) ++ mmc_writel(host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT); ++ ++ mmc_writel(host, REG_DMAC, ++ SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON); ++} ++ ++static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, ++ struct mmc_request *req) ++{ ++ u32 arg, cmd_val, ri; ++ unsigned long expire = jiffies + msecs_to_jiffies(1000); ++ ++ cmd_val = SDXC_START | SDXC_RESP_EXPIRE | ++ SDXC_STOP_ABORT_CMD | SDXC_CHECK_RESPONSE_CRC; ++ ++ if (req->cmd->opcode == SD_IO_RW_EXTENDED) { ++ cmd_val |= SD_IO_RW_DIRECT; ++ arg = (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | ++ ((req->cmd->arg >> 28) & 0x7); ++ } else { ++ cmd_val |= MMC_STOP_TRANSMISSION; ++ arg = 0; ++ } ++ ++ mmc_writel(host, REG_CARG, arg); ++ mmc_writel(host, REG_CMDR, cmd_val); ++ ++ do { ++ ri = mmc_readl(host, REG_RINTR); ++ } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) && ++ time_before(jiffies, expire)); ++ ++ if (!(ri & SDXC_COMMAND_DONE) || (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] = mmc_readl(host, REG_RESP0); ++ } ++ ++ mmc_writel(host, REG_RINTR, 0xffff); ++} ++ ++static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *host) ++{ ++ struct mmc_command *cmd = host->mrq->cmd; ++ struct mmc_data *data = host->mrq->data; ++ ++ /* For some cmds timeout is normal with sd/mmc cards */ ++ if ((host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == ++ SDXC_RESP_TIMEOUT && (cmd->opcode == SD_IO_SEND_OP_COND || ++ cmd->opcode == SD_IO_RW_DIRECT)) ++ return; ++ ++ dev_err(mmc_dev(host->mmc), ++ "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", ++ host->mmc->index, cmd->opcode, ++ data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", ++ host->int_sum & SDXC_RESP_ERROR ? " RE" : "", ++ host->int_sum & SDXC_RESP_CRC_ERROR ? " RCE" : "", ++ host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "", ++ host->int_sum & SDXC_RESP_TIMEOUT ? " RTO" : "", ++ host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "", ++ host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "", ++ host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "", ++ host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "", ++ host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : "" ++ ); ++} ++ ++/* Called in interrupt context! */ ++static irqreturn_t sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) ++{ ++ struct mmc_request *mrq = host->mrq; ++ struct mmc_data *data = mrq->data; ++ u32 rval; ++ ++ mmc_writel(host, REG_IMASK, host->sdio_imask); ++ mmc_writel(host, REG_IDIE, 0); ++ ++ if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) { ++ sunxi_mmc_dump_errinfo(host); ++ mrq->cmd->error = -ETIMEDOUT; ++ ++ if (data) { ++ data->error = -ETIMEDOUT; ++ host->manual_stop_mrq = mrq; ++ } ++ ++ if (mrq->stop) ++ mrq->stop->error = -ETIMEDOUT; ++ } else { ++ if (mrq->cmd->flags & MMC_RSP_136) { ++ mrq->cmd->resp[0] = mmc_readl(host, REG_RESP3); ++ mrq->cmd->resp[1] = mmc_readl(host, REG_RESP2); ++ mrq->cmd->resp[2] = mmc_readl(host, REG_RESP1); ++ mrq->cmd->resp[3] = mmc_readl(host, REG_RESP0); ++ } else { ++ mrq->cmd->resp[0] = mmc_readl(host, REG_RESP0); ++ } ++ ++ if (data) ++ data->bytes_xfered = data->blocks * data->blksz; ++ } ++ ++ if (data) { ++ mmc_writel(host, REG_IDST, 0x337); ++ mmc_writel(host, REG_DMAC, 0); ++ rval = mmc_readl(host, REG_GCTRL); ++ rval |= SDXC_DMA_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval &= ~SDXC_DMA_ENABLE_BIT; ++ mmc_writel(host, REG_GCTRL, rval); ++ rval |= SDXC_FIFO_RESET; ++ mmc_writel(host, REG_GCTRL, rval); ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ } ++ ++ mmc_writel(host, REG_RINTR, 0xffff); ++ ++ host->mrq = NULL; ++ host->int_sum = 0; ++ host->wait_dma = false; ++ ++ return host->manual_stop_mrq ? IRQ_WAKE_THREAD : IRQ_HANDLED; ++} ++ ++static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) ++{ ++ struct sunxi_mmc_host *host = dev_id; ++ struct mmc_request *mrq; ++ u32 msk_int, idma_int; ++ bool finalize = false; ++ bool sdio_int = false; ++ irqreturn_t ret = IRQ_HANDLED; ++ ++ spin_lock(&host->lock); ++ ++ idma_int = mmc_readl(host, REG_IDST); ++ msk_int = mmc_readl(host, REG_MISTA); ++ ++ dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", ++ host->mrq, msk_int, idma_int); ++ ++ mrq = host->mrq; ++ if (mrq) { ++ if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT) ++ host->wait_dma = false; ++ ++ host->int_sum |= msk_int; ++ ++ /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finalize */ ++ if ((host->int_sum & SDXC_RESP_TIMEOUT) && ++ !(host->int_sum & SDXC_COMMAND_DONE)) ++ mmc_writel(host, REG_IMASK, ++ host->sdio_imask | SDXC_COMMAND_DONE); ++ /* Don't wait for dma on error */ ++ else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) ++ finalize = true; ++ else if ((host->int_sum & SDXC_INTERRUPT_DONE_BIT) && ++ !host->wait_dma) ++ finalize = true; ++ } ++ ++ if (msk_int & SDXC_SDIO_INTERRUPT) ++ sdio_int = true; ++ ++ mmc_writel(host, REG_RINTR, msk_int); ++ mmc_writel(host, REG_IDST, idma_int); ++ ++ if (finalize) ++ ret = sunxi_mmc_finalize_request(host); ++ ++ spin_unlock(&host->lock); ++ ++ if (finalize && ret == IRQ_HANDLED) ++ mmc_request_done(host->mmc, mrq); ++ ++ if (sdio_int) ++ mmc_signal_sdio_irq(host->mmc); ++ ++ return ret; ++} ++ ++static irqreturn_t sunxi_mmc_handle_manual_stop(int irq, void *dev_id) ++{ ++ struct sunxi_mmc_host *host = dev_id; ++ struct mmc_request *mrq; ++ unsigned long iflags; ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ mrq = host->manual_stop_mrq; ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ if (!mrq) { ++ dev_err(mmc_dev(host->mmc), "no request for manual stop\n"); ++ return IRQ_HANDLED; ++ } ++ ++ dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); ++ sunxi_mmc_send_manual_stop(host, mrq); ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ host->manual_stop_mrq = NULL; ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ mmc_request_done(host->mmc, mrq); ++ ++ return IRQ_HANDLED; ++} ++ ++static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) ++{ ++ unsigned long expire = jiffies + msecs_to_jiffies(250); ++ u32 rval; ++ ++ rval = mmc_readl(host, REG_CLKCR); ++ rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON); ++ ++ if (oclk_en) ++ rval |= SDXC_CARD_CLOCK_ON; ++ ++ mmc_writel(host, REG_CLKCR, rval); ++ ++ rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER; ++ mmc_writel(host, REG_CMDR, rval); ++ ++ do { ++ rval = mmc_readl(host, REG_CMDR); ++ } while (time_before(jiffies, expire) && (rval & SDXC_START)); ++ ++ /* clear irq status bits set by the command */ ++ mmc_writel(host, REG_RINTR, ++ mmc_readl(host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT); ++ ++ if (rval & SDXC_START) { ++ dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, ++ struct mmc_ios *ios) ++{ ++ u32 rate, oclk_dly, rval, sclk_dly, src_clk; ++ int ret; ++ ++ rate = clk_round_rate(host->clk_mmc, ios->clock); ++ dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %d\n", ++ ios->clock, rate); ++ ++ /* setting clock rate */ ++ ret = clk_set_rate(host->clk_mmc, rate); ++ if (ret) { ++ dev_err(mmc_dev(host->mmc), "error setting clk to %d: %d\n", ++ rate, ret); ++ return ret; ++ } ++ ++ ret = sunxi_mmc_oclk_onoff(host, 0); ++ if (ret) ++ return ret; ++ ++ /* clear internal divider */ ++ rval = mmc_readl(host, REG_CLKCR); ++ rval &= ~0xff; ++ mmc_writel(host, REG_CLKCR, rval); ++ ++ /* determine delays */ ++ if (rate <= 400000) { ++ oclk_dly = 0; ++ sclk_dly = 7; ++ } else if (rate <= 25000000) { ++ oclk_dly = 0; ++ sclk_dly = 5; ++ } else if (rate <= 50000000) { ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ oclk_dly = 2; ++ sclk_dly = 4; ++ } else { ++ oclk_dly = 3; ++ sclk_dly = 5; ++ } ++ } else { ++ /* rate > 50000000 */ ++ oclk_dly = 2; ++ sclk_dly = 4; ++ } ++ ++ src_clk = clk_get_rate(clk_get_parent(host->clk_mmc)); ++ if (src_clk >= 300000000 && src_clk <= 400000000) { ++ if (oclk_dly) ++ oclk_dly--; ++ if (sclk_dly) ++ sclk_dly--; ++ } ++ ++ clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); ++ ++ return sunxi_mmc_oclk_onoff(host, 1); ++} ++ ++static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ u32 rval; ++ ++ /* Set the power state */ ++ switch (ios->power_mode) { ++ case MMC_POWER_ON: ++ break; ++ ++ case MMC_POWER_UP: ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); ++ ++ host->ferror = sunxi_mmc_init_host(mmc); ++ if (host->ferror) ++ return; ++ ++ dev_dbg(mmc_dev(mmc), "power on!\n"); ++ break; ++ ++ case MMC_POWER_OFF: ++ dev_dbg(mmc_dev(mmc), "power off!\n"); ++ sunxi_mmc_reset_host(host); ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ break; ++ } ++ ++ /* set bus width */ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_1: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH1); ++ break; ++ case MMC_BUS_WIDTH_4: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH4); ++ break; ++ case MMC_BUS_WIDTH_8: ++ mmc_writel(host, REG_WIDTH, SDXC_WIDTH8); ++ break; ++ } ++ ++ /* set ddr mode */ ++ rval = mmc_readl(host, REG_GCTRL); ++ if (ios->timing == MMC_TIMING_UHS_DDR50) ++ rval |= SDXC_DDR_MODE; ++ else ++ rval &= ~SDXC_DDR_MODE; ++ mmc_writel(host, REG_GCTRL, rval); ++ ++ /* set up clock */ ++ if (ios->clock && ios->power_mode) { ++ host->ferror = sunxi_mmc_clk_set_rate(host, ios); ++ /* Android code had a usleep_range(50000, 55000); here */ ++ } ++} ++ ++static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ unsigned long flags; ++ u32 imask; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ imask = mmc_readl(host, REG_IMASK); ++ if (enable) { ++ host->sdio_imask = SDXC_SDIO_INTERRUPT; ++ imask |= SDXC_SDIO_INTERRUPT; ++ } else { ++ host->sdio_imask = 0; ++ imask &= ~SDXC_SDIO_INTERRUPT; ++ } ++ mmc_writel(host, REG_IMASK, imask); ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++static void sunxi_mmc_hw_reset(struct mmc_host *mmc) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ mmc_writel(host, REG_HWRST, 0); ++ udelay(10); ++ mmc_writel(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); ++ int ret; ++ ++ /* Check for set_ios errors (should never happen) */ ++ if (host->ferror) { ++ mrq->cmd->error = host->ferror; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ if (data) { ++ ret = sunxi_mmc_map_dma(host, data); ++ if (ret < 0) { ++ dev_err(mmc_dev(mmc), "map DMA failed\n"); ++ cmd->error = ret; ++ data->error = ret; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ } ++ ++ if (cmd->opcode == MMC_GO_IDLE_STATE) { ++ cmd_val |= SDXC_SEND_INIT_SEQUENCE; ++ imask |= SDXC_COMMAND_DONE; ++ } ++ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ cmd_val |= SDXC_RESP_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 = true; ++ } else { ++ imask |= SDXC_COMMAND_DONE; ++ } ++ } else { ++ imask |= SDXC_COMMAND_DONE; ++ } ++ ++ dev_dbg(mmc_dev(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); ++ ++ if (host->mrq || host->manual_stop_mrq) { ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ if (data) ++ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ ++ dev_err(mmc_dev(mmc), "request already pending\n"); ++ mrq->cmd->error = -EBUSY; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ if (data) { ++ mmc_writel(host, REG_BLKSZ, data->blksz); ++ mmc_writel(host, REG_BCNTR, data->blksz * data->blocks); ++ sunxi_mmc_start_dma(host, data); ++ } ++ ++ host->mrq = mrq; ++ mmc_writel(host, REG_IMASK, host->sdio_imask | imask); ++ mmc_writel(host, REG_CARG, cmd->arg); ++ mmc_writel(host, REG_CMDR, cmd_val); ++ ++ spin_unlock_irqrestore(&host->lock, iflags); ++} ++ ++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; ++ ++ ret = mmc_regulator_get_supply(host->mmc); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "Could not get vmmc supply\n"); ++ return ret; ++ } ++ ++ 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_mmc = devm_clk_get(&pdev->dev, "mmc"); ++ if (IS_ERR(host->clk_mmc)) { ++ dev_err(&pdev->dev, "Could not get mmc clock\n"); ++ return PTR_ERR(host->clk_mmc); ++ } ++ ++ host->reset = devm_reset_control_get(&pdev->dev, "ahb"); ++ ++ ret = clk_prepare_enable(host->clk_ahb); ++ if (ret) { ++ dev_err(&pdev->dev, "Enable ahb clk err %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(host->clk_mmc); ++ if (ret) { ++ dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret); ++ goto error_disable_clk_ahb; ++ } ++ ++ if (!IS_ERR(host->reset)) { ++ ret = reset_control_deassert(host->reset); ++ if (ret) { ++ dev_err(&pdev->dev, "reset err %d\n", ret); ++ goto error_disable_clk_mmc; ++ } ++ } ++ ++ /* ++ * Sometimes the controller asserts the irq on boot for some reason, ++ * make sure the controller is in a sane state before enabling irqs. ++ */ ++ ret = sunxi_mmc_reset_host(host); ++ if (ret) ++ goto error_assert_reset; ++ ++ host->irq = platform_get_irq(pdev, 0); ++ return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq, ++ sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host); ++ ++error_assert_reset: ++ if (!IS_ERR(host->reset)) ++ reset_control_assert(host->reset); ++error_disable_clk_mmc: ++ clk_disable_unprepare(host->clk_mmc); ++error_disable_clk_ahb: ++ clk_disable_unprepare(host->clk_ahb); ++ 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; ++ } ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ spin_lock_init(&host->lock); ++ ++ 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; ++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto error_free_dma; ++ ++ 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); ++ disable_irq(host->irq); ++ sunxi_mmc_reset_host(host); ++ ++ if (!IS_ERR(host->reset)) ++ reset_control_assert(host->reset); ++ ++ clk_disable_unprepare(host->clk_mmc); ++ clk_disable_unprepare(host->clk_ahb); ++ ++ 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 "); ++MODULE_ALIAS("platform:sunxi-mmc"); diff --git a/debian/patches/series b/debian/patches/series index 22d532ab8..46319efcf 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -69,3 +69,28 @@ bugfix/all/0002-Staging-speakup-Update-__speakup_paste_selection-tty.patch features/all/x86-memtest-WARN-if-bad-RAM-found.patch features/all/efi-autoload-efivars.patch features/all/mvsas-Recognise-device-subsystem-9485-9485-as-88SE94.patch + +features/arm/clk-sunxi-factors-automatic-reparenting-support.patch +features/arm/clk-sunxi-Implement-MMC-phase-control.patch +features/arm/clk-sunxi-Fixup-clk_sunxi_mmc_phase_control-to-take-.patch +features/arm/mmc-sunxi-Add-driver-for-SD-MMC-hosts-found-on-Allwi.patch +features/arm/ARM-dts-sun5i-Add-pin-muxing-info-for-the-mmc-contro.patch +features/arm/ARM-dts-sun6i-Add-pin-muxing-info-for-the-mmc-contro.patch +features/arm/ARM-dts-sun4i-Add-mmc-controller-nodes.patch +features/arm/ARM-dts-sun4i-Add-pin-muxing-info-for-the-mmc0-contr.patch +features/arm/ARM-dts-sun4i-Enable-mmc-controller-on-various-A10-b.patch +features/arm/ARM-dts-sun5i-Add-mmc-controller-nodes.patch +features/arm/ARM-dts-sun5i-Enable-mmc-controller-on-various-A10s-.patch +features/arm/ARM-dts-sun6i-Add-mmc-clocks.patch +features/arm/ARM-dts-sun6i-Add-mmc-controller-nodes.patch +features/arm/ARM-dts-sun6i-Add-new-sun6i-a31-m9-dts-file-for-Mele.patch +features/arm/ARM-dts-sun7i-Add-mmc-controller-nodes.patch +features/arm/ARM-dts-sun7i-Add-pin-muxing-info-for-the-mmc-contro.patch +features/arm/ARM-dts-sun7i-Enable-mmc-controller-on-various-A20-b.patch +features/arm/ARM-dts-sun7i-Add-basic-support-for-the-Cubietruck-W.patch +features/arm/ARM-dts-sunxi-Add-reg_vcc3v3-supply-to-sunxi-common-.patch +features/arm/ARM-dts-sun4i-Add-reg_vcc3v3-to-sun4i-board-mmc-node.patch +features/arm/ARM-dts-sun5i-Add-reg_vcc3v3-to-sun5i-board-mmc-node.patch +features/arm/ARM-dts-sun6i-Add-reg_vcc3v3-to-sun6i-board-mmc-node.patch +features/arm/ARM-dts-sun7i-Add-reg_vcc3v3-to-sun7i-board-mmc-node.patch +features/arm/ARM-dts-sun7i-cubietruck-set-mmc3-bus-width-property.patch