diff options
author | Zoltan Herpai <wigyori@uid0.hu> | 2014-03-06 00:09:30 +0000 |
---|---|---|
committer | Zoltan Herpai <wigyori@uid0.hu> | 2014-03-06 00:09:30 +0000 |
commit | ac4b9dbb3c9b056008e00ee3d02fe3dad65641b7 (patch) | |
tree | ef1ef8907c63a75c4ac441f8c95325a6d5abb9ec /target/linux | |
parent | 2c771cc71f3b6aceda5fe81f44a79b724e0941d0 (diff) | |
download | mtk-20170518-ac4b9dbb3c9b056008e00ee3d02fe3dad65641b7.zip mtk-20170518-ac4b9dbb3c9b056008e00ee3d02fe3dad65641b7.tar.gz mtk-20170518-ac4b9dbb3c9b056008e00ee3d02fe3dad65641b7.tar.bz2 |
sunxi: driver refresh for 3.13 - update gmac / mmc / usb / ahci drivers to follow mainline dev trees - add driver for spi - update clock support - update a31 support - move to new DT compats where appropriate - re-order patchqueue where needed - verified working a20 smp - move most DTSes off files/ - update defconfig
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
SVN-Revision: 39782
Diffstat (limited to 'target/linux')
179 files changed, 14841 insertions, 4719 deletions
diff --git a/target/linux/sunxi/config-3.13 b/target/linux/sunxi/config-3.13 index fc3de01..a7f42fb 100644 --- a/target/linux/sunxi/config-3.13 +++ b/target/linux/sunxi/config-3.13 @@ -1,4 +1,4 @@ -# CONFIG_AHCI_SUNXI is not set +CONFIG_AHCI_SUNXI=y CONFIG_ALIGNMENT_TRAP=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y @@ -47,6 +47,7 @@ CONFIG_AUDIT=y CONFIG_AUDIT_GENERIC=y CONFIG_AUTO_ZRELADDR=y CONFIG_AVERAGE=y +CONFIG_BCH=y CONFIG_BINFMT_MISC=y CONFIG_BLK_CGROUP=y CONFIG_BLK_DEV_SD=y @@ -139,6 +140,7 @@ CONFIG_EXT4_FS=y CONFIG_FRAME_POINTER=y CONFIG_FRAME_WARN=2048 CONFIG_FREEZER=y +CONFIG_FS_MBCACHE=y CONFIG_FS_POSIX_ACL=y CONFIG_GARP=y CONFIG_GENERIC_ACL=y @@ -152,6 +154,7 @@ CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_NET_UTILS=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y CONFIG_GENERIC_PINCONF=y CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_GENERIC_SMP_IDLE_THREAD=y @@ -225,6 +228,7 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_TOUCHSCREEN=y CONFIG_IOSCHED_CFQ=y CONFIG_IPC_NS=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -236,7 +240,6 @@ CONFIG_IRQCHIP=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y -# CONFIG_JFFS2_CMODE_PRIORITY is not set CONFIG_KALLSYMS=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_XZ is not set @@ -260,7 +263,6 @@ CONFIG_MMC_BLOCK=y CONFIG_MMC_SUNXI=y CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MTD is not set CONFIG_MULTI_IRQ_HANDLER=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NAMESPACES=y @@ -284,6 +286,7 @@ CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y CONFIG_OF_NET=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND3=y @@ -294,6 +297,7 @@ CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PERF_EVENTS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PHYLIB=y +CONFIG_PHY_SUN4I_USB=y CONFIG_PID_NS=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_SINGLE is not set @@ -340,7 +344,6 @@ CONFIG_RESOURCE_COUNTERS=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y CONFIG_SATA_AHCI_PLATFORM=y -# CONFIG_SATA_RCAR is not set CONFIG_SCHED_HRTICK=y CONFIG_SCSI=y CONFIG_SECURITYFS=y @@ -360,6 +363,10 @@ CONFIG_SLUB_DEBUG=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_SUN4I=y +# CONFIG_SPI_SUN6I is not set # CONFIG_STAGING is not set # CONFIG_STMMAC_DA is not set # CONFIG_STMMAC_DEBUG_FS is not set @@ -371,6 +378,7 @@ CONFIG_STRICT_DEVMEM=y CONFIG_SUN4I_TIMER=y CONFIG_SUN5I_HSTIMER=y CONFIG_SUNXI_WATCHDOG=y +CONFIG_SWIOTLB=y CONFIG_SWP_EMULATE=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_TASKSTATS=y @@ -381,6 +389,7 @@ CONFIG_TASK_XACCT=y # CONFIG_THUMB2_KERNEL is not set CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_TREE_PREEMPT_RCU=y CONFIG_UEVENT_HELPER_PATH="" CONFIG_UID16=y @@ -390,9 +399,8 @@ CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_COMMON=y CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_STORAGE=y -CONFIG_USB_SUNXI_EHCI=y CONFIG_USB_SUPPORT=y # CONFIG_USER_NS is not set CONFIG_USE_OF=y diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts deleted file mode 100644 index fa5ebbd..0000000 --- a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2012 Stefan Roese - * Stefan Roese <sr@denx.de> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -/dts-v1/; -/include/ "sun4i-a10.dtsi" - -/ { - model = "Olimex A10-Olinuxino LIME"; - compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10"; - - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - mdio@01c0b080 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - sdc0: sdc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&sdc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_olinuxino>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; - status = "okay"; - }; - - sata: ahci@01c18000 { - pwr-supply = <®_ahci_5v>; - status = "okay"; - }; - - pinctrl@01c20800 { - ahci_pwr_pin: ahci_pwr_pin@0 { - allwinner,pins = "PC3"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <0>; - }; - - mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; - allwinner,drive = <0>; - allwinner,pull = <0>; - }; - - led_pins_olinuxino: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; - allwinner,drive = <1>; - allwinner,pull = <0>; - }; - - usb1_vbus_pin: usb1_vbus_pin@0 { - allwinner,pins = "PH6"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <2>; - }; - - usb2_vbus_pin: usb2_vbus_pin@0 { - allwinner,pins = "PH3"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <2>; - }; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - ehci0: ehci0@0x01c14000 { - vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; - - ehci1: ehci1@0x01c1c000 { - vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_olinuxino>; - - green { - label = "a10-olinuxino-lime:green:usr"; - gpios = <&pio 7 2 0>; - default-state = "on"; - }; - }; - - regulators { - compatible = "simple-bus"; - - reg_usb1_vbus: usb1-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; - - reg_usb2_vbus: usb2-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; - }; - - regulators { - compatible = "simple-bus"; - pinctrl-names = "default"; - - reg_ahci_5v: ahci-5v { - compatible = "regulator-fixed"; - regulator-name = "ahci-5v"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - pinctrl-0 = <&ahci_pwr_pin>; - gpio = <&pio 2 3 0>; - enable-active-high; - }; - }; -}; diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts deleted file mode 100644 index 0cc7952..0000000 --- a/target/linux/sunxi/files/arch/arm/boot/dts/sun4i-a10-pcduino.dts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2012 Stefan Roese - * Stefan Roese <sr@denx.de> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -/dts-v1/; -/include/ "sun4i-a10.dtsi" - -/ { - model = "pcDuino"; - compatible = "pcduino,a10-pcduino", "allwinner,sun4i-a10"; - - aliases { - serial0 = &uart0; - serial1 = &uart1; - }; - - chosen { - bootargs = "earlyprintk console=ttyS0,115200"; - }; - - soc@01c00000 { - emac: ethernet@01c0b000 { - pinctrl-names = "default"; - pinctrl-0 = <&emac_pins_a>; - phy = <&phy1>; - status = "okay"; - }; - - mdio@01c0b080 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - sdc0: sdc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&sdc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_pcduino>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; - status = "okay"; - }; - - pinctrl@01c20800 { - mmc0_cd_pin_pcduino: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; - allwinner,drive = <0>; - allwinner,pull = <0>; - }; - - led_pins_pcduino: led_pins@0 { - allwinner,pins = "PH20", "PH21"; - allwinner,function = "gpio_out"; - allwinner,drive = <1>; - allwinner,pull = <0>; - }; - - usb1_vbus_pin: usb1_vbus_pin@0 { - allwinner,pins = "PH6"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <2>; - }; - - usb2_vbus_pin: usb2_vbus_pin@0 { - allwinner,pins = "PH3"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <2>; - }; - }; - - uart0: serial@01c28000 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; - - i2c0: i2c@01c2ac00 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; - - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; - - ehci0: ehci0@0x01c14000 { - vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; - - ehci1: ehci1@0x01c1c000 { - vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_pcduino>; - - blue { - label = "pcduino:blue:usr"; - gpios = <&pio 7 21 0>; /* LED1 */ - }; - - green { - label = "pcduino:green:usr"; - gpios = <&pio 7 20 0>; /* LED2 */ - linux,default-trigger = "heartbeat"; - }; - }; - - regulators { - compatible = "simple-bus"; - - reg_usb1_vbus: usb1-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; - - reg_usb2_vbus: usb2-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; - }; - - regulators { - compatible = "simple-bus"; - pinctrl-names = "default"; - - vcc_3v3_reg: regulator@0 { - compatible = "regulator-fixed"; - regulator-name = "vcc_3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - }; -}; diff --git a/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts index 4ef28fd..8b14779 100644 --- a/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +++ b/target/linux/sunxi/files/arch/arm/boot/dts/sun7i-a20-cubietruck.dts @@ -19,45 +19,7 @@ compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; soc@01c00000 { - sdc0: sdc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&sdc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_cubietruck>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; - status = "okay"; - }; - - ehci0: ehci0@0x01c14000 { - vbus-supply = <®_usb1_vbus>; - status = "okay"; - }; - - sata: ahci@01c18000 { - pwr-supply = <®_ahci_5v>; - status = "okay"; - }; - - ehci1: ehci1@0x01c1c000 { - vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - pinctrl@01c20800 { - mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; - allwinner,drive = <0>; - allwinner,pull = <0>; - }; - - ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 { - allwinner,pins = "PH12"; - allwinner,function = "gpio_out"; - allwinner,drive = <0>; - allwinner,pull = <0>; - }; - led_pins_cubietruck: led_pins@0 { allwinner,pins = "PH7", "PH11", "PH20", "PH21"; allwinner,function = "gpio_out"; @@ -112,41 +74,4 @@ gpios = <&pio 7 7 0>; }; }; - - regulators { - compatible = "simple-bus"; - pinctrl-names = "default"; - - reg_ahci_5v: ahci-5v { - compatible = "regulator-fixed"; - regulator-name = "ahci-5v"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - pinctrl-0 = <&ahci_pwr_pin_cubietruck>; - gpio = <&pio 7 12 0>; - enable-active-high; - }; - - reg_usb1_vbus: usb1-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; - - reg_usb2_vbus: usb2-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; - }; }; diff --git a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c b/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c deleted file mode 100644 index e091ebb..0000000 --- a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Driver for sunxi SD/MMC host controllers - * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. - * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com> - * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> - * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch> - * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/err.h> - -#include <linux/clk.h> -#include <linux/clk-private.h> -#include <linux/clk/sunxi.h> - -#include <linux/gpio.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -#include <linux/regulator/consumer.h> - -#include <linux/of_address.h> -#include <linux/of_gpio.h> -#include <linux/of_platform.h> - -#include <linux/mmc/host.h> -#include <linux/mmc/sd.h> -#include <linux/mmc/mmc.h> -#include <linux/mmc/core.h> -#include <linux/mmc/card.h> - -#include "sunxi-mci.h" - -static void sunxi_mmc_init_host(struct mmc_host *mmc) -{ - u32 rval; - struct sunxi_mmc_host *smc_host = mmc_priv(mmc); - - /* reset controller */ - rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset; - mci_writel(smc_host, REG_GCTRL, rval); - - mci_writel(smc_host, REG_FTRGL, 0x20070008); - mci_writel(smc_host, REG_TMOUT, 0xffffffff); - mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask); - mci_writel(smc_host, REG_RINTR, 0xffffffff); - mci_writel(smc_host, REG_DBGC, 0xdeb); - mci_writel(smc_host, REG_FUNS, 0xceaa0000); - mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); - rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb; - rval &= ~SDXC_AccessDoneDirect; - mci_writel(smc_host, REG_GCTRL, rval); -} - -static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host) -{ - mci_writel(smc_host, REG_GCTRL, SDXC_HWReset); -} - -/* /\* UHS-I Operation Modes */ -/* * DS 25MHz 12.5MB/s 3.3V */ -/* * HS 50MHz 25MB/s 3.3V */ -/* * SDR12 25MHz 12.5MB/s 1.8V */ -/* * SDR25 50MHz 25MB/s 1.8V */ -/* * SDR50 100MHz 50MB/s 1.8V */ -/* * SDR104 208MHz 104MB/s 1.8V */ -/* * DDR50 50MHz 50MB/s 1.8V */ -/* * MMC Operation Modes */ -/* * DS 26MHz 26MB/s 3/1.8/1.2V */ -/* * HS 52MHz 52MB/s 3/1.8/1.2V */ -/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */ -/* * HS200 200MHz 200MB/s 1.8/1.2V */ -/* * */ -/* * Spec. Timing */ -/* * SD3.0 */ -/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */ -/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */ -/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */ -/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */ -/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */ -/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */ -/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ - -/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */ -/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */ -/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */ -/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */ -/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */ - -/* * eMMC4.5 */ -/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */ -/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ -/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ -/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */ -/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ -/* *\/ */ - -static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, - struct mmc_data *data) -{ - struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; - struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; - int i, max_len = (1 << host->idma_des_size_bits); - - for (i = 0; i < data->sg_len; i++) { - pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | - SDXC_IDMAC_DES0_DIC; - - if (data->sg[i].length == max_len) - pdes[i].buf_size = 0; /* 0 == max_len */ - else - pdes[i].buf_size = data->sg[i].length; - - pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); - pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; - } - pdes[0].config |= SDXC_IDMAC_DES0_FD; - pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; - - wmb(); /* Ensure idma_des hit main mem before we start the idmac */ -} - -static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data) -{ - if (data->flags & MMC_DATA_WRITE) - return DMA_TO_DEVICE; - else - return DMA_FROM_DEVICE; -} - -static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host, - struct mmc_data *data) -{ - u32 dma_len; - u32 i; - u32 temp; - struct scatterlist *sg; - - dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len, - sunxi_mmc_get_dma_dir(data)); - if (dma_len == 0) { - dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n"); - return -ENOMEM; - } - - for_each_sg(data->sg, sg, data->sg_len, i) { - if (sg->offset & 3 || sg->length & 3) { - dev_err(mmc_dev(smc_host->mmc), - "unaligned scatterlist: os %x length %d\n", - sg->offset, sg->length); - return -EINVAL; - } - } - - sunxi_mmc_init_idma_des(smc_host, data); - - temp = mci_readl(smc_host, REG_GCTRL); - temp |= SDXC_DMAEnb; - mci_writel(smc_host, REG_GCTRL, temp); - temp |= SDXC_DMAReset; - mci_writel(smc_host, REG_GCTRL, temp); - - mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST); - - if (!(data->flags & MMC_DATA_WRITE)) - mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt); - - mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn); - - return 0; -} - -static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, - struct mmc_request *req) -{ - u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD - | SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION; - u32 ri = 0; - unsigned long expire = jiffies + msecs_to_jiffies(1000); - - mci_writel(host, REG_CARG, 0); - mci_writel(host, REG_CMDR, cmd_val); - do { - ri = mci_readl(host, REG_RINTR); - } while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) && - time_before(jiffies, expire)); - - if (ri & SDXC_IntErrBit) { - dev_err(mmc_dev(host->mmc), "send stop command failed\n"); - if (req->stop) - req->stop->resp[0] = -ETIMEDOUT; - } else { - if (req->stop) - req->stop->resp[0] = mci_readl(host, REG_RESP0); - } - - mci_writel(host, REG_RINTR, 0xffff); -} - -static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host) -{ - struct mmc_command *cmd = smc_host->mrq->cmd; - struct mmc_data *data = smc_host->mrq->data; - - /* For some cmds timeout is normal with sd/mmc cards */ - if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout && - (cmd->opcode == 5 || cmd->opcode == 52)) - return; - - dev_err(mmc_dev(smc_host->mmc), - "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", - smc_host->mmc->index, cmd->opcode, - data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", - smc_host->int_sum & SDXC_RespErr ? " RE" : "", - smc_host->int_sum & SDXC_RespCRCErr ? " RCE" : "", - smc_host->int_sum & SDXC_DataCRCErr ? " DCE" : "", - smc_host->int_sum & SDXC_RespTimeout ? " RTO" : "", - smc_host->int_sum & SDXC_DataTimeout ? " DTO" : "", - smc_host->int_sum & SDXC_FIFORunErr ? " FE" : "", - smc_host->int_sum & SDXC_HardWLocked ? " HL" : "", - smc_host->int_sum & SDXC_StartBitErr ? " SBE" : "", - smc_host->int_sum & SDXC_EndBitErr ? " EBE" : "" - ); -} - -static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) -{ - struct mmc_request *mrq; - unsigned long iflags; - - spin_lock_irqsave(&host->lock, iflags); - - mrq = host->mrq; - if (!mrq) { - spin_unlock_irqrestore(&host->lock, iflags); - dev_err(mmc_dev(host->mmc), "no request to finalize\n"); - return; - } - - if (host->int_sum & SDXC_IntErrBit) { - sunxi_mmc_dump_errinfo(host); - mrq->cmd->error = -ETIMEDOUT; - if (mrq->data) - mrq->data->error = -ETIMEDOUT; - if (mrq->stop) - mrq->stop->error = -ETIMEDOUT; - } else { - if (mrq->cmd->flags & MMC_RSP_136) { - mrq->cmd->resp[0] = mci_readl(host, REG_RESP3); - mrq->cmd->resp[1] = mci_readl(host, REG_RESP2); - mrq->cmd->resp[2] = mci_readl(host, REG_RESP1); - mrq->cmd->resp[3] = mci_readl(host, REG_RESP0); - } else { - mrq->cmd->resp[0] = mci_readl(host, REG_RESP0); - } - if (mrq->data) - mrq->data->bytes_xfered = - mrq->data->blocks * mrq->data->blksz; - } - - if (mrq->data) { - struct mmc_data *data = mrq->data; - u32 temp; - - mci_writel(host, REG_IDST, 0x337); - mci_writel(host, REG_DMAC, 0); - temp = mci_readl(host, REG_GCTRL); - mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset); - temp &= ~SDXC_DMAEnb; - mci_writel(host, REG_GCTRL, temp); - temp |= SDXC_FIFOReset; - mci_writel(host, REG_GCTRL, temp); - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - sunxi_mmc_get_dma_dir(data)); - } - - mci_writel(host, REG_RINTR, 0xffff); - - dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n", - mrq->cmd->resp[0], mrq->cmd->resp[1], - mrq->cmd->resp[2], mrq->cmd->resp[3]); - - host->mrq = NULL; - host->int_sum = 0; - host->wait_dma = 0; - - spin_unlock_irqrestore(&host->lock, iflags); - - if (mrq->data && mrq->data->error) { - dev_err(mmc_dev(host->mmc), - "data error, sending stop command\n"); - sunxi_mmc_send_manual_stop(host, mrq); - } - - mmc_request_done(host->mmc, mrq); -} - -static s32 sunxi_mmc_get_ro(struct mmc_host *mmc) -{ - struct sunxi_mmc_host *host = mmc_priv(mmc); - - int read_only = 0; - - if (gpio_is_valid(host->wp_pin)) { - pinctrl_request_gpio(host->wp_pin); - read_only = gpio_get_value(host->wp_pin); - } - - return read_only; -} - -static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) -{ - struct sunxi_mmc_host *host = dev_id; - u32 finalize = 0; - u32 sdio_int = 0; - u32 msk_int; - u32 idma_int; - - spin_lock(&host->lock); - - idma_int = mci_readl(host, REG_IDST); - msk_int = mci_readl(host, REG_MISTA); - - dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", - host->mrq, msk_int, idma_int); - - if (host->mrq) { - if (idma_int & SDXC_IDMACReceiveInt) - host->wait_dma = 0; - - host->int_sum |= msk_int; - - /* Wait for CmdDone on RespTimeout before finishing the req */ - if ((host->int_sum & SDXC_RespTimeout) && - !(host->int_sum & SDXC_CmdDone)) - mci_writel(host, REG_IMASK, - host->sdio_imask | SDXC_CmdDone); - else if (host->int_sum & SDXC_IntErrBit) - finalize = 1; /* Don't wait for dma on error */ - else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma) - finalize = 1; /* Done */ - - if (finalize) { - mci_writel(host, REG_IMASK, host->sdio_imask); - mci_writel(host, REG_IDIE, 0); - } - } - - if (msk_int & SDXC_SDIOInt) - sdio_int = 1; - - mci_writel(host, REG_RINTR, msk_int); - mci_writel(host, REG_IDST, idma_int); - - spin_unlock(&host->lock); - - if (finalize) - tasklet_schedule(&host->tasklet); - - if (sdio_int) - mmc_signal_sdio_irq(host->mmc); - - return IRQ_HANDLED; -} - -static void sunxi_mmc_tasklet(unsigned long data) -{ - struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data; - sunxi_mmc_finalize_request(smc_host); -} - -static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) -{ - unsigned long expire = jiffies + msecs_to_jiffies(2000); - u32 rval; - - rval = mci_readl(host, REG_CLKCR); - rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn); - if (oclk_en) - rval |= SDXC_CardClkOn; - if (!host->io_flag) - rval |= SDXC_LowPowerOn; - mci_writel(host, REG_CLKCR, rval); - - rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver; - if (host->voltage_switching) - rval |= SDXC_VolSwitch; - mci_writel(host, REG_CMDR, rval); - do { - rval = mci_readl(host, REG_CMDR); - } while (time_before(jiffies, expire) && (rval & SDXC_Start)); - - if (rval & SDXC_Start) { - dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); - host->ferror = 1; - } -} - -static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host, - u32 oclk_dly, u32 sclk_dly) -{ - unsigned long iflags; - struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); - - spin_lock_irqsave(&smc_host->lock, iflags); - clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); - spin_unlock_irqrestore(&smc_host->lock, iflags); -} - -struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = { - { MMC_CLK_400K, 0, 7 }, - { MMC_CLK_25M, 0, 5 }, - { MMC_CLK_50M, 3, 5 }, - { MMC_CLK_50MDDR, 2, 4 }, - { MMC_CLK_50MDDR_8BIT, 2, 4 }, - { MMC_CLK_100M, 1, 4 }, - { MMC_CLK_200M, 1, 4 }, -}; - -static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, - unsigned int rate) -{ - u32 newrate; - u32 src_clk; - u32 oclk_dly; - u32 sclk_dly; - u32 temp; - struct sunxi_mmc_clk_dly *dly = NULL; - - newrate = clk_round_rate(smc_host->clk_mod, rate); - if (smc_host->clk_mod_rate == newrate) { - dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n", - rate, newrate); - return; - } - - dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n", - rate, newrate); - - /* setting clock rate */ - clk_disable(smc_host->clk_mod); - clk_set_rate(smc_host->clk_mod, newrate); - clk_enable(smc_host->clk_mod); - smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod); - dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate); - - sunxi_mmc_oclk_onoff(smc_host, 0); - /* clear internal divider */ - temp = mci_readl(smc_host, REG_CLKCR); - temp &= ~0xff; - mci_writel(smc_host, REG_CLKCR, temp); - - /* determine delays */ - if (rate <= 400000) { - dly = &mmc_clk_dly[MMC_CLK_400K]; - } else if (rate <= 25000000) { - dly = &mmc_clk_dly[MMC_CLK_25M]; - } else if (rate <= 50000000) { - if (smc_host->ddr) { - if (smc_host->bus_width == 8) - dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT]; - else - dly = &mmc_clk_dly[MMC_CLK_50MDDR]; - } else { - dly = &mmc_clk_dly[MMC_CLK_50M]; - } - } else if (rate <= 104000000) { - dly = &mmc_clk_dly[MMC_CLK_100M]; - } else if (rate <= 208000000) { - dly = &mmc_clk_dly[MMC_CLK_200M]; - } else - dly = &mmc_clk_dly[MMC_CLK_50M]; - - oclk_dly = dly->oclk_dly; - sclk_dly = dly->sclk_dly; - - src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod)); - if (src_clk >= 300000000 && src_clk <= 400000000) { - if (oclk_dly) - oclk_dly--; - if (sclk_dly) - sclk_dly--; - } - - sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly); - sunxi_mmc_oclk_onoff(smc_host, 1); - - /* oclk_onoff sets various irq status bits, clear these */ - mci_writel(smc_host, REG_RINTR, - mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt); -} - -static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct sunxi_mmc_host *host = mmc_priv(mmc); - u32 temp; - s32 err; - - /* Set the power state */ - switch (ios->power_mode) { - case MMC_POWER_ON: - break; - - case MMC_POWER_UP: - if (!IS_ERR(host->vmmc)) { - mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd); - udelay(200); - } - - err = clk_prepare_enable(host->clk_ahb); - if (err) { - dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err); - host->ferror = 1; - return; - } - err = clk_prepare_enable(host->clk_mod); - if (err) { - dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err); - host->ferror = 1; - return; - } - - sunxi_mmc_init_host(mmc); - enable_irq(host->irq); - - dev_dbg(mmc_dev(host->mmc), "power on!\n"); - host->ferror = 0; - break; - - case MMC_POWER_OFF: - dev_dbg(mmc_dev(host->mmc), "power off!\n"); - disable_irq(host->irq); - sunxi_mmc_exit_host(host); - clk_disable_unprepare(host->clk_ahb); - clk_disable_unprepare(host->clk_mod); - if (!IS_ERR(host->vmmc)) - mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); - host->ferror = 0; - break; - } - - /* set bus width */ - switch (ios->bus_width) { - case MMC_BUS_WIDTH_1: - mci_writel(host, REG_WIDTH, SDXC_WIDTH1); - host->bus_width = 1; - break; - case MMC_BUS_WIDTH_4: - mci_writel(host, REG_WIDTH, SDXC_WIDTH4); - host->bus_width = 4; - break; - case MMC_BUS_WIDTH_8: - mci_writel(host, REG_WIDTH, SDXC_WIDTH8); - host->bus_width = 8; - break; - } - - /* set ddr mode */ - temp = mci_readl(host, REG_GCTRL); - if (ios->timing == MMC_TIMING_UHS_DDR50) { - temp |= SDXC_DDR_MODE; - host->ddr = 1; - } else { - temp &= ~SDXC_DDR_MODE; - host->ddr = 0; - } - mci_writel(host, REG_GCTRL, temp); - - /* set up clock */ - if (ios->clock && ios->power_mode) { - dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock); - sunxi_mmc_clk_set_rate(host, ios->clock); - usleep_range(50000, 55000); - } -} - -static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) -{ - struct sunxi_mmc_host *smc_host = mmc_priv(mmc); - unsigned long flags; - u32 imask; - - spin_lock_irqsave(&smc_host->lock, flags); - imask = mci_readl(smc_host, REG_IMASK); - if (enable) { - smc_host->sdio_imask = SDXC_SDIOInt; - imask |= SDXC_SDIOInt; - } else { - smc_host->sdio_imask = 0; - imask &= ~SDXC_SDIOInt; - } - mci_writel(smc_host, REG_IMASK, imask); - spin_unlock_irqrestore(&smc_host->lock, flags); -} - -static void sunxi_mmc_hw_reset(struct mmc_host *mmc) -{ - struct sunxi_mmc_host *smc_host = mmc_priv(mmc); - mci_writel(smc_host, REG_HWRST, 0); - udelay(10); - mci_writel(smc_host, REG_HWRST, 1); - udelay(300); -} - -static int sunxi_mmc_card_present(struct mmc_host *mmc) -{ - struct sunxi_mmc_host *host = mmc_priv(mmc); - - switch (host->cd_mode) { - case CARD_DETECT_BY_GPIO_POLL: - return !gpio_get_value(host->cd_pin); /* Signal inverted */ - case CARD_ALWAYS_PRESENT: - return 1; - } - return 0; /* Never reached */ -} - -static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct sunxi_mmc_host *host = mmc_priv(mmc); - struct mmc_command *cmd = mrq->cmd; - struct mmc_data *data = mrq->data; - unsigned long iflags; - u32 imask = SDXC_IntErrBit; - u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f); - u32 byte_cnt = 0; - int ret; - - if (!sunxi_mmc_card_present(mmc) || host->ferror) { - dev_dbg(mmc_dev(host->mmc), "no medium present\n"); - mrq->cmd->error = -ENOMEDIUM; - mmc_request_done(mmc, mrq); - return; - } - - if (data) { - byte_cnt = data->blksz * data->blocks; - mci_writel(host, REG_BLKSZ, data->blksz); - mci_writel(host, REG_BCNTR, byte_cnt); - ret = sunxi_mmc_prepare_dma(host, data); - if (ret < 0) { - dev_err(mmc_dev(host->mmc), "prepare DMA failed\n"); - cmd->error = ret; - cmd->data->error = ret; - mmc_request_done(host->mmc, mrq); - return; - } - } - - if (cmd->opcode == MMC_GO_IDLE_STATE) { - cmd_val |= SDXC_SendInitSeq; - imask |= SDXC_CmdDone; - } - - if (cmd->opcode == SD_SWITCH_VOLTAGE) { - cmd_val |= SDXC_VolSwitch; - imask |= SDXC_VolChgDone; - host->voltage_switching = 1; - sunxi_mmc_oclk_onoff(host, 1); - } - - if (cmd->flags & MMC_RSP_PRESENT) { - cmd_val |= SDXC_RspExp; - if (cmd->flags & MMC_RSP_136) - cmd_val |= SDXC_LongRsp; - if (cmd->flags & MMC_RSP_CRC) - cmd_val |= SDXC_CheckRspCRC; - - if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { - cmd_val |= SDXC_DataExp | SDXC_WaitPreOver; - if (cmd->data->flags & MMC_DATA_STREAM) { - imask |= SDXC_AutoCMDDone; - cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop; - } - if (cmd->data->stop) { - imask |= SDXC_AutoCMDDone; - cmd_val |= SDXC_SendAutoStop; - } else - imask |= SDXC_DataOver; - - if (cmd->data->flags & MMC_DATA_WRITE) - cmd_val |= SDXC_Write; - else - host->wait_dma = 1; - } else - imask |= SDXC_CmdDone; - } else - imask |= SDXC_CmdDone; - - dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", - cmd_val & 0x3f, cmd_val, cmd->arg, imask, - mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); - - spin_lock_irqsave(&host->lock, iflags); - host->mrq = mrq; - mci_writel(host, REG_IMASK, host->sdio_imask | imask); - spin_unlock_irqrestore(&host->lock, iflags); - - mci_writel(host, REG_CARG, cmd->arg); - mci_writel(host, REG_CMDR, cmd_val); -} - -static const struct of_device_id sunxi_mmc_of_match[] = { - { .compatible = "allwinner,sun4i-mmc", }, - { .compatible = "allwinner,sun5i-mmc", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); - -static struct mmc_host_ops sunxi_mmc_ops = { - .request = sunxi_mmc_request, - .set_ios = sunxi_mmc_set_ios, - .get_ro = sunxi_mmc_get_ro, - .get_cd = sunxi_mmc_card_present, - .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, - .hw_reset = sunxi_mmc_hw_reset, -}; - -static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, - struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int ret; - - if (of_device_is_compatible(np, "allwinner,sun4i-mmc")) - host->idma_des_size_bits = 13; - else - host->idma_des_size_bits = 16; - - host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc"); - if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - host->reg_base = devm_ioremap_resource(&pdev->dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); - if (IS_ERR(host->reg_base)) - return PTR_ERR(host->reg_base); - - host->irq = platform_get_irq(pdev, 0); - ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0, - "sunxi-mci", host); - if (ret) - return ret; - disable_irq(host->irq); - - host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(host->clk_ahb)) { - dev_err(&pdev->dev, "Could not get ahb clock\n"); - return PTR_ERR(host->clk_ahb); - } - - host->clk_mod = devm_clk_get(&pdev->dev, "mod"); - if (IS_ERR(host->clk_mod)) { - dev_err(&pdev->dev, "Could not get mod clock\n"); - return PTR_ERR(host->clk_mod); - } - - of_property_read_u32(np, "bus-width", &host->bus_width); - if (host->bus_width != 1 && host->bus_width != 4) { - dev_err(&pdev->dev, "Invalid bus-width %d\n", host->bus_width); - return -EINVAL; - } - - of_property_read_u32(np, "cd-mode", &host->cd_mode); - switch (host->cd_mode) { - case CARD_DETECT_BY_GPIO_POLL: - host->cd_pin = of_get_named_gpio(np, "cd-gpios", 0); - if (!gpio_is_valid(host->cd_pin)) { - dev_err(&pdev->dev, "Invalid cd-gpios\n"); - return -EINVAL; - } - ret = devm_gpio_request(&pdev->dev, host->cd_pin, "mmc_cd"); - if (ret) { - dev_err(&pdev->dev, "Could not get cd-gpios\n"); - return ret; - } - gpio_direction_input(host->cd_pin); - break; - case CARD_ALWAYS_PRESENT: - break; - default: - dev_err(&pdev->dev, "Invalid cd-mode %d\n", host->cd_mode); - return -EINVAL; - } - - host->wp_pin = of_get_named_gpio(np, "wp-gpios", 0); - if (gpio_is_valid(host->wp_pin)) { - ret = devm_gpio_request(&pdev->dev, host->wp_pin, "mmc_wp"); - if (ret) { - dev_err(&pdev->dev, "Could not get wp-gpios\n"); - return ret; - } - gpio_direction_input(host->wp_pin); - } - - return 0; -} - -static int sunxi_mmc_probe(struct platform_device *pdev) -{ - struct sunxi_mmc_host *host; - struct mmc_host *mmc; - int ret; - - mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); - if (!mmc) { - dev_err(&pdev->dev, "mmc alloc host failed\n"); - return -ENOMEM; - } - - host = mmc_priv(mmc); - host->mmc = mmc; - spin_lock_init(&host->lock); - tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host); - - ret = sunxi_mmc_resource_request(host, pdev); - if (ret) - goto error_free_host; - - host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, - &host->sg_dma, GFP_KERNEL); - if (!host->sg_cpu) { - dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); - ret = -ENOMEM; - goto error_free_host; - } - - mmc->ops = &sunxi_mmc_ops; - mmc->max_blk_count = 8192; - mmc->max_blk_size = 4096; - mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); - mmc->max_seg_size = (1 << host->idma_des_size_bits); - mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; - /* 400kHz ~ 50MHz */ - mmc->f_min = 400000; - mmc->f_max = 50000000; - /* available voltages */ - if (!IS_ERR(host->vmmc)) - mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc); - else - mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - - mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | - MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | - MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL | - MMC_CAP_DRIVER_TYPE_A; - if (host->bus_width == 4) - mmc->caps |= MMC_CAP_4_BIT_DATA; - mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; - - ret = mmc_add_host(mmc); - if (ret) - goto error_free_dma; - - dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); - platform_set_drvdata(pdev, mmc); - return 0; - -error_free_dma: - dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); -error_free_host: - mmc_free_host(mmc); - return ret; -} - -static int sunxi_mmc_remove(struct platform_device *pdev) -{ - struct mmc_host *mmc = platform_get_drvdata(pdev); - struct sunxi_mmc_host *host = mmc_priv(mmc); - - mmc_remove_host(mmc); - sunxi_mmc_exit_host(host); - tasklet_disable(&host->tasklet); - dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); - mmc_free_host(mmc); - - return 0; -} - -static struct platform_driver sunxi_mmc_driver = { - .driver = { - .name = "sunxi-mci", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(sunxi_mmc_of_match), - }, - .probe = sunxi_mmc_probe, - .remove = sunxi_mmc_remove, -}; -module_platform_driver(sunxi_mmc_driver); - -MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>"); -MODULE_ALIAS("platform:sunxi-mmc"); diff --git a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h b/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h deleted file mode 100644 index 332d3ae..0000000 --- a/target/linux/sunxi/files/drivers/mmc/host/sunxi-mci.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Driver for sunxi SD/MMC host controllers - * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd. - * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com> - * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch> - * (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch> - * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ - -#ifndef __SUNXI_MCI_H__ -#define __SUNXI_MCI_H__ - -/* register offset define */ -#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ -#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ -#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ -#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ -#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ -#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ -#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ -#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ -#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ -#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ -#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ -#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ -#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ -#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ -#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ -#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ -#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ -#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ -#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ -#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ -#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ -#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ -#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ -#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ -#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ -#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ -#define SDXC_REG_CHDA (0x90) -#define SDXC_REG_CBDA (0x94) - -#define mci_readl(host, reg) \ - __raw_readl((host)->reg_base + SDXC_##reg) -#define mci_writel(host, reg, value) \ - __raw_writel((value), (host)->reg_base + SDXC_##reg) - -/* global control register bits */ -#define SDXC_SoftReset BIT(0) -#define SDXC_FIFOReset BIT(1) -#define SDXC_DMAReset BIT(2) -#define SDXC_HWReset (SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset) -#define SDXC_INTEnb BIT(4) -#define SDXC_DMAEnb BIT(5) -#define SDXC_DebounceEnb BIT(8) -#define SDXC_PosedgeLatchData BIT(9) -#define SDXC_DDR_MODE BIT(10) -#define SDXC_MemAccessDone BIT(29) -#define SDXC_AccessDoneDirect BIT(30) -#define SDXC_ACCESS_BY_AHB BIT(31) -#define SDXC_ACCESS_BY_DMA (0U << 31) -/* clock control bits */ -#define SDXC_CardClkOn BIT(16) -#define SDXC_LowPowerOn BIT(17) -/* bus width */ -#define SDXC_WIDTH1 (0) -#define SDXC_WIDTH4 (1) -#define SDXC_WIDTH8 (2) -/* smc command bits */ -#define SDXC_RspExp BIT(6) -#define SDXC_LongRsp BIT(7) -#define SDXC_CheckRspCRC BIT(8) -#define SDXC_DataExp BIT(9) -#define SDXC_Write BIT(10) -#define SDXC_Seqmod BIT(11) -#define SDXC_SendAutoStop BIT(12) -#define SDXC_WaitPreOver BIT(13) -#define SDXC_StopAbortCMD BIT(14) -#define SDXC_SendInitSeq BIT(15) -#define SDXC_UPCLKOnly BIT(21) -#define SDXC_RdCEATADev BIT(22) -#define SDXC_CCSExp BIT(23) -#define SDXC_EnbBoot BIT(24) -#define SDXC_AltBootOpt BIT(25) -#define SDXC_BootACKExp BIT(26) -#define SDXC_BootAbort BIT(27) -#define SDXC_VolSwitch BIT(28) -#define SDXC_UseHoldReg BIT(29) -#define SDXC_Start BIT(31) -/* interrupt bits */ -#define SDXC_RespErr BIT(1) -#define SDXC_CmdDone BIT(2) -#define SDXC_DataOver BIT(3) -#define SDXC_TxDataReq BIT(4) -#define SDXC_RxDataReq BIT(5) -#define SDXC_RespCRCErr BIT(6) -#define SDXC_DataCRCErr BIT(7) -#define SDXC_RespTimeout BIT(8) -#define SDXC_DataTimeout BIT(9) -#define SDXC_VolChgDone BIT(10) -#define SDXC_FIFORunErr BIT(11) -#define SDXC_HardWLocked BIT(12) -#define SDXC_StartBitErr BIT(13) -#define SDXC_AutoCMDDone BIT(14) -#define SDXC_EndBitErr BIT(15) -#define SDXC_SDIOInt BIT(16) -#define SDXC_CardInsert BIT(30) -#define SDXC_CardRemove BIT(31) -#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | \ - SDXC_DataCRCErr | SDXC_RespTimeout | \ - SDXC_DataTimeout | SDXC_FIFORunErr | \ - SDXC_HardWLocked | SDXC_StartBitErr | \ - SDXC_EndBitErr) /* 0xbbc2 */ -#define SDXC_IntDoneBit (SDXC_AutoCMDDone | SDXC_DataOver | \ - SDXC_CmdDone | SDXC_VolChgDone) -/* status */ -#define SDXC_RXWLFlag BIT(0) -#define SDXC_TXWLFlag BIT(1) -#define SDXC_FIFOEmpty BIT(2) -#define SDXC_FIFOFull BIT(3) -#define SDXC_CardPresent BIT(8) -#define SDXC_CardDataBusy BIT(9) -#define SDXC_DataFSMBusy BIT(10) -#define SDXC_DMAReq BIT(31) -#define SDXC_FIFO_SIZE (16) -/* Function select */ -#define SDXC_CEATAOn (0xceaaU << 16) -#define SDXC_SendIrqRsp BIT(0) -#define SDXC_SDIORdWait BIT(1) -#define SDXC_AbtRdData BIT(2) -#define SDXC_SendCCSD BIT(8) -#define SDXC_SendAutoStopCCSD BIT(9) -#define SDXC_CEATADevIntEnb BIT(10) -/* IDMA controller bus mod bit field */ -#define SDXC_IDMACSoftRST BIT(0) -#define SDXC_IDMACFixBurst BIT(1) -#define SDXC_IDMACIDMAOn BIT(7) -#define SDXC_IDMACRefetchDES BIT(31) -/* IDMA status bit field */ -#define SDXC_IDMACTransmitInt BIT(0) -#define SDXC_IDMACReceiveInt BIT(1) -#define SDXC_IDMACFatalBusErr BIT(2) -#define SDXC_IDMACDesInvalid BIT(4) -#define SDXC_IDMACCardErrSum BIT(5) -#define SDXC_IDMACNormalIntSum BIT(8) -#define SDXC_IDMACAbnormalIntSum BIT(9) -#define SDXC_IDMACHostAbtInTx BIT(10) -#define SDXC_IDMACHostAbtInRx BIT(10) -#define SDXC_IDMACIdle (0U << 13) -#define SDXC_IDMACSuspend (1U << 13) -#define SDXC_IDMACDESCRd (2U << 13) -#define SDXC_IDMACDESCCheck (3U << 13) -#define SDXC_IDMACRdReqWait (4U << 13) -#define SDXC_IDMACWrReqWait (5U << 13) -#define SDXC_IDMACRd (6U << 13) -#define SDXC_IDMACWr (7U << 13) -#define SDXC_IDMACDESCClose (8U << 13) - -struct sunxi_idma_des { - u32 config; -#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ -#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ -#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ -#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ -#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ -#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ -#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ - - /* - * If the idma-des-size-bits of property is ie 13, bufsize bits are: - * Bits 0-12: buf1 size - * Bits 13-25: buf2 size - * Bits 26-31: not used - * Since we only ever set buf1 size, we can simply store it directly. - */ - u32 buf_size; - u32 buf_addr_ptr1; - u32 buf_addr_ptr2; -}; - -struct sunxi_mmc_host { - struct mmc_host *mmc; - struct regulator *vmmc; - - /* IO mapping base */ - void __iomem *reg_base; - - spinlock_t lock; - struct tasklet_struct tasklet; - - /* clock management */ - struct clk *clk_ahb; - struct clk *clk_mod; - - /* indicator pins */ - int wp_pin; - int cd_pin; - int cd_mode; -#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */ -#define CARD_ALWAYS_PRESENT (2) /* mmc always present */ - - /* ios information */ - u32 clk_mod_rate; - u32 bus_width; - u32 idma_des_size_bits; - u32 ddr; - u32 voltage_switching; - - /* irq */ - int irq; - u32 int_sum; - u32 sdio_imask; - - /* flags */ - u32 power_on:1; - u32 io_flag:1; - u32 wait_dma:1; - - dma_addr_t sg_dma; - void *sg_cpu; - - struct mmc_request *mrq; - u32 ferror; -}; - -#define MMC_CLK_400K 0 -#define MMC_CLK_25M 1 -#define MMC_CLK_50M 2 -#define MMC_CLK_50MDDR 3 -#define MMC_CLK_50MDDR_8BIT 4 -#define MMC_CLK_100M 5 -#define MMC_CLK_200M 6 -#define MMC_CLK_MOD_NUM 7 - -struct sunxi_mmc_clk_dly { - u32 mode; - u32 oclk_dly; - u32 sclk_dly; -}; - -#endif diff --git a/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch b/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch deleted file mode 100644 index db3b296..0000000 --- a/target/linux/sunxi/patches-3.13/124-clk-sunxi-muxable-ahb-clock.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 9490107c16c8eaa35b07794e19d5d2eddea8e44b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar> -Date: Sat, 14 Sep 2013 20:48:40 -0300 -Subject: [PATCH] clk: sunxi: Implement muxable AHB clock -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -sun5i and sun7i have a mux to change the AHB clock parent, this commit -adds support for it on the driver. - -Signed-off-by: Emilio López <emilio@elopez.com.ar> ---- - Documentation/devicetree/bindings/clock/sunxi.txt | 1 + - drivers/clk/sunxi/clk-sunxi.c | 37 +++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/Documentation/devicetree/bindings/clock/sunxi.txt -+++ b/Documentation/devicetree/bindings/clock/sunxi.txt -@@ -15,6 +15,7 @@ Required properties: - "allwinner,sun4i-axi-clk" - for the AXI clock - "allwinner,sun4i-axi-gates-clk" - for the AXI gates - "allwinner,sun4i-ahb-clk" - for the AHB clock -+ "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13 - "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10 - "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 - "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s ---- a/drivers/clk/sunxi/clk-sunxi.c -+++ b/drivers/clk/sunxi/clk-sunxi.c -@@ -249,7 +249,32 @@ static void sun4i_get_pll5_factors(u32 * - *n = DIV_ROUND_UP(div, (*k+1)); - } - -+/** -+ * sun5i_get_ahb_factors() - calculates p factor for AHB -+ * AHB rate is calculated as follows -+ * rate = parent_rate >> p -+ */ -+ -+static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate, -+ u8 *n, u8 *k, u8 *m, u8 *p) -+{ -+ u8 div; -+ -+ /* This clock can only divide, so we will never achieve a higher -+ * rate than the parent's */ -+ if (*freq > parent_rate) -+ *freq = parent_rate; -+ -+ /* Normalize value to a parent multiple */ -+ div = *freq / parent_rate; -+ *freq = parent_rate * div; -+ -+ /* we were called to round the frequency, we can now return */ -+ if (n == NULL) -+ return; - -+ *p = div; -+} - - /** - * sun4i_get_apb1_factors() - calculates m, p factors for APB1 -@@ -375,6 +400,11 @@ static struct clk_factors_config sun4i_p - .kwidth = 2, - }; - -+static struct clk_factors_config sun5i_a13_ahb_config = { -+ .pshift = 4, -+ .pwidth = 2, -+}; -+ - static struct clk_factors_config sun4i_apb1_config = { - .mshift = 0, - .mwidth = 5, -@@ -408,6 +438,12 @@ static const struct factors_data sun4i_p - .getter = sun4i_get_pll5_factors, - }; - -+static const struct factors_data sun5i_a13_ahb_data __initconst = { -+ .mux = 6, -+ .table = &sun5i_a13_ahb_config, -+ .getter = sun5i_a13_get_ahb_factors, -+}; -+ - static const struct factors_data sun4i_apb1_data __initconst = { - .table = &sun4i_apb1_config, - .getter = sun4i_get_apb1_factors, -@@ -916,6 +952,7 @@ free_clkdata: - static const struct of_device_id clk_factors_match[] __initconst = { - {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, - {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, -+ {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,}, - {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, - {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, - {} diff --git a/target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch b/target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch index 0ec3bb5..0ec3bb5 100644 --- a/target/linux/sunxi/patches-3.13/126-regulator-dont-print-error-when-no-regulator-found.patch +++ b/target/linux/sunxi/patches-3.13/124-regulator-dont-print-error-when-no-regulator-found.patch diff --git a/target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch b/target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch index 8d0e23a..8d0e23a 100644 --- a/target/linux/sunxi/patches-3.13/127-dt-sun6i-add-nodes-for-additional-cores.patch +++ b/target/linux/sunxi/patches-3.13/125-dt-sun6i-add-nodes-for-additional-cores.patch diff --git a/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch b/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch deleted file mode 100644 index cb28aa1..0000000 --- a/target/linux/sunxi/patches-3.13/125-dt-sunxi-update-ahb-clock-sun57i.patch +++ /dev/null @@ -1,60 +0,0 @@ -From c8fe5648aff581545ce5744f73ee1312080b8ef4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar> -Date: Sat, 14 Sep 2013 20:44:03 -0300 -Subject: [PATCH] ARM: sunxi: dt: Update AHB clock to be muxable on sun[57]i -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -sun5i and sun7i have a mux to select the parent clock for AHB. This -commit implements the required changes on the device trees. - -Signed-off-by: Emilio López <emilio@elopez.com.ar> ---- - arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++-- - arch/arm/boot/dts/sun5i-a13.dtsi | 4 ++-- - arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++-- - 3 files changed, 6 insertions(+), 6 deletions(-) - ---- a/arch/arm/boot/dts/sun5i-a10s.dtsi -+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi -@@ -111,9 +111,9 @@ - - ahb: ahb@01c20054 { - #clock-cells = <0>; -- compatible = "allwinner,sun4i-ahb-clk"; -+ compatible = "allwinner,sun5i-a13-ahb-clk"; - reg = <0x01c20054 0x4>; -- clocks = <&axi>; -+ clocks = <&axi>, <&cpu>, <&pll6 1>; - }; - - ahb_gates: ahb_gates@01c20060 { ---- a/arch/arm/boot/dts/sun5i-a13.dtsi -+++ b/arch/arm/boot/dts/sun5i-a13.dtsi -@@ -115,9 +115,9 @@ - - ahb: ahb@01c20054 { - #clock-cells = <0>; -- compatible = "allwinner,sun4i-ahb-clk"; -+ compatible = "allwinner,sun5i-a13-ahb-clk"; - reg = <0x01c20054 0x4>; -- clocks = <&axi>; -+ clocks = <&axi>, <&cpu>, <&pll6 1>; - }; - - ahb_gates: ahb_gates@01c20060 { ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -101,9 +101,9 @@ - - ahb: ahb@01c20054 { - #clock-cells = <0>; -- compatible = "allwinner,sun4i-ahb-clk"; -+ compatible = "allwinner,sun5i-a13-ahb-clk"; - reg = <0x01c20054 0x4>; -- clocks = <&axi>; -+ clocks = <&axi>, <&pll6 1>, <&pll6 2>; - }; - - ahb_gates: ahb_gates@01c20060 { diff --git a/target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch b/target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch index 102bdba..84ca843 100644 --- a/target/linux/sunxi/patches-3.13/211-dt-sun7i-add-external-clk-output.patch +++ b/target/linux/sunxi/patches-3.13/126-dt-sun7i-add-external-clock-outputs.patch @@ -1,6 +1,6 @@ -From 6dd612e3d7e0c76f863efaddae4738fadc461f72 Mon Sep 17 00:00:00 2001 +From 0aff0370cbffeadc14456556b904c80e30b3717e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wens@csie.org> -Date: Tue, 24 Dec 2013 21:26:18 +0800 +Date: Wed, 1 Jan 2014 10:30:48 +0800 Subject: [PATCH] ARM: dts: sun7i: external clock outputs This commit adds the two external clock outputs available on A20 to @@ -9,13 +9,16 @@ the first input of the clock outputs, which according to AW's A20 user manual, is the 24MHz oscillator divided by 750. Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- - arch/arm/boot/dts/sun7i-a20.dtsi | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) + arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index edad6f1..0d54998 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -312,6 +312,33 @@ +@@ -303,6 +303,34 @@ clocks = <&osc24M>, <&pll6 2>, <&pll5 1>; clock-output-names = "mbus"; }; @@ -23,12 +26,13 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org> + /* + * Dummy clock used by output clocks + */ -+ osc24M_32k: osc24M_32k { ++ osc24M_32k: clk@1 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <750>; + clock-mult = <1>; + clocks = <&osc24M>; ++ clock-output-names = "osc24M_32k"; + }; + + clk_out_a: clk@01c201f0 { @@ -48,4 +52,7 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org> + }; }; - timer { + soc@01c00000 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch new file mode 100644 index 0000000..dfcdba4 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/127-1-dt-sun4i-rename-clock-node-names.patch @@ -0,0 +1,139 @@ +From dfb12c0c35b6cca5e55f40870b65af87988adb3e Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:41 +0800 +Subject: [PATCH] ARM: dts: sun4i: rename clock node names to clk@N + +Device tree naming conventions state that node names should match +node function. Change fully functioning clock nodes to match and +add clock-output-names to all sunxi clock nodes. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 28273f9..26cf191 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -58,34 +58,38 @@ + clock-frequency = <0>; + }; + +- osc24M: osc24M@01c20050 { ++ osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; + }; + +- osc32k: osc32k { ++ osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; ++ clock-output-names = "osc32k"; + }; + +- pll1: pll1@01c20000 { ++ pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll1"; + }; + +- pll4: pll4@01c20018 { ++ pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll4"; + }; + +- pll5: pll5@01c20020 { ++ pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; +@@ -93,7 +97,7 @@ + clock-output-names = "pll5_ddr", "pll5_other"; + }; + +- pll6: pll6@01c20028 { ++ pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; +@@ -107,6 +111,7 @@ + compatible = "allwinner,sun4i-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; ++ clock-output-names = "cpu"; + }; + + axi: axi@01c20054 { +@@ -114,9 +119,10 @@ + compatible = "allwinner,sun4i-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; ++ clock-output-names = "axi"; + }; + +- axi_gates: axi_gates@01c2005c { ++ axi_gates: clk@01c2005c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-axi-gates-clk"; + reg = <0x01c2005c 0x4>; +@@ -129,9 +135,10 @@ + compatible = "allwinner,sun4i-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; ++ clock-output-names = "ahb"; + }; + +- ahb_gates: ahb_gates@01c20060 { ++ ahb_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-ahb-gates-clk"; + reg = <0x01c20060 0x8>; +@@ -154,9 +161,10 @@ + compatible = "allwinner,sun4i-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; ++ clock-output-names = "apb0"; + }; + +- apb0_gates: apb0_gates@01c20068 { ++ apb0_gates: clk@01c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-apb0-gates-clk"; + reg = <0x01c20068 0x4>; +@@ -171,6 +179,7 @@ + compatible = "allwinner,sun4i-apb1-mux-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; ++ clock-output-names = "apb1_mux"; + }; + + apb1: apb1@01c20058 { +@@ -178,9 +187,10 @@ + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&apb1_mux>; ++ clock-output-names = "apb1"; + }; + +- apb1_gates: apb1_gates@01c2006c { ++ apb1_gates: clk@01c2006c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-apb1-gates-clk"; + reg = <0x01c2006c 0x4>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch new file mode 100644 index 0000000..1678a8b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/127-2-dt-sun5i-rename-clock-node-names.patch @@ -0,0 +1,261 @@ +From 3dce8324949eaa1ab4b750e8422ce78ddceb7aa4 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:42 +0800 +Subject: [PATCH] ARM: dts: sun5i: rename clock node names to clk@N + +Device tree naming conventions state that node names should match +node function. Change fully functioning clock nodes to match and +add clock-output-names to all sunxi clock nodes. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 30 ++++++++++++++++++++---------- + arch/arm/boot/dts/sun5i-a13.dtsi | 30 ++++++++++++++++++++---------- + 2 files changed, 40 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 2318082..b114be7 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -51,34 +51,38 @@ + clock-frequency = <0>; + }; + +- osc24M: osc24M@01c20050 { ++ osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; + }; + +- osc32k: osc32k { ++ osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; ++ clock-output-names = "osc32k"; + }; + +- pll1: pll1@01c20000 { ++ pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll1"; + }; + +- pll4: pll4@01c20018 { ++ pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll4"; + }; + +- pll5: pll5@01c20020 { ++ pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; +@@ -86,7 +90,7 @@ + clock-output-names = "pll5_ddr", "pll5_other"; + }; + +- pll6: pll6@01c20028 { ++ pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; +@@ -100,6 +104,7 @@ + compatible = "allwinner,sun4i-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; ++ clock-output-names = "cpu"; + }; + + axi: axi@01c20054 { +@@ -107,9 +112,10 @@ + compatible = "allwinner,sun4i-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; ++ clock-output-names = "axi"; + }; + +- axi_gates: axi_gates@01c2005c { ++ axi_gates: clk@01c2005c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-axi-gates-clk"; + reg = <0x01c2005c 0x4>; +@@ -122,9 +128,10 @@ + compatible = "allwinner,sun4i-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; ++ clock-output-names = "ahb"; + }; + +- ahb_gates: ahb_gates@01c20060 { ++ ahb_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a10s-ahb-gates-clk"; + reg = <0x01c20060 0x8>; +@@ -143,9 +150,10 @@ + compatible = "allwinner,sun4i-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; ++ clock-output-names = "apb0"; + }; + +- apb0_gates: apb0_gates@01c20068 { ++ apb0_gates: clk@01c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a10s-apb0-gates-clk"; + reg = <0x01c20068 0x4>; +@@ -159,6 +167,7 @@ + compatible = "allwinner,sun4i-apb1-mux-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; ++ clock-output-names = "apb1_mux"; + }; + + apb1: apb1@01c20058 { +@@ -166,9 +175,10 @@ + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&apb1_mux>; ++ clock-output-names = "apb1"; + }; + +- apb1_gates: apb1_gates@01c2006c { ++ apb1_gates: clk@01c2006c { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a10s-apb1-gates-clk"; + reg = <0x01c2006c 0x4>; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 6de40b6..5c121fc 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -52,34 +52,38 @@ + clock-frequency = <0>; + }; + +- osc24M: osc24M@01c20050 { ++ osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; + }; + +- osc32k: osc32k { ++ osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; ++ clock-output-names = "osc32k"; + }; + +- pll1: pll1@01c20000 { ++ pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll1"; + }; + +- pll4: pll4@01c20018 { ++ pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll4"; + }; + +- pll5: pll5@01c20020 { ++ pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; +@@ -87,7 +91,7 @@ + clock-output-names = "pll5_ddr", "pll5_other"; + }; + +- pll6: pll6@01c20028 { ++ pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; +@@ -101,6 +105,7 @@ + compatible = "allwinner,sun4i-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; ++ clock-output-names = "cpu"; + }; + + axi: axi@01c20054 { +@@ -108,9 +113,10 @@ + compatible = "allwinner,sun4i-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; ++ clock-output-names = "axi"; + }; + +- axi_gates: axi_gates@01c2005c { ++ axi_gates: clk@01c2005c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-axi-gates-clk"; + reg = <0x01c2005c 0x4>; +@@ -123,9 +129,10 @@ + compatible = "allwinner,sun4i-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; ++ clock-output-names = "ahb"; + }; + +- ahb_gates: ahb_gates@01c20060 { ++ ahb_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a13-ahb-gates-clk"; + reg = <0x01c20060 0x8>; +@@ -143,9 +150,10 @@ + compatible = "allwinner,sun4i-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; ++ clock-output-names = "apb0"; + }; + +- apb0_gates: apb0_gates@01c20068 { ++ apb0_gates: clk@01c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a13-apb0-gates-clk"; + reg = <0x01c20068 0x4>; +@@ -158,6 +166,7 @@ + compatible = "allwinner,sun4i-apb1-mux-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; ++ clock-output-names = "apb1_mux"; + }; + + apb1: apb1@01c20058 { +@@ -165,9 +174,10 @@ + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&apb1_mux>; ++ clock-output-names = "apb1"; + }; + +- apb1_gates: apb1_gates@01c2006c { ++ apb1_gates: clk@01c2006c { + #clock-cells = <1>; + compatible = "allwinner,sun5i-a13-apb1-gates-clk"; + reg = <0x01c2006c 0x4>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch new file mode 100644 index 0000000..fe0a1a0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/127-3-dt-sun6i-rename-clock-node-names.patch @@ -0,0 +1,112 @@ +From 5cd0fa24e51d342f175d31ecb72c2e957a6bd0af Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:43 +0800 +Subject: [PATCH] ARM: dts: sun6i: rename clock node names to clk@N + +Device tree naming conventions state that node names should match +node function. Change fully functioning clock nodes to match and +add clock-output-names to all sunxi clock nodes. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index fc07f70..d3f1995 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -70,17 +70,19 @@ + clock-frequency = <24000000>; + }; + +- osc32k: osc32k { ++ osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; ++ clock-output-names = "osc32k"; + }; + +- pll1: pll1@01c20000 { ++ pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun6i-a31-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll1"; + }; + + pll6: clk@01c20028 { +@@ -103,6 +105,7 @@ + * Allwinner. + */ + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>; ++ clock-output-names = "cpu"; + }; + + axi: axi@01c20050 { +@@ -110,6 +113,7 @@ + compatible = "allwinner,sun4i-axi-clk"; + reg = <0x01c20050 0x4>; + clocks = <&cpu>; ++ clock-output-names = "axi"; + }; + + ahb1_mux: ahb1_mux@01c20054 { +@@ -117,6 +121,7 @@ + compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; ++ clock-output-names = "ahb1_mux"; + }; + + ahb1: ahb1@01c20054 { +@@ -124,9 +129,10 @@ + compatible = "allwinner,sun4i-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb1_mux>; ++ clock-output-names = "ahb1"; + }; + +- ahb1_gates: ahb1_gates@01c20060 { ++ ahb1_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-ahb1-gates-clk"; + reg = <0x01c20060 0x8>; +@@ -152,9 +158,10 @@ + compatible = "allwinner,sun4i-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb1>; ++ clock-output-names = "apb1"; + }; + +- apb1_gates: apb1_gates@01c20060 { ++ apb1_gates: clk@01c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-apb1-gates-clk"; + reg = <0x01c20068 0x4>; +@@ -169,6 +176,7 @@ + compatible = "allwinner,sun4i-apb1-mux-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>; ++ clock-output-names = "apb2_mux"; + }; + + apb2: apb2@01c20058 { +@@ -176,9 +184,10 @@ + compatible = "allwinner,sun6i-a31-apb2-div-clk"; + reg = <0x01c20058 0x4>; + clocks = <&apb2_mux>; ++ clock-output-names = "apb2"; + }; + +- apb2_gates: apb2_gates@01c2006c { ++ apb2_gates: clk@01c2006c { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-apb2-gates-clk"; + reg = <0x01c2006c 0x4>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch b/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch new file mode 100644 index 0000000..0fba0bc --- /dev/null +++ b/target/linux/sunxi/patches-3.13/127-4-dt-sun7i-rename-clock-node-names.patch @@ -0,0 +1,132 @@ +From cb6050998de262d5acf2207c5451d4f5995a5bff Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:44 +0800 +Subject: [PATCH] ARM: dts: sun7i: rename clock node names to clk@N + +Device tree naming conventions state that node names should match +node function. Change fully functioning clock nodes to match and +add clock-output-names to all sunxi clock nodes. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index fe0fe47..cefd7ac 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -54,11 +54,12 @@ + #size-cells = <1>; + ranges; + +- osc24M: osc24M@01c20050 { ++ osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; + }; + + osc32k: clk@0 { +@@ -68,21 +69,23 @@ + clock-output-names = "osc32k"; + }; + +- pll1: pll1@01c20000 { ++ pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll1"; + }; + +- pll4: pll4@01c20018 { ++ pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-pll1-clk"; + reg = <0x01c20018 0x4>; + clocks = <&osc24M>; ++ clock-output-names = "pll4"; + }; + +- pll5: pll5@01c20020 { ++ pll5: clk@01c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll5-clk"; + reg = <0x01c20020 0x4>; +@@ -90,7 +93,7 @@ + clock-output-names = "pll5_ddr", "pll5_other"; + }; + +- pll6: pll6@01c20028 { ++ pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-pll6-clk"; + reg = <0x01c20028 0x4>; +@@ -103,6 +106,7 @@ + compatible = "allwinner,sun4i-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>; ++ clock-output-names = "cpu"; + }; + + axi: axi@01c20054 { +@@ -110,6 +114,7 @@ + compatible = "allwinner,sun4i-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; ++ clock-output-names = "axi"; + }; + + ahb: ahb@01c20054 { +@@ -117,9 +122,10 @@ + compatible = "allwinner,sun4i-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; ++ clock-output-names = "ahb"; + }; + +- ahb_gates: ahb_gates@01c20060 { ++ ahb_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun7i-a20-ahb-gates-clk"; + reg = <0x01c20060 0x8>; +@@ -144,9 +150,10 @@ + compatible = "allwinner,sun4i-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; ++ clock-output-names = "apb0"; + }; + +- apb0_gates: apb0_gates@01c20068 { ++ apb0_gates: clk@01c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun7i-a20-apb0-gates-clk"; + reg = <0x01c20068 0x4>; +@@ -162,6 +169,7 @@ + compatible = "allwinner,sun4i-apb1-mux-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; ++ clock-output-names = "apb1_mux"; + }; + + apb1: apb1@01c20058 { +@@ -169,9 +177,10 @@ + compatible = "allwinner,sun4i-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&apb1_mux>; ++ clock-output-names = "apb1"; + }; + +- apb1_gates: apb1_gates@01c2006c { ++ apb1_gates: clk@01c2006c { + #clock-cells = <1>; + compatible = "allwinner,sun7i-a20-apb1-gates-clk"; + reg = <0x01c2006c 0x4>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch b/target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch index cb8b109..cb8b109 100644 --- a/target/linux/sunxi/patches-3.13/130-dt-sunxi-add-mbusclk.patch +++ b/target/linux/sunxi/patches-3.13/128-dt-sunxi-add-mbusclk.patch diff --git a/target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch b/target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch index 70a5787..70a5787 100644 --- a/target/linux/sunxi/patches-3.13/131-dt-sunxi-add-emac-aliases.patch +++ b/target/linux/sunxi/patches-3.13/130-1-dt-sunxi-add-emac-aliases.patch diff --git a/target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch b/target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch index 543dd57..543dd57 100644 --- a/target/linux/sunxi/patches-3.13/132-dt-sun7i-update-eth-aliases.patch +++ b/target/linux/sunxi/patches-3.13/130-2-dt-sun7i-update-eth-aliases.patch diff --git a/target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch b/target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch index 4bb315d..dc9f8ac 100644 --- a/target/linux/sunxi/patches-3.13/133-dt-sun7i-add-arch-timers.patch +++ b/target/linux/sunxi/patches-3.13/131-dt-sun7i-add-arch-timers.patch @@ -1,4 +1,4 @@ -From 26523a27f47828e50212201ba25862fe1e2b845c Mon Sep 17 00:00:00 2001 +From fdc4530902ed845fc0f31b9bbcc45e05fefe21da Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 1 Dec 2013 22:40:34 +0100 Subject: [PATCH] ARM: dts: sun7i: Add arch timers @@ -14,9 +14,11 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index f4ecd79..fa2ef07 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -304,6 +304,14 @@ +@@ -370,6 +370,14 @@ }; }; @@ -31,3 +33,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> soc@01c00000 { compatible = "simple-bus"; #address-cells = <1>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch b/target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch index 93b7252..93b7252 100644 --- a/target/linux/sunxi/patches-3.13/135-dt-sun5i-a13-add-olinuxino-micro.patch +++ b/target/linux/sunxi/patches-3.13/132-dt-sun5i-a13-add-olinuxino-micro.patch diff --git a/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch b/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch new file mode 100644 index 0000000..16c0aa0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/150-1-dt-sun7i-add-gmac-clock-node.patch @@ -0,0 +1,56 @@ +From bc7a0478e6dac1304fdfdb6f3056f438b632da62 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 10 Feb 2014 18:35:48 +0800 +Subject: [PATCH] ARM: dts: sun7i: Add GMAC clock node to sun7i DTSI + +The GMAC uses 1 of 2 sources for its transmit clock, depending on the +PHY interface mode. Add both sources as dummy clocks, and as parents +to the GMAC clock node. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index cefd7ac..7d98edc 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -322,6 +322,34 @@ + }; + + /* ++ * The following two are dummy clocks, placeholders used in the gmac_tx ++ * clock. The gmac driver will choose one parent depending on the PHY ++ * interface mode, using clk_set_rate auto-reparenting. ++ * The actual TX clock rate is not controlled by the gmac_tx clock. ++ */ ++ mii_phy_tx_clk: clk@2 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ clock-output-names = "mii_phy_tx"; ++ }; ++ ++ gmac_int_tx_clk: clk@3 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_int_tx"; ++ }; ++ ++ gmac_tx_clk: clk@01c20164 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun7i-a20-gmac-clk"; ++ reg = <0x01c20164 0x4>; ++ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; ++ clock-output-names = "gmac_tx"; ++ }; ++ ++ /* + * Dummy clock used by output clocks + */ + osc24M_32k: clk@1 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch b/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch new file mode 100644 index 0000000..5d68104 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/150-2-dt-sun7i-add-gmac-ctrler-node.patch @@ -0,0 +1,39 @@ +From 7584e81f6d9fecf0ad6e2854654b183432adb918 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 10 Feb 2014 18:35:49 +0800 +Subject: [PATCH] ARM: dts: sun7i: Add GMAC controller node to sun7i DTSI + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 7d98edc..87eab0d 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -645,6 +645,21 @@ + status = "disabled"; + }; + ++ gmac: ethernet@01c50000 { ++ compatible = "allwinner,sun7i-a20-gmac"; ++ reg = <0x01c50000 0x10000>; ++ interrupts = <0 85 4>; ++ interrupt-names = "macirq"; ++ clocks = <&ahb_gates 49>, <&gmac_tx_clk>; ++ clock-names = "stmmaceth", "allwinner_gmac_tx"; ++ snps,pbl = <2>; ++ snps,fixed-burst; ++ snps,force_sf_dma_mode; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + hstimer@01c60000 { + compatible = "allwinner,sun7i-a20-hstimer"; + reg = <0x01c60000 0x1000>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch b/target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch index 34c0fc3..01523f0 100644 --- a/target/linux/sunxi/patches-3.13/195-dt-sun7i-add-gmac-pinmuxing.patch +++ b/target/linux/sunxi/patches-3.13/150-3-dt-sun7i-gmac-add-pinmuxing.patch @@ -1,6 +1,6 @@ -From 777ba9f88e1a566a6ed26fe1e8dfff4b8c1448fc Mon Sep 17 00:00:00 2001 +From 249ac8d24efdc07f521b796b96796ffa55abe0a5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:39 +0800 +Date: Mon, 10 Feb 2014 18:35:50 +0800 Subject: [PATCH] ARM: dts: sun7i: Add pin muxing options for the GMAC The A20 has EMAC and GMAC muxed on the same pins. @@ -8,37 +8,46 @@ Add pin sets with gmac function for MII and RGMII mode to the DTSI. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- - arch/arm/boot/dts/sun7i-a20.dtsi | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) + arch/arm/boot/dts/sun7i-a20.dtsi | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 87eab0d..9bb6fdf 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -428,6 +428,28 @@ +@@ -484,6 +484,32 @@ + allwinner,drive = <0>; allwinner,pull = <0>; }; - -+ gmac_pins_mii: gmac_mii { ++ ++ gmac_pins_mii_a: gmac_mii@0 { + allwinner,pins = "PA0", "PA1", "PA2", + "PA3", "PA4", "PA5", "PA6", + "PA7", "PA8", "PA9", "PA10", + "PA11", "PA12", "PA13", "PA14", + "PA15", "PA16"; + allwinner,function = "gmac"; -+ allwinner,drive = <3>; ++ allwinner,drive = <0>; + allwinner,pull = <0>; + }; + -+ gmac_pins_rgmii: gmac_rgmii { ++ gmac_pins_rgmii_a: gmac_rgmii@0 { + allwinner,pins = "PA0", "PA1", "PA2", + "PA3", "PA4", "PA5", "PA6", + "PA7", "PA8", "PA10", + "PA11", "PA12", "PA13", + "PA15", "PA16"; + allwinner,function = "gmac"; ++ /* ++ * data lines in RGMII mode use DDR mode ++ * and need a higher signal drive strength ++ */ + allwinner,drive = <3>; + allwinner,pull = <0>; + }; -+ - mmc0_pins_a: mmc0@0 { - allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; - allwinner,function = "mmc0"; + }; + + timer@01c20c00 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch b/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch new file mode 100644 index 0000000..2c908ac --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-0-stmmac-fixup-0.patch @@ -0,0 +1,50 @@ +From 33ba4079ea8c611c1aeca34f2d6d53a8214c14c5 Mon Sep 17 00:00:00 2001 +From: Rashika Kheria <rashika.kheria@gmail.com> +Date: Thu, 19 Dec 2013 14:19:44 +0530 +Subject: [PATCH] drivers: net: Mark functions as static in stmmac_platform.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch marks the function stmmac_pltfr_freeze() and +stmmac_pltfr_restore() in stmmac_platform.c as static because they are +not used outside this file. + +Thus, it also removes the following warnings in +ethernet/stmicro/stmmac/stmmac_platform.c: + +drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:222:5: warning: no previous prototype for ‘stmmac_pltfr_freeze’ [-Wmissing-prototypes] +drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:236:5: warning: no previous prototype for ‘stmmac_pltfr_restore’ [-Wmissing-prototypes] + +Signed-off-by: Rashika Kheria <rashika.kheria@gmail.com> +Reviewed-by: Josh Triplett <josh@joshtriplett.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 51c9069..38bd1f4 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -219,7 +219,7 @@ static int stmmac_pltfr_resume(struct device *dev) + return stmmac_resume(ndev); + } + +-int stmmac_pltfr_freeze(struct device *dev) ++static int stmmac_pltfr_freeze(struct device *dev) + { + int ret; + struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev); +@@ -233,7 +233,7 @@ int stmmac_pltfr_freeze(struct device *dev) + return ret; + } + +-int stmmac_pltfr_restore(struct device *dev) ++static int stmmac_pltfr_restore(struct device *dev) + { + struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev); + struct net_device *ndev = dev_get_drvdata(dev); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch b/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch new file mode 100644 index 0000000..efd7aff --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-1-stmmac-fixup-1.patch @@ -0,0 +1,77 @@ +From 9cbadf094d9d479413dc8cfa77dff9e732184337 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:51:43 +0000 +Subject: [PATCH] net: stmmac: support max-speed device tree property + +This patch adds support to "max-speed" property which is a standard +Ethernet device tree property. max-speed specifies maximum speed +(specified in megabits per second) supported the device. + +Depending on the clocking schemes some of the boards can only support +few link speeds, so having a way to limit the link speed in the mac +driver would allow such setups to work reliably. + +Without this patch there is no way to tell the driver to limit the +link speed. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++++ + include/linux/stmmac.h | 1 + + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index ecdc8ab..15192c0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -776,6 +776,7 @@ static int stmmac_init_phy(struct net_device *dev) + char phy_id_fmt[MII_BUS_ID_SIZE + 3]; + char bus_id[MII_BUS_ID_SIZE]; + int interface = priv->plat->interface; ++ int max_speed = priv->plat->max_speed; + priv->oldlink = 0; + priv->speed = 0; + priv->oldduplex = -1; +@@ -800,7 +801,8 @@ static int stmmac_init_phy(struct net_device *dev) + + /* Stop Advertising 1000BASE Capability if interface is not GMII */ + if ((interface == PHY_INTERFACE_MODE_MII) || +- (interface == PHY_INTERFACE_MODE_RMII)) ++ (interface == PHY_INTERFACE_MODE_RMII) || ++ (max_speed < 1000 && max_speed > 0)) + phydev->advertising &= ~(SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 38bd1f4..9377ee6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -42,6 +42,10 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, + *mac = of_get_mac_address(np); + plat->interface = of_get_phy_mode(np); + ++ /* Get max speed of operation from device tree */ ++ if (of_property_read_u32(np, "max-speed", &plat->max_speed)) ++ plat->max_speed = -1; ++ + plat->bus_id = of_alias_get_id(np, "ethernet"); + if (plat->bus_id < 0) + plat->bus_id = 0; +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index bb5deb0..33ace71 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -110,6 +110,7 @@ struct plat_stmmacenet_data { + int force_sf_dma_mode; + int force_thresh_dma_mode; + int riwt_off; ++ int max_speed; + void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*bus_setup)(void __iomem *ioaddr); + int (*init)(struct platform_device *pdev); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch b/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch new file mode 100644 index 0000000..0f2527f --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-2-stmmac-fixup-2.patch @@ -0,0 +1,31 @@ +From 984203ceff27e9d6d94fbae4b043fc9afb658121 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:51:58 +0000 +Subject: [PATCH] net: stmmac: mdio: remove reset gpio free + +This patch removes gpio_free for reset line of the phy, driver stores +the gpio number in its private data-structure to use in future. As the +driver uses this pin in future this pin should not be freed. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +index fe7bc99..aab12d2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +@@ -166,7 +166,6 @@ static int stmmac_mdio_reset(struct mii_bus *bus) + udelay(data->delays[1]); + gpio_set_value(reset_gpio, active_low ? 1 : 0); + udelay(data->delays[2]); +- gpio_free(reset_gpio); + } + } + #endif +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch b/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch new file mode 100644 index 0000000..d9c843a --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-3-stmmac-fixup-3.patch @@ -0,0 +1,223 @@ +From 09f8d6960b69e474eef9d2aebdd0d536d00af0c8 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:06 +0000 +Subject: [PATCH] net: stmmac: move dma allocation to new function + +This patch moves dma resource allocation to a new function +alloc_dma_desc_resources, the reason for moving this to a new function +is to keep the memory allocations in a separate function. One more reason +it to get suspend and hibernation cases working without releasing and +allocating these resources during suspend-resume and freeze-restore +cases. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 169 +++++++++++----------- + 1 file changed, 85 insertions(+), 84 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 15192c0..532f2b4 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -996,66 +996,6 @@ static int init_dma_desc_rings(struct net_device *dev) + pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__, + txsize, rxsize, bfsize); + +- if (priv->extend_desc) { +- priv->dma_erx = dma_alloc_coherent(priv->device, rxsize * +- sizeof(struct +- dma_extended_desc), +- &priv->dma_rx_phy, +- GFP_KERNEL); +- if (!priv->dma_erx) +- goto err_dma; +- +- priv->dma_etx = dma_alloc_coherent(priv->device, txsize * +- sizeof(struct +- dma_extended_desc), +- &priv->dma_tx_phy, +- GFP_KERNEL); +- if (!priv->dma_etx) { +- dma_free_coherent(priv->device, priv->dma_rx_size * +- sizeof(struct dma_extended_desc), +- priv->dma_erx, priv->dma_rx_phy); +- goto err_dma; +- } +- } else { +- priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * +- sizeof(struct dma_desc), +- &priv->dma_rx_phy, +- GFP_KERNEL); +- if (!priv->dma_rx) +- goto err_dma; +- +- priv->dma_tx = dma_alloc_coherent(priv->device, txsize * +- sizeof(struct dma_desc), +- &priv->dma_tx_phy, +- GFP_KERNEL); +- if (!priv->dma_tx) { +- dma_free_coherent(priv->device, priv->dma_rx_size * +- sizeof(struct dma_desc), +- priv->dma_rx, priv->dma_rx_phy); +- goto err_dma; +- } +- } +- +- priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), +- GFP_KERNEL); +- if (!priv->rx_skbuff_dma) +- goto err_rx_skbuff_dma; +- +- priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), +- GFP_KERNEL); +- if (!priv->rx_skbuff) +- goto err_rx_skbuff; +- +- priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t), +- GFP_KERNEL); +- if (!priv->tx_skbuff_dma) +- goto err_tx_skbuff_dma; +- +- priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), +- GFP_KERNEL); +- if (!priv->tx_skbuff) +- goto err_tx_skbuff; +- + if (netif_msg_probe(priv)) { + pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, + (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); +@@ -1123,30 +1063,6 @@ static int init_dma_desc_rings(struct net_device *dev) + err_init_rx_buffers: + while (--i >= 0) + stmmac_free_rx_buffers(priv, i); +- kfree(priv->tx_skbuff); +-err_tx_skbuff: +- kfree(priv->tx_skbuff_dma); +-err_tx_skbuff_dma: +- kfree(priv->rx_skbuff); +-err_rx_skbuff: +- kfree(priv->rx_skbuff_dma); +-err_rx_skbuff_dma: +- if (priv->extend_desc) { +- dma_free_coherent(priv->device, priv->dma_tx_size * +- sizeof(struct dma_extended_desc), +- priv->dma_etx, priv->dma_tx_phy); +- dma_free_coherent(priv->device, priv->dma_rx_size * +- sizeof(struct dma_extended_desc), +- priv->dma_erx, priv->dma_rx_phy); +- } else { +- dma_free_coherent(priv->device, +- priv->dma_tx_size * sizeof(struct dma_desc), +- priv->dma_tx, priv->dma_tx_phy); +- dma_free_coherent(priv->device, +- priv->dma_rx_size * sizeof(struct dma_desc), +- priv->dma_rx, priv->dma_rx_phy); +- } +-err_dma: + return ret; + } + +@@ -1182,6 +1098,85 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv) + } + } + ++static int alloc_dma_desc_resources(struct stmmac_priv *priv) ++{ ++ unsigned int txsize = priv->dma_tx_size; ++ unsigned int rxsize = priv->dma_rx_size; ++ int ret = -ENOMEM; ++ ++ priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), ++ GFP_KERNEL); ++ if (!priv->rx_skbuff_dma) ++ return -ENOMEM; ++ ++ priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), ++ GFP_KERNEL); ++ if (!priv->rx_skbuff) ++ goto err_rx_skbuff; ++ ++ priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t), ++ GFP_KERNEL); ++ if (!priv->tx_skbuff_dma) ++ goto err_tx_skbuff_dma; ++ ++ priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), ++ GFP_KERNEL); ++ if (!priv->tx_skbuff) ++ goto err_tx_skbuff; ++ ++ if (priv->extend_desc) { ++ priv->dma_erx = dma_alloc_coherent(priv->device, rxsize * ++ sizeof(struct ++ dma_extended_desc), ++ &priv->dma_rx_phy, ++ GFP_KERNEL); ++ if (!priv->dma_erx) ++ goto err_dma; ++ ++ priv->dma_etx = dma_alloc_coherent(priv->device, txsize * ++ sizeof(struct ++ dma_extended_desc), ++ &priv->dma_tx_phy, ++ GFP_KERNEL); ++ if (!priv->dma_etx) { ++ dma_free_coherent(priv->device, priv->dma_rx_size * ++ sizeof(struct dma_extended_desc), ++ priv->dma_erx, priv->dma_rx_phy); ++ goto err_dma; ++ } ++ } else { ++ priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * ++ sizeof(struct dma_desc), ++ &priv->dma_rx_phy, ++ GFP_KERNEL); ++ if (!priv->dma_rx) ++ goto err_dma; ++ ++ priv->dma_tx = dma_alloc_coherent(priv->device, txsize * ++ sizeof(struct dma_desc), ++ &priv->dma_tx_phy, ++ GFP_KERNEL); ++ if (!priv->dma_tx) { ++ dma_free_coherent(priv->device, priv->dma_rx_size * ++ sizeof(struct dma_desc), ++ priv->dma_rx, priv->dma_rx_phy); ++ goto err_dma; ++ } ++ } ++ ++ return 0; ++ ++err_dma: ++ kfree(priv->tx_skbuff); ++err_tx_skbuff: ++ kfree(priv->tx_skbuff_dma); ++err_tx_skbuff_dma: ++ kfree(priv->rx_skbuff); ++err_rx_skbuff: ++ kfree(priv->rx_skbuff_dma); ++ return ret; ++} ++ + static void free_dma_desc_resources(struct stmmac_priv *priv) + { + /* Release the DMA TX/RX socket buffers */ +@@ -1623,6 +1618,12 @@ static int stmmac_open(struct net_device *dev) + priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); + priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); + ++ alloc_dma_desc_resources(priv); ++ if (ret < 0) { ++ pr_err("%s: DMA descriptors allocation failed\n", __func__); ++ goto dma_desc_error; ++ } ++ + ret = init_dma_desc_rings(dev); + if (ret < 0) { + pr_err("%s: DMA descriptors initialization failed\n", __func__); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch b/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch new file mode 100644 index 0000000..e006fda --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-4-stmmac-fixup-4.patch @@ -0,0 +1,214 @@ +From 523f11b5d4fd72efb72b04cd7006bfd1d1d4f341 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:14 +0000 +Subject: [PATCH] net: stmmac: move hardware setup for stmmac_open to new + function + +This patch moves hardware setup part of the code in stmmac_open to a new +function stmmac_hw_setup, the reason for doing this is to make hw +initialization independent function so that PM functions can re-use it to +re-initialize the IP after returning from low power state. +This will also avoid code duplication across stmmac_resume/restore and +stmmac_open. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 155 ++++++++++++---------- + 1 file changed, 88 insertions(+), 67 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 532f2b4..341c8dc3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1586,6 +1586,86 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) + } + + /** ++ * stmmac_hw_setup: setup mac in a usable state. ++ * @dev : pointer to the device structure. ++ * Description: ++ * This function sets up the ip in a usable state. ++ * Return value: ++ * 0 on success and an appropriate (-)ve integer as defined in errno.h ++ * file on failure. ++ */ ++static int stmmac_hw_setup(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ int ret; ++ ++ ret = init_dma_desc_rings(dev); ++ if (ret < 0) { ++ pr_err("%s: DMA descriptors initialization failed\n", __func__); ++ return ret; ++ } ++ /* DMA initialization and SW reset */ ++ ret = stmmac_init_dma_engine(priv); ++ if (ret < 0) { ++ pr_err("%s: DMA engine initialization failed\n", __func__); ++ return ret; ++ } ++ ++ /* Copy the MAC addr into the HW */ ++ priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); ++ ++ /* If required, perform hw setup of the bus. */ ++ if (priv->plat->bus_setup) ++ priv->plat->bus_setup(priv->ioaddr); ++ ++ /* Initialize the MAC Core */ ++ priv->hw->mac->core_init(priv->ioaddr); ++ ++ /* Enable the MAC Rx/Tx */ ++ stmmac_set_mac(priv->ioaddr, true); ++ ++ /* Set the HW DMA mode and the COE */ ++ stmmac_dma_operation_mode(priv); ++ ++ stmmac_mmc_setup(priv); ++ ++ ret = stmmac_init_ptp(priv); ++ if (ret) ++ pr_warn("%s: failed PTP initialisation\n", __func__); ++ ++#ifdef CONFIG_STMMAC_DEBUG_FS ++ ret = stmmac_init_fs(dev); ++ if (ret < 0) ++ pr_warn("%s: failed debugFS registration\n", __func__); ++#endif ++ /* Start the ball rolling... */ ++ pr_debug("%s: DMA RX/TX processes started...\n", dev->name); ++ priv->hw->dma->start_tx(priv->ioaddr); ++ priv->hw->dma->start_rx(priv->ioaddr); ++ ++ /* Dump DMA/MAC registers */ ++ if (netif_msg_hw(priv)) { ++ priv->hw->mac->dump_regs(priv->ioaddr); ++ priv->hw->dma->dump_regs(priv->ioaddr); ++ } ++ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; ++ ++ priv->eee_enabled = stmmac_eee_init(priv); ++ ++ stmmac_init_tx_coalesce(priv); ++ ++ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { ++ priv->rx_riwt = MAX_DMA_RIWT; ++ priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); ++ } ++ ++ if (priv->pcs && priv->hw->mac->ctrl_ane) ++ priv->hw->mac->ctrl_ane(priv->ioaddr, 0); ++ ++ return 0; ++} ++ ++/** + * stmmac_open - open entry point of the driver + * @dev : pointer to the device structure. + * Description: +@@ -1613,6 +1693,10 @@ static int stmmac_open(struct net_device *dev) + } + } + ++ /* Extra statistics */ ++ memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); ++ priv->xstats.threshold = tc; ++ + /* Create and initialize the TX/RX descriptors chains. */ + priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); + priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); +@@ -1624,28 +1708,14 @@ static int stmmac_open(struct net_device *dev) + goto dma_desc_error; + } + +- ret = init_dma_desc_rings(dev); ++ ret = stmmac_hw_setup(dev); + if (ret < 0) { +- pr_err("%s: DMA descriptors initialization failed\n", __func__); +- goto dma_desc_error; +- } +- +- /* DMA initialization and SW reset */ +- ret = stmmac_init_dma_engine(priv); +- if (ret < 0) { +- pr_err("%s: DMA engine initialization failed\n", __func__); ++ pr_err("%s: Hw setup failed\n", __func__); + goto init_error; + } + +- /* Copy the MAC addr into the HW */ +- priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); +- +- /* If required, perform hw setup of the bus. */ +- if (priv->plat->bus_setup) +- priv->plat->bus_setup(priv->ioaddr); +- +- /* Initialize the MAC Core */ +- priv->hw->mac->core_init(priv->ioaddr); ++ if (priv->phydev) ++ phy_start(priv->phydev); + + /* Request the IRQ lines */ + ret = request_irq(dev->irq, stmmac_interrupt, +@@ -1678,55 +1748,6 @@ static int stmmac_open(struct net_device *dev) + } + } + +- /* Enable the MAC Rx/Tx */ +- stmmac_set_mac(priv->ioaddr, true); +- +- /* Set the HW DMA mode and the COE */ +- stmmac_dma_operation_mode(priv); +- +- /* Extra statistics */ +- memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); +- priv->xstats.threshold = tc; +- +- stmmac_mmc_setup(priv); +- +- ret = stmmac_init_ptp(priv); +- if (ret) +- pr_warn("%s: failed PTP initialisation\n", __func__); +- +-#ifdef CONFIG_STMMAC_DEBUG_FS +- ret = stmmac_init_fs(dev); +- if (ret < 0) +- pr_warn("%s: failed debugFS registration\n", __func__); +-#endif +- /* Start the ball rolling... */ +- pr_debug("%s: DMA RX/TX processes started...\n", dev->name); +- priv->hw->dma->start_tx(priv->ioaddr); +- priv->hw->dma->start_rx(priv->ioaddr); +- +- /* Dump DMA/MAC registers */ +- if (netif_msg_hw(priv)) { +- priv->hw->mac->dump_regs(priv->ioaddr); +- priv->hw->dma->dump_regs(priv->ioaddr); +- } +- +- if (priv->phydev) +- phy_start(priv->phydev); +- +- priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; +- +- priv->eee_enabled = stmmac_eee_init(priv); +- +- stmmac_init_tx_coalesce(priv); +- +- if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { +- priv->rx_riwt = MAX_DMA_RIWT; +- priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); +- } +- +- if (priv->pcs && priv->hw->mac->ctrl_ane) +- priv->hw->mac->ctrl_ane(priv->ioaddr, 0); +- + napi_enable(&priv->napi); + netif_start_queue(dev); + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch b/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch new file mode 100644 index 0000000..1a60574 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-5-stmmac-fixup-5.patch @@ -0,0 +1,45 @@ +From 073752aa59b3db120b2508d5bdd0598ada25fd25 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:27 +0000 +Subject: [PATCH] net: stmmac: make stmmac_mdio_reset non-static + +This patch promotes stmmac_mdio_reset function from static to +non-static, so that power management functions can decide to reset if +the IP comes out from lowe power state specially hibernation cases. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + + drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 92be6b3..5a568015 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -110,6 +110,7 @@ struct stmmac_priv { + + int stmmac_mdio_unregister(struct net_device *ndev); + int stmmac_mdio_register(struct net_device *ndev); ++int stmmac_mdio_reset(struct mii_bus *mii); + void stmmac_set_ethtool_ops(struct net_device *netdev); + extern const struct stmmac_desc_ops enh_desc_ops; + extern const struct stmmac_desc_ops ndesc_ops; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +index aab12d2..a468eb1 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +@@ -128,7 +128,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, + * @bus: points to the mii_bus structure + * Description: reset the MII bus + */ +-static int stmmac_mdio_reset(struct mii_bus *bus) ++int stmmac_mdio_reset(struct mii_bus *bus) + { + #if defined(CONFIG_STMMAC_PLATFORM) + struct net_device *ndev = bus->priv; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch b/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch new file mode 100644 index 0000000..25564c6 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-6-stmmac-fixup-6.patch @@ -0,0 +1,57 @@ +From 623997fb90eab7a135c2c68a332c8450a488baca Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:35 +0000 +Subject: [PATCH] net: stmmac: fix power management suspend-resume case + +The driver PM resume assumes that the IP is still powered up and the +all the register contents are not disturbed when it comes out of low +power suspend case. This assumption is wrong, basically the driver +should not consider any state of registers after it comes out of low +power. However driver can keep the part of the IP powered up if its a +wake up source. But it can not assume the register state of the IP. Also +its possible that SOC glue layer can take the power off the IP if its +not wake-up source to reduce the power consumption. + +This patch re initializes hardware by calling stmmac_hw_setup function in +resume case. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 341c8dc3..742a83f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2887,18 +2887,19 @@ int stmmac_resume(struct net_device *ndev) + * this bit because it can generate problems while resuming + * from another devices (e.g. serial console). + */ +- if (device_may_wakeup(priv->device)) ++ if (device_may_wakeup(priv->device)) { + priv->hw->mac->pmt(priv->ioaddr, 0); +- else ++ } else { + /* enable the clk prevously disabled */ + clk_prepare_enable(priv->stmmac_clk); ++ /* reset the phy so that it's ready */ ++ if (priv->mii) ++ stmmac_mdio_reset(priv->mii); ++ } + + netif_device_attach(ndev); + +- /* Enable the MAC and DMA */ +- stmmac_set_mac(priv->ioaddr, true); +- priv->hw->dma->start_tx(priv->ioaddr); +- priv->hw->dma->start_rx(priv->ioaddr); ++ stmmac_hw_setup(ndev); + + napi_enable(&priv->napi); + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch b/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch new file mode 100644 index 0000000..67e0c5b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-7-stmmac-fixup-7.patch @@ -0,0 +1,146 @@ +From 33a23e223749c45ff8099ff9baa235301a3ad07f Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:44 +0000 +Subject: [PATCH] net: stmmac: use suspend functions for hibernation + +In hibernation freeze case the driver just releases the resources like +dma buffers, irqs, unregisters the drivers and during restore it does +register, request the resources. This is not really necessary, as part +of power management all the data structures are intact, all the +previously allocated resources can be used after coming out of low +power. + +This patch uses the suspend and resume callbacks for freeze and +restore which initializes the hardware correctly without unregistering +or releasing the resources, this should also help in reducing the time +to restore. + +Also this patch fixes a bug in stmmac_pltfr_restore and +stmmac_pltfr_freeze where it tries to get hold of platform data via +dev_get_platdata call, which would return NULL in device tree cases and +the next if statement would crash as there is no NULL check. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 - + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 -------- + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 ++++++---------------- + 3 files changed, 12 insertions(+), 50 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 5a568015..027f1dd 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -117,8 +117,6 @@ struct stmmac_priv { + extern const struct stmmac_hwtimestamp stmmac_ptp; + int stmmac_ptp_register(struct stmmac_priv *priv); + void stmmac_ptp_unregister(struct stmmac_priv *priv); +-int stmmac_freeze(struct net_device *ndev); +-int stmmac_restore(struct net_device *ndev); + int stmmac_resume(struct net_device *ndev); + int stmmac_suspend(struct net_device *ndev); + int stmmac_dvr_remove(struct net_device *ndev); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 742a83f..c1298a0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2912,22 +2912,6 @@ int stmmac_resume(struct net_device *ndev) + + return 0; + } +- +-int stmmac_freeze(struct net_device *ndev) +-{ +- if (!ndev || !netif_running(ndev)) +- return 0; +- +- return stmmac_release(ndev); +-} +- +-int stmmac_restore(struct net_device *ndev) +-{ +- if (!ndev || !netif_running(ndev)) +- return 0; +- +- return stmmac_open(ndev); +-} + #endif /* CONFIG_PM */ + + /* Driver can be configured w/ and w/ both PCI and Platf drivers +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 9377ee6..6d0bf22 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -211,55 +211,35 @@ static int stmmac_pltfr_remove(struct platform_device *pdev) + #ifdef CONFIG_PM + static int stmmac_pltfr_suspend(struct device *dev) + { +- struct net_device *ndev = dev_get_drvdata(dev); +- +- return stmmac_suspend(ndev); +-} +- +-static int stmmac_pltfr_resume(struct device *dev) +-{ +- struct net_device *ndev = dev_get_drvdata(dev); +- +- return stmmac_resume(ndev); +-} +- +-static int stmmac_pltfr_freeze(struct device *dev) +-{ + int ret; +- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev); + struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); + struct platform_device *pdev = to_platform_device(dev); + +- ret = stmmac_freeze(ndev); +- if (plat_dat->exit) +- plat_dat->exit(pdev); ++ ret = stmmac_suspend(ndev); ++ if (priv->plat->exit) ++ priv->plat->exit(pdev); + + return ret; + } + +-static int stmmac_pltfr_restore(struct device *dev) ++static int stmmac_pltfr_resume(struct device *dev) + { +- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev); + struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); + struct platform_device *pdev = to_platform_device(dev); + +- if (plat_dat->init) +- plat_dat->init(pdev); ++ if (priv->plat->init) ++ priv->plat->init(pdev); + +- return stmmac_restore(ndev); ++ return stmmac_resume(ndev); + } + +-static const struct dev_pm_ops stmmac_pltfr_pm_ops = { +- .suspend = stmmac_pltfr_suspend, +- .resume = stmmac_pltfr_resume, +- .freeze = stmmac_pltfr_freeze, +- .thaw = stmmac_pltfr_restore, +- .restore = stmmac_pltfr_restore, +-}; +-#else +-static const struct dev_pm_ops stmmac_pltfr_pm_ops; + #endif /* CONFIG_PM */ + ++static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, ++ stmmac_pltfr_suspend, stmmac_pltfr_resume); ++ + static const struct of_device_id stmmac_dt_ids[] = { + { .compatible = "st,spear600-gmac"}, + { .compatible = "snps,dwmac-3.610"}, +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch b/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch new file mode 100644 index 0000000..b4ffecb --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-8-stmmac-fixup-8.patch @@ -0,0 +1,50 @@ +From db88f10ad6a84c5bcb71bf51f0988a4bb1733bea Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:52:52 +0000 +Subject: [PATCH] net: stmmac: restore pinstate in pm resume. + +This patch adds code to restore default pinstate of the pins when it +comes back from low power state. Without this patch the state of the +pins would be unknown and the driver would not work. + +This patch also adds code to put the pins in to sleep state when the +driver enters low power state. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index c1298a0..df7d8d6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -43,6 +43,7 @@ + #include <linux/dma-mapping.h> + #include <linux/slab.h> + #include <linux/prefetch.h> ++#include <linux/pinctrl/consumer.h> + #ifdef CONFIG_STMMAC_DEBUG_FS + #include <linux/debugfs.h> + #include <linux/seq_file.h> +@@ -2864,6 +2865,7 @@ int stmmac_suspend(struct net_device *ndev) + priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); + else { + stmmac_set_mac(priv->ioaddr, false); ++ pinctrl_pm_select_sleep_state(priv->device); + /* Disable clock in case of PWM is off */ + clk_disable_unprepare(priv->stmmac_clk); + } +@@ -2890,6 +2892,7 @@ int stmmac_resume(struct net_device *ndev) + if (device_may_wakeup(priv->device)) { + priv->hw->mac->pmt(priv->ioaddr, 0); + } else { ++ pinctrl_pm_select_default_state(priv->device); + /* enable the clk prevously disabled */ + clk_prepare_enable(priv->stmmac_clk); + /* reset the phy so that it's ready */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch b/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch new file mode 100644 index 0000000..5d6e6a5 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/151-9-stmmac-fixup-9.patch @@ -0,0 +1,73 @@ +From 89f7f2cfdd7ade55d5230501c21271690790ceda Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Date: Thu, 16 Jan 2014 10:53:00 +0000 +Subject: [PATCH] net: stmmac: notify the PM core of a wakeup event. + +In PM_SUSPEND_FREEZE and WOL(Wakeup On Lan) case, when the driver gets a +wakeup event, either the driver or platform specific PM code should notify +the pm core about it, so that the system can wakeup from low power. + +In cases where there is no involvement of platform specific PM, it +becomes driver responsibility to notify the PM core to wakeup the +system. + +Without this WOL with PM_SUSPEND_FREEZE does not work on STi based SOCs. + +Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com> +Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 027f1dd..73709e9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -105,6 +105,7 @@ struct stmmac_priv { + unsigned int default_addend; + u32 adv_ts; + int use_riwt; ++ int irq_wake; + spinlock_t ptp_lock; + }; + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index df7d8d6..cddcf76 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2320,6 +2320,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) + struct net_device *dev = (struct net_device *)dev_id; + struct stmmac_priv *priv = netdev_priv(dev); + ++ if (priv->irq_wake) ++ pm_wakeup_event(priv->device, 0); ++ + if (unlikely(!dev)) { + pr_err("%s: invalid dev pointer\n", __func__); + return IRQ_NONE; +@@ -2861,9 +2864,10 @@ int stmmac_suspend(struct net_device *ndev) + stmmac_clear_descriptors(priv); + + /* Enable Power down mode by programming the PMT regs */ +- if (device_may_wakeup(priv->device)) ++ if (device_may_wakeup(priv->device)) { + priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); +- else { ++ priv->irq_wake = 1; ++ } else { + stmmac_set_mac(priv->ioaddr, false); + pinctrl_pm_select_sleep_state(priv->device); + /* Disable clock in case of PWM is off */ +@@ -2891,6 +2895,7 @@ int stmmac_resume(struct net_device *ndev) + */ + if (device_may_wakeup(priv->device)) { + priv->hw->mac->pmt(priv->ioaddr, 0); ++ priv->irq_wake = 0; + } else { + pinctrl_pm_select_default_state(priv->device); + /* enable the clk prevously disabled */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch b/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch new file mode 100644 index 0000000..323f861 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/152-1-dt-sun7i-enable-gmac-cubietruck.patch @@ -0,0 +1,38 @@ +From 957f00fbab201f429ad81cc87ee3177e4289567d Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 10 Feb 2014 18:35:51 +0800 +Subject: [PATCH] ARM: dts: sun7i: cubietruck: Enable the GMAC + +The CubieTruck uses the GMAC with an RGMII phy. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +--- + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index f9dcb61..025ce52 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -51,6 +51,18 @@ + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; + }; ++ ++ gmac: ethernet@01c50000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac_pins_rgmii_a>; ++ phy = <&phy1>; ++ phy-mode = "rgmii"; ++ status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; + }; + + leds { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch b/target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch index e76cd03..0f1471a 100644 --- a/target/linux/sunxi/patches-3.13/196-2-dt-sun7i-enable-gmac-cubieboard2.patch +++ b/target/linux/sunxi/patches-3.13/152-2-dt-sun7i-enable-gmac-cubieboard2.patch @@ -1,6 +1,6 @@ -From e28b63650ff934751b9fe56415dc2491a6c6b704 Mon Sep 17 00:00:00 2001 +From 7405ae68d251191677e51aadb4308d6ce5212bbe Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:41 +0800 +Date: Mon, 10 Feb 2014 18:35:52 +0800 Subject: [PATCH] ARM: dts: sun7i: cubieboard2: Enable GMAC instead of EMAC GMAC has better performance and fewer hardware issues. @@ -8,9 +8,11 @@ Use the GMAC in MII mode for ethernet instead of the EMAC. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 ++++++++--------------- - 1 file changed, 8 insertions(+), 15 deletions(-) + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index 5c51cb8..7bf4935 100644 --- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts @@ -19,21 +19,6 @@ @@ -32,21 +34,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org> - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>; -@@ -111,6 +96,14 @@ - vbus-supply = <®_usb2_vbus>; + pinctrl@01c20800 { + led_pins_cubieboard2: led_pins@0 { + allwinner,pins = "PH20", "PH21"; +@@ -60,6 +45,18 @@ + pinctrl-0 = <&i2c1_pins_a>; status = "okay"; }; + + gmac: ethernet@01c50000 { + pinctrl-names = "default"; -+ pinctrl-0 = <&gmac_pins_mii>; -+ snps,phy-addr = <1>; ++ pinctrl-0 = <&gmac_pins_mii_a>; ++ phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; + }; }; leds { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch b/target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch index 42526af..d58dccb 100644 --- a/target/linux/sunxi/patches-3.13/196-3-dt-sun7i-enable-gmac-a20-micro.patch +++ b/target/linux/sunxi/patches-3.13/152-3-dt-sun7i-enable-gmac-a20-micro.patch @@ -1,16 +1,19 @@ -From e39d51b2236ab17628fe5d110296cd33a9c4427e Mon Sep 17 00:00:00 2001 +From e401b86036245d2d62d825f0e3e12286c111b281 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:42 +0800 -Subject: [PATCH] ARM: dts: sun7i: olinuxino-micro: Enable GMAC instead of EMAC +Date: Mon, 10 Feb 2014 18:35:53 +0800 +Subject: [PATCH] ARM: dts: sun7i: a20-olinuxino-micro: Enable GMAC instead of + EMAC GMAC has better performance and fewer hardware issues. Use the GMAC in MII mode for ethernet instead of the EMAC. Signed-off-by: Chen-Yu Tsai <wens@csie.org> --- - arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++--------------- - 1 file changed, 8 insertions(+), 15 deletions(-) + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 27 +++++++++++-------------- + 1 file changed, 12 insertions(+), 15 deletions(-) +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index ead3013..b02a796 100644 --- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts @@ -19,21 +19,6 @@ @@ -32,21 +35,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org> - }; - }; - - mmc0: mmc@01c0f000 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>; -@@ -146,6 +131,14 @@ - vbus-supply = <®_usb2_vbus>; + pinctrl@01c20800 { + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PH2"; +@@ -78,6 +63,18 @@ + pinctrl-0 = <&i2c2_pins_a>; status = "okay"; }; + + gmac: ethernet@01c50000 { + pinctrl-names = "default"; -+ pinctrl-0 = <&gmac_pins_mii>; -+ snps,phy-addr = <1>; ++ pinctrl-0 = <&gmac_pins_mii_a>; ++ phy = <&phy1>; + phy-mode = "mii"; + status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; + }; }; leds { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch b/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch deleted file mode 100644 index fcf3497..0000000 --- a/target/linux/sunxi/patches-3.13/152-sunxi-mmc-add-Kconfig.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 447675f817b95881e9922f002de3fc7f6d6e9207 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch> -Date: Fri, 6 Sep 2013 22:34:33 +0200 -Subject: [PATCH] ARM: sunxi-mci: Add driver for SD/MMC hosts found within - Allwinner A1X SoCs - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/mmc/host/Kconfig | 8 + - drivers/mmc/host/Makefile | 2 + - drivers/mmc/host/sunxi-mci.c | 1056 ++++++++++++++++++++++++++++++++++++++++++ - drivers/mmc/host/sunxi-mci.h | 334 +++++++++++++ - 4 files changed, 1400 insertions(+) - create mode 100644 drivers/mmc/host/sunxi-mci.c - create mode 100644 drivers/mmc/host/sunxi-mci.h - ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -690,3 +690,11 @@ config MMC_REALTEK_PCI - help - Say Y here to include driver code to support SD/MMC card interface - of Realtek PCI-E card reader -+ -+config MMC_SUNXI -+ tristate "Allwinner A1X SD/MMC Host Controller support" -+ depends on ARCH_SUNXI -+ default y -+ help -+ This selects support for the SD/MMC Host Controller on -+ Allwinner A1X based SoCs. ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -53,6 +53,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o - - obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o - -+obj-$(CONFIG_MMC_SUNXI) += sunxi-mci.o -+ - obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o - obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o - obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o diff --git a/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch b/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch deleted file mode 100644 index 1c5a453..0000000 --- a/target/linux/sunxi/patches-3.13/153-1-dt-sun4i-add-mmc.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 677631fa522e4ac24f636535e3abb5cd1a5ef40e Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Sat, 14 Dec 2013 22:58:12 +0100 -Subject: [PATCH] ARM: dts: sun4i: Add support for mmc - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun4i-a10-a1000.dts | 16 ++++++++++++++++ - arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++ - arch/arm/boot/dts/sun4i-a10.dtsi | 17 +++++++++++++++++ - 3 files changed, 49 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts -+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts -@@ -39,7 +39,23 @@ - }; - }; - -+ mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>; -+ pinctrl-1 = <&mmc0_cd_pin_a1000>; -+ cd-gpios = <&pio 7 1 0>; /* PH1 */ -+ cd-mode = <1>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ mmc0_cd_pin_a1000: mmc0_cd_pin@0 { -+ allwinner,pins = "PH1"; -+ allwinner,function = "gpio_in"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - emac_power_pin_a1000: emac_power_pin@0 { - allwinner,pins = "PH15"; - allwinner,function = "gpio_out"; ---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -@@ -42,7 +42,23 @@ - }; - }; - -+ mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>; -+ pinctrl-1 = <&mmc0_cd_pin_cubieboard>; -+ cd-gpios = <&pio 7 1 0>; /* PH1 */ -+ cd-mode = <1>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { -+ allwinner,pins = "PH1"; -+ allwinner,function = "gpio_in"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - led_pins_cubieboard: led_pins@0 { - allwinner,pins = "PH20", "PH21"; - allwinner,function = "gpio_out"; ---- a/arch/arm/boot/dts/sun4i-a10.dtsi -+++ b/arch/arm/boot/dts/sun4i-a10.dtsi -@@ -328,6 +328,16 @@ - #size-cells = <0>; - }; - -+ mmc0: mmc@01c0f000 { -+ compatible = "allwinner,sun4i-a10-mmc"; -+ reg = <0x01c0f000 0x1000>; -+ clocks = <&ahb_gates 8>, <&mmc0_clk>; -+ clock-names = "ahb", "mod"; -+ interrupts = <32>; -+ bus-width = <4>; -+ status = "disabled"; -+ }; -+ - intc: interrupt-controller@01c20400 { - compatible = "allwinner,sun4i-ic"; - reg = <0x01c20400 0x400>; -@@ -398,6 +408,13 @@ - allwinner,drive = <0>; - allwinner,pull = <0>; - }; -+ -+ mmc0_pins_a: mmc0@0 { -+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; -+ allwinner,function = "mmc0"; -+ allwinner,drive = <3>; -+ allwinner,pull = <0>; -+ }; - }; - - timer@01c20c00 { diff --git a/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch b/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch new file mode 100644 index 0000000..e8137fb --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-1-stmmac-enable-main-clock-when-probing.patch @@ -0,0 +1,96 @@ +From 62866e98737e77c87f9dec99edea76ab54360770 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:40 +0800 +Subject: [PATCH] net: stmmac: Enable stmmac main clock when probing hardware + +The stmmac driver does not enable the main clock during the probe phase. +If the clock was not enabled by the boot loader or was disabled by the +kernel, hardware features and the MDIO bus would not be probed properly. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++------------ + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index cddcf76..0d2c4cb 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1680,8 +1680,6 @@ static int stmmac_open(struct net_device *dev) + struct stmmac_priv *priv = netdev_priv(dev); + int ret; + +- clk_prepare_enable(priv->stmmac_clk); +- + stmmac_check_ether_addr(priv); + + if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && +@@ -1819,7 +1817,6 @@ static int stmmac_release(struct net_device *dev) + #ifdef CONFIG_STMMAC_DEBUG_FS + stmmac_exit_fs(); + #endif +- clk_disable_unprepare(priv->stmmac_clk); + + stmmac_release_ptp(priv); + +@@ -2727,10 +2724,18 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + if ((phyaddr >= 0) && (phyaddr <= 31)) + priv->plat->phy_addr = phyaddr; + ++ priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); ++ if (IS_ERR(priv->stmmac_clk)) { ++ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", ++ __func__); ++ goto error_clk_get; ++ } ++ clk_prepare_enable(priv->stmmac_clk); ++ + /* Init MAC and get the capabilities */ + ret = stmmac_hw_init(priv); + if (ret) +- goto error_free_netdev; ++ goto error_hw_init; + + ndev->netdev_ops = &stmmac_netdev_ops; + +@@ -2768,12 +2773,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + goto error_netdev_register; + } + +- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); +- if (IS_ERR(priv->stmmac_clk)) { +- pr_warn("%s: warning: cannot get CSR clock\n", __func__); +- goto error_clk_get; +- } +- + /* If a specific clk_csr value is passed from the platform + * this means that the CSR Clock Range selection cannot be + * changed at run-time and it is fixed. Viceversa the driver'll try to +@@ -2801,12 +2800,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + return priv; + + error_mdio_register: +- clk_put(priv->stmmac_clk); +-error_clk_get: + unregister_netdev(ndev); + error_netdev_register: + netif_napi_del(&priv->napi); +-error_free_netdev: ++error_hw_init: ++ clk_disable_unprepare(priv->stmmac_clk); ++error_clk_get: + free_netdev(ndev); + + return NULL; +@@ -2833,6 +2832,7 @@ int stmmac_dvr_remove(struct net_device *ndev) + stmmac_mdio_unregister(ndev); + netif_carrier_off(ndev); + unregister_netdev(ndev); ++ clk_disable_unprepare(priv->stmmac_clk); + free_netdev(ndev); + + return 0; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch b/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch new file mode 100644 index 0000000..188eaf0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-2-stmmac-add-support-for-optional-reset-control.patch @@ -0,0 +1,158 @@ +From c5e4ddbdfa1134a36589c1466ed4abb85fe6f976 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:41 +0800 +Subject: [PATCH] net: stmmac: Add support for optional reset control + +The DWMAC has a reset assert line, which is used on some SoCs. Add an +optional reset control to stmmac driver core. + +To support reset control deferred probing, this patch changes the driver +probe function to return the actual error, instead of just -EINVAL. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/devicetree/bindings/net/stmmac.txt | 3 +++ + drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 + + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++ + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++++++- + drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 ++-- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++-- + 6 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt +index eba0e5e..d132513 100644 +--- a/Documentation/devicetree/bindings/net/stmmac.txt ++++ b/Documentation/devicetree/bindings/net/stmmac.txt +@@ -30,6 +30,9 @@ Required properties: + + Optional properties: + - mac-address: 6 bytes, mac address ++- resets: Should contain a phandle to the STMMAC reset signal, if any ++- reset-names: Should contain the reset signal name "stmmaceth", if a ++ reset phandle is given + + Examples: + +diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig +index 6e52c0f..b59d1ef 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -5,6 +5,7 @@ config STMMAC_ETH + select PHYLIB + select CRC32 + select PTP_1588_CLOCK ++ select RESET_CONTROLLER + ---help--- + This is the driver for the Ethernet IPs are built around a + Synopsys IP Core and only tested on the STMicroelectronics +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 73709e9..c1c141f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -32,6 +32,7 @@ + #include <linux/pci.h> + #include "common.h" + #include <linux/ptp_clock_kernel.h> ++#include <linux/reset.h> + + struct stmmac_priv { + /* Frequently used values are kept adjacent for cache effect */ +@@ -91,6 +92,7 @@ struct stmmac_priv { + int wolopts; + int wol_irq; + struct clk *stmmac_clk; ++ struct reset_control *stmmac_rst; + int clk_csr; + struct timer_list eee_ctrl_timer; + int lpi_irq; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 0d2c4cb..0c5c120 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -51,6 +51,7 @@ + #include <linux/net_tstamp.h> + #include "stmmac_ptp.h" + #include "stmmac.h" ++#include <linux/reset.h> + + #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) + #define JUMBO_LEN 9000 +@@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + if (IS_ERR(priv->stmmac_clk)) { + dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", + __func__); ++ ret = PTR_ERR(priv->stmmac_clk); + goto error_clk_get; + } + clk_prepare_enable(priv->stmmac_clk); + ++ priv->stmmac_rst = devm_reset_control_get(priv->device, ++ STMMAC_RESOURCE_NAME); ++ if (IS_ERR(priv->stmmac_rst)) { ++ if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) { ++ ret = -EPROBE_DEFER; ++ goto error_hw_init; ++ } ++ dev_info(priv->device, "no reset control found\n"); ++ priv->stmmac_rst = NULL; ++ } ++ if (priv->stmmac_rst) ++ reset_control_deassert(priv->stmmac_rst); ++ + /* Init MAC and get the capabilities */ + ret = stmmac_hw_init(priv); + if (ret) +@@ -2808,7 +2823,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + error_clk_get: + free_netdev(ndev); + +- return NULL; ++ return ERR_PTR(ret); + } + + /** +@@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev) + stmmac_mdio_unregister(ndev); + netif_carrier_off(ndev); + unregister_netdev(ndev); ++ if (priv->stmmac_rst) ++ reset_control_assert(priv->stmmac_rst); + clk_disable_unprepare(priv->stmmac_clk); + free_netdev(ndev); + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +index 37ba2e0..2916089 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +@@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev, + stmmac_default_data(); + + priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr); +- if (!priv) { ++ if (IS_ERR(priv)) { + pr_err("%s: main driver probe failed", __func__); +- ret = -ENODEV; ++ ret = PTR_ERR(priv); + goto err_out; + } + priv->dev->irq = pdev->irq; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 6d0bf22..cc6b89a7 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) + } + + priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr); +- if (!priv) { ++ if (IS_ERR(priv)) { + pr_err("%s: main driver probe failed", __func__); +- return -ENODEV; ++ return PTR_ERR(priv); + } + + /* Get MAC address if available (DT) */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch b/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch deleted file mode 100644 index e0368a1..0000000 --- a/target/linux/sunxi/patches-3.13/153-3-dt-sun7i-add-mmc.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 3cce544eb5964c14653dddde731cac4cbff97d90 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Sat, 14 Dec 2013 22:58:15 +0100 -Subject: [PATCH] ARM: dts: sun7i: Add support for mmc - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 16 ++++++++++++ - arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 16 ++++++++++++ - arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 32 +++++++++++++++++++++++ - arch/arm/boot/dts/sun7i-a20.dtsi | 34 +++++++++++++++++++++++++ - 4 files changed, 98 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -@@ -34,7 +34,23 @@ - }; - }; - -+ mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>; -+ pinctrl-1 = <&mmc0_cd_pin_cubieboard2>; -+ cd-gpios = <&pio 7 1 0>; /* PH1 */ -+ cd-mode = <1>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 { -+ allwinner,pins = "PH1"; -+ allwinner,function = "gpio_in"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - led_pins_cubieboard2: led_pins@0 { - allwinner,pins = "PH20", "PH21"; - allwinner,function = "gpio_out"; ---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -@@ -34,7 +34,39 @@ - }; - }; - -+ mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>; -+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>; -+ cd-gpios = <&pio 7 1 0>; /* PH1 */ -+ cd-mode = <1>; -+ status = "okay"; -+ }; -+ -+ mmc3: mmc@01c12000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc3_pins_a>; -+ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>; -+ cd-gpios = <&pio 7 11 0>; /* PH11 */ -+ cd-mode = <1>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { -+ allwinner,pins = "PH1"; -+ allwinner,function = "gpio_in"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ -+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { -+ allwinner,pins = "PH11"; -+ allwinner,function = "gpio_in"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - led_pins_olinuxino: led_pins@0 { - allwinner,pins = "PH2"; - allwinner,function = "gpio_out"; ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -334,6 +334,26 @@ - #size-cells = <0>; - }; - -+ mmc0: mmc@01c0f000 { -+ compatible = "allwinner,sun5i-a13-mmc"; -+ reg = <0x01c0f000 0x1000>; -+ clocks = <&ahb_gates 8>, <&mmc0_clk>; -+ clock-names = "ahb", "mod"; -+ interrupts = <0 32 4>; -+ bus-width = <4>; -+ status = "disabled"; -+ }; -+ -+ mmc3: mmc@01c12000 { -+ compatible = "allwinner,sun5i-a13-mmc"; -+ reg = <0x01c12000 0x1000>; -+ clocks = <&ahb_gates 11>, <&mmc3_clk>; -+ clock-names = "ahb", "mod"; -+ interrupts = <0 35 4>; -+ bus-width = <4>; -+ status = "disabled"; -+ }; -+ - pio: pinctrl@01c20800 { - compatible = "allwinner,sun7i-a20-pinctrl"; - reg = <0x01c20800 0x400>; -@@ -397,6 +417,20 @@ - allwinner,drive = <0>; - allwinner,pull = <0>; - }; -+ -+ mmc0_pins_a: mmc0@0 { -+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; -+ allwinner,function = "mmc0"; -+ allwinner,drive = <3>; -+ allwinner,pull = <0>; -+ }; -+ -+ mmc3_pins_a: mmc3@0 { -+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9"; -+ allwinner,function = "mmc3"; -+ allwinner,drive = <3>; -+ allwinner,pull = <0>; -+ }; - }; - - timer@01c20c00 { diff --git a/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch b/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch new file mode 100644 index 0000000..2c477c5 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-3-stmmac-allocate-pass-board-specific-data-to-callbacks.patch @@ -0,0 +1,124 @@ +From 938dfdaa3c0f92e9a490d324f3bce43bbaef7632 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:42 +0800 +Subject: [PATCH] net: stmmac: Allocate and pass soc/board specific data to + callbacks + +The current .init and .exit callbacks requires access to driver +private data structures. This is not a good seperation and abstraction. + +Instead, we add a new .setup callback for allocating private data, and +pass the returned pointer to the other callbacks. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/networking/stmmac.txt | 12 ++++++++---- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 18 ++++++++++++++---- + include/linux/stmmac.h | 6 ++++-- + 3 files changed, 26 insertions(+), 10 deletions(-) + +diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt +index cdd916d..2090895 100644 +--- a/Documentation/networking/stmmac.txt ++++ b/Documentation/networking/stmmac.txt +@@ -127,8 +127,9 @@ struct plat_stmmacenet_data { + int riwt_off; + void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*bus_setup)(void __iomem *ioaddr); +- int (*init)(struct platform_device *pdev); +- void (*exit)(struct platform_device *pdev); ++ void *(*setup)(struct platform_device *pdev); ++ int (*init)(struct platform_device *pdev, void *priv); ++ void (*exit)(struct platform_device *pdev, void *priv); + void *custom_cfg; + void *custom_data; + void *bsp_priv; +@@ -169,10 +170,13 @@ Where: + o bus_setup: perform HW setup of the bus. For example, on some ST platforms + this field is used to configure the AMBA bridge to generate more + efficient STBus traffic. +- o init/exit: callbacks used for calling a custom initialization; ++ o setup/init/exit: callbacks used for calling a custom initialization; + this is sometime necessary on some platforms (e.g. ST boxes) + where the HW needs to have set some PIO lines or system cfg +- registers. ++ registers. setup should return a pointer to private data, ++ which will be stored in bsp_priv, and then passed to init and ++ exit callbacks. init/exit callbacks should not use or modify ++ platform data. + o custom_cfg/custom_data: this is a custom configuration that can be passed + while initializing the resources. + o bsp_priv: another private pointer. +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index cc6b89a7..704a5e0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -144,9 +144,16 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) + } + } + ++ /* Custom setup (if needed) */ ++ if (plat_dat->setup) { ++ plat_dat->bsp_priv = plat_dat->setup(pdev); ++ if (IS_ERR(plat_dat->bsp_priv)) ++ return PTR_ERR(plat_dat->bsp_priv); ++ } ++ + /* Custom initialisation (if needed)*/ + if (plat_dat->init) { +- ret = plat_dat->init(pdev); ++ ret = plat_dat->init(pdev, plat_dat->bsp_priv); + if (unlikely(ret)) + return ret; + } +@@ -203,7 +210,10 @@ static int stmmac_pltfr_remove(struct platform_device *pdev) + int ret = stmmac_dvr_remove(ndev); + + if (priv->plat->exit) +- priv->plat->exit(pdev); ++ priv->plat->exit(pdev, priv->plat->bsp_priv); ++ ++ if (priv->plat->free) ++ priv->plat->free(pdev, priv->plat->bsp_priv); + + return ret; + } +@@ -218,7 +228,7 @@ static int stmmac_pltfr_suspend(struct device *dev) + + ret = stmmac_suspend(ndev); + if (priv->plat->exit) +- priv->plat->exit(pdev); ++ priv->plat->exit(pdev, priv->plat->bsp_priv); + + return ret; + } +@@ -230,7 +240,7 @@ static int stmmac_pltfr_resume(struct device *dev) + struct platform_device *pdev = to_platform_device(dev); + + if (priv->plat->init) +- priv->plat->init(pdev); ++ priv->plat->init(pdev, priv->plat->bsp_priv); + + return stmmac_resume(ndev); + } +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index 33ace71..0a5a7ac 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -113,8 +113,10 @@ struct plat_stmmacenet_data { + int max_speed; + void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*bus_setup)(void __iomem *ioaddr); +- int (*init)(struct platform_device *pdev); +- void (*exit)(struct platform_device *pdev); ++ void *(*setup)(struct platform_device *pdev); ++ void (*free)(struct platform_device *pdev, void *priv); ++ int (*init)(struct platform_device *pdev, void *priv); ++ void (*exit)(struct platform_device *pdev, void *priv); + void *custom_cfg; + void *custom_data; + void *bsp_priv; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch b/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch new file mode 100644 index 0000000..17caee3 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-4-stmmac-honor-dt-parameter-to-dma-store-and-fwd.patch @@ -0,0 +1,31 @@ +From 6aedb8c06df732625cf998c1428396914f3139b4 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:44 +0800 +Subject: [PATCH] net: stmmac: Honor DT parameter to force DMA store and + forward mode + +"snps,force_sf_dma_mode" is documented in stmmac device tree bindings, +but is never handled by the driver. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 704a5e0..634260e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -56,6 +56,8 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, + sizeof(struct stmmac_mdio_bus_data), + GFP_KERNEL); + ++ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode"); ++ + /* + * Currently only the properties needed on SPEAr600 + * are provided. All other properties should be added +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch b/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch new file mode 100644 index 0000000..5b9b09c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-5-stmmac-deprecate-snps-phy-addr.patch @@ -0,0 +1,55 @@ +From 436f7ecdcc08f71ddc106b7bbe3bcbf1785f3bff Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:45 +0800 +Subject: [PATCH] net: stmmac: Deprecate snps, phy-addr and auto-detect PHY + address + +The snps,phy-addr device tree property is non-standard, and should be +removed in favor of proper phy node support. Remove it from the binding +documents and warn if the property is still used. + +Most PHYs respond to address 0, but a few don't, so auto-detect PHY +address by default, to make up for the lack of explicit address selection. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/devicetree/bindings/net/stmmac.txt | 1 - + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 9 ++++++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt +index d132513..aefb639 100644 +--- a/Documentation/devicetree/bindings/net/stmmac.txt ++++ b/Documentation/devicetree/bindings/net/stmmac.txt +@@ -12,7 +12,6 @@ Required properties: + property + - phy-mode: String, operation mode of the PHY interface. + Supported values are: "mii", "rmii", "gmii", "rgmii". +-- snps,phy-addr phy address to connect to. + - snps,reset-gpio gpio number for phy reset. + - snps,reset-active-low boolean flag to indicate if phy reset is active low. + - snps,reset-delays-us is triplet of delays +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 634260e..82110f1 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -50,7 +50,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, + if (plat->bus_id < 0) + plat->bus_id = 0; + +- of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr); ++ /* Default to phy auto-detection */ ++ plat->phy_addr = -1; ++ ++ /* "snps,phy-addr" is not a standard property. Mark it as deprecated ++ * and warn of its use. Remove this when phy node support is added. ++ */ ++ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) ++ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); + + plat->mdio_bus_data = devm_kzalloc(&pdev->dev, + sizeof(struct stmmac_mdio_bus_data), +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch b/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch new file mode 100644 index 0000000..99ccd34 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-6-stmmac-use-drvdata-callback-with-compat-strings.patch @@ -0,0 +1,123 @@ +From 022066f50f53000679d31eb407693085f37b3f14 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:46 +0800 +Subject: [PATCH] net: stmmac: Use driver data and callbacks tied with + compatible strings + +The stmmac driver core allows passing feature flags and callbacks via +platform data. Add a similar stmmac_of_data to pass flags and callbacks +tied to compatible strings. This allows us to extend stmmac with glue +layers for different SoCs. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++++++++++++++++----- + include/linux/stmmac.h | 18 +++++++++ + 2 files changed, 52 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 82110f1..bf119db 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -26,8 +26,20 @@ + #include <linux/io.h> + #include <linux/of.h> + #include <linux/of_net.h> ++#include <linux/of_device.h> + #include "stmmac.h" + ++static const struct of_device_id stmmac_dt_ids[] = { ++ /* SoC specific glue layers should come before generic bindings */ ++ { .compatible = "st,spear600-gmac"}, ++ { .compatible = "snps,dwmac-3.610"}, ++ { .compatible = "snps,dwmac-3.70a"}, ++ { .compatible = "snps,dwmac-3.710"}, ++ { .compatible = "snps,dwmac"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, stmmac_dt_ids); ++ + #ifdef CONFIG_OF + static int stmmac_probe_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat, +@@ -35,10 +47,32 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, + { + struct device_node *np = pdev->dev.of_node; + struct stmmac_dma_cfg *dma_cfg; ++ const struct of_device_id *device; + + if (!np) + return -ENODEV; + ++ device = of_match_device(stmmac_dt_ids, &pdev->dev); ++ if (!device) ++ return -ENODEV; ++ ++ if (device->data) { ++ const struct stmmac_of_data *data = device->data; ++ plat->has_gmac = data->has_gmac; ++ plat->enh_desc = data->enh_desc; ++ plat->tx_coe = data->tx_coe; ++ plat->rx_coe = data->rx_coe; ++ plat->bugged_jumbo = data->bugged_jumbo; ++ plat->pmt = data->pmt; ++ plat->riwt_off = data->riwt_off; ++ plat->fix_mac_speed = data->fix_mac_speed; ++ plat->bus_setup = data->bus_setup; ++ plat->setup = data->setup; ++ plat->free = data->free; ++ plat->init = data->init; ++ plat->exit = data->exit; ++ } ++ + *mac = of_get_mac_address(np); + plat->interface = of_get_phy_mode(np); + +@@ -259,16 +293,6 @@ static int stmmac_pltfr_resume(struct device *dev) + static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, + stmmac_pltfr_suspend, stmmac_pltfr_resume); + +-static const struct of_device_id stmmac_dt_ids[] = { +- { .compatible = "st,spear600-gmac"}, +- { .compatible = "snps,dwmac-3.610"}, +- { .compatible = "snps,dwmac-3.70a"}, +- { .compatible = "snps,dwmac-3.710"}, +- { .compatible = "snps,dwmac"}, +- { /* sentinel */ } +-}; +-MODULE_DEVICE_TABLE(of, stmmac_dt_ids); +- + struct platform_driver stmmac_pltfr_driver = { + .probe = stmmac_pltfr_probe, + .remove = stmmac_pltfr_remove, +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index 0a5a7ac..1367974 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -121,4 +121,22 @@ struct plat_stmmacenet_data { + void *custom_data; + void *bsp_priv; + }; ++ ++/* of_data for SoC glue layer device tree bindings */ ++ ++struct stmmac_of_data { ++ int has_gmac; ++ int enh_desc; ++ int tx_coe; ++ int rx_coe; ++ int bugged_jumbo; ++ int pmt; ++ int riwt_off; ++ void (*fix_mac_speed)(void *priv, unsigned int speed); ++ void (*bus_setup)(void __iomem *ioaddr); ++ void *(*setup)(struct platform_device *pdev); ++ void (*free)(struct platform_device *pdev, void *priv); ++ int (*init)(struct platform_device *pdev, void *priv); ++ void (*exit)(struct platform_device *pdev, void *priv); ++}; + #endif +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch new file mode 100644 index 0000000..d0d9f13 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/153-7-stmmac-sunxi-extensions-for-a20.patch @@ -0,0 +1,273 @@ +From af0bd4e9ba809391f275d0c094ac0bfbfbb3f430 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Fri, 17 Jan 2014 21:24:47 +0800 +Subject: [PATCH] net: stmmac: sunxi platform extensions for GMAC in Allwinner + A20 SoC's + +The Allwinner A20 has an ethernet controller that seems to be +an early version of Synopsys DesignWare MAC 10/100/1000 Universal, +which is supported by the stmmac driver. + +Allwinner's GMAC requires setting additional registers in the SoC's +clock control unit. + +The exact version of the DWMAC IP that Allwinner uses is unknown, +thus the exact feature set is unknown. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + .../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++ + drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++ + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + + drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 140 +++++++++++++++++++++ + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 + + .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 + + 6 files changed, 185 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt + create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt +new file mode 100644 +index 0000000..ea4d752 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt +@@ -0,0 +1,27 @@ ++* Allwinner GMAC ethernet controller ++ ++This device is a platform glue layer for stmmac. ++Please see stmmac.txt for the other unchanged properties. ++ ++Required properties: ++ - compatible: Should be "allwinner,sun7i-a20-gmac" ++ - clocks: Should contain the GMAC main clock, and tx clock ++ The tx clock type should be "allwinner,sun7i-a20-gmac-clk" ++ - clock-names: Should contain the clock names "stmmaceth", ++ and "allwinner_gmac_tx" ++ ++Optional properties: ++- phy-supply: phandle to a regulator if the PHY needs one ++ ++Examples: ++ ++ gmac: ethernet@01c50000 { ++ compatible = "allwinner,sun7i-a20-gmac"; ++ reg = <0x01c50000 0x10000>, ++ <0x01c20164 0x4>; ++ interrupts = <0 85 1>; ++ interrupt-names = "macirq"; ++ clocks = <&ahb_gates 49>, <&gmac_tx>; ++ clock-names = "stmmaceth", "allwinner_gmac_tx"; ++ phy-mode = "mii"; ++ }; +diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig +index b59d1ef..e2f202e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -26,6 +26,17 @@ config STMMAC_PLATFORM + + If unsure, say N. + ++config DWMAC_SUNXI ++ bool "Allwinner GMAC support" ++ depends on STMMAC_PLATFORM && ARCH_SUNXI ++ default y ++ ---help--- ++ Support for Allwinner A20/A31 GMAC ethernet controllers. ++ ++ This selects Allwinner SoC glue layer support for the ++ stmmac device driver. This driver is used for A20/A31 ++ GMAC ethernet controller. ++ + config STMMAC_PCI + bool "STMMAC PCI bus support" + depends on STMMAC_ETH && PCI +diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile +index 356a9dd..ecadece 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -1,6 +1,7 @@ + obj-$(CONFIG_STMMAC_ETH) += stmmac.o + stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o + stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o ++stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o + stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ + chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ + dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +new file mode 100644 +index 0000000..771cd15f +--- /dev/null ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c +@@ -0,0 +1,140 @@ ++/** ++ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer ++ * ++ * Copyright (C) 2013 Chen-Yu Tsai ++ * ++ * Chen-Yu Tsai <wens@csie.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/stmmac.h> ++#include <linux/clk.h> ++#include <linux/phy.h> ++#include <linux/of_net.h> ++#include <linux/regulator/consumer.h> ++ ++struct sunxi_priv_data { ++ int interface; ++ int clk_enabled; ++ struct clk *tx_clk; ++ struct regulator *regulator; ++}; ++ ++static void *sun7i_gmac_setup(struct platform_device *pdev) ++{ ++ struct sunxi_priv_data *gmac; ++ struct device *dev = &pdev->dev; ++ ++ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); ++ if (!gmac) ++ return ERR_PTR(-ENOMEM); ++ ++ gmac->interface = of_get_phy_mode(dev->of_node); ++ ++ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx"); ++ if (IS_ERR(gmac->tx_clk)) { ++ dev_err(dev, "could not get tx clock\n"); ++ return gmac->tx_clk; ++ } ++ ++ /* Optional regulator for PHY */ ++ gmac->regulator = devm_regulator_get_optional(dev, "phy"); ++ if (IS_ERR(gmac->regulator)) { ++ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) ++ return ERR_PTR(-EPROBE_DEFER); ++ dev_info(dev, "no regulator found\n"); ++ gmac->regulator = NULL; ++ } ++ ++ return gmac; ++} ++ ++#define SUN7I_GMAC_GMII_RGMII_RATE 125000000 ++#define SUN7I_GMAC_MII_RATE 25000000 ++ ++static int sun7i_gmac_init(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ int ret; ++ ++ if (gmac->regulator) { ++ ret = regulator_enable(gmac->regulator); ++ if (ret) ++ return ret; ++ } ++ ++ /* Set GMAC interface port mode ++ * ++ * The GMAC TX clock lines are configured by setting the clock ++ * rate, which then uses the auto-reparenting feature of the ++ * clock driver, and enabling/disabling the clock. ++ */ ++ if (gmac->interface == PHY_INTERFACE_MODE_RGMII) { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); ++ clk_prepare_enable(gmac->tx_clk); ++ gmac->clk_enabled = 1; ++ } else { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE); ++ clk_prepare(gmac->tx_clk); ++ } ++ ++ return 0; ++} ++ ++static void sun7i_gmac_exit(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ ++ if (gmac->clk_enabled) { ++ clk_disable(gmac->tx_clk); ++ gmac->clk_enabled = 0; ++ } ++ clk_unprepare(gmac->tx_clk); ++ ++ if (gmac->regulator) ++ regulator_disable(gmac->regulator); ++} ++ ++static void sun7i_fix_speed(void *priv, unsigned int speed) ++{ ++ struct sunxi_priv_data *gmac = priv; ++ ++ /* only GMII mode requires us to reconfigure the clock lines */ ++ if (gmac->interface != PHY_INTERFACE_MODE_GMII) ++ return; ++ ++ if (gmac->clk_enabled) { ++ clk_disable(gmac->tx_clk); ++ gmac->clk_enabled = 0; ++ } ++ clk_unprepare(gmac->tx_clk); ++ ++ if (speed == 1000) { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE); ++ clk_prepare_enable(gmac->tx_clk); ++ gmac->clk_enabled = 1; ++ } else { ++ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE); ++ clk_prepare(gmac->tx_clk); ++ } ++} ++ ++/* of_data specifying hardware features and callbacks. ++ * hardware features were copied from Allwinner drivers. */ ++const struct stmmac_of_data sun7i_gmac_data = { ++ .has_gmac = 1, ++ .tx_coe = 1, ++ .fix_mac_speed = sun7i_fix_speed, ++ .setup = sun7i_gmac_setup, ++ .init = sun7i_gmac_init, ++ .exit = sun7i_gmac_exit, ++}; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index c1c141f..d9af26e 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -130,6 +130,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, + bool stmmac_eee_init(struct stmmac_priv *priv); + + #ifdef CONFIG_STMMAC_PLATFORM ++#ifdef CONFIG_DWMAC_SUNXI ++extern const struct stmmac_of_data sun7i_gmac_data; ++#endif + extern struct platform_driver stmmac_pltfr_driver; + static inline int stmmac_register_platform(void) + { +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index bf119db..9d4baa8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -30,6 +30,9 @@ + #include "stmmac.h" + + static const struct of_device_id stmmac_dt_ids[] = { ++#ifdef CONFIG_DWMAC_SUNXI ++ { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data}, ++#endif + /* SoC specific glue layers should come before generic bindings */ + { .compatible = "st,spear600-gmac"}, + { .compatible = "snps,dwmac-3.610"}, +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch b/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch deleted file mode 100644 index 0be3ac4..0000000 --- a/target/linux/sunxi/patches-3.13/154-mmc-update-compat-nodes.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/drivers/mmc/host/sunxi-mci.c -+++ b/drivers/mmc/host/sunxi-mci.c -@@ -715,8 +715,8 @@ static void sunxi_mmc_request(struct mmc - } - - static const struct of_device_id sunxi_mmc_of_match[] = { -- { .compatible = "allwinner,sun4i-mmc", }, -- { .compatible = "allwinner,sun5i-mmc", }, -+ { .compatible = "allwinner,sun4i-a10-mmc", }, -+ { .compatible = "allwinner,sun5i-a13-mmc", }, - { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); -@@ -736,7 +736,7 @@ static int sunxi_mmc_resource_request(st - struct device_node *np = pdev->dev.of_node; - int ret; - -- if (of_device_is_compatible(np, "allwinner,sun4i-mmc")) -+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc")) - host->idma_des_size_bits = 13; - else - host->idma_des_size_bits = 16; diff --git a/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch b/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch new file mode 100644 index 0000000..bc6f0e9 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-1-phy-core-phy_get_leave-error-logging-to-caller.patch @@ -0,0 +1,45 @@ +From cc8e5932c671ba2d3ce511a15c19c47b015bc4ab Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 5 Jan 2014 00:00:30 +0100 +Subject: [PATCH] phy-core: phy_get: Leave error logging to the caller + +In various cases errors may be expected, ie probe-deferral or a call to +phy_get from a driver where the use of a phy is optional. + +Rather then adding all sort of complicated checks for this, and/or adding +special functions like devm_phy_get_optional, simply don't log an error, +and let deciding if get_phy returning an error really should result in a +dev_err up to the caller. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/phy/phy-core.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 5f5b0f4..b355553 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -404,17 +404,11 @@ struct phy *phy_get(struct device *dev, const char *string) + index = of_property_match_string(dev->of_node, "phy-names", + string); + phy = of_phy_get(dev, index); +- if (IS_ERR(phy)) { +- dev_err(dev, "unable to find phy\n"); +- return phy; +- } + } else { + phy = phy_lookup(dev, string); +- if (IS_ERR(phy)) { +- dev_err(dev, "unable to find phy\n"); +- return phy; +- } + } ++ if (IS_ERR(phy)) ++ return phy; + + if (!try_module_get(phy->ops->owner)) + return ERR_PTR(-EPROBE_DEFER); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch b/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch new file mode 100644 index 0000000..5caeb8b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-2-phy-core-dont-porpagate-ENOSUPP.patch @@ -0,0 +1,40 @@ +From 37e3cce7288f7d5c34ae630f16faf48bd3d01c18 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 5 Jan 2014 22:40:39 +0100 +Subject: [PATCH] phy-core: Don't propagate -ENOSUPP from + phy_pm_runtime_get_sync to caller + +The phy-core allows phy_init and phy_power_on to be called multiple times, +but before this patch -ENOSUPP from phy_pm_runtime_get_sync would be +propagated to the caller for the 2nd and later calls. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/phy/phy-core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index b355553..6c73837 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -176,6 +176,8 @@ int phy_init(struct phy *phy) + dev_err(&phy->dev, "phy init failed --> %d\n", ret); + goto out; + } ++ } else { ++ ret = 0; /* Override possible ret == -ENOTSUPP */ + } + ++phy->init_count; + +@@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy) + dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); + goto out; + } ++ } else { ++ ret = 0; /* Override possible ret == -ENOTSUPP */ + } + ++phy->power_count; + mutex_unlock(&phy->mutex); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch b/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch new file mode 100644 index 0000000..15be07e --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-3-phy-core-no-module-build.patch @@ -0,0 +1,48 @@ +From 87c01c9ef0602abaa909771c6c6eab1f4c2c384d Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 11 Feb 2014 16:55:57 +0100 +Subject: [PATCH] phy-core: Don't allow building phy-core as a module + +include/phy/phy.h has stub code in there for when building without the +phy-core enabled. This is useful for generic drivers such as ahci-platform, +ehci-platoform and ohci-platform which have support for driving an optional +phy passed to them through the devicetree. + +Since on some boards this phy functionality is not needed, being able to +disable the phy subsystem without needing a lot of #ifdef magic in the +driver using it is quite useful. + +However this breaks when the module using the phy subsystem is build-in and +the phy-core is not, which leads to the build failing with missing symbol +errors in the linking stage of the zImage. + +Which leads to gems such as this being added to the Kconfig for achi_platform: + + depends on GENERIC_PHY || !GENERIC_PHY + +Rather then duplicating this code in a lot of places using the phy-core, +I believe it is better to simply not allow the phy-core to be built as a +module. The phy core is quite small and has no external dependencies, so +always building it in when enabling it should not be an issue. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/phy/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index afa2354..4ef8755 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -5,7 +5,7 @@ + menu "PHY Subsystem" + + config GENERIC_PHY +- tristate "PHY Core" ++ bool "PHY Core" + help + Generic PHY support. + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch b/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch new file mode 100644 index 0000000..518c8d7 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-4-libahci-allow-override-start_engine.patch @@ -0,0 +1,222 @@ +From 9b10bc9f84fc221fcef9ddca92972af9b442f49d Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 2 Dec 2013 16:13:32 +0100 +Subject: [PATCH] libahci: Allow drivers to override start_engine + +Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a +special register to be poked before starting the DMA engine. + +This register gets reset on an ahci_stop_engine call, so there is no other +place then ahci_start_engine where this poking can be done. + +This commit allows drivers to override ahci_start_engine behavior for use by +the Allwinner AHCI driver (and potentially other drivers in the future). + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci.c | 6 ++++-- + drivers/ata/ahci.h | 6 ++++++ + drivers/ata/libahci.c | 26 +++++++++++++++++++------- + drivers/ata/sata_highbank.c | 3 ++- + 4 files changed, 31 insertions(+), 10 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index dc2756f..eda68b4 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -564,6 +564,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) + { + struct ata_port *ap = link->ap; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + bool online; + int rc; + +@@ -574,7 +575,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), + deadline, &online, NULL); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); + +@@ -589,6 +590,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, + { + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -604,7 +606,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), + deadline, &online, NULL); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* The pseudo configuration device on SIMG4726 attached to + * ASUS P5W-DH Deluxe doesn't send signature FIS after +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 2289efd..64d1a99d 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -323,6 +323,12 @@ struct ahci_host_priv { + u32 em_msg_type; /* EM message type */ + struct clk *clk; /* Only for platforms supporting clk */ + void *plat_data; /* Other platform data */ ++ /* ++ * Optional ahci_start_engine override, if not set this gets set to the ++ * default ahci_start_engine during ahci_save_initial_config, this can ++ * be overridden anytime before the host is activated. ++ */ ++ void (*start_engine)(struct ata_port *ap); + }; + + extern int ahci_ignore_sss; +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 36605ab..f839bb3 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -394,6 +394,9 @@ static ssize_t ahci_show_em_supported(struct device *dev, + * + * If inconsistent, config values are fixed up by this function. + * ++ * If it is not set already this function sets hpriv->start_engine to ++ * ahci_start_engine. ++ * + * LOCKING: + * None. + */ +@@ -500,6 +503,9 @@ void ahci_save_initial_config(struct device *dev, + hpriv->cap = cap; + hpriv->cap2 = cap2; + hpriv->port_map = port_map; ++ ++ if (!hpriv->start_engine) ++ hpriv->start_engine = ahci_start_engine; + } + EXPORT_SYMBOL_GPL(ahci_save_initial_config); + +@@ -766,7 +772,7 @@ static void ahci_start_port(struct ata_port *ap) + + /* enable DMA */ + if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* turn on LEDs */ + if (ap->flags & ATA_FLAG_EM) { +@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap) + + /* restart engine */ + out_restart: +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + return rc; + } + EXPORT_SYMBOL_GPL(ahci_kick_engine); +@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, + const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class, + rc = sata_link_hardreset(link, timing, deadline, &online, + ahci_check_ready); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + if (online) + *class = ahci_dev_classify(ap); +@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap) + + void ahci_error_handler(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + sata_pmp_error_handler(ap); +@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) + + static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + struct ata_device *dev = ap->link.device; + u32 devslp, dm, dito, mdat, deto; +@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) + PORT_DEVSLP_ADSE); + writel(devslp, port_mmio + PORT_DEVSLP); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* enable device sleep feature for the drive */ + err_mask = ata_dev_set_feature(dev, +@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) + + static void ahci_enable_fbs(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 fbs; +@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap) + } else + dev_err(ap->host->dev, "Failed to enable FBS\n"); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + static void ahci_disable_fbs(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 fbs; +@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap) + pp->fbs_enabled = false; + } + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + static void ahci_pmp_attach(struct ata_port *ap) +diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c +index 870b11e..b3b18d1 100644 +--- a/drivers/ata/sata_highbank.c ++++ b/drivers/ata/sata_highbank.c +@@ -403,6 +403,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, + static const unsigned long timing[] = { 5, 100, 500}; + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -431,7 +432,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, + break; + } while (!online && retry--); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + if (online) + *class = ahci_dev_classify(ap); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch b/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch new file mode 100644 index 0000000..11d9a2c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-5-ahci-platform-devs-with-more-than-1-clock.patch @@ -0,0 +1,255 @@ +From bdad8090b5efdb24fa9db00d8e2891927b68dcec Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Thu, 16 Jan 2014 14:32:35 +0100 +Subject: [PATCH] ahci-platform: Add support for devices with more then 1 clock + +The allwinner-sun4i AHCI controller needs 2 clocks to be enabled and the +imx AHCI controller needs 3 clocks to be enabled. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../devicetree/bindings/ata/ahci-platform.txt | 1 + + drivers/ata/ahci.h | 3 +- + drivers/ata/ahci_platform.c | 119 ++++++++++++++++----- + include/linux/ahci_platform.h | 4 + + 4 files changed, 99 insertions(+), 28 deletions(-) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 89de156..3ced07d 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -10,6 +10,7 @@ Required properties: + + Optional properties: + - dma-coherent : Present if dma operations are coherent ++- clocks : a list of phandle + clock specifier pairs + + Example: + sata@ffe08000 { +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 64d1a99d..c12862b 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -51,6 +51,7 @@ + + enum { + AHCI_MAX_PORTS = 32, ++ AHCI_MAX_CLKS = 3, + AHCI_MAX_SG = 168, /* hardware max is 64K */ + AHCI_DMA_BOUNDARY = 0xffffffff, + AHCI_MAX_CMDS = 32, +@@ -321,7 +322,7 @@ struct ahci_host_priv { + u32 em_loc; /* enclosure management location */ + u32 em_buf_sz; /* EM buffer size in byte */ + u32 em_msg_type; /* EM message type */ +- struct clk *clk; /* Only for platforms supporting clk */ ++ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + void *plat_data; /* Other platform data */ + /* + * Optional ahci_start_engine override, if not set this gets set to the +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 4b231ba..609975d 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -87,6 +87,66 @@ struct ata_port_operations ahci_platform_ops = { + AHCI_SHT("ahci_platform"), + }; + ++/** ++ * ahci_platform_enable_clks - Enable platform clocks ++ * @hpriv: host private area to store config values ++ * ++ * This function enables all the clks found in hpriv->clks, starting ++ * at index 0. If any clk fails to enable it disables all the clks ++ * already enabled in reverse order, and then returns an error. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) ++{ ++ int c, rc; ++ ++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { ++ rc = clk_prepare_enable(hpriv->clks[c]); ++ if (rc) ++ goto disable_unprepare_clk; ++ } ++ return 0; ++ ++disable_unprepare_clk: ++ while (--c >= 0) ++ clk_disable_unprepare(hpriv->clks[c]); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); ++ ++/** ++ * ahci_platform_disable_clks - Disable platform clocks ++ * @hpriv: host private area to store config values ++ * ++ * This function disables all the clks found in hpriv->clks, in reverse ++ * order of ahci_platform_enable_clks (starting at the end of the array). ++ * ++ * LOCKING: ++ * None. ++ */ ++void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) ++{ ++ int c; ++ ++ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) ++ if (hpriv->clks[c]) ++ clk_disable_unprepare(hpriv->clks[c]); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); ++ ++static void ahci_put_clks(struct ahci_host_priv *hpriv) ++{ ++ int c; ++ ++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) ++ clk_put(hpriv->clks[c]); ++} ++ + static int ahci_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -97,6 +157,7 @@ static int ahci_probe(struct platform_device *pdev) + struct ahci_host_priv *hpriv; + struct ata_host *host; + struct resource *mem; ++ struct clk *clk; + int irq; + int n_ports; + int i; +@@ -131,17 +192,31 @@ static int ahci_probe(struct platform_device *pdev) + return -ENOMEM; + } + +- hpriv->clk = clk_get(dev, NULL); +- if (IS_ERR(hpriv->clk)) { +- dev_err(dev, "can't get clock\n"); +- } else { +- rc = clk_prepare_enable(hpriv->clk); +- if (rc) { +- dev_err(dev, "clock prepare enable failed"); +- goto free_clk; ++ for (i = 0; i < AHCI_MAX_CLKS; i++) { ++ /* ++ * For now we must use clk_get(dev, NULL) for the first clock, ++ * because some platforms (da850, spear13xx) are not yet ++ * converted to use devicetree for clocks. For new platforms ++ * this is equivalent to of_clk_get(dev->of_node, 0). ++ */ ++ if (i == 0) ++ clk = clk_get(dev, NULL); ++ else ++ clk = of_clk_get(dev->of_node, i); ++ ++ if (IS_ERR(clk)) { ++ rc = PTR_ERR(clk); ++ if (rc == -EPROBE_DEFER) ++ goto free_clk; ++ break; + } ++ hpriv->clks[i] = clk; + } + ++ rc = ahci_enable_clks(dev, hpriv); ++ if (rc) ++ goto free_clk; ++ + /* + * Some platforms might need to prepare for mmio region access, + * which could be done in the following init call. So, the mmio +@@ -222,11 +297,9 @@ static int ahci_probe(struct platform_device *pdev) + if (pdata && pdata->exit) + pdata->exit(dev); + disable_unprepare_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); ++ ahci_disable_clks(hpriv); + free_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_put(hpriv->clk); ++ ahci_put_clks(hpriv); + return rc; + } + +@@ -239,10 +312,8 @@ static void ahci_host_stop(struct ata_host *host) + if (pdata && pdata->exit) + pdata->exit(dev); + +- if (!IS_ERR(hpriv->clk)) { +- clk_disable_unprepare(hpriv->clk); +- clk_put(hpriv->clk); +- } ++ ahci_disable_clks(hpriv); ++ ahci_put_clks(hpriv); + } + + #ifdef CONFIG_PM_SLEEP +@@ -277,8 +348,7 @@ static int ahci_suspend(struct device *dev) + if (pdata && pdata->suspend) + return pdata->suspend(dev); + +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); ++ ahci_disable_clks(hpriv); + + return 0; + } +@@ -290,13 +360,9 @@ static int ahci_resume(struct device *dev) + struct ahci_host_priv *hpriv = host->private_data; + int rc; + +- if (!IS_ERR(hpriv->clk)) { +- rc = clk_prepare_enable(hpriv->clk); +- if (rc) { +- dev_err(dev, "clock prepare enable failed"); +- return rc; +- } +- } ++ rc = ahci_enable_clks(dev, hpriv); ++ if (rc) ++ return rc; + + if (pdata && pdata->resume) { + rc = pdata->resume(dev); +@@ -317,8 +383,7 @@ static int ahci_resume(struct device *dev) + return 0; + + disable_unprepare_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); ++ ahci_disable_clks(hpriv); + + return rc; + } +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index 73a2500..769d065 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -19,6 +19,7 @@ + + struct device; + struct ata_port_info; ++struct ahci_host_priv; + + struct ahci_platform_data { + int (*init)(struct device *dev, void __iomem *addr); +@@ -30,4 +31,7 @@ struct ahci_platform_data { + unsigned int mask_port_map; + }; + ++int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); ++void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); ++ + #endif /* _AHCI_PLATFORM_H */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch b/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch new file mode 100644 index 0000000..fad0a7f --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-6-ahci-platform-support-optional-regulator.patch @@ -0,0 +1,141 @@ +From ba6850946d9e1959be1b00f6ae06454546350c75 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Fri, 17 Jan 2014 13:23:21 +0100 +Subject: [PATCH] ahci-platform: Add support for an optional regulator for + sata-target power + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../devicetree/bindings/ata/ahci-platform.txt | 1 + + drivers/ata/ahci.h | 2 ++ + drivers/ata/ahci_platform.c | 36 ++++++++++++++++++++-- + 3 files changed, 37 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 3ced07d..1ac807f 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -11,6 +11,7 @@ Required properties: + Optional properties: + - dma-coherent : Present if dma operations are coherent + - clocks : a list of phandle + clock specifier pairs ++- target-supply : regulator for SATA target power + + Example: + sata@ffe08000 { +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index c12862b..bf8100c 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -37,6 +37,7 @@ + + #include <linux/clk.h> + #include <linux/libata.h> ++#include <linux/regulator/consumer.h> + + /* Enclosure Management Control */ + #define EM_CTRL_MSG_TYPE 0x000f0000 +@@ -323,6 +324,7 @@ struct ahci_host_priv { + u32 em_buf_sz; /* EM buffer size in byte */ + u32 em_msg_type; /* EM message type */ + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ ++ struct regulator *target_pwr; /* Optional */ + void *plat_data; /* Other platform data */ + /* + * Optional ahci_start_engine override, if not set this gets set to the +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 609975d..907c076 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -192,6 +192,14 @@ static int ahci_probe(struct platform_device *pdev) + return -ENOMEM; + } + ++ hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); ++ if (IS_ERR(hpriv->target_pwr)) { ++ rc = PTR_ERR(hpriv->target_pwr); ++ if (rc == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ hpriv->target_pwr = NULL; ++ } ++ + for (i = 0; i < AHCI_MAX_CLKS; i++) { + /* + * For now we must use clk_get(dev, NULL) for the first clock, +@@ -213,9 +221,15 @@ static int ahci_probe(struct platform_device *pdev) + hpriv->clks[i] = clk; + } + ++ if (hpriv->target_pwr) { ++ rc = regulator_enable(hpriv->target_pwr); ++ if (rc) ++ goto free_clk; ++ } ++ + rc = ahci_enable_clks(dev, hpriv); + if (rc) +- goto free_clk; ++ goto disable_regulator; + + /* + * Some platforms might need to prepare for mmio region access, +@@ -298,6 +312,9 @@ static int ahci_probe(struct platform_device *pdev) + pdata->exit(dev); + disable_unprepare_clk: + ahci_disable_clks(hpriv); ++disable_regulator: ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); + free_clk: + ahci_put_clks(hpriv); + return rc; +@@ -314,6 +331,9 @@ static void ahci_host_stop(struct ata_host *host) + + ahci_disable_clks(hpriv); + ahci_put_clks(hpriv); ++ ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); + } + + #ifdef CONFIG_PM_SLEEP +@@ -350,6 +370,9 @@ static int ahci_suspend(struct device *dev) + + ahci_disable_clks(hpriv); + ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++ + return 0; + } + +@@ -360,9 +383,15 @@ static int ahci_resume(struct device *dev) + struct ahci_host_priv *hpriv = host->private_data; + int rc; + ++ if (hpriv->target_pwr) { ++ rc = regulator_enable(hpriv->target_pwr); ++ if (rc) ++ return rc; ++ } ++ + rc = ahci_enable_clks(dev, hpriv); + if (rc) +- return rc; ++ goto disable_regulator; + + if (pdata && pdata->resume) { + rc = pdata->resume(dev); +@@ -384,6 +413,9 @@ static int ahci_resume(struct device *dev) + + disable_unprepare_clk: + ahci_disable_clks(hpriv); ++disable_regulator: ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); + + return rc; + } +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch b/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch new file mode 100644 index 0000000..0fdc87d --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-7-ahci-platform-add-resource-helpers.patch @@ -0,0 +1,211 @@ +From 05d5a60ae336c122e478cc002afccc880d462b3b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 20 Jan 2014 14:54:40 +0100 +Subject: [PATCH] ahci-platform: Add enable_ / disable_resources helper + functions + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci_platform.c | 112 ++++++++++++++++++++++++++++-------------- + include/linux/ahci_platform.h | 2 + + 2 files changed, 77 insertions(+), 37 deletions(-) + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 907c076..6ebbc17 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -139,6 +139,68 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) + } + EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); + ++/** ++ * ahci_platform_enable_resources - Enable platform resources ++ * @hpriv: host private area to store config values ++ * ++ * This function enables all ahci_platform managed resources in ++ * the following order: ++ * 1) Regulator ++ * 2) Clocks (through ahci_platform_enable_clks) ++ * ++ * If resource enabling fails at any point the previous enabled ++ * resources are disabled in reverse order. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) ++{ ++ int rc; ++ ++ if (hpriv->target_pwr) { ++ rc = regulator_enable(hpriv->target_pwr); ++ if (rc) ++ return rc; ++ } ++ ++ rc = ahci_platform_enable_clks(hpriv); ++ if (rc) ++ goto disable_regulator; ++ ++ return 0; ++ ++disable_regulator: ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); ++ ++/** ++ * ahci_platform_disable_resources - Disable platform resources ++ * @hpriv: host private area to store config values ++ * ++ * This function disables all ahci_platform managed resources in ++ * the following order: ++ * 1) Clocks (through ahci_platform_disable_clks) ++ * 2) Regulator ++ * ++ * LOCKING: ++ * None. ++ */ ++void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) ++{ ++ ahci_platform_disable_clks(hpriv); ++ ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); ++ + static void ahci_put_clks(struct ahci_host_priv *hpriv) + { + int c; +@@ -221,15 +283,9 @@ static int ahci_probe(struct platform_device *pdev) + hpriv->clks[i] = clk; + } + +- if (hpriv->target_pwr) { +- rc = regulator_enable(hpriv->target_pwr); +- if (rc) +- goto free_clk; +- } +- +- rc = ahci_enable_clks(dev, hpriv); ++ rc = ahci_platform_enable_resources(hpriv); + if (rc) +- goto disable_regulator; ++ goto free_clk; + + /* + * Some platforms might need to prepare for mmio region access, +@@ -240,7 +296,7 @@ static int ahci_probe(struct platform_device *pdev) + if (pdata && pdata->init) { + rc = pdata->init(dev, hpriv->mmio); + if (rc) +- goto disable_unprepare_clk; ++ goto disable_resources; + } + + ahci_save_initial_config(dev, hpriv, +@@ -310,11 +366,8 @@ static int ahci_probe(struct platform_device *pdev) + pdata_exit: + if (pdata && pdata->exit) + pdata->exit(dev); +-disable_unprepare_clk: +- ahci_disable_clks(hpriv); +-disable_regulator: +- if (hpriv->target_pwr) +- regulator_disable(hpriv->target_pwr); ++disable_resources: ++ ahci_platform_disable_resources(hpriv); + free_clk: + ahci_put_clks(hpriv); + return rc; +@@ -329,11 +382,8 @@ static void ahci_host_stop(struct ata_host *host) + if (pdata && pdata->exit) + pdata->exit(dev); + +- ahci_disable_clks(hpriv); ++ ahci_platform_disable_resources(hpriv); + ahci_put_clks(hpriv); +- +- if (hpriv->target_pwr) +- regulator_disable(hpriv->target_pwr); + } + + #ifdef CONFIG_PM_SLEEP +@@ -368,10 +418,7 @@ static int ahci_suspend(struct device *dev) + if (pdata && pdata->suspend) + return pdata->suspend(dev); + +- ahci_disable_clks(hpriv); +- +- if (hpriv->target_pwr) +- regulator_disable(hpriv->target_pwr); ++ ahci_platform_disable_resources(hpriv); + + return 0; + } +@@ -383,26 +430,20 @@ static int ahci_resume(struct device *dev) + struct ahci_host_priv *hpriv = host->private_data; + int rc; + +- if (hpriv->target_pwr) { +- rc = regulator_enable(hpriv->target_pwr); +- if (rc) +- return rc; +- } +- +- rc = ahci_enable_clks(dev, hpriv); ++ rc = ahci_platform_enable_resources(hpriv); + if (rc) +- goto disable_regulator; ++ return rc; + + if (pdata && pdata->resume) { + rc = pdata->resume(dev); + if (rc) +- goto disable_unprepare_clk; ++ goto disable_resources; + } + + if (dev->power.power_state.event == PM_EVENT_SUSPEND) { + rc = ahci_reset_controller(host); + if (rc) +- goto disable_unprepare_clk; ++ goto disable_resources; + + ahci_init_controller(host); + } +@@ -411,11 +452,8 @@ static int ahci_resume(struct device *dev) + + return 0; + +-disable_unprepare_clk: +- ahci_disable_clks(hpriv); +-disable_regulator: +- if (hpriv->target_pwr) +- regulator_disable(hpriv->target_pwr); ++disable_resources: ++ ahci_platform_disable_resources(hpriv); + + return rc; + } +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index 769d065..b674b01 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -33,5 +33,7 @@ struct ahci_platform_data { + + int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); + void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); ++int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); ++void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); + + #endif /* _AHCI_PLATFORM_H */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch b/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch new file mode 100644 index 0000000..8f0ba4c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-8-ahci-plat-libraryise-ahci_probe.patch @@ -0,0 +1,344 @@ +From 98601575da5276173233dd575bdd61cccdeb861a Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 20 Jan 2014 14:58:04 +0100 +Subject: [PATCH] ahci-platform: "Library-ise" ahci_probe functionality + +ahci_probe consists of 3 steps: +1) Get resources (get mmio, clks, regulator) +2) Enable resources, handled by ahci_platform_enable_resouces +3) The more or less standard ahci-host controller init sequence + +This commit refactors step 1 and 3 into separate functions, so the platform +drivers for AHCI implementations which need a specific order in step 2, +and / or need to do some custom register poking at some time, can re-use +ahci-platform.c code without needing to copy and paste it. + +Note that ahci_platform_init_host's prototype takes the 3 non function +members of ahci_platform_data as arguments, the idea is that drivers using +the new exported utility functions will not use ahci_platform_data at all, +and hopefully in the future ahci_platform_data can go away entirely. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci_platform.c | 195 ++++++++++++++++++++++++++++-------------- + include/linux/ahci_platform.h | 14 +++ + 2 files changed, 144 insertions(+), 65 deletions(-) + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 6ebbc17..7f3f2ac 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -201,64 +201,64 @@ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) + } + EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); + +-static void ahci_put_clks(struct ahci_host_priv *hpriv) ++static void ahci_platform_put_resources(struct device *dev, void *res) + { ++ struct ahci_host_priv *hpriv = res; + int c; + + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) + clk_put(hpriv->clks[c]); + } + +-static int ahci_probe(struct platform_device *pdev) ++/** ++ * ahci_platform_get_resources - Get platform resources ++ * @pdev: platform device to get resources for ++ * ++ * This function allocates an ahci_host_priv struct, and gets the ++ * following resources, storing a reference to them inside the returned ++ * struct: ++ * ++ * 1) mmio registers (IORESOURCE_MEM 0, mandatory) ++ * 2) regulator for controlling the targets power (optional) ++ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, ++ * or for non devicetree enabled platforms a single clock ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value ++ */ ++struct ahci_host_priv *ahci_platform_get_resources( ++ struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct ahci_platform_data *pdata = dev_get_platdata(dev); +- const struct platform_device_id *id = platform_get_device_id(pdev); +- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0]; +- const struct ata_port_info *ppi[] = { &pi, NULL }; + struct ahci_host_priv *hpriv; +- struct ata_host *host; +- struct resource *mem; + struct clk *clk; +- int irq; +- int n_ports; +- int i; +- int rc; ++ int i, rc = -ENOMEM; + +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!mem) { +- dev_err(dev, "no mmio space\n"); +- return -EINVAL; +- } ++ if (!devres_open_group(dev, NULL, GFP_KERNEL)) ++ return ERR_PTR(-ENOMEM); + +- irq = platform_get_irq(pdev, 0); +- if (irq <= 0) { +- dev_err(dev, "no irq\n"); +- return -EINVAL; +- } ++ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), ++ GFP_KERNEL); ++ if (!hpriv) ++ goto err_out; + +- if (pdata && pdata->ata_port_info) +- pi = *pdata->ata_port_info; ++ devres_add(dev, hpriv); + +- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); +- if (!hpriv) { +- dev_err(dev, "can't alloc ahci_host_priv\n"); +- return -ENOMEM; +- } +- +- hpriv->flags |= (unsigned long)pi.private_data; +- +- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); ++ hpriv->mmio = devm_ioremap_resource(dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); + if (!hpriv->mmio) { +- dev_err(dev, "can't map %pR\n", mem); +- return -ENOMEM; ++ dev_err(dev, "no mmio space\n"); ++ goto err_out; + } + + hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); + if (IS_ERR(hpriv->target_pwr)) { + rc = PTR_ERR(hpriv->target_pwr); + if (rc == -EPROBE_DEFER) +- return -EPROBE_DEFER; ++ goto err_out; + hpriv->target_pwr = NULL; + } + +@@ -277,33 +277,62 @@ static int ahci_probe(struct platform_device *pdev) + if (IS_ERR(clk)) { + rc = PTR_ERR(clk); + if (rc == -EPROBE_DEFER) +- goto free_clk; ++ goto err_out; + break; + } + hpriv->clks[i] = clk; + } + +- rc = ahci_platform_enable_resources(hpriv); +- if (rc) +- goto free_clk; ++ devres_remove_group(dev, NULL); ++ return hpriv; + +- /* +- * Some platforms might need to prepare for mmio region access, +- * which could be done in the following init call. So, the mmio +- * region shouldn't be accessed before init (if provided) has +- * returned successfully. +- */ +- if (pdata && pdata->init) { +- rc = pdata->init(dev, hpriv->mmio); +- if (rc) +- goto disable_resources; +- } ++err_out: ++ devres_release_group(dev, NULL); ++ return ERR_PTR(rc); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_get_resources); ++ ++/** ++ * ahci_platform_init_host - Bring up an ahci-platform host ++ * @pdev: platform device pointer for the host ++ * @hpriv: ahci-host private data for the host ++ * @pi_template: template for the ata_port_info to use ++ * @force_port_map: param passed to ahci_save_initial_config ++ * @mask_port_map: param passed to ahci_save_initial_config ++ * ++ * This function does all the usual steps needed to bring up an ++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) ++ * must be initialized / enabled before calling this. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_init_host(struct platform_device *pdev, ++ struct ahci_host_priv *hpriv, ++ const struct ata_port_info *pi_template, ++ unsigned int force_port_map, ++ unsigned int mask_port_map) ++{ ++ struct device *dev = &pdev->dev; ++ struct ata_port_info pi = *pi_template; ++ const struct ata_port_info *ppi[] = { &pi, NULL }; ++ struct ata_host *host; ++ int i, irq, n_ports, rc; + +- ahci_save_initial_config(dev, hpriv, +- pdata ? pdata->force_port_map : 0, +- pdata ? pdata->mask_port_map : 0); ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev, "no irq\n"); ++ return -EINVAL; ++ } + + /* prepare host */ ++ hpriv->flags |= (unsigned long)pi.private_data; ++ ++ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); ++ + if (hpriv->cap & HOST_CAP_NCQ) + pi.flags |= ATA_FLAG_NCQ; + +@@ -320,10 +349,8 @@ static int ahci_probe(struct platform_device *pdev) + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); + + host = ata_host_alloc_pinfo(dev, ppi, n_ports); +- if (!host) { +- rc = -ENOMEM; +- goto pdata_exit; +- } ++ if (!host) ++ return -ENOMEM; + + host->private_data = hpriv; + +@@ -338,7 +365,8 @@ static int ahci_probe(struct platform_device *pdev) + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + +- ata_port_desc(ap, "mmio %pR", mem); ++ ata_port_desc(ap, "mmio %pR", ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); + ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); + + /* set enclosure management message type */ +@@ -352,13 +380,53 @@ static int ahci_probe(struct platform_device *pdev) + + rc = ahci_reset_controller(host); + if (rc) +- goto pdata_exit; ++ return rc; + + ahci_init_controller(host); + ahci_print_info(host, "platform"); + +- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, +- &ahci_platform_sht); ++ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, ++ &ahci_platform_sht); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_init_host); ++ ++static int ahci_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_platform_data *pdata = dev_get_platdata(dev); ++ const struct platform_device_id *id = platform_get_device_id(pdev); ++ const struct ata_port_info *pi_template; ++ struct ahci_host_priv *hpriv; ++ int rc; ++ ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ /* ++ * Some platforms might need to prepare for mmio region access, ++ * which could be done in the following init call. So, the mmio ++ * region shouldn't be accessed before init (if provided) has ++ * returned successfully. ++ */ ++ if (pdata && pdata->init) { ++ rc = pdata->init(dev, hpriv->mmio); ++ if (rc) ++ goto disable_resources; ++ } ++ ++ if (pdata && pdata->ata_port_info) ++ pi_template = pdata->ata_port_info; ++ else ++ pi_template = &ahci_port_info[id ? id->driver_data : 0]; ++ ++ rc = ahci_platform_init_host(pdev, hpriv, pi_template, ++ pdata ? pdata->force_port_map : 0, ++ pdata ? pdata->mask_port_map : 0); + if (rc) + goto pdata_exit; + +@@ -368,8 +436,6 @@ static int ahci_probe(struct platform_device *pdev) + pdata->exit(dev); + disable_resources: + ahci_platform_disable_resources(hpriv); +-free_clk: +- ahci_put_clks(hpriv); + return rc; + } + +@@ -383,7 +449,6 @@ static void ahci_host_stop(struct ata_host *host) + pdata->exit(dev); + + ahci_platform_disable_resources(hpriv); +- ahci_put_clks(hpriv); + } + + #ifdef CONFIG_PM_SLEEP +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index b674b01..b80c51c 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -20,7 +20,14 @@ + struct device; + struct ata_port_info; + struct ahci_host_priv; ++struct platform_device; + ++/* ++ * Note ahci_platform_data is deprecated, it is only kept around for use ++ * by the old da850 and spear13xx ahci code. ++ * New drivers should instead declare their own platform_driver struct, and ++ * use ahci_platform* functions in their own probe, suspend and resume methods. ++ */ + struct ahci_platform_data { + int (*init)(struct device *dev, void __iomem *addr); + void (*exit)(struct device *dev); +@@ -35,5 +42,12 @@ struct ahci_platform_data { + void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); + int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); + void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); ++struct ahci_host_priv *ahci_platform_get_resources( ++ struct platform_device *pdev); ++int ahci_platform_init_host(struct platform_device *pdev, ++ struct ahci_host_priv *hpriv, ++ const struct ata_port_info *pi_template, ++ unsigned int force_port_map, ++ unsigned int mask_port_map); + + #endif /* _AHCI_PLATFORM_H */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch b/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch new file mode 100644 index 0000000..49ddac0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/160-9-ahci-plat-libraryise-suspend-resume.patch @@ -0,0 +1,188 @@ +From 041cf8356a4eb91ee8118004b2bc9c78cdd7866c Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 20 Jan 2014 15:52:07 +0100 +Subject: [PATCH] ahci-platform: "Library-ise" suspend / resume functionality + +Split suspend / resume code into host suspend / resume functionality and +resource enable / disabling phases, and export the new suspend_ / resume_host +functions. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci_platform.c | 109 ++++++++++++++++++++++++++++++++++++------ + include/linux/ahci_platform.h | 5 ++ + 2 files changed, 99 insertions(+), 15 deletions(-) + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 7f3f2ac..bdadec1 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -452,14 +452,26 @@ static void ahci_host_stop(struct ata_host *host) + } + + #ifdef CONFIG_PM_SLEEP +-static int ahci_suspend(struct device *dev) ++/** ++ * ahci_platform_suspend_host - Suspend an ahci-platform host ++ * @dev: device pointer for the host ++ * ++ * This function does all the usual steps needed to suspend an ++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) ++ * must be disabled after calling this. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_suspend_host(struct device *dev) + { +- struct ahci_platform_data *pdata = dev_get_platdata(dev); + struct ata_host *host = dev_get_drvdata(dev); + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->mmio; + u32 ctl; +- int rc; + + if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { + dev_err(dev, "firmware update required for suspend/resume\n"); +@@ -476,7 +488,64 @@ static int ahci_suspend(struct device *dev) + writel(ctl, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + +- rc = ata_host_suspend(host, PMSG_SUSPEND); ++ return ata_host_suspend(host, PMSG_SUSPEND); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); ++ ++/** ++ * ahci_platform_resume_host - Resume an ahci-platform host ++ * @dev: device pointer for the host ++ * ++ * This function does all the usual steps needed to resume an ++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) ++ * must be initialized / enabled before calling this. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_resume_host(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ int rc; ++ ++ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { ++ rc = ahci_reset_controller(host); ++ if (rc) ++ return rc; ++ ++ ahci_init_controller(host); ++ } ++ ++ ata_host_resume(host); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_resume_host); ++ ++/** ++ * ahci_platform_suspend - Suspend an ahci-platform device ++ * @dev: the platform device to suspend ++ * ++ * This function suspends the host associated with the device, followed ++ * by disabling all the resources of the device. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_suspend(struct device *dev) ++{ ++ struct ahci_platform_data *pdata = dev_get_platdata(dev); ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int rc; ++ ++ rc = ahci_platform_suspend_host(dev); + if (rc) + return rc; + +@@ -487,8 +556,22 @@ static int ahci_suspend(struct device *dev) + + return 0; + } ++EXPORT_SYMBOL_GPL(ahci_platform_suspend); + +-static int ahci_resume(struct device *dev) ++/** ++ * ahci_platform_resume - Resume an ahci-platform device ++ * @dev: the platform device to resume ++ * ++ * This function enables all the resources of the device followed by ++ * resuming the host associated with the device. ++ * ++ * LOCKING: ++ * None. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_resume(struct device *dev) + { + struct ahci_platform_data *pdata = dev_get_platdata(dev); + struct ata_host *host = dev_get_drvdata(dev); +@@ -505,15 +588,9 @@ static int ahci_resume(struct device *dev) + goto disable_resources; + } + +- if (dev->power.power_state.event == PM_EVENT_SUSPEND) { +- rc = ahci_reset_controller(host); +- if (rc) +- goto disable_resources; +- +- ahci_init_controller(host); +- } +- +- ata_host_resume(host); ++ rc = ahci_platform_resume_host(dev); ++ if (rc) ++ goto disable_resources; + + return 0; + +@@ -522,9 +599,11 @@ static int ahci_resume(struct device *dev) + + return rc; + } ++EXPORT_SYMBOL_GPL(ahci_platform_resume); + #endif + +-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); ++static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, ++ ahci_platform_resume); + + static const struct of_device_id ahci_of_match[] = { + { .compatible = "snps,spear-ahci", }, +diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h +index b80c51c..542f268 100644 +--- a/include/linux/ahci_platform.h ++++ b/include/linux/ahci_platform.h +@@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platform_device *pdev, + unsigned int force_port_map, + unsigned int mask_port_map); + ++int ahci_platform_suspend_host(struct device *dev); ++int ahci_platform_resume_host(struct device *dev); ++int ahci_platform_suspend(struct device *dev); ++int ahci_platform_resume(struct device *dev); ++ + #endif /* _AHCI_PLATFORM_H */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch b/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch deleted file mode 100644 index b832dc4..0000000 --- a/target/linux/sunxi/patches-3.13/160-ahci-add-pre-start-hook.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 3eec76bc21d78e56ac8404b59f29dd9dbbd1528a Mon Sep 17 00:00:00 2001 -From: Oliver Schinagl <oliver@schinagl.nl> -Date: Mon, 2 Dec 2013 16:13:32 +0100 -Subject: [PATCH] libahci: Add a pre ahci_start_engine hook - -Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which need a -special register to be poked before starting the DMA engine. - -This register gets reset on an ahci_stop_engine call, so there is no other -place then ahci_start_engine where this poking can be done. - -This commit adds a pre ahci_start_engine hook for use by the Allwinner AHCI -driver (and potentially other drivers in the future). - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/ata/ahci.h | 2 ++ - drivers/ata/libahci.c | 4 ++++ - 2 files changed, 6 insertions(+) - ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -323,6 +323,8 @@ struct ahci_host_priv { - u32 em_msg_type; /* EM message type */ - struct clk *clk; /* Only for platforms supporting clk */ - void *plat_data; /* Other platform data */ -+ /* Optional pre ahci_start_engine hook */ -+ void (*pre_start_engine)(struct ata_port *ap); - }; - - extern int ahci_ignore_sss; ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -568,8 +568,12 @@ static int ahci_scr_write(struct ata_lin - void ahci_start_engine(struct ata_port *ap) - { - void __iomem *port_mmio = ahci_port_base(ap); -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u32 tmp; - -+ if (hpriv->pre_start_engine) -+ hpriv->pre_start_engine(ap); -+ - /* start DMA */ - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_START; diff --git a/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch b/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch new file mode 100644 index 0000000..b7c9064 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/161-ahci-add-sunxi-to-ahci_platform.patch @@ -0,0 +1,352 @@ +From 93dd2c512a24c552f1146d746aac112da7677430 Mon Sep 17 00:00:00 2001 +From: Olliver Schinagl <oliver@schinagl.nl> +Date: Sat, 18 Jan 2014 15:00:45 +0100 +Subject: [PATCH] ARM: sunxi: Add support for Allwinner SUNXi SoCs sata to + ahci_platform + +This patch adds support for the ahci sata controler found on Allwinner A10 +and A20 SoCs to the ahci_platform driver. + +Orignally written by Olliver Schinagl using the approach of having a platform +device which probe method creates a new child platform device which gets +driven by ahci_platform.c, as done by ahci_imx.c . + +Refactored by Hans de Goede to add most of the non sunxi specific functionality +to ahci_platform.c and use a platform_data pointer from of_device_id for the +sunxi specific bits. + +Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../devicetree/bindings/ata/ahci-platform.txt | 15 +- + drivers/ata/Kconfig | 9 + + drivers/ata/Makefile | 1 + + drivers/ata/ahci_sunxi.c | 249 +++++++++++++++++++++ + 4 files changed, 271 insertions(+), 3 deletions(-) + create mode 100644 drivers/ata/ahci_sunxi.c + +diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt +index 1ac807f..499bfed 100644 +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -4,7 +4,9 @@ SATA nodes are defined to describe on-chip Serial ATA controllers. + Each SATA controller should have its own node. + + Required properties: +-- compatible : compatible list, contains "snps,spear-ahci" ++- compatible : compatible list, one of "snps,spear-ahci", ++ "snps,exynos5440-ahci", "ibm,476gtr-ahci", or ++ "allwinner,sun4i-a10-ahci" + - interrupts : <interrupt mapping for SATA IRQ> + - reg : <registers mapping> + +@@ -13,10 +15,17 @@ Optional properties: + - clocks : a list of phandle + clock specifier pairs + - target-supply : regulator for SATA target power + +-Example: ++Examples: + sata@ffe08000 { + compatible = "snps,spear-ahci"; + reg = <0xffe08000 0x1000>; + interrupts = <115>; +- + }; ++ ++ ahci: sata@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <56>; ++ clocks = <&pll6 0>, <&ahb_gates 25>; ++ target-supply = <®_ahci_5v>; ++ }; +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index 4e73772..cc67cc0 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -106,6 +106,15 @@ config AHCI_IMX + + If unsure, say N. + ++config AHCI_SUNXI ++ tristate "Allwinner sunxi AHCI SATA support" ++ depends on ARCH_SUNXI && SATA_AHCI_PLATFORM ++ help ++ This option enables support for the Allwinner sunxi SoC's ++ onboard AHCI SATA. ++ ++ If unsure, say N. ++ + config SATA_FSL + tristate "Freescale 3.0Gbps SATA support" + depends on FSL_SOC +diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile +index 46518c6..246050b 100644 +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o + obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o + obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o + obj-$(CONFIG_AHCI_IMX) += ahci_imx.o ++obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o + + # SFF w/ custom DMA + obj-$(CONFIG_PDC_ADMA) += pdc_adma.o +diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c +new file mode 100644 +index 0000000..001f7dfc +--- /dev/null ++++ b/drivers/ata/ahci_sunxi.c +@@ -0,0 +1,249 @@ ++/* ++ * Allwinner sunxi AHCI SATA platform driver ++ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl> ++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> ++ * ++ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov ++ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>, ++ * Daniel Wang <danielwang@allwinnertech.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ */ ++ ++#include <linux/ahci_platform.h> ++#include <linux/clk.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include "ahci.h" ++ ++#define AHCI_BISTAFR 0x00a0 ++#define AHCI_BISTCR 0x00a4 ++#define AHCI_BISTFCTR 0x00a8 ++#define AHCI_BISTSR 0x00ac ++#define AHCI_BISTDECR 0x00b0 ++#define AHCI_DIAGNR0 0x00b4 ++#define AHCI_DIAGNR1 0x00b8 ++#define AHCI_OOBR 0x00bc ++#define AHCI_PHYCS0R 0x00c0 ++#define AHCI_PHYCS1R 0x00c4 ++#define AHCI_PHYCS2R 0x00c8 ++#define AHCI_TIMER1MS 0x00e0 ++#define AHCI_GPARAM1R 0x00e8 ++#define AHCI_GPARAM2R 0x00ec ++#define AHCI_PPARAMR 0x00f0 ++#define AHCI_TESTR 0x00f4 ++#define AHCI_VERSIONR 0x00f8 ++#define AHCI_IDR 0x00fc ++#define AHCI_RWCR 0x00fc ++#define AHCI_P0DMACR 0x0170 ++#define AHCI_P0PHYCR 0x0178 ++#define AHCI_P0PHYSR 0x017c ++ ++static void sunxi_clrbits(void __iomem *reg, u32 clr_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val &= ~(clr_val); ++ writel(reg_val, reg); ++} ++ ++static void sunxi_setbits(void __iomem *reg, u32 set_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val |= set_val; ++ writel(reg_val, reg); ++} ++ ++static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val &= ~(clr_val); ++ reg_val |= set_val; ++ writel(reg_val, reg); ++} ++ ++static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift) ++{ ++ return (readl(reg) >> shift) & mask; ++} ++ ++static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base) ++{ ++ u32 reg_val; ++ int timeout; ++ ++ /* This magic is from the original code */ ++ writel(0, reg_base + AHCI_RWCR); ++ mdelay(5); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, ++ (0x7 << 24), ++ (0x5 << 24) | BIT(23) | BIT(18)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R, ++ (0x3 << 16) | (0x1f << 8) | (0x3 << 6), ++ (0x2 << 16) | (0x6 << 8) | (0x2 << 6)); ++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15)); ++ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, ++ (0x7 << 20), (0x3 << 20)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R, ++ (0x1f << 5), (0x19 << 5)); ++ mdelay(5); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19)); ++ ++ timeout = 250; /* Power up takes aprox 50 us */ ++ do { ++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28); ++ if (reg_val == 0x02) ++ break; ++ ++ if (--timeout == 0) { ++ dev_err(dev, "PHY power up failed.\n"); ++ return -EIO; ++ } ++ udelay(1); ++ } while (1); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24)); ++ ++ timeout = 100; /* Calibration takes aprox 10 us */ ++ do { ++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24); ++ if (reg_val == 0x00) ++ break; ++ ++ if (--timeout == 0) { ++ dev_err(dev, "PHY calibration failed.\n"); ++ return -EIO; ++ } ++ udelay(1); ++ } while (1); ++ ++ mdelay(15); ++ ++ writel(0x7, reg_base + AHCI_RWCR); ++ ++ return 0; ++} ++ ++static void ahci_sunxi_start_engine(struct ata_port *ap) ++{ ++ void __iomem *port_mmio = ahci_port_base(ap); ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ ++ /* Setup DMA before DMA start */ ++ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400); ++ ++ /* Start DMA */ ++ sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START); ++} ++ ++static const struct ata_port_info ahci_sunxi_port_info = { ++ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | ++ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), ++ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_platform_ops, ++}; ++ ++static int ahci_sunxi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_host_priv *hpriv; ++ int rc; ++ ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); ++ ++ hpriv->start_engine = ahci_sunxi_start_engine; ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ rc = ahci_sunxi_phy_init(dev, hpriv->mmio); ++ if (rc) ++ goto disable_resources; ++ ++ rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0); ++ if (rc) ++ goto disable_resources; ++ ++ return 0; ++ ++disable_resources: ++ ahci_platform_disable_resources(hpriv); ++ return rc; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++int ahci_sunxi_resume(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int rc; ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ rc = ahci_sunxi_phy_init(dev, hpriv->mmio); ++ if (rc) ++ goto disable_resources; ++ ++ rc = ahci_platform_resume_host(dev); ++ if (rc) ++ goto disable_resources; ++ ++ return 0; ++ ++disable_resources: ++ ahci_platform_disable_resources(hpriv); ++ return rc; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend, ++ ahci_sunxi_resume); ++ ++static const struct of_device_id ahci_sunxi_of_match[] = { ++ { .compatible = "allwinner,sun4i-a10-ahci", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match); ++ ++static struct platform_driver ahci_sunxi_driver = { ++ .probe = ahci_sunxi_probe, ++ .remove = ata_platform_remove_one, ++ .driver = { ++ .name = "ahci-sunxi", ++ .owner = THIS_MODULE, ++ .of_match_table = ahci_sunxi_of_match, ++ .pm = &ahci_sunxi_pm_ops, ++ }, ++}; ++module_platform_driver(ahci_sunxi_driver); ++ ++MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver"); ++MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch b/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch deleted file mode 100644 index 9731b9c..0000000 --- a/target/linux/sunxi/patches-3.13/161-sunxi-ahci-add-driver.patch +++ /dev/null @@ -1,436 +0,0 @@ -From 22345cc059de4a6ea1dc7657dd6ad86ca16a8814 Mon Sep 17 00:00:00 2001 -From: Oliver Schinagl <oliver@schinagl.nl> -Date: Tue, 3 Dec 2013 12:07:01 +0100 -Subject: [PATCH] ARM: sunxi: Add ahci-sunxi driver for the Allwinner SUNXi - SoCs sata - -This patch adds support for the ahci sata controler found on Allwinner A10 -and A20 SoCs. - -Orignally written by Olliver Schinagl using the approach of having a platform -device which probe method creates a new child platform device which gets -driven by ahci_platform.c, as done by ahci_imx.c . - -Given that almost all functionality already is shared through libahci / -ata-core, and that ahci_platform.c cannot cleanly handle somewhat more complex -platform specific ahci cases, such as the sunxi case, it was refactored into -a stand-alone platform driver by Hans de Goede. - -Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - .../devicetree/bindings/ata/ahci-sunxi.txt | 24 ++ - drivers/ata/Kconfig | 9 + - drivers/ata/Makefile | 1 + - drivers/ata/ahci_sunxi.c | 349 +++++++++++++++++++++ - 4 files changed, 383 insertions(+) - create mode 100644 Documentation/devicetree/bindings/ata/ahci-sunxi.txt - create mode 100644 drivers/ata/ahci_sunxi.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt -@@ -0,0 +1,24 @@ -+Allwinner SUNXI AHCI SATA Controller -+ -+SATA nodes are defined to describe on-chip Serial ATA controllers. -+Each SATA controller should have its own node. -+ -+Required properties: -+- compatible : compatible list, contains "allwinner,sun4i-a10-ahci" -+- reg : <registers mapping> -+- interrupts : <interrupt mapping for AHCI IRQ> -+- clocks : clocks for ACHI -+- clock-names : clock names for AHCI -+ -+Optional properties: -+- pwr-supply : regulator to control the power supply GPIO -+ -+Example: -+ ahci@01c18000 { -+ compatible = "allwinner,sun4i-a10-ahci"; -+ reg = <0x01c18000 0x1000>; -+ interrupts = <0 56 1>; -+ clocks = <&ahb_gates 25>, <&pll6 0>; -+ clock-names = "ahb_sata", "pll6_sata"; -+ pwr-supply = <®_ahci_5v>; -+ }; ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -106,6 +106,15 @@ config AHCI_IMX - - If unsure, say N. - -+config AHCI_SUNXI -+ tristate "Allwinner sunxi AHCI SATA support" -+ depends on ARCH_SUNXI -+ help -+ This option enables support for the Allwinner sunxi SoC's -+ onboard AHCI SATA. -+ -+ If unsure, say N. -+ - config SATA_FSL - tristate "Freescale 3.0Gbps SATA support" - depends on FSL_SOC ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o - obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o - obj-$(CONFIG_AHCI_IMX) += ahci_imx.o -+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o ---- /dev/null -+++ b/drivers/ata/ahci_sunxi.c -@@ -0,0 +1,349 @@ -+/* -+ * Allwinner sunxi AHCI SATA platform driver -+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl> -+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> -+ * -+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov -+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>, -+ * Daniel Wang <danielwang@allwinnertech.com> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#include <linux/clk.h> -+#include <linux/errno.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/of_device.h> -+#include <linux/platform_device.h> -+#include <linux/regulator/consumer.h> -+#include "ahci.h" -+ -+#define AHCI_BISTAFR 0x00a0 -+#define AHCI_BISTCR 0x00a4 -+#define AHCI_BISTFCTR 0x00a8 -+#define AHCI_BISTSR 0x00ac -+#define AHCI_BISTDECR 0x00b0 -+#define AHCI_DIAGNR0 0x00b4 -+#define AHCI_DIAGNR1 0x00b8 -+#define AHCI_OOBR 0x00bc -+#define AHCI_PHYCS0R 0x00c0 -+#define AHCI_PHYCS1R 0x00c4 -+#define AHCI_PHYCS2R 0x00c8 -+#define AHCI_TIMER1MS 0x00e0 -+#define AHCI_GPARAM1R 0x00e8 -+#define AHCI_GPARAM2R 0x00ec -+#define AHCI_PPARAMR 0x00f0 -+#define AHCI_TESTR 0x00f4 -+#define AHCI_VERSIONR 0x00f8 -+#define AHCI_IDR 0x00fc -+#define AHCI_RWCR 0x00fc -+#define AHCI_P0DMACR 0x0170 -+#define AHCI_P0PHYCR 0x0178 -+#define AHCI_P0PHYSR 0x017c -+ -+struct sunxi_ahci { -+ struct ahci_host_priv hpriv; -+ struct regulator *pwr; -+ struct clk *sata_clk; -+ struct clk *ahb_clk; -+}; -+ -+static void sunxi_clrbits(void __iomem *reg, u32 clr_val) -+{ -+ u32 reg_val; -+ -+ reg_val = readl(reg); -+ reg_val &= ~(clr_val); -+ writel(reg_val, reg); -+} -+ -+static void sunxi_setbits(void __iomem *reg, u32 set_val) -+{ -+ u32 reg_val; -+ -+ reg_val = readl(reg); -+ reg_val |= set_val; -+ writel(reg_val, reg); -+} -+ -+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val) -+{ -+ u32 reg_val; -+ -+ reg_val = readl(reg); -+ reg_val &= ~(clr_val); -+ reg_val |= set_val; -+ writel(reg_val, reg); -+} -+ -+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift) -+{ -+ return (readl(reg) >> shift) & mask; -+} -+ -+static int sunxi_ahci_phy_init(struct device *dev, void __iomem *reg_base) -+{ -+ u32 reg_val; -+ int timeout; -+ -+ /* This magic is from the original code */ -+ writel(0, reg_base + AHCI_RWCR); -+ mdelay(5); -+ -+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19)); -+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, -+ (0x7 << 24), -+ (0x5 << 24) | BIT(23) | BIT(18)); -+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R, -+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6), -+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6)); -+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15)); -+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19)); -+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, -+ (0x7 << 20), (0x3 << 20)); -+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R, -+ (0x1f << 5), (0x19 << 5)); -+ mdelay(5); -+ -+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19)); -+ -+ timeout = 0x100000; -+ do { -+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28); -+ } while (--timeout && (reg_val != 0x2)); -+ if (!timeout) { -+ dev_err(dev, "PHY power up failed.\n"); -+ return -EIO; -+ } -+ -+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24)); -+ -+ timeout = 0x100000; -+ do { -+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24); -+ } while (--timeout && reg_val); -+ if (!timeout) { -+ dev_err(dev, "PHY calibration failed.\n"); -+ return -EIO; -+ } -+ mdelay(15); -+ -+ writel(0x7, reg_base + AHCI_RWCR); -+ -+ return 0; -+} -+ -+void sunxi_ahci_pre_start_engine(struct ata_port *ap) -+{ -+ struct ahci_host_priv *hpriv = ap->host->private_data; -+ -+ /* Setup DMA before DMA start */ -+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400); -+} -+ -+static int sunxi_ahci_enable_clks(struct sunxi_ahci *ahci) -+{ -+ int ret; -+ -+ ret = clk_prepare_enable(ahci->sata_clk); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(ahci->ahb_clk); -+ if (ret) -+ clk_disable_unprepare(ahci->sata_clk); -+ -+ return ret; -+} -+ -+static void sunxi_ahci_disable_clks(struct sunxi_ahci *ahci) -+{ -+ clk_disable_unprepare(ahci->ahb_clk); -+ clk_disable_unprepare(ahci->sata_clk); -+} -+ -+static void sunxi_ahci_host_stop(struct ata_host *host) -+{ -+ struct ahci_host_priv *hpriv = host->private_data; -+ struct sunxi_ahci *ahci = hpriv->plat_data; -+ -+ if (!IS_ERR(ahci->pwr)) -+ regulator_disable(ahci->pwr); -+ -+ sunxi_ahci_disable_clks(ahci); -+} -+ -+static struct ata_port_operations sunxi_ahci_platform_ops = { -+ .inherits = &ahci_ops, -+ .host_stop = sunxi_ahci_host_stop, -+}; -+ -+static const struct ata_port_info sunxiahci_port_info = { -+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | -+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), -+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &sunxi_ahci_platform_ops, -+}; -+ -+static struct scsi_host_template sunxi_ahci_platform_sht = { -+ AHCI_SHT("sunxi_ahci"), -+}; -+ -+static int sunxi_ahci_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct ata_port_info *ppi[] = { &sunxiahci_port_info, NULL }; -+ struct sunxi_ahci *ahci; -+ struct ata_host *host; -+ int ret; -+ -+ ahci = devm_kzalloc(&pdev->dev, sizeof(*ahci), GFP_KERNEL); -+ if (!ahci) -+ return -ENOMEM; -+ -+ ahci->pwr = devm_regulator_get_optional(dev, "pwr"); -+ if (IS_ERR(ahci->pwr) && PTR_ERR(ahci->pwr) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ host = ata_host_alloc_pinfo(dev, ppi, 1); -+ if (!host) -+ return -ENOMEM; -+ -+ host->private_data = &ahci->hpriv; -+ host->flags |= ATA_HOST_PARALLEL_SCAN; -+ -+ ahci->hpriv.flags = (unsigned long)ppi[0]->private_data; -+ ahci->hpriv.plat_data = ahci; -+ ahci->hpriv.pre_start_engine = sunxi_ahci_pre_start_engine; -+ ahci->hpriv.mmio = devm_ioremap_resource(dev, -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); -+ if (IS_ERR(ahci->hpriv.mmio)) -+ return PTR_ERR(ahci->hpriv.mmio); -+ -+ ahci->ahb_clk = devm_clk_get(&pdev->dev, "ahb_sata"); -+ if (IS_ERR(ahci->ahb_clk)) -+ return PTR_ERR(ahci->ahb_clk); -+ -+ ahci->sata_clk = devm_clk_get(&pdev->dev, "pll6_sata"); -+ if (IS_ERR(ahci->sata_clk)) -+ return PTR_ERR(ahci->sata_clk); -+ -+ ret = sunxi_ahci_enable_clks(ahci); -+ if (ret) -+ return ret; -+ -+ if (!IS_ERR(ahci->pwr)) { -+ ret = regulator_enable(ahci->pwr); -+ if (ret) { -+ sunxi_ahci_disable_clks(ahci); -+ return ret; -+ } -+ } -+ -+ ret = sunxi_ahci_phy_init(dev, ahci->hpriv.mmio); -+ if (ret) { -+ sunxi_ahci_host_stop(host); -+ return ret; -+ } -+ -+ ahci_save_initial_config(dev, &ahci->hpriv, 0, 0); -+ -+ ret = ahci_reset_controller(host); -+ if (ret) { -+ sunxi_ahci_host_stop(host); -+ return ret; -+ } -+ -+ ahci_init_controller(host); -+ ahci_print_info(host, "sunxi"); -+ -+ ret = ata_host_activate(host, platform_get_irq(pdev, 0), -+ ahci_interrupt, 0, &sunxi_ahci_platform_sht); -+ if (ret) -+ sunxi_ahci_host_stop(host); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int sunxi_ahci_susp(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ struct sunxi_ahci *ahci = hpriv->plat_data; -+ int ret; -+ -+ /* -+ * AHCI spec rev1.1 section 8.3.3: -+ * Software must disable interrupts prior to requesting a -+ * transition of the HBA to D3 state. -+ */ -+ sunxi_clrbits(hpriv->mmio + HOST_CTL, HOST_IRQ_EN); -+ -+ ret = ata_host_suspend(host, PMSG_SUSPEND); -+ if (ret) -+ return ret; -+ -+ sunxi_ahci_disable_clks(ahci); -+ -+ return 0; -+} -+ -+static int sunxi_ahci_resume(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ struct sunxi_ahci *ahci = hpriv->plat_data; -+ int ret; -+ -+ ret = sunxi_ahci_enable_clks(ahci); -+ if (ret) -+ return ret; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ ret = ahci_reset_controller(host); -+ if (ret) -+ return ret; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+#endif -+ -+static SIMPLE_DEV_PM_OPS(sunxi_ahci_pmo, sunxi_ahci_susp, sunxi_ahci_resume); -+ -+static const struct of_device_id sunxi_ahci_of_match[] = { -+ { .compatible = "allwinner,sun4i-a10-ahci" }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, sunxi_ahci_of_match); -+ -+static struct platform_driver sunxi_ahci_driver = { -+ .probe = sunxi_ahci_probe, -+ .remove = ata_platform_remove_one, -+ .driver = { -+ .name = "sunxi-ahci", -+ .owner = THIS_MODULE, -+ .of_match_table = sunxi_ahci_of_match, -+ .pm = &sunxi_ahci_pmo, -+ }, -+}; -+module_platform_driver(sunxi_ahci_driver); -+ -+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA platform driver"); -+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch b/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch new file mode 100644 index 0000000..3fea6ce --- /dev/null +++ b/target/linux/sunxi/patches-3.13/162-1-ahci-plat-add-dt-compat.patch @@ -0,0 +1,31 @@ +From 90189e2c18e983da0ce22e44cd610f9ce2db69b1 Mon Sep 17 00:00:00 2001 +From: Roger Quadros <rogerq@ti.com> +Date: Mon, 20 Jan 2014 16:32:33 +0200 +Subject: [PATCH] ata: ahci_platform: Add DT compatible for Synopsis DWC AHCI + controller + +Add compatible string "snps,dwc-ahci", which should be used +for Synopsis Designware SATA cores. e.g. on TI OMAP5 and DRA7 platforms. + +Signed-off-by: Roger Quadros <rogerq@ti.com> +Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci_platform.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index bdadec1..d7e55ba 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -609,6 +609,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, + { .compatible = "snps,spear-ahci", }, + { .compatible = "snps,exynos5440-ahci", }, + { .compatible = "ibm,476gtr-ahci", }, ++ { .compatible = "snps,dwc-ahci", }, + {}, + }; + MODULE_DEVICE_TABLE(of, ahci_of_match); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch b/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch deleted file mode 100644 index 6d2afac..0000000 --- a/target/linux/sunxi/patches-3.13/162-1-dt-sun4i-add-ahci-nodes.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 23af610e09f78822ade4067a400ff9ceb5b020ea Mon Sep 17 00:00:00 2001 -From: Oliver Schinagl <oliver@schinagl.nl> -Date: Tue, 3 Dec 2013 12:10:11 +0100 -Subject: [PATCH] ARM: sun4i: dts: Add ahci / sata support - -This patch adds sunxi sata support to A10 boards that have such a connector. -Some boards also feature a regulator via a GPIO and support for this is also -added. - -Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++ - arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 27 +++++++++++++++++++++++++++ - arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++ - 3 files changed, 40 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts -+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts -@@ -48,6 +48,10 @@ - status = "okay"; - }; - -+ sata: ahci@01c18000 { -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { - mmc0_cd_pin_a1000: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; ---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -@@ -51,7 +51,19 @@ - status = "okay"; - }; - -+ sata: ahci@01c18000 { -+ pwr-supply = <®_ahci_5v>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ ahci_pwr_pin_cubieboard: ahci_pwr_pin@0 { -+ allwinner,pins = "PB8"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; -@@ -102,4 +114,19 @@ - linux,default-trigger = "heartbeat"; - }; - }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ pinctrl-names = "default"; -+ -+ reg_ahci_5v: ahci-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "ahci-5v"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ pinctrl-0 = <&ahci_pwr_pin_cubieboard>; -+ gpio = <&pio 1 8 0>; -+ enable-active-high; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/sun4i-a10.dtsi -+++ b/arch/arm/boot/dts/sun4i-a10.dtsi -@@ -338,6 +338,15 @@ - status = "disabled"; - }; - -+ sata: ahci@01c18000 { -+ compatible = "allwinner,sun4i-a10-ahci"; -+ reg = <0x01c18000 0x1000>; -+ interrupts = <56>; -+ clocks = <&ahb_gates 25>, <&pll6 0>; -+ clock-names = "ahb_sata", "pll6_sata"; -+ status = "disabled"; -+ }; -+ - intc: interrupt-controller@01c20400 { - compatible = "allwinner,sun4i-ic"; - reg = <0x01c20400 0x400>; diff --git a/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch b/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch new file mode 100644 index 0000000..1ab704b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/162-2-ahci-plat-manage-sata-phy.patch @@ -0,0 +1,142 @@ +From 154a670a945c54300749d5ba008f30bbd6089017 Mon Sep 17 00:00:00 2001 +From: Roger Quadros <rogerq@ti.com> +Date: Mon, 27 Jan 2014 16:41:18 +0200 +Subject: [PATCH] ata: ahci_platform: Manage SATA PHY + +Some platforms have a PHY hooked up to the +SATA controller. The PHY needs to be initialized +and powered up for SATA to work. We do that +using the PHY framework. + +CC: Balaji T K <balajitk@ti.com> +Signed-off-by: Roger Quadros <rogerq@ti.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci.h | 2 ++ + drivers/ata/ahci_platform.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 47 insertions(+), 2 deletions(-) + +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index bf8100c..3ab7ac9 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -37,6 +37,7 @@ + + #include <linux/clk.h> + #include <linux/libata.h> ++#include <linux/phy/phy.h> + #include <linux/regulator/consumer.h> + + /* Enclosure Management Control */ +@@ -325,6 +326,7 @@ struct ahci_host_priv { + u32 em_msg_type; /* EM message type */ + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct regulator *target_pwr; /* Optional */ ++ struct phy *phy; /* If platform uses phy */ + void *plat_data; /* Other platform data */ + /* + * Optional ahci_start_engine override, if not set this gets set to the +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index d7e55ba..99d38c1 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -23,6 +23,7 @@ + #include <linux/platform_device.h> + #include <linux/libata.h> + #include <linux/ahci_platform.h> ++#include <linux/phy/phy.h> + #include "ahci.h" + + static void ahci_host_stop(struct ata_host *host); +@@ -147,6 +148,7 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) + * the following order: + * 1) Regulator + * 2) Clocks (through ahci_platform_enable_clks) ++ * 3) Phy + * + * If resource enabling fails at any point the previous enabled + * resources are disabled in reverse order. +@@ -171,8 +173,23 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) + if (rc) + goto disable_regulator; + ++ if (hpriv->phy) { ++ rc = phy_init(hpriv->phy); ++ if (rc) ++ goto disable_clks; ++ ++ rc = phy_power_on(hpriv->phy); ++ if (rc) { ++ phy_exit(hpriv->phy); ++ goto disable_clks; ++ } ++ } ++ + return 0; + ++disable_clks: ++ ahci_platform_disable_clks(hpriv); ++ + disable_regulator: + if (hpriv->target_pwr) + regulator_disable(hpriv->target_pwr); +@@ -186,14 +203,20 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) + * + * This function disables all ahci_platform managed resources in + * the following order: +- * 1) Clocks (through ahci_platform_disable_clks) +- * 2) Regulator ++ * 1) Phy ++ * 2) Clocks (through ahci_platform_disable_clks) ++ * 3) Regulator + * + * LOCKING: + * None. + */ + void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) + { ++ if (hpriv->phy) { ++ phy_power_off(hpriv->phy); ++ phy_exit(hpriv->phy); ++ } ++ + ahci_platform_disable_clks(hpriv); + + if (hpriv->target_pwr) +@@ -222,6 +245,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res) + * 2) regulator for controlling the targets power (optional) + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, + * or for non devicetree enabled platforms a single clock ++ * 4) phy (optional) + * + * LOCKING: + * None. +@@ -283,6 +307,25 @@ struct ahci_host_priv *ahci_platform_get_resources( + hpriv->clks[i] = clk; + } + ++ hpriv->phy = devm_phy_get(dev, "sata-phy"); ++ if (IS_ERR(hpriv->phy)) { ++ rc = PTR_ERR(hpriv->phy); ++ switch (rc) { ++ case -ENODEV: ++ case -ENOSYS: ++ /* continue normally */ ++ hpriv->phy = NULL; ++ break; ++ ++ case -EPROBE_DEFER: ++ goto err_out; ++ ++ default: ++ dev_err(dev, "couldn't get sata-phy\n"); ++ goto err_out; ++ } ++ } ++ + devres_remove_group(dev, NULL); + return hpriv; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch b/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch deleted file mode 100644 index 5532a3f..0000000 --- a/target/linux/sunxi/patches-3.13/162-2-dt-sun7i-add-ahci-nodes.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 4ce1f4c3ab04a697e9861b77582077b905b3f8a0 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Fri, 3 Jan 2014 10:27:51 +0100 -Subject: [PATCH] ARM: sun7i: dts: Add ahci / sata support - -This patch adds sunxi sata support to A20 boards that have such a connector. -Some boards also feature a regulator via a GPIO and support for this is also -added. - -Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 +++++++++++++++++++++++++ - arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 27 +++++++++++++++++++++++++ - arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 26 ++++++++++++++++++++++++ - arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++ - 4 files changed, 89 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -@@ -43,7 +43,19 @@ - status = "okay"; - }; - -+ sata: ahci@01c18000 { -+ pwr-supply = <®_ahci_5v>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ ahci_pwr_pin_cubieboard2: ahci_pwr_pin@0 { -+ allwinner,pins = "PB8"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; -@@ -93,4 +105,19 @@ - gpios = <&pio 7 20 0>; - }; - }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ pinctrl-names = "default"; -+ -+ reg_ahci_5v: ahci-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "ahci-5v"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ pinctrl-0 = <&ahci_pwr_pin_cubieboard2>; -+ gpio = <&pio 1 8 0>; -+ enable-active-high; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -@@ -43,6 +43,11 @@ - status = "okay"; - }; - -+ sata: ahci@01c18000 { -+ pwr-supply = <®_ahci_5v>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { - mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; -@@ -58,6 +63,13 @@ - allwinner,pull = <0>; - }; - -+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 { -+ allwinner,pins = "PH12"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - led_pins_cubietruck: led_pins@0 { - allwinner,pins = "PH7", "PH11", "PH20", "PH21"; - allwinner,function = "gpio_out"; -@@ -149,4 +161,19 @@ - gpio = <&pio 7 3 0>; - }; - }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ pinctrl-names = "default"; -+ -+ reg_ahci_5v: ahci-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "ahci-5v"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>; -+ gpio = <&pio 7 12 0>; -+ enable-active-high; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -@@ -52,7 +52,19 @@ - status = "okay"; - }; - -+ sata: ahci@01c18000 { -+ pwr-supply = <®_ahci_5v>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { -+ ahci_pwr_pin_olinuxinom: ahci_pwr_pin@0 { -+ allwinner,pins = "PB8"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <0>; -+ }; -+ - mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; - allwinner,function = "gpio_in"; -@@ -123,4 +135,18 @@ - default-state = "on"; - }; - }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_ahci_5v: ahci-5v { -+ compatible = "regulator-fixed"; -+ regulator-name = "ahci-5v"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ pinctrl-0 = <&ahci_pwr_pin_olinuxinom>; -+ gpio = <&pio 1 8 0>; -+ enable-active-high; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -433,6 +433,15 @@ - }; - }; - -+ sata: ahci@01c18000 { -+ compatible = "allwinner,sun4i-a10-ahci"; -+ reg = <0x01c18000 0x1000>; -+ interrupts = <0 56 1>; -+ clocks = <&ahb_gates 25>, <&pll6 0>; -+ clock-names = "ahb_sata", "pll6_sata"; -+ status = "disabled"; -+ }; -+ - timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; - reg = <0x01c20c00 0x90>; diff --git a/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch b/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch new file mode 100644 index 0000000..18953d1 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/162-3-ahci-plat-runtime-resume.patch @@ -0,0 +1,85 @@ +From 48379fed3987d587a25a48e155872e9d3125490d Mon Sep 17 00:00:00 2001 +From: Roger Quadros <rogerq@ti.com> +Date: Wed, 9 Oct 2013 15:08:59 +0300 +Subject: [PATCH] ata: ahci_platform: runtime resume the device before use + +On OMAP platforms the device needs to be runtime resumed before +it can be accessed. The OMAP HWMOD framework takes care of +enabling the module and its resources based on the +device's runtime PM state. + +In this patch we runtime resume during .probe() and runtime suspend +after .remove(). + +We also update the runtime PM state during .resume(). + +CC: Balaji T K <balajitk@ti.com> +Signed-off-by: Roger Quadros <rogerq@ti.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci.h | 1 + + drivers/ata/ahci_platform.c | 15 +++++++++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 3ab7ac9..51af275b 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -324,6 +324,7 @@ struct ahci_host_priv { + u32 em_loc; /* enclosure management location */ + u32 em_buf_sz; /* EM buffer size in byte */ + u32 em_msg_type; /* EM message type */ ++ bool got_runtime_pm; /* Did we do pm_runtime_get? */ + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct regulator *target_pwr; /* Optional */ + struct phy *phy; /* If platform uses phy */ +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 99d38c1..75698a4 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -24,6 +24,7 @@ + #include <linux/libata.h> + #include <linux/ahci_platform.h> + #include <linux/phy/phy.h> ++#include <linux/pm_runtime.h> + #include "ahci.h" + + static void ahci_host_stop(struct ata_host *host); +@@ -229,6 +230,11 @@ static void ahci_platform_put_resources(struct device *dev, void *res) + struct ahci_host_priv *hpriv = res; + int c; + ++ if (hpriv->got_runtime_pm) { ++ pm_runtime_put_sync(dev); ++ pm_runtime_disable(dev); ++ } ++ + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) + clk_put(hpriv->clks[c]); + } +@@ -326,6 +332,10 @@ struct ahci_host_priv *ahci_platform_get_resources( + } + } + ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ hpriv->got_runtime_pm = true; ++ + devres_remove_group(dev, NULL); + return hpriv; + +@@ -635,6 +645,11 @@ int ahci_platform_resume(struct device *dev) + if (rc) + goto disable_resources; + ++ /* We resumed so update PM runtime state */ ++ pm_runtime_disable(dev); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ + return 0; + + disable_resources: +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch b/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch new file mode 100644 index 0000000..4be6c15 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/163-ahci_sunxi-use-mdelay.patch @@ -0,0 +1,47 @@ +From 09de09bc2c236dccb0ed5ed38015e829550a5c28 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 23 Feb 2014 11:37:17 +0100 +Subject: [PATCH] ahci_sunxi: Use msleep instead of mdelay + +ahci_sunxi_phy_init is called from the probe and resume code paths, and +sleeping is safe in both, so use msleep instead of mdelay. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/ata/ahci_sunxi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c +index 001f7dfc..d1bf3f7 100644 +--- a/drivers/ata/ahci_sunxi.c ++++ b/drivers/ata/ahci_sunxi.c +@@ -90,7 +90,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base) + + /* This magic is from the original code */ + writel(0, reg_base + AHCI_RWCR); +- mdelay(5); ++ msleep(5); + + sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19)); + sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, +@@ -105,7 +105,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base) + (0x7 << 20), (0x3 << 20)); + sunxi_clrsetbits(reg_base + AHCI_PHYCS2R, + (0x1f << 5), (0x19 << 5)); +- mdelay(5); ++ msleep(5); + + sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19)); + +@@ -137,7 +137,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base) + udelay(1); + } while (1); + +- mdelay(15); ++ msleep(15); + + writel(0x7, reg_base + AHCI_RWCR); + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch b/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch new file mode 100644 index 0000000..88063ed --- /dev/null +++ b/target/linux/sunxi/patches-3.13/164-1-dt-sun4i-add-ahci.patch @@ -0,0 +1,122 @@ +From 3cae1df0e62432a80db86c80e261eb9bbed326ee Mon Sep 17 00:00:00 2001 +From: Oliver Schinagl <oliver@schinagl.nl> +Date: Tue, 3 Dec 2013 12:10:11 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add ahci / sata support + +This patch adds sunxi sata support to A10 boards that have such a connector. +Some boards also feature a regulator via a GPIO and support for this is also +added. + +Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++ + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 6 +++++ + arch/arm/boot/dts/sun4i-a10.dtsi | 8 +++++++ + arch/arm/boot/dts/sunxi-ahci-reg.dtsi | 36 ++++++++++++++++++++++++++++++ + 4 files changed, 54 insertions(+) + create mode 100644 arch/arm/boot/dts/sunxi-ahci-reg.dtsi + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index cbd2e13..d6ec839 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -35,6 +35,10 @@ + }; + }; + ++ ahci: sata@01c18000 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + emac_power_pin_a1000: emac_power_pin@0 { + allwinner,pins = "PH15"; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index b139ee6..6df237d8 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -12,6 +12,7 @@ + + /dts-v1/; + /include/ "sun4i-a10.dtsi" ++/include/ "sunxi-ahci-reg.dtsi" + + / { + model = "Cubietech Cubieboard"; +@@ -33,6 +34,11 @@ + }; + }; + ++ ahci: sata@01c18000 { ++ target-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + led_pins_cubieboard: led_pins@0 { + allwinner,pins = "PH20", "PH21"; +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 336dbec..454077a 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -338,6 +338,14 @@ + #size-cells = <0>; + }; + ++ ahci: sata@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <56>; ++ clocks = <&pll6 0>, <&ahb_gates 25>; ++ status = "disabled"; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +diff --git a/arch/arm/boot/dts/sunxi-ahci-reg.dtsi b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi +new file mode 100644 +index 0000000..7072af1 +--- /dev/null ++++ b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi +@@ -0,0 +1,36 @@ ++/* ++ * sunxi boards sata target power supply common code ++ * ++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/ { ++ soc@01c00000 { ++ pio: pinctrl@01c20800 { ++ ahci_pwr_pin_a: ahci_pwr_pin@0 { ++ allwinner,pins = "PB8"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ }; ++ }; ++ ++ reg_ahci_5v: ahci-5v { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ahci_pwr_pin_a>; ++ regulator-name = "ahci-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&pio 1 8 0>; ++ }; ++}; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch b/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch new file mode 100644 index 0000000..d43dab8 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/164-2-dt-sun7i-add-ahci.patch @@ -0,0 +1,127 @@ +From c7b99b7afc3882c1b38a15da8d1625dd448c6fee Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Fri, 3 Jan 2014 10:27:51 +0100 +Subject: [PATCH] ARM: sun7i: dt: Add ahci / sata support + +This patch adds sunxi sata support to A20 boards that have such a connector. +Some boards also feature a regulator via a GPIO and support for this is also +added. + +Signed-off-by: Olliver Schinagl <oliver@schinagl.nl> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 6 ++++++ + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 18 ++++++++++++++++++ + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 6 ++++++ + arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ + 4 files changed, 38 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index 7bf4935..07823c2 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -13,12 +13,18 @@ + + /dts-v1/; + /include/ "sun7i-a20.dtsi" ++/include/ "sunxi-ahci-reg.dtsi" + + / { + model = "Cubietech Cubieboard2"; + compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ ahci: sata@01c18000 { ++ target-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + led_pins_cubieboard2: led_pins@0 { + allwinner,pins = "PH20", "PH21"; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index 025ce52..403bd2e 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -13,13 +13,26 @@ + + /dts-v1/; + /include/ "sun7i-a20.dtsi" ++/include/ "sunxi-ahci-reg.dtsi" + + / { + model = "Cubietech Cubietruck"; + compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ ahci: sata@01c18000 { ++ target-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { ++ ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 { ++ allwinner,pins = "PH12"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + led_pins_cubietruck: led_pins@0 { + allwinner,pins = "PH7", "PH11", "PH20", "PH21"; + allwinner,function = "gpio_out"; +@@ -90,4 +103,9 @@ + gpios = <&pio 7 7 0>; + }; + }; ++ ++ reg_ahci_5v: ahci-5v { ++ pinctrl-0 = <&ahci_pwr_pin_cubietruck>; ++ gpio = <&pio 7 12 0>; ++ }; + }; +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index b02a796..d5c6799 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -13,12 +13,18 @@ + + /dts-v1/; + /include/ "sun7i-a20.dtsi" ++/include/ "sunxi-ahci-reg.dtsi" + + / { + model = "Olimex A20-Olinuxino Micro"; + compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ ahci: sata@01c18000 { ++ target-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PH2"; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index daaafd0..3385994 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -392,6 +392,14 @@ + #size-cells = <0>; + }; + ++ ahci: sata@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <0 56 4>; ++ clocks = <&pll6 0>, <&ahb_gates 25>; ++ status = "disabled"; ++ }; ++ + pio: pinctrl@01c20800 { + compatible = "allwinner,sun7i-a20-pinctrl"; + reg = <0x01c20800 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch b/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch new file mode 100644 index 0000000..99bb343 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-1-mmc-add-driver.patch @@ -0,0 +1,1187 @@ +From 00f082cbfe43bd45ddcff3572875ee9fbeafdfdd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch> +Date: Sat, 15 Feb 2014 16:37:33 +0100 +Subject: [PATCH] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner + sunxi SoCs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is based on the driver Allwinner ships in their Android kernel sources. + +Initial porting to upstream kernels done by David Lanzendörfer, additional +fixes and cleanups by Hans de Goede. + +It uses dma in bus-master mode using a built-in designware idmac controller, +which is identical to the one found in the mmc-dw hosts. +The rest of the host is not identical to mmc-dw. + +Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/Kconfig | 7 + + drivers/mmc/host/Makefile | 2 + + drivers/mmc/host/sunxi-mmc.c | 876 +++++++++++++++++++++++++++++++++++++++++++ + drivers/mmc/host/sunxi-mmc.h | 239 ++++++++++++ + 4 files changed, 1124 insertions(+) + create mode 100644 drivers/mmc/host/sunxi-mmc.c + create mode 100644 drivers/mmc/host/sunxi-mmc.h + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 1384f67..7caf266 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -689,3 +689,10 @@ config MMC_REALTEK_PCI + help + Say Y here to include driver code to support SD/MMC card interface + of Realtek PCI-E card reader ++ ++config MMC_SUNXI ++ tristate "Allwinner sunxi SD/MMC Host Controller support" ++ depends on ARCH_SUNXI ++ help ++ This selects support for the SD/MMC Host Controller on ++ Allwinner sunxi SoCs. +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index 3483b6b..f3c7c243 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -54,6 +54,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o + + obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o + ++obj-$(CONFIG_MMC_SUNXI) += sunxi-mmc.o ++ + obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o + obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o + obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +new file mode 100644 +index 0000000..2dc446c +--- /dev/null ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -0,0 +1,876 @@ ++/* ++ * Driver for sunxi SD/MMC host controllers ++ * (C) Copyright 2014-2015 Reuuimlla Technology Co., Ltd. ++ * (C) Copyright 2014-2015 Aaron Maoye <leafy.myeh@reuuimllatech.com> ++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch> ++ * (C) Copyright 2014-2015 David Lanzendörfer <david.lanzendoerfer@o2s.ch> ++ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/io.h> ++#include <linux/device.h> ++#include <linux/interrupt.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++ ++#include <linux/clk.h> ++#include <linux/clk-private.h> ++#include <linux/clk/sunxi.h> ++ ++#include <linux/gpio.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/scatterlist.h> ++#include <linux/dma-mapping.h> ++#include <linux/slab.h> ++#include <linux/regulator/consumer.h> ++ ++#include <linux/of_address.h> ++#include <linux/of_gpio.h> ++#include <linux/of_platform.h> ++ ++#include <linux/mmc/host.h> ++#include <linux/mmc/sd.h> ++#include <linux/mmc/sdio.h> ++#include <linux/mmc/mmc.h> ++#include <linux/mmc/core.h> ++#include <linux/mmc/card.h> ++#include <linux/mmc/slot-gpio.h> ++ ++#include "sunxi-mmc.h" ++ ++static int sunxi_mmc_init_host(struct mmc_host *mmc) ++{ ++ u32 rval; ++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc); ++ int ret; ++ ++ ret = clk_prepare_enable(smc_host->clk_ahb); ++ if (ret) { ++ dev_err(mmc_dev(smc_host->mmc), "AHB clk err %d\n", ret); ++ return ret; ++ } ++ ret = clk_prepare_enable(smc_host->clk_mod); ++ if (ret) { ++ dev_err(mmc_dev(smc_host->mmc), "MOD clk err %d\n", ret); ++ clk_disable_unprepare(smc_host->clk_ahb); ++ return ret; ++ } ++ ++ /* reset controller */ ++ rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HARDWARE_RESET; ++ mci_writel(smc_host, REG_GCTRL, rval); ++ ++ mci_writel(smc_host, REG_FTRGL, 0x20070008); ++ mci_writel(smc_host, REG_TMOUT, 0xffffffff); ++ mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask); ++ mci_writel(smc_host, REG_RINTR, 0xffffffff); ++ mci_writel(smc_host, REG_DBGC, 0xdeb); ++ mci_writel(smc_host, REG_FUNS, 0xceaa0000); ++ mci_writel(smc_host, REG_DLBA, smc_host->sg_dma); ++ rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTERRUPT_ENABLE_BIT; ++ rval &= ~SDXC_ACCESS_DONE_DIRECT; ++ mci_writel(smc_host, REG_GCTRL, rval); ++ ++ return 0; ++} ++ ++static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host) ++{ ++ mci_writel(smc_host, REG_GCTRL, SDXC_HARDWARE_RESET); ++ clk_disable_unprepare(smc_host->clk_ahb); ++ clk_disable_unprepare(smc_host->clk_mod); ++} ++ ++/* /\* UHS-I Operation Modes */ ++/* * DS 25MHz 12.5MB/s 3.3V */ ++/* * HS 50MHz 25MB/s 3.3V */ ++/* * SDR12 25MHz 12.5MB/s 1.8V */ ++/* * SDR25 50MHz 25MB/s 1.8V */ ++/* * SDR50 100MHz 50MB/s 1.8V */ ++/* * SDR104 208MHz 104MB/s 1.8V */ ++/* * DDR50 50MHz 50MB/s 1.8V */ ++/* * MMC Operation Modes */ ++/* * DS 26MHz 26MB/s 3/1.8/1.2V */ ++/* * HS 52MHz 52MB/s 3/1.8/1.2V */ ++/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */ ++/* * HS200 200MHz 200MB/s 1.8/1.2V */ ++/* * */ ++/* * Spec. Timing */ ++/* * SD3.0 */ ++/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */ ++/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */ ++/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */ ++/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */ ++/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */ ++/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */ ++/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ ++ ++/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */ ++/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */ ++/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */ ++/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */ ++/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */ ++ ++/* * eMMC4.5 */ ++/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */ ++/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ ++/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */ ++/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */ ++/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */ ++/* *\/ */ ++ ++static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, ++ struct mmc_data *data) ++{ ++ struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; ++ struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma; ++ int i, max_len = (1 << host->idma_des_size_bits); ++ ++ for (i = 0; i < data->sg_len; i++) { ++ pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | ++ SDXC_IDMAC_DES0_DIC; ++ ++ if (data->sg[i].length == max_len) ++ pdes[i].buf_size = 0; /* 0 == max_len */ ++ else ++ pdes[i].buf_size = data->sg[i].length; ++ ++ pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]); ++ pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1]; ++ } ++ ++ pdes[0].config |= SDXC_IDMAC_DES0_FD; ++ pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; ++ ++ wmb(); /* Ensure idma_des hit main mem before we start the idmac */ ++} ++ ++static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data) ++{ ++ if (data->flags & MMC_DATA_WRITE) ++ return DMA_TO_DEVICE; ++ else ++ return DMA_FROM_DEVICE; ++} ++ ++static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host, ++ struct mmc_data *data) ++{ ++ u32 dma_len; ++ u32 i; ++ u32 temp; ++ struct scatterlist *sg; ++ ++ dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ if (dma_len == 0) { ++ dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n"); ++ return -ENOMEM; ++ } ++ ++ for_each_sg(data->sg, sg, data->sg_len, i) { ++ if (sg->offset & 3 || sg->length & 3) { ++ dev_err(mmc_dev(smc_host->mmc), ++ "unaligned scatterlist: os %x length %d\n", ++ sg->offset, sg->length); ++ return -EINVAL; ++ } ++ } ++ ++ sunxi_mmc_init_idma_des(smc_host, data); ++ ++ temp = mci_readl(smc_host, REG_GCTRL); ++ temp |= SDXC_DMA_ENABLE_BIT; ++ mci_writel(smc_host, REG_GCTRL, temp); ++ temp |= SDXC_DMA_RESET; ++ mci_writel(smc_host, REG_GCTRL, temp); ++ mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_SOFT_RESET); ++ ++ if (!(data->flags & MMC_DATA_WRITE)) ++ mci_writel(smc_host, REG_IDIE, SDXC_IDMAC_RECEIVE_INTERRUPT); ++ ++ mci_writel(smc_host, REG_DMAC, SDXC_IDMAC_FIX_BURST | SDXC_IDMAC_IDMA_ON); ++ ++ return 0; ++} ++ ++static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host, ++ struct mmc_request *req) ++{ ++ u32 cmd_val = SDXC_START | SDXC_RESPONSE_EXPIRE | SDXC_STOP_ABORT_CMD ++ | SDXC_CHECK_RESPONSE_CRC | MMC_STOP_TRANSMISSION; ++ u32 ri = 0; ++ unsigned long expire = jiffies + msecs_to_jiffies(1000); ++ ++ mci_writel(host, REG_CARG, 0); ++ mci_writel(host, REG_CMDR, cmd_val); ++ ++ do { ++ ri = mci_readl(host, REG_RINTR); ++ } while (!(ri & (SDXC_COMMAND_DONE | SDXC_INTERRUPT_ERROR_BIT)) && ++ time_before(jiffies, expire)); ++ ++ if (ri & SDXC_INTERRUPT_ERROR_BIT) { ++ dev_err(mmc_dev(host->mmc), "send stop command failed\n"); ++ if (req->stop) ++ req->stop->resp[0] = -ETIMEDOUT; ++ } else { ++ if (req->stop) ++ req->stop->resp[0] = mci_readl(host, REG_RESP0); ++ } ++ ++ mci_writel(host, REG_RINTR, 0xffff); ++} ++ ++static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host) ++{ ++ struct mmc_command *cmd = smc_host->mrq->cmd; ++ struct mmc_data *data = smc_host->mrq->data; ++ ++ /* For some cmds timeout is normal with sd/mmc cards */ ++ if ((smc_host->int_sum & SDXC_INTERRUPT_ERROR_BIT) == SDXC_RESPONSE_TIMEOUT && ++ (cmd->opcode == SD_IO_SEND_OP_COND || cmd->opcode == SD_IO_RW_DIRECT)) ++ return; ++ ++ dev_err(mmc_dev(smc_host->mmc), ++ "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", ++ smc_host->mmc->index, cmd->opcode, ++ data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", ++ smc_host->int_sum & SDXC_RESPONSE_ERROR ? " RE" : "", ++ smc_host->int_sum & SDXC_RESPONSE_CRC_ERROR ? " RCE" : "", ++ smc_host->int_sum & SDXC_DATA_CRC_ERROR ? " DCE" : "", ++ smc_host->int_sum & SDXC_RESPONSE_TIMEOUT ? " RTO" : "", ++ smc_host->int_sum & SDXC_DATA_TIMEOUT ? " DTO" : "", ++ smc_host->int_sum & SDXC_FIFO_RUN_ERROR ? " FE" : "", ++ smc_host->int_sum & SDXC_HARD_WARE_LOCKED ? " HL" : "", ++ smc_host->int_sum & SDXC_START_BIT_ERROR ? " SBE" : "", ++ smc_host->int_sum & SDXC_END_BIT_ERROR ? " EBE" : "" ++ ); ++} ++ ++static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host) ++{ ++ struct mmc_request *mrq; ++ unsigned long iflags; ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ ++ mrq = host->mrq; ++ if (!mrq) { ++ spin_unlock_irqrestore(&host->lock, iflags); ++ dev_err(mmc_dev(host->mmc), "no request to finalize\n"); ++ return; ++ } ++ ++ if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) { ++ sunxi_mmc_dump_errinfo(host); ++ mrq->cmd->error = -ETIMEDOUT; ++ if (mrq->data) ++ mrq->data->error = -ETIMEDOUT; ++ if (mrq->stop) ++ mrq->stop->error = -ETIMEDOUT; ++ } else { ++ if (mrq->cmd->flags & MMC_RSP_136) { ++ mrq->cmd->resp[0] = mci_readl(host, REG_RESP3); ++ mrq->cmd->resp[1] = mci_readl(host, REG_RESP2); ++ mrq->cmd->resp[2] = mci_readl(host, REG_RESP1); ++ mrq->cmd->resp[3] = mci_readl(host, REG_RESP0); ++ } else { ++ mrq->cmd->resp[0] = mci_readl(host, REG_RESP0); ++ } ++ if (mrq->data) ++ mrq->data->bytes_xfered = ++ mrq->data->blocks * mrq->data->blksz; ++ } ++ ++ if (mrq->data) { ++ struct mmc_data *data = mrq->data; ++ u32 temp; ++ ++ mci_writel(host, REG_IDST, 0x337); ++ mci_writel(host, REG_DMAC, 0); ++ temp = mci_readl(host, REG_GCTRL); ++ mci_writel(host, REG_GCTRL, temp|SDXC_DMA_RESET); ++ temp &= ~SDXC_DMA_ENABLE_BIT; ++ mci_writel(host, REG_GCTRL, temp); ++ temp |= SDXC_FIFO_RESET; ++ mci_writel(host, REG_GCTRL, temp); ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, ++ sunxi_mmc_get_dma_dir(data)); ++ } ++ ++ mci_writel(host, REG_RINTR, 0xffff); ++ ++ dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n", ++ mrq->cmd->resp[0], mrq->cmd->resp[1], ++ mrq->cmd->resp[2], mrq->cmd->resp[3]); ++ ++ host->mrq = NULL; ++ host->int_sum = 0; ++ host->wait_dma = 0; ++ ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ if (mrq->data && mrq->data->error) { ++ dev_err(mmc_dev(host->mmc), ++ "data error, sending stop command\n"); ++ sunxi_mmc_send_manual_stop(host, mrq); ++ } ++ ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id) ++{ ++ struct sunxi_mmc_host *host = dev_id; ++ u32 finalize = 0; ++ u32 sdio_int = 0; ++ u32 msk_int; ++ u32 idma_int; ++ ++ spin_lock(&host->lock); ++ ++ idma_int = mci_readl(host, REG_IDST); ++ msk_int = mci_readl(host, REG_MISTA); ++ ++ dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n", ++ host->mrq, msk_int, idma_int); ++ ++ if (host->mrq) { ++ if (idma_int & SDXC_IDMAC_RECEIVE_INTERRUPT) ++ host->wait_dma = 0; ++ ++ host->int_sum |= msk_int; ++ ++ /* Wait for COMMAND_DONE on RESPONSE_TIMEOUT before finishing the req */ ++ if ((host->int_sum & SDXC_RESPONSE_TIMEOUT) && ++ !(host->int_sum & SDXC_COMMAND_DONE)) ++ mci_writel(host, REG_IMASK, ++ host->sdio_imask | SDXC_COMMAND_DONE); ++ else if (host->int_sum & SDXC_INTERRUPT_ERROR_BIT) ++ finalize = 1; /* Don't wait for dma on error */ ++ else if (host->int_sum & SDXC_INTERRUPT_DONE_BIT && !host->wait_dma) ++ finalize = 1; /* Done */ ++ ++ if (finalize) { ++ mci_writel(host, REG_IMASK, host->sdio_imask); ++ mci_writel(host, REG_IDIE, 0); ++ } ++ } ++ ++ if (msk_int & SDXC_SDIO_INTERRUPT) ++ sdio_int = 1; ++ ++ mci_writel(host, REG_RINTR, msk_int); ++ mci_writel(host, REG_IDST, idma_int); ++ ++ spin_unlock(&host->lock); ++ ++ if (finalize) ++ tasklet_schedule(&host->tasklet); ++ ++ if (sdio_int) ++ mmc_signal_sdio_irq(host->mmc); ++ ++ return IRQ_HANDLED; ++} ++ ++static void sunxi_mmc_tasklet(unsigned long data) ++{ ++ struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data; ++ sunxi_mmc_finalize_request(smc_host); ++} ++ ++static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) ++{ ++ unsigned long expire = jiffies + msecs_to_jiffies(2000); ++ u32 rval; ++ ++ rval = mci_readl(host, REG_CLKCR); ++ rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON); ++ ++ if (oclk_en) ++ rval |= SDXC_CARD_CLOCK_ON; ++ ++ if (!host->io_flag) ++ rval |= SDXC_LOW_POWER_ON; ++ ++ mci_writel(host, REG_CLKCR, rval); ++ ++ rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER; ++ if (host->voltage_switching) ++ rval |= SDXC_VOLTAGE_SWITCH; ++ mci_writel(host, REG_CMDR, rval); ++ ++ do { ++ rval = mci_readl(host, REG_CMDR); ++ } while (time_before(jiffies, expire) && (rval & SDXC_START)); ++ ++ if (rval & SDXC_START) { ++ dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n"); ++ host->ferror = 1; ++ } ++} ++ ++static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host, ++ u32 oclk_dly, u32 sclk_dly) ++{ ++ unsigned long iflags; ++ struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); ++ ++ spin_lock_irqsave(&smc_host->lock, iflags); ++ clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); ++ spin_unlock_irqrestore(&smc_host->lock, iflags); ++} ++ ++struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = { ++ { MMC_CLK_400K, 0, 7 }, ++ { MMC_CLK_25M, 0, 5 }, ++ { MMC_CLK_50M, 3, 5 }, ++ { MMC_CLK_50MDDR, 2, 4 }, ++ { MMC_CLK_50MDDR_8BIT, 2, 4 }, ++ { MMC_CLK_100M, 1, 4 }, ++ { MMC_CLK_200M, 1, 4 }, ++}; ++ ++static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, ++ unsigned int rate) ++{ ++ u32 newrate; ++ u32 src_clk; ++ u32 oclk_dly; ++ u32 sclk_dly; ++ u32 temp; ++ struct sunxi_mmc_clk_dly *dly = NULL; ++ ++ newrate = clk_round_rate(smc_host->clk_mod, rate); ++ if (smc_host->clk_mod_rate == newrate) { ++ dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n", ++ rate, newrate); ++ return; ++ } ++ ++ dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n", ++ rate, newrate); ++ ++ /* setting clock rate */ ++ clk_disable(smc_host->clk_mod); ++ clk_set_rate(smc_host->clk_mod, newrate); ++ clk_enable(smc_host->clk_mod); ++ smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod); ++ dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate); ++ ++ sunxi_mmc_oclk_onoff(smc_host, 0); ++ /* clear internal divider */ ++ temp = mci_readl(smc_host, REG_CLKCR); ++ temp &= ~0xff; ++ mci_writel(smc_host, REG_CLKCR, temp); ++ ++ /* determine delays */ ++ if (rate <= 400000) { ++ dly = &mmc_clk_dly[MMC_CLK_400K]; ++ } else if (rate <= 25000000) { ++ dly = &mmc_clk_dly[MMC_CLK_25M]; ++ } else if (rate <= 50000000) { ++ if (smc_host->ddr) { ++ if (smc_host->bus_width == 8) ++ dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT]; ++ else ++ dly = &mmc_clk_dly[MMC_CLK_50MDDR]; ++ } else { ++ dly = &mmc_clk_dly[MMC_CLK_50M]; ++ } ++ } else if (rate <= 104000000) { ++ dly = &mmc_clk_dly[MMC_CLK_100M]; ++ } else if (rate <= 208000000) { ++ dly = &mmc_clk_dly[MMC_CLK_200M]; ++ } else { ++ dly = &mmc_clk_dly[MMC_CLK_50M]; ++ } ++ ++ oclk_dly = dly->oclk_dly; ++ sclk_dly = dly->sclk_dly; ++ ++ src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod)); ++ ++ if (src_clk >= 300000000 && src_clk <= 400000000) { ++ if (oclk_dly) ++ oclk_dly--; ++ if (sclk_dly) ++ sclk_dly--; ++ } ++ ++ sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly); ++ sunxi_mmc_oclk_onoff(smc_host, 1); ++ ++ /* oclk_onoff sets various irq status bits, clear these */ ++ mci_writel(smc_host, REG_RINTR, ++ mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT); ++} ++ ++static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ u32 temp; ++ s32 err; ++ ++ /* Set the power state */ ++ switch (ios->power_mode) { ++ case MMC_POWER_ON: ++ break; ++ ++ case MMC_POWER_UP: ++ if (!IS_ERR(host->vmmc)) { ++ mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd); ++ udelay(200); ++ } ++ ++ err = sunxi_mmc_init_host(mmc); ++ if (err) { ++ host->ferror = 1; ++ return; ++ } ++ enable_irq(host->irq); ++ ++ dev_dbg(mmc_dev(host->mmc), "power on!\n"); ++ host->ferror = 0; ++ break; ++ ++ case MMC_POWER_OFF: ++ dev_dbg(mmc_dev(host->mmc), "power off!\n"); ++ disable_irq(host->irq); ++ sunxi_mmc_exit_host(host); ++ if (!IS_ERR(host->vmmc)) ++ mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); ++ host->ferror = 0; ++ break; ++ } ++ ++ /* set bus width */ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_1: ++ mci_writel(host, REG_WIDTH, SDXC_WIDTH1); ++ host->bus_width = 1; ++ break; ++ case MMC_BUS_WIDTH_4: ++ mci_writel(host, REG_WIDTH, SDXC_WIDTH4); ++ host->bus_width = 4; ++ break; ++ case MMC_BUS_WIDTH_8: ++ mci_writel(host, REG_WIDTH, SDXC_WIDTH8); ++ host->bus_width = 8; ++ break; ++ } ++ ++ /* set ddr mode */ ++ temp = mci_readl(host, REG_GCTRL); ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ temp |= SDXC_DDR_MODE; ++ host->ddr = 1; ++ } else { ++ temp &= ~SDXC_DDR_MODE; ++ host->ddr = 0; ++ } ++ mci_writel(host, REG_GCTRL, temp); ++ ++ /* set up clock */ ++ if (ios->clock && ios->power_mode) { ++ dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock); ++ sunxi_mmc_clk_set_rate(host, ios->clock); ++ usleep_range(50000, 55000); ++ } ++} ++ ++static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc); ++ unsigned long flags; ++ int ret; ++ u32 imask; ++ ++ spin_lock_irqsave(&smc_host->lock, flags); ++ ++ /* Make sure the controller is in a sane state before enabling irqs */ ++ ret = sunxi_mmc_init_host(host->mmc); ++ if (ret) { ++ spin_unlock_irqrestore(&smc_host->lock, flags); ++ return ret; ++ } ++ ++ imask = mci_readl(smc_host, REG_IMASK); ++ if (enable) { ++ smc_host->sdio_imask = SDXC_SDIO_INTERRUPT; ++ imask |= SDXC_SDIO_INTERRUPT; ++ } else { ++ smc_host->sdio_imask = 0; ++ imask &= ~SDXC_SDIO_INTERRUPT; ++ } ++ mci_writel(smc_host, REG_IMASK, imask); ++ spin_unlock_irqrestore(&smc_host->lock, flags); ++} ++ ++static void sunxi_mmc_hw_reset(struct mmc_host *mmc) ++{ ++ struct sunxi_mmc_host *smc_host = mmc_priv(mmc); ++ mci_writel(smc_host, REG_HWRST, 0); ++ udelay(10); ++ mci_writel(smc_host, REG_HWRST, 1); ++ udelay(300); ++} ++ ++static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd = mrq->cmd; ++ struct mmc_data *data = mrq->data; ++ unsigned long iflags; ++ u32 imask = SDXC_INTERRUPT_ERROR_BIT; ++ u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f); ++ u32 byte_cnt = 0; ++ int ret; ++ ++ if (!mmc_gpio_get_cd(mmc) || host->ferror) { ++ dev_dbg(mmc_dev(host->mmc), "no medium present\n"); ++ mrq->cmd->error = -ENOMEDIUM; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ if (data) { ++ byte_cnt = data->blksz * data->blocks; ++ mci_writel(host, REG_BLKSZ, data->blksz); ++ mci_writel(host, REG_BCNTR, byte_cnt); ++ ret = sunxi_mmc_prepare_dma(host, data); ++ if (ret < 0) { ++ dev_err(mmc_dev(host->mmc), "prepare DMA failed\n"); ++ cmd->error = ret; ++ cmd->data->error = ret; ++ mmc_request_done(host->mmc, mrq); ++ return; ++ } ++ } ++ ++ if (cmd->opcode == MMC_GO_IDLE_STATE) { ++ cmd_val |= SDXC_SEND_INIT_SEQUENCE; ++ imask |= SDXC_COMMAND_DONE; ++ } ++ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) { ++ cmd_val |= SDXC_VOLTAGE_SWITCH; ++ imask |= SDXC_VOLTAGE_CHANGE_DONE; ++ host->voltage_switching = 1; ++ sunxi_mmc_oclk_onoff(host, 1); ++ } ++ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ cmd_val |= SDXC_RESPONSE_EXPIRE; ++ if (cmd->flags & MMC_RSP_136) ++ cmd_val |= SDXC_LONG_RESPONSE; ++ if (cmd->flags & MMC_RSP_CRC) ++ cmd_val |= SDXC_CHECK_RESPONSE_CRC; ++ ++ if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) { ++ cmd_val |= SDXC_DATA_EXPIRE | SDXC_WAIT_PRE_OVER; ++ if (cmd->data->flags & MMC_DATA_STREAM) { ++ imask |= SDXC_AUTO_COMMAND_DONE; ++ cmd_val |= SDXC_SEQUENCE_MODE | SDXC_SEND_AUTO_STOP; ++ } ++ if (cmd->data->stop) { ++ imask |= SDXC_AUTO_COMMAND_DONE; ++ cmd_val |= SDXC_SEND_AUTO_STOP; ++ } else ++ imask |= SDXC_DATA_OVER; ++ ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ cmd_val |= SDXC_WRITE; ++ else ++ host->wait_dma = 1; ++ } else ++ imask |= SDXC_COMMAND_DONE; ++ } else ++ imask |= SDXC_COMMAND_DONE; ++ ++ dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n", ++ cmd_val & 0x3f, cmd_val, cmd->arg, imask, ++ mrq->data ? mrq->data->blksz * mrq->data->blocks : 0); ++ ++ spin_lock_irqsave(&host->lock, iflags); ++ host->mrq = mrq; ++ mci_writel(host, REG_IMASK, host->sdio_imask | imask); ++ spin_unlock_irqrestore(&host->lock, iflags); ++ ++ mci_writel(host, REG_CARG, cmd->arg); ++ mci_writel(host, REG_CMDR, cmd_val); ++} ++ ++static const struct of_device_id sunxi_mmc_of_match[] = { ++ { .compatible = "allwinner,sun4i-a10-mmc", }, ++ { .compatible = "allwinner,sun5i-a13-mmc", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); ++ ++static struct mmc_host_ops sunxi_mmc_ops = { ++ .request = sunxi_mmc_request, ++ .set_ios = sunxi_mmc_set_ios, ++ .get_ro = mmc_gpio_get_ro, ++ .get_cd = mmc_gpio_get_cd, ++ .enable_sdio_irq = sunxi_mmc_enable_sdio_irq, ++ .hw_reset = sunxi_mmc_hw_reset, ++}; ++ ++static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, ++ struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ int ret; ++ ++ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc")) ++ host->idma_des_size_bits = 13; ++ else ++ host->idma_des_size_bits = 16; ++ ++ host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc"); ++ if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ host->reg_base = devm_ioremap_resource(&pdev->dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ if (IS_ERR(host->reg_base)) ++ return PTR_ERR(host->reg_base); ++ ++ host->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(host->clk_ahb)) { ++ dev_err(&pdev->dev, "Could not get ahb clock\n"); ++ return PTR_ERR(host->clk_ahb); ++ } ++ ++ host->clk_mod = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(host->clk_mod)) { ++ dev_err(&pdev->dev, "Could not get mod clock\n"); ++ return PTR_ERR(host->clk_mod); ++ } ++ ++ /* Make sure the controller is in a sane state before enabling irqs */ ++ ret = sunxi_mmc_init_host(host->mmc); ++ if (ret) ++ return ret; ++ ++ host->irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0, ++ "sunxi-mmc", host); ++ if (ret == 0) ++ disable_irq(host->irq); ++ ++ /* And put it back in reset */ ++ sunxi_mmc_exit_host(host); ++ ++ return ret; ++} ++ ++static int sunxi_mmc_probe(struct platform_device *pdev) ++{ ++ struct sunxi_mmc_host *host; ++ struct mmc_host *mmc; ++ int ret; ++ ++ mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); ++ if (!mmc) { ++ dev_err(&pdev->dev, "mmc alloc host failed\n"); ++ return -ENOMEM; ++ } ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto error_free_host; ++ ++ host = mmc_priv(mmc); ++ host->mmc = mmc; ++ spin_lock_init(&host->lock); ++ tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host); ++ ++ ret = sunxi_mmc_resource_request(host, pdev); ++ if (ret) ++ goto error_free_host; ++ ++ host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, ++ &host->sg_dma, GFP_KERNEL); ++ if (!host->sg_cpu) { ++ dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n"); ++ ret = -ENOMEM; ++ goto error_free_host; ++ } ++ ++ mmc->ops = &sunxi_mmc_ops; ++ mmc->max_blk_count = 8192; ++ mmc->max_blk_size = 4096; ++ mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); ++ mmc->max_seg_size = (1 << host->idma_des_size_bits); ++ mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; ++ /* 400kHz ~ 50MHz */ ++ mmc->f_min = 400000; ++ mmc->f_max = 50000000; ++ /* available voltages */ ++ if (!IS_ERR(host->vmmc)) ++ mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc); ++ else ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | ++ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | ++ MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_DRIVER_TYPE_A; ++ mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; ++ ++ ret = mmc_add_host(mmc); ++ ++ if (ret) ++ goto error_free_dma; ++ ++ dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); ++ platform_set_drvdata(pdev, mmc); ++ return 0; ++ ++error_free_dma: ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); ++error_free_host: ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static int sunxi_mmc_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct sunxi_mmc_host *host = mmc_priv(mmc); ++ ++ mmc_remove_host(mmc); ++ sunxi_mmc_exit_host(host); ++ tasklet_disable(&host->tasklet); ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); ++ mmc_free_host(mmc); ++ ++ return 0; ++} ++ ++static struct platform_driver sunxi_mmc_driver = { ++ .driver = { ++ .name = "sunxi-mmc", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(sunxi_mmc_of_match), ++ }, ++ .probe = sunxi_mmc_probe, ++ .remove = sunxi_mmc_remove, ++}; ++module_platform_driver(sunxi_mmc_driver); ++ ++MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>"); ++MODULE_ALIAS("platform:sunxi-mmc"); +diff --git a/drivers/mmc/host/sunxi-mmc.h b/drivers/mmc/host/sunxi-mmc.h +new file mode 100644 +index 0000000..cbd6d49 +--- /dev/null ++++ b/drivers/mmc/host/sunxi-mmc.h +@@ -0,0 +1,239 @@ ++/* ++ * Driver for sunxi SD/MMC host controllers ++ * (C) Copyright 2014-2015 Reuuimlla Technology Co., Ltd. ++ * (C) Copyright 2014-2015 Aaron Maoye <leafy.myeh@reuuimllatech.com> ++ * (C) Copyright 2014-2015 O2S GmbH <www.o2s.ch> ++ * (C) Copyright 2014-2015 David Lanzendörfer <david.lanzendoerfer@o2s.ch> ++ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ */ ++ ++#ifndef __SUNXI_MCI_H__ ++#define __SUNXI_MCI_H__ ++ ++/* register offset define */ ++#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */ ++#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */ ++#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */ ++#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */ ++#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */ ++#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */ ++#define SDXC_REG_CMDR (0x18) /* SMC Command Register */ ++#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */ ++#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */ ++#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */ ++#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */ ++#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */ ++#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */ ++#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ ++#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ ++#define SDXC_REG_STAS (0x3C) /* SMC Status Register */ ++#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ ++#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ ++#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ ++#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ ++#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ ++#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ ++#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ ++#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ ++#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ ++#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ ++#define SDXC_REG_CHDA (0x90) ++#define SDXC_REG_CBDA (0x94) ++ ++#define mci_readl(host, reg) \ ++ readl((host)->reg_base + SDXC_##reg) ++#define mci_writel(host, reg, value) \ ++ writel((value), (host)->reg_base + SDXC_##reg) ++ ++/* global control register bits */ ++#define SDXC_SOFT_RESET BIT(0) ++#define SDXC_FIFO_RESET BIT(1) ++#define SDXC_DMA_RESET BIT(2) ++#define SDXC_HARDWARE_RESET (SDXC_SOFT_RESET|SDXC_FIFO_RESET|SDXC_DMA_RESET) ++#define SDXC_INTERRUPT_ENABLE_BIT BIT(4) ++#define SDXC_DMA_ENABLE_BIT BIT(5) ++#define SDXC_DEBOUNCE_ENABLE_BIT BIT(8) ++#define SDXC_POSEDGE_LATCH_DATA BIT(9) ++#define SDXC_DDR_MODE BIT(10) ++#define SDXC_MEMORY_ACCESS_DONE BIT(29) ++#define SDXC_ACCESS_DONE_DIRECT BIT(30) ++#define SDXC_ACCESS_BY_AHB BIT(31) ++#define SDXC_ACCESS_BY_DMA (0U << 31) ++/* clock control bits */ ++#define SDXC_CARD_CLOCK_ON BIT(16) ++#define SDXC_LOW_POWER_ON BIT(17) ++/* bus width */ ++#define SDXC_WIDTH1 (0) ++#define SDXC_WIDTH4 (1) ++#define SDXC_WIDTH8 (2) ++/* smc command bits */ ++#define SDXC_RESPONSE_EXPIRE BIT(6) ++#define SDXC_LONG_RESPONSE BIT(7) ++#define SDXC_CHECK_RESPONSE_CRC BIT(8) ++#define SDXC_DATA_EXPIRE BIT(9) ++#define SDXC_WRITE BIT(10) ++#define SDXC_SEQUENCE_MODE BIT(11) ++#define SDXC_SEND_AUTO_STOP BIT(12) ++#define SDXC_WAIT_PRE_OVER BIT(13) ++#define SDXC_STOP_ABORT_CMD BIT(14) ++#define SDXC_SEND_INIT_SEQUENCE BIT(15) ++#define SDXC_UPCLK_ONLY BIT(21) ++#define SDXC_READ_CEATA_DEV BIT(22) ++#define SDXC_CCS_EXPIRE BIT(23) ++#define SDXC_ENABLE_BIT_BOOT BIT(24) ++#define SDXC_ALT_BOOT_OPTIONS BIT(25) ++#define SDXC_BOOT_ACK_EXPIRE BIT(26) ++#define SDXC_BOOT_ABORT BIT(27) ++#define SDXC_VOLTAGE_SWITCH BIT(28) ++#define SDXC_USE_HOLD_REGISTER BIT(29) ++#define SDXC_START BIT(31) ++/* interrupt bits */ ++#define SDXC_RESPONSE_ERROR BIT(1) ++#define SDXC_COMMAND_DONE BIT(2) ++#define SDXC_DATA_OVER BIT(3) ++#define SDXC_TX_DATA_REQUEST BIT(4) ++#define SDXC_RX_DATA_REQUEST BIT(5) ++#define SDXC_RESPONSE_CRC_ERROR BIT(6) ++#define SDXC_DATA_CRC_ERROR BIT(7) ++#define SDXC_RESPONSE_TIMEOUT BIT(8) ++#define SDXC_DATA_TIMEOUT BIT(9) ++#define SDXC_VOLTAGE_CHANGE_DONE BIT(10) ++#define SDXC_FIFO_RUN_ERROR BIT(11) ++#define SDXC_HARD_WARE_LOCKED BIT(12) ++#define SDXC_START_BIT_ERROR BIT(13) ++#define SDXC_AUTO_COMMAND_DONE BIT(14) ++#define SDXC_END_BIT_ERROR BIT(15) ++#define SDXC_SDIO_INTERRUPT BIT(16) ++#define SDXC_CARD_INSERT BIT(30) ++#define SDXC_CARD_REMOVE BIT(31) ++#define SDXC_INTERRUPT_ERROR_BIT (SDXC_RESPONSE_ERROR | SDXC_RESPONSE_CRC_ERROR | \ ++ SDXC_DATA_CRC_ERROR | SDXC_RESPONSE_TIMEOUT | \ ++ SDXC_DATA_TIMEOUT | SDXC_FIFO_RUN_ERROR | \ ++ SDXC_HARD_WARE_LOCKED | SDXC_START_BIT_ERROR | \ ++ SDXC_END_BIT_ERROR) /* 0xbbc2 */ ++#define SDXC_INTERRUPT_DONE_BIT (SDXC_AUTO_COMMAND_DONE | SDXC_DATA_OVER | \ ++ SDXC_COMMAND_DONE | SDXC_VOLTAGE_CHANGE_DONE) ++/* status */ ++#define SDXC_RXWL_FLAG BIT(0) ++#define SDXC_TXWL_FLAG BIT(1) ++#define SDXC_FIFO_EMPTY BIT(2) ++#define SDXC_FIFO_FULL BIT(3) ++#define SDXC_CARD_PRESENT BIT(8) ++#define SDXC_CARD_DATA_BUSY BIT(9) ++#define SDXC_DATA_FSM_BUSY BIT(10) ++#define SDXC_DMA_REQUEST BIT(31) ++#define SDXC_FIFO_SIZE (16) ++/* Function select */ ++#define SDXC_CEATA_ON (0xceaaU << 16) ++#define SDXC_SEND_IRQ_RESPONSE BIT(0) ++#define SDXC_SDIO_READ_WAIT BIT(1) ++#define SDXC_ABORT_READ_DATA BIT(2) ++#define SDXC_SEND_CCSD BIT(8) ++#define SDXC_SEND_AUTO_STOPCCSD BIT(9) ++#define SDXC_CEATA_DEV_INTERRUPT_ENABLE_BIT BIT(10) ++/* IDMA controller bus mod bit field */ ++#define SDXC_IDMAC_SOFT_RESET BIT(0) ++#define SDXC_IDMAC_FIX_BURST BIT(1) ++#define SDXC_IDMAC_IDMA_ON BIT(7) ++#define SDXC_IDMAC_REFETCH_DES BIT(31) ++/* IDMA status bit field */ ++#define SDXC_IDMAC_TRANSMIT_INTERRUPT BIT(0) ++#define SDXC_IDMAC_RECEIVE_INTERRUPT BIT(1) ++#define SDXC_IDMAC_FATAL_BUS_ERROR BIT(2) ++#define SDXC_IDMAC_DESTINATION_INVALID BIT(4) ++#define SDXC_IDMAC_CARD_ERROR_SUM BIT(5) ++#define SDXC_IDMAC_NORMAL_INTERRUPT_SUM BIT(8) ++#define SDXC_IDMAC_ABNORMAL_INTERRUPT_SUM BIT(9) ++#define SDXC_IDMAC_HOST_ABORT_INTERRUPT_TX BIT(10) ++#define SDXC_IDMAC_HOST_ABORT_INTERRUPT_RX BIT(10) ++#define SDXC_IDMAC_IDLE (0U << 13) ++#define SDXC_IDMAC_SUSPEND (1U << 13) ++#define SDXC_IDMAC_DESC_READ (2U << 13) ++#define SDXC_IDMAC_DESC_CHECK (3U << 13) ++#define SDXC_IDMAC_READ_REQUEST_WAIT (4U << 13) ++#define SDXC_IDMAC_WRITE_REQUEST_WAIT (5U << 13) ++#define SDXC_IDMAC_READ (6U << 13) ++#define SDXC_IDMAC_WRITE (7U << 13) ++#define SDXC_IDMAC_DESC_CLOSE (8U << 13) ++ ++/* ++* If the idma-des-size-bits of property is ie 13, bufsize bits are: ++* Bits 0-12: buf1 size ++* Bits 13-25: buf2 size ++* Bits 26-31: not used ++* Since we only ever set buf1 size, we can simply store it directly. ++*/ ++#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */ ++#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */ ++#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */ ++#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */ ++#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */ ++#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ ++#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ ++ ++struct sunxi_idma_des { ++ u32 config; ++ u32 buf_size; ++ u32 buf_addr_ptr1; ++ u32 buf_addr_ptr2; ++}; ++ ++struct sunxi_mmc_host { ++ struct mmc_host *mmc; ++ struct regulator *vmmc; ++ ++ /* IO mapping base */ ++ void __iomem *reg_base; ++ ++ spinlock_t lock; ++ struct tasklet_struct tasklet; ++ ++ /* clock management */ ++ struct clk *clk_ahb; ++ struct clk *clk_mod; ++ ++ /* ios information */ ++ u32 clk_mod_rate; ++ u32 bus_width; ++ u32 idma_des_size_bits; ++ u32 ddr; ++ u32 voltage_switching; ++ ++ /* irq */ ++ int irq; ++ u32 int_sum; ++ u32 sdio_imask; ++ ++ /* flags */ ++ u32 power_on:1; ++ u32 io_flag:1; ++ u32 wait_dma:1; ++ ++ dma_addr_t sg_dma; ++ void *sg_cpu; ++ ++ struct mmc_request *mrq; ++ u32 ferror; ++}; ++ ++#define MMC_CLK_400K 0 ++#define MMC_CLK_25M 1 ++#define MMC_CLK_50M 2 ++#define MMC_CLK_50MDDR 3 ++#define MMC_CLK_50MDDR_8BIT 4 ++#define MMC_CLK_100M 5 ++#define MMC_CLK_200M 6 ++#define MMC_CLK_MOD_NUM 7 ++ ++struct sunxi_mmc_clk_dly { ++ u32 mode; ++ u32 oclk_dly; ++ u32 sclk_dly; ++}; ++ ++#endif +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch b/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch new file mode 100644 index 0000000..e968576 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-2-mmc-simplify-clkdelay.patch @@ -0,0 +1,56 @@ +From 40889884d53094fe9987a45f9df99fdf1f311910 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 16 Feb 2014 10:47:51 +0100 +Subject: [PATCH] sunxi-mmc: Simplify clk delay setting + +clk_sunxi_mmc_phase_control() does its own locking, so there is no need to +lock at the host. Without the locking having a separate sunxi_mmc_set_clk_dly() +makes no sense, so simply call clk_sunxi_mmc_phase_control() directly. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index f33bc30..f4bfaf0 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -420,17 +420,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) + } + } + +-static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host, +- u32 oclk_dly, u32 sclk_dly) +-{ +- unsigned long iflags; +- struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); +- +- spin_lock_irqsave(&smc_host->lock, iflags); +- clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); +- spin_unlock_irqrestore(&smc_host->lock, iflags); +-} +- + struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = { + { MMC_CLK_400K, 0, 7 }, + { MMC_CLK_25M, 0, 5 }, +@@ -450,6 +439,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, + u32 sclk_dly; + u32 temp; + struct sunxi_mmc_clk_dly *dly = NULL; ++ struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod); + + newrate = clk_round_rate(smc_host->clk_mod, rate); + if (smc_host->clk_mod_rate == newrate) { +@@ -508,7 +498,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host, + sclk_dly--; + } + +- sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly); ++ clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly); + sunxi_mmc_oclk_onoff(smc_host, 1); + + /* oclk_onoff sets various irq status bits, clear these */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch b/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch new file mode 100644 index 0000000..843d39e --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-3-mmc-dont-set-mmc_clk-in-lowpower.patch @@ -0,0 +1,49 @@ +From 0a6ec6db90c73b037428bf3a94a6281754007c25 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 16:55:54 +0100 +Subject: [PATCH] sunxi-mmc: Don't set mmc clk in low power mode + +The android driver uses an io-flag to descern whether a controller is +hooked up to a sdcard slot, or to an onboard sdio dev. And for sdcard slots +it sets the clock in a low-power mode. + +This is causing transmission errors when talking to the sdio-wifi on the +cubietruck, and this may be the cause of problems with some type sdcards +too. This patch fixes things by simply never setting the clk in low power +mode. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 3 --- + drivers/mmc/host/sunxi-mmc.h | 1 - + 2 files changed, 4 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index f4bfaf0..c1a9d8a 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -400,9 +400,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) + if (oclk_en) + rval |= SDXC_CARD_CLOCK_ON; + +- if (!host->io_flag) +- rval |= SDXC_LOW_POWER_ON; +- + mci_writel(host, REG_CLKCR, rval); + + rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER; +diff --git a/drivers/mmc/host/sunxi-mmc.h b/drivers/mmc/host/sunxi-mmc.h +index cbd6d49..a738850 100644 +--- a/drivers/mmc/host/sunxi-mmc.h ++++ b/drivers/mmc/host/sunxi-mmc.h +@@ -211,7 +211,6 @@ struct sunxi_mmc_host { + + /* flags */ + u32 power_on:1; +- u32 io_flag:1; + u32 wait_dma:1; + + dma_addr_t sg_dma; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch b/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch new file mode 100644 index 0000000..2ff34be --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-4-mmc-stop-claiming-UHS.patch @@ -0,0 +1,32 @@ +From 3ec947a9717509e204c7f09609717951beb7ef04 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 17:11:58 +0100 +Subject: [PATCH] sunxi-mmc: Stop claiming UHS modes + +UHS requires a regulator to set the signaling voltage, as well as special +code to handle the signal voltage switching. We've never added the code +for this from the android driver to the upstream driver, so stop claiming +support for this. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index c1a9d8a..2eaed10 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -803,8 +803,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev) + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | +- MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | +- MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_DRIVER_TYPE_A; ++ MMC_CAP_SDIO_IRQ; + mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; + + ret = mmc_add_host(mmc); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch b/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch new file mode 100644 index 0000000..9118563 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-5-mmc-fix-caps-override.patch @@ -0,0 +1,34 @@ +From dffb4d4d1fe3a6ba93102756152ec4518dbeac00 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 17:13:19 +0100 +Subject: [PATCH] sunxi-mmc: Or in caps, rather then overriding them + +Now that we use mmc_of_parse() there are already some caps set by mmc_of_parse, +so or in our driver caps, rather then using an assignment. This fixes the +card running only in 1 bit mode instead of 4 bit mode problem we've had +since we switched to using mmc_of_parse(). + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index 2eaed10..d5e8ff9 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -802,9 +802,9 @@ static int sunxi_mmc_probe(struct platform_device *pdev) + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + +- mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | ++ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | + MMC_CAP_SDIO_IRQ; +- mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP; ++ mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; + + ret = mmc_add_host(mmc); + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch b/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch new file mode 100644 index 0000000..21aee13 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-6-mmc-dont-call-mmc_of_parser-until-ready.patch @@ -0,0 +1,45 @@ +From 73797537f3904fec60a647b3b209bf7add092ad5 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 21:59:08 +0100 +Subject: [PATCH] sunxi-mmc: Don't call mmc_of_parse until we're ready to + +mmc_of_parse registers an irq handler for the gpio pins for cd, this irq +handler will reference host->ops, so don't call mmc_of_parse until we're +done setting everything up. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index d5e8ff9..cceae68 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -766,10 +766,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev) + return -ENOMEM; + } + +- ret = mmc_of_parse(mmc); +- if (ret) +- goto error_free_host; +- + host = mmc_priv(mmc); + host->mmc = mmc; + spin_lock_init(&host->lock); +@@ -806,8 +802,11 @@ static int sunxi_mmc_probe(struct platform_device *pdev) + MMC_CAP_SDIO_IRQ; + mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; + +- ret = mmc_add_host(mmc); ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto error_free_dma; + ++ ret = mmc_add_host(mmc); + if (ret) + goto error_free_dma; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch b/target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch index 6601ebb..f9cdcc6 100644 --- a/target/linux/sunxi/patches-3.13/150-2-clk-sunxi-export-func.patch +++ b/target/linux/sunxi/patches-3.13/170-7-clk-export-mmc-phasectrl.patch @@ -1,4 +1,4 @@ -From a8cfe8ebdb18e6724b6520e08602b8e72e762ab9 Mon Sep 17 00:00:00 2001 +From 7bd0d82ef525e8949425fe271fb86eacf3822821 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sun, 15 Dec 2013 19:44:01 +0100 Subject: [PATCH] ARM: sunxi: clk: export clk_sunxi_mmc_phase_control @@ -9,6 +9,9 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> 1 file changed, 22 insertions(+) create mode 100644 include/linux/clk/sunxi.h +diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h +new file mode 100644 +index 0000000..1ef5c89 --- /dev/null +++ b/include/linux/clk/sunxi.h @@ -0,0 +1,22 @@ @@ -34,3 +37,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> +void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output); + +#endif +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch b/target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch index e31358b..f3b7f5a 100644 --- a/target/linux/sunxi/patches-3.13/150-1-clk-sunxi-implement-mmc-phasectrl.patch +++ b/target/linux/sunxi/patches-3.13/170-8-clk-sunxi-implement-mmc-phasectrl.patch @@ -1,4 +1,4 @@ -From 4f43ab43125a12dbc23e352ac0eb4fd80a876fb5 Mon Sep 17 00:00:00 2001 +From fcba369ee1af8657353bb1e37807aa492c462263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar> Date: Fri, 20 Sep 2013 20:29:17 -0300 Subject: [PATCH] clk: sunxi: Implement MMC phase control @@ -11,9 +11,11 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar> drivers/clk/sunxi/clk-sunxi.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 3283179..46a38b4 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c -@@ -361,6 +361,41 @@ static void sun4i_get_mod0_factors(u32 * +@@ -500,6 +500,41 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) /** @@ -55,3 +57,6 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar> * sunxi_factors_clk_setup() - Setup function for factor clocks */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch b/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch new file mode 100644 index 0000000..90727f3 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/170-9-mmc-fixup-revert-sdio.patch @@ -0,0 +1,44 @@ +From 0483aa124d32bdcafc84623a31141a49e71cc72d Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 16 Feb 2014 08:54:20 +0100 +Subject: [PATCH] sunxi-mmc: fixup: revert "add host initialization for when + the sdio irq is enabled" + +This is not necessary since when the host is not initialized at this point +yet the irq line from the mmc controller is not enabled, so writing the +host controller interrupt mask cannot cause interrupts at this point. + +More over doing this is wrong, as it leads to unbalanced calling of +clk_prepare_enable and regulator_power_on. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/mmc/host/sunxi-mmc.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c +index 2dc446c..f33bc30 100644 +--- a/drivers/mmc/host/sunxi-mmc.c ++++ b/drivers/mmc/host/sunxi-mmc.c +@@ -593,18 +593,9 @@ static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) + { + struct sunxi_mmc_host *smc_host = mmc_priv(mmc); + unsigned long flags; +- int ret; + u32 imask; + + spin_lock_irqsave(&smc_host->lock, flags); +- +- /* Make sure the controller is in a sane state before enabling irqs */ +- ret = sunxi_mmc_init_host(host->mmc); +- if (ret) { +- spin_unlock_irqrestore(&smc_host->lock, flags); +- return ret; +- } +- + imask = mci_readl(smc_host, REG_IMASK); + if (enable) { + smc_host->sdio_imask = SDXC_SDIO_INTERRUPT; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch b/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch deleted file mode 100644 index f058f56..0000000 --- a/target/linux/sunxi/patches-3.13/170-clk-sunxi-add-support-for-usbclocks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 109e7dc17a77f84d56e76dea873363a8262bc806 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Thu, 19 Sep 2013 21:59:32 +0200 -Subject: [PATCH] clk: sunxi: Add support for USB clocks - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/clk/sunxi/clk-sunxi.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/clk/sunxi/clk-sunxi.c -+++ b/drivers/clk/sunxi/clk-sunxi.c -@@ -705,6 +705,10 @@ static const struct gates_data sun4i_ahb - .mask = {0x7F77FFF, 0x14FB3F}, - }; - -+static const struct gates_data sun47i_usb_gates_data __initconst = { -+ .mask = {0x1C0}, -+}; -+ - static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = { - .mask = {0x147667e7, 0x185915}, - }; -@@ -1021,6 +1025,7 @@ static const struct of_device_id clk_mux - static const struct of_device_id clk_gates_match[] __initconst = { - {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,}, - {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,}, -+ {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,}, - {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, - {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, - {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, diff --git a/target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch b/target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch index 1ee9081..60c6448 100644 --- a/target/linux/sunxi/patches-3.13/151-pinctrl-sun5i-a13-port-F.patch +++ b/target/linux/sunxi/patches-3.13/171-1-pinctrl-sunxi-fix-port-F-multiplexing.patch @@ -1,7 +1,7 @@ -From 33b0123664b627005728cfe7b1967b790392ceec Mon Sep 17 00:00:00 2001 +From 85f17a0d652853455ac633fc965cea8431038518 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Sat, 14 Dec 2013 17:20:13 +0100 -Subject: [PATCH] ARM: sunxi: fix sun5i-a13 port F multiplexing +Subject: [PATCH] pinctrl-sunxi: Fix sun5i-a13 port F multiplexing The correct value for selecting the mmc0 function on port F pins is 2 not 4, as per the data-sheet: @@ -13,9 +13,11 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> drivers/pinctrl/pinctrl-sunxi-pins.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) +diff --git a/drivers/pinctrl/pinctrl-sunxi-pins.h b/drivers/pinctrl/pinctrl-sunxi-pins.h +index 6fd8d4d..3d60669 100644 --- a/drivers/pinctrl/pinctrl-sunxi-pins.h +++ b/drivers/pinctrl/pinctrl-sunxi-pins.h -@@ -1932,27 +1932,27 @@ static const struct sunxi_desc_pin sun5i +@@ -1932,27 +1932,27 @@ SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0, SUNXI_FUNCTION(0x0, "gpio_in"), SUNXI_FUNCTION(0x1, "gpio_out"), @@ -49,3 +51,6 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> /* Hole */ SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0, SUNXI_FUNCTION(0x0, "gpio_in"), +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch b/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch new file mode 100644 index 0000000..84710c6 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/171-2-pinctrl-sunxi-fix-hang-on-gpio-irq.patch @@ -0,0 +1,49 @@ +From 613c8489f6b576166aa31d32cbd573f6b7952e06 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sat, 15 Feb 2014 12:58:17 +0100 +Subject: [PATCH] pinctrl-sunxi: Fix hang on gpio irq + +Our irq handler was missing chained_irq_enter / exit calls, causing a +hard hang as soon as a gpio irq happened. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/pinctrl/pinctrl-sunxi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c +index 74635cc..cc9bd1b 100644 +--- a/drivers/pinctrl/pinctrl-sunxi.c ++++ b/drivers/pinctrl/pinctrl-sunxi.c +@@ -13,6 +13,7 @@ + #include <linux/io.h> + #include <linux/clk.h> + #include <linux/gpio.h> ++#include <linux/irqchip/chained_irq.h> + #include <linux/irqdomain.h> + #include <linux/module.h> + #include <linux/of.h> +@@ -665,9 +666,12 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d) + + static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) + { ++ struct irq_chip *chip = irq_get_chip(irq); + struct sunxi_pinctrl *pctl = irq_get_handler_data(irq); + const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG); + ++ chained_irq_enter(chip, desc); ++ + /* Clear all interrupts */ + writel(reg, pctl->membase + IRQ_STATUS_REG); + +@@ -679,6 +683,7 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc) + generic_handle_irq(pin_irq); + } + } ++ chained_irq_exit(chip, desc); + } + + static struct of_device_id sunxi_pinctrl_match[] = { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch b/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch new file mode 100644 index 0000000..f600a82 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/171-3-pinctrl-sunxi-fix-masking-with-irqtype.patch @@ -0,0 +1,26 @@ +From 9d506cbf0e7b0e017d78f244e2b4c0fc71206c6c Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sat, 15 Feb 2014 12:56:42 +0100 +Subject: [PATCH] pinctrl-sunxi: Fix masking when setting irq type + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/pinctrl/pinctrl-sunxi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c +index cc9bd1b..917af0a 100644 +--- a/drivers/pinctrl/pinctrl-sunxi.c ++++ b/drivers/pinctrl/pinctrl-sunxi.c +@@ -583,7 +583,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, + spin_lock_irqsave(&pctl->lock, flags); + + regval = readl(pctl->membase + reg); +- regval &= ~IRQ_CFG_IRQ_MASK; ++ regval &= ~(IRQ_CFG_IRQ_MASK << index); + writel(regval | (mode << index), pctl->membase + reg); + + spin_unlock_irqrestore(&pctl->lock, flags); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch b/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch new file mode 100644 index 0000000..182cf73 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/171-4-pinctrl-sunxi-fix-irqregister-offset-calcs.patch @@ -0,0 +1,46 @@ +From a5f3d2672d5b9efe93be0bf66d69156bf806220b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 22:04:20 +0100 +Subject: [PATCH] pinctrl-sunxi: Fix interrupt register offset calculation + +This fixing setting the interrupt type for eints >= 8. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/pinctrl/pinctrl-sunxi.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h +index 01c494f..552b0e9 100644 +--- a/drivers/pinctrl/pinctrl-sunxi.h ++++ b/drivers/pinctrl/pinctrl-sunxi.h +@@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin) + + static inline u32 sunxi_irq_cfg_reg(u16 irq) + { +- u8 reg = irq / IRQ_CFG_IRQ_PER_REG; ++ u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04; + return reg + IRQ_CFG_REG; + } + +@@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq) + + static inline u32 sunxi_irq_ctrl_reg(u16 irq) + { +- u8 reg = irq / IRQ_CTRL_IRQ_PER_REG; ++ u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04; + return reg + IRQ_CTRL_REG; + } + +@@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq) + + static inline u32 sunxi_irq_status_reg(u16 irq) + { +- u8 reg = irq / IRQ_STATUS_IRQ_PER_REG; ++ u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04; + return reg + IRQ_STATUS_REG; + } + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch b/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch deleted file mode 100644 index 00a9561..0000000 --- a/target/linux/sunxi/patches-3.13/171-clk-sunxi-add-support-for-sun5i-usbclocks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6b5cb5cada555c90562aed82e8891439a35009ab Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Sun, 6 Oct 2013 14:04:50 +0200 -Subject: [PATCH] clk: sun5i: Add support for USB clocks - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/clk/sunxi/clk-sunxi.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/clk/sunxi/clk-sunxi.c -+++ b/drivers/clk/sunxi/clk-sunxi.c -@@ -709,6 +709,10 @@ static const struct gates_data sun47i_us - .mask = {0x1C0}, - }; - -+static const struct gates_data sun5i_usb_gates_data __initconst = { -+ .mask = {0x140}, -+}; -+ - static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = { - .mask = {0x147667e7, 0x185915}, - }; -@@ -1028,6 +1032,7 @@ static const struct of_device_id clk_gat - {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,}, - {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,}, - {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,}, -+ {.compatible = "allwinner,sun5i-usb-gates-clk", .data = &sun5i_usb_gates_data,}, - {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, - {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, - {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, diff --git a/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch b/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch deleted file mode 100644 index 8ff1fc5..0000000 --- a/target/linux/sunxi/patches-3.13/172-usb-add-ehci-driver.patch +++ /dev/null @@ -1,493 +0,0 @@ -From 825ce97e1faa39bfd30c3dca95fba5eb021cb534 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Wed, 18 Sep 2013 21:45:03 +0200 -Subject: [PATCH] ARM: sunxi: usb: Add Allwinner sunXi EHCI driver - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> - -Conflicts: - drivers/usb/host/Makefile ---- - drivers/usb/host/Kconfig | 9 + - drivers/usb/host/Makefile | 1 + - drivers/usb/host/ehci-sunxi.c | 446 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 456 insertions(+) - create mode 100644 drivers/usb/host/ehci-sunxi.c - ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -273,6 +273,15 @@ config USB_OCTEON_EHCI - USB 2.0 device support. All CN6XXX based chips with USB are - supported. - -+config USB_SUNXI_EHCI -+ tristate "Allwinner sunXi EHCI support" -+ depends on ARCH_SUNXI -+ default n -+ help -+ Enable support for the Allwinner sunXi on-chip EHCI -+ controller. It is needed for high-speed (480Mbit/sec) -+ USB 2.0 device support. -+ - endif # USB_EHCI_HCD - - config USB_OXU210HP_HCD ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci- - obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o - obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o - obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o -+obj-$(CONFIG_USB_SUNXI_EHCI) += ehci-sunxi.o - - obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o - obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o ---- /dev/null -+++ b/drivers/usb/host/ehci-sunxi.c -@@ -0,0 +1,446 @@ -+/* -+ * Copyright (C) 2013 Roman Byshko -+ * -+ * Roman Byshko <rbyshko@gmail.com> -+ * -+ * Based on code from -+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com> -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/bitops.h> -+#include <linux/clk.h> -+#include <linux/dma-mapping.h> -+#include <linux/io.h> -+#include <linux/irq.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+#include <linux/regulator/consumer.h> -+#include <linux/reset.h> -+#include <linux/usb.h> -+#include <linux/usb/hcd.h> -+ -+#include "ehci.h" -+ -+#define DRV_DESC "Allwinner sunXi EHCI driver" -+#define DRV_NAME "sunxi-ehci" -+ -+#define SUNXI_USB_PASSBY_EN 1 -+ -+#define SUNXI_EHCI_AHB_ICHR8_EN BIT(10) -+#define SUNXI_EHCI_AHB_INCR4_BURST_EN BIT(9) -+#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN BIT(8) -+#define SUNXI_EHCI_ULPI_BYPASS_EN BIT(0) -+ -+struct sunxi_ehci_hcd { -+ struct clk *phy_clk; -+ struct clk *ahb_ehci_clk; -+ struct reset_control *reset; -+ struct regulator *vbus_reg; -+ void __iomem *csr; -+ void __iomem *pmuirq; -+ int irq; -+ int id; -+}; -+ -+ -+static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci,u32 addr, u32 data, u32 len) -+{ -+ u32 j = 0; -+ u32 temp = 0; -+ u32 usbc_bit = 0; -+ void __iomem *dest = sunxi_ehci->csr; -+ -+ usbc_bit = BIT(sunxi_ehci->id << 1); -+ -+ for (j = 0; j < len; j++) { -+ temp = readl(dest); -+ -+ /* clear the address portion */ -+ temp &= ~(0xff << 8); -+ -+ /* set the address */ -+ temp |= ((addr + j) << 8); -+ writel(temp, dest); -+ -+ /* set the data bit and clear usbc bit*/ -+ temp = readb(dest); -+ if (data & 0x1) -+ temp |= BIT(7); -+ else -+ temp &= ~BIT(7); -+ temp &= ~usbc_bit; -+ writeb(temp, dest); -+ -+ /* flip usbc_bit */ -+ __set_bit(usbc_bit, dest); -+ __clear_bit(usbc_bit, dest); -+ -+ data >>= 1; -+ } -+} -+ -+/* FIXME: should this function be protected by a lock? -+ * ehci1 and ehci0 could call it concurrently with same csr. -+ */ -+static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci) -+{ -+ /* The following comments are machine -+ * translated from Chinese, you have been warned! -+ */ -+ -+ /* adjust PHY's magnitude and rate */ -+ usb_phy_write(sunxi_ehci, 0x20, 0x14, 5); -+ -+ /* threshold adjustment disconnect */ -+ usb_phy_write(sunxi_ehci, 0x2a, 3, 2); -+ -+ return; -+} -+ -+static void sunxi_usb_passby(struct sunxi_ehci_hcd *sunxi_ehci, int enable) -+{ -+ unsigned long reg_value = 0; -+ unsigned long bits = 0; -+ static DEFINE_SPINLOCK(lock); -+ unsigned long flags = 0; -+ void __iomem *addr = sunxi_ehci->pmuirq; -+ -+ bits = SUNXI_EHCI_AHB_ICHR8_EN | -+ SUNXI_EHCI_AHB_INCR4_BURST_EN | -+ SUNXI_EHCI_AHB_INCRX_ALIGN_EN | -+ SUNXI_EHCI_ULPI_BYPASS_EN; -+ -+ spin_lock_irqsave(&lock, flags); -+ -+ reg_value = readl(addr); -+ -+ if (enable) -+ reg_value |= bits; -+ else -+ reg_value &= ~bits; -+ -+ writel(reg_value, addr); -+ -+ spin_unlock_irqrestore(&lock, flags); -+ -+ return; -+} -+ -+static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci) -+{ -+ regulator_disable(sunxi_ehci->vbus_reg); -+ -+ sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN); -+ -+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk); -+ clk_disable_unprepare(sunxi_ehci->phy_clk); -+ -+ reset_control_assert(sunxi_ehci->reset); -+} -+ -+static int sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci) -+{ -+ int ret; -+ -+ ret = clk_prepare_enable(sunxi_ehci->phy_clk); -+ if (ret) -+ return ret; -+ -+ ret = reset_control_deassert(sunxi_ehci->reset); -+ if (ret) -+ goto fail1; -+ -+ ret = clk_prepare_enable(sunxi_ehci->ahb_ehci_clk); -+ if (ret) -+ goto fail2; -+ -+ sunxi_usb_phy_init(sunxi_ehci); -+ -+ sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN); -+ -+ ret = regulator_enable(sunxi_ehci->vbus_reg); -+ if (ret) -+ goto fail3; -+ -+ return 0; -+ -+fail3: -+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk); -+fail2: -+ reset_control_assert(sunxi_ehci->reset); -+fail1: -+ clk_disable_unprepare(sunxi_ehci->phy_clk); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM -+static int sunxi_ehci_suspend(struct device *dev) -+{ -+ struct sunxi_ehci_hcd *sunxi_ehci = NULL; -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ int ret; -+ -+ bool do_wakeup = device_may_wakeup(dev); -+ -+ ret = ehci_suspend(hcd, do_wakeup); -+ -+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv; -+ -+ sunxi_ehci_disable(sunxi_ehci); -+ -+ return ret; -+} -+ -+static int sunxi_ehci_resume(struct device *dev) -+{ -+ struct sunxi_ehci_hcd *sunxi_ehci = NULL; -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ int ret; -+ -+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv; -+ -+ ret = sunxi_ehci_enable(sunxi_ehci); -+ if (ret) -+ return ret; -+ -+ return ehci_resume(hcd, false); -+} -+ -+ -+static const struct dev_pm_ops sunxi_ehci_pmops = { -+ .suspend = sunxi_ehci_suspend, -+ .resume = sunxi_ehci_resume, -+}; -+ -+#define SUNXI_EHCI_PMOPS (&sunxi_ehci_pmops) -+#else /* !CONFIG_PM */ -+#define SUNXI_EHCI_PMOPS NULL -+#endif /* CONFIG_PM */ -+ -+static const struct ehci_driver_overrides sunxi_overrides __initconst = { -+ .reset = NULL, -+ .extra_priv_size = sizeof(struct sunxi_ehci_hcd), -+}; -+ -+/* FIXME: Should there be two instances of hc_driver, -+ * or one is enough to handle two EHCI controllers? */ -+static struct hc_driver __read_mostly sunxi_ehci_hc_driver; -+ -+static int sunxi_ehci_init(struct platform_device *pdev, struct usb_hcd *hcd, -+ struct sunxi_ehci_hcd *sunxi_ehci) -+{ -+ void __iomem *ehci_regs = NULL; -+ struct resource *res = NULL; -+ -+ sunxi_ehci->vbus_reg = devm_regulator_get(&pdev->dev, "vbus"); -+ if (IS_ERR(sunxi_ehci->vbus_reg)) { -+ if (PTR_ERR(sunxi_ehci->vbus_reg) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ -+ dev_info(&pdev->dev, "no USB VBUS power supply found\n"); -+ } -+ -+ sunxi_ehci->id = of_alias_get_id(pdev->dev.of_node, "ehci"); -+ if (sunxi_ehci->id < 0) -+ return sunxi_ehci->id; -+ -+ /* FIXME: should res be freed on some failure? */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "failed to get I/O memory\n"); -+ return -ENXIO; -+ } -+ ehci_regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(ehci_regs)) -+ return PTR_ERR(ehci_regs); -+ -+ hcd->rsrc_start = res->start; -+ hcd->rsrc_len = resource_size(res); -+ hcd->regs = ehci_regs; -+ hcd_to_ehci(hcd)->caps = ehci_regs; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (!res) { -+ dev_err(&pdev->dev, "failed to get I/O memory\n"); -+ return -ENXIO; -+ } -+ sunxi_ehci->pmuirq = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(sunxi_ehci->pmuirq)) -+ return PTR_ERR(sunxi_ehci->pmuirq); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -+ if (!res) { -+ dev_err(&pdev->dev, "failed to get I/O memory\n"); -+ return -ENXIO; -+ } -+ -+ /* FIXME: this one byte needs to be shared between both EHCIs, -+ * that is why ioremap instead of devm_ioremap_resource, -+ * memory is not unmaped back for now. -+ */ -+ sunxi_ehci->csr = ioremap(res->start, resource_size(res)); -+ if (IS_ERR(sunxi_ehci->csr)) { -+ dev_err(&pdev->dev, "failed to remap memory\n"); -+ return PTR_ERR(sunxi_ehci->csr); -+ } -+ -+ sunxi_ehci->irq = platform_get_irq(pdev, 0); -+ if (!sunxi_ehci->irq) { -+ dev_err(&pdev->dev, "failed to get IRQ\n"); -+ return -ENODEV; -+ } -+ -+ sunxi_ehci->phy_clk = devm_clk_get(&pdev->dev, "usb_phy"); -+ if (IS_ERR(sunxi_ehci->phy_clk)) { -+ dev_err(&pdev->dev, "failed to get usb_phy clock\n"); -+ return PTR_ERR(sunxi_ehci->phy_clk); -+ } -+ sunxi_ehci->ahb_ehci_clk = devm_clk_get(&pdev->dev, "ahb_ehci"); -+ if (IS_ERR(sunxi_ehci->ahb_ehci_clk)) { -+ dev_err(&pdev->dev, "failed to get ahb_ehci clock\n"); -+ return PTR_ERR(sunxi_ehci->ahb_ehci_clk); -+ } -+ -+ sunxi_ehci->reset = reset_control_get(&pdev->dev, "ehci_reset"); -+ if (IS_ERR(sunxi_ehci->reset)) -+ { -+ dev_err(&pdev->dev, "failed to get ehci_reset reset line\n"); -+ return PTR_ERR(sunxi_ehci->reset); -+ } -+ -+ return 0; -+} -+ -+static int sunxi_ehci_probe(struct platform_device *pdev) -+{ -+ struct sunxi_ehci_hcd *sunxi_ehci = NULL; -+ struct usb_hcd *hcd = NULL; -+ int ret; -+ -+ if (pdev->num_resources != 4) { -+ dev_err(&pdev->dev, "invalid number of resources: %i\n", -+ pdev->num_resources); -+ return -ENODEV; -+ } -+ -+ if (pdev->resource[0].flags != IORESOURCE_MEM -+ || pdev->resource[1].flags != IORESOURCE_MEM -+ || pdev->resource[2].flags != IORESOURCE_MEM -+ || pdev->resource[3].flags != IORESOURCE_IRQ) { -+ dev_err(&pdev->dev, "invalid resource type\n"); -+ return -ENODEV; -+ } -+ -+ if (!pdev->dev.dma_mask) -+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; -+ if (!pdev->dev.coherent_dma_mask) -+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); -+ -+ hcd = usb_create_hcd(&sunxi_ehci_hc_driver, &pdev->dev, -+ dev_name(&pdev->dev)); -+ if (!hcd) { -+ dev_err(&pdev->dev, "unable to create HCD\n"); -+ return -ENOMEM; -+ } -+ -+ platform_set_drvdata(pdev, hcd); -+ -+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv; -+ ret = sunxi_ehci_init(pdev, hcd, sunxi_ehci); -+ if (ret) -+ goto fail1; -+ -+ ret = sunxi_ehci_enable(sunxi_ehci); -+ if (ret) -+ goto fail1; -+ -+ ret = usb_add_hcd(hcd, sunxi_ehci->irq, IRQF_SHARED | IRQF_DISABLED); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to add USB HCD\n"); -+ goto fail2; -+ } -+ -+ return 0; -+ -+fail2: -+ sunxi_ehci_disable(sunxi_ehci); -+ -+fail1: -+ usb_put_hcd(hcd); -+ return ret; -+} -+ -+static int sunxi_ehci_remove(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ struct sunxi_ehci_hcd *sunxi_ehci = NULL; -+ -+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv; -+ -+ usb_remove_hcd(hcd); -+ -+ sunxi_ehci_disable(sunxi_ehci); -+ -+ usb_put_hcd(hcd); -+ -+ return 0; -+} -+ -+static void sunxi_ehci_shutdown(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ struct sunxi_ehci_hcd *sunxi_ehci = NULL; -+ -+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv; -+ -+ usb_hcd_platform_shutdown(pdev); -+ -+ sunxi_ehci_disable(sunxi_ehci); -+} -+ -+static const struct of_device_id ehci_of_match[] = { -+ {.compatible = "allwinner,sunxi-ehci"}, -+ {}, -+}; -+ -+static struct platform_driver ehci_sunxi_driver = { -+ .driver = { -+ .of_match_table = ehci_of_match, -+ .name = DRV_NAME, -+ .pm = SUNXI_EHCI_PMOPS, -+ }, -+ .probe = sunxi_ehci_probe, -+ .remove = sunxi_ehci_remove, -+ .shutdown = sunxi_ehci_shutdown, -+}; -+ -+static int __init sunxi_ehci_init_module(void) -+{ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ pr_info(DRV_NAME ": " DRV_DESC "\n"); -+ -+ ehci_init_driver(&sunxi_ehci_hc_driver, &sunxi_overrides); -+ -+ return platform_driver_register(&ehci_sunxi_driver); -+} -+module_init(sunxi_ehci_init_module); -+ -+static void __exit sunxi_ehci_exit_module(void) -+{ -+ platform_driver_unregister(&ehci_sunxi_driver); -+} -+module_exit(sunxi_ehci_exit_module); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:" DRV_NAME); -+MODULE_DEVICE_TABLE(of, ehci_of_match); -+MODULE_AUTHOR("Roman Byshko <rbyshko@gmail.com>"); diff --git a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch new file mode 100644 index 0000000..4bdbb04 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-mmc.patch @@ -0,0 +1,129 @@ +From 6c6bc98f6a2b1f91071564efdb77c90307610018 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch> +Date: Sat, 15 Feb 2014 14:02:51 +0100 +Subject: [PATCH] ARM: dts: sun4i: Add support for mmc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 +++++ + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 +++++ + arch/arm/boot/dts/sun4i-a10.dtsi | 54 ++++++++++++++++++++++++++++++ + 3 files changed, 70 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index d6ec839..4b2a694 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -35,6 +35,14 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + status = "okay"; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index 6df237d8..ef85b8e 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -34,6 +34,14 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 454077a..a8e0df3 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -338,6 +338,46 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <32>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <33>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <34>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c12000 0x1000>; ++ clocks = <&ahb_gates 11>, <&mmc3_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <35>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -416,6 +456,20 @@ + allwinner,drive = <0>; + allwinner,pull = <0>; + }; ++ ++ mmc0_pins_a: mmc0@0 { ++ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; ++ allwinner,function = "mmc0"; ++ allwinner,drive = <3>; ++ allwinner,pull = <0>; ++ }; ++ ++ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 { ++ allwinner,pins = "PH1"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <0>; ++ allwinner,pull = <1>; ++ }; + }; + + timer@01c20c00 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch deleted file mode 100644 index 947f06b..0000000 --- a/target/linux/sunxi/patches-3.13/173-1-dt-sun4i-add-usbclock-nodes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 04f41bafdff26bd895f2a1f894fd427779d7ed51 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Thu, 19 Sep 2013 21:58:47 +0200 -Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10.dtsi -+++ b/arch/arm/boot/dts/sun4i-a10.dtsi -@@ -93,6 +93,14 @@ - clock-output-names = "pll6_sata", "pll6_other", "pll6"; - }; - -+ usb:usb@0x01c200cc { -+ #clock-cells = <1>; -+ compatible = "allwinner,sun47i-usb-gates-clk"; -+ reg = <0x01c200cc 0x4>; -+ clocks = <&pll6 1>; -+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy"; -+ }; -+ - /* dummy is 200M */ - cpu: cpu@01c20054 { - #clock-cells = <0>; diff --git a/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch deleted file mode 100644 index 3e69714..0000000 --- a/target/linux/sunxi/patches-3.13/173-2-dt-sun4i-add-ehci-bindings.patch +++ /dev/null @@ -1,58 +0,0 @@ -From ec53e86224acaa3891148fa298bb1504f3579d6b Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Wed, 18 Sep 2013 00:30:04 +0200 -Subject: [PATCH] ARM: sun4i: dt: Add USB EHCI bindings - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> - -Conflicts: - arch/arm/boot/dts/sun4i-a10.dtsi ---- - arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10.dtsi -+++ b/arch/arm/boot/dts/sun4i-a10.dtsi -@@ -17,6 +17,8 @@ - - aliases { - ethernet0 = &emac; -+ ehci1 = &ehci0; -+ ehci2 = &ehci1; - }; - - cpus { -@@ -563,5 +565,33 @@ - clock-frequency = <100000>; - status = "disabled"; - }; -+ -+ usb_rst: reset@0x01c200cc { -+ #reset-cells = <1>; -+ compatible = "allwinner,sun4i-clock-reset"; -+ reg = <0x01c200cc 0x4>; -+ }; -+ -+ ehci0: ehci0@0x01c14000 { -+ compatible = "allwinner,sunxi-ehci"; -+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>; -+ interrupts = <39>; -+ resets = <&usb_rst 1>; -+ reset-names = "ehci_reset"; -+ clocks = <&usb 8>, <&ahb_gates 1>; -+ clock-names = "usb_phy", "ahb_ehci"; -+ status = "disabled"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ compatible = "allwinner,sunxi-ehci"; -+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>; -+ interrupts = <40>; -+ resets = <&usb_rst 2>; -+ reset-names = "ehci_reset"; -+ clocks = <&usb 8>, <&ahb_gates 3>; -+ clock-names = "usb_phy", "ahb_ehci"; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch index dfeabf7..f688b6c 100644 --- a/target/linux/sunxi/patches-3.13/153-2-dt-sun5i-add-mmc.patch +++ b/target/linux/sunxi/patches-3.13/173-2-dt-sun5i-add-mmc.patch @@ -1,38 +1,42 @@ -From 48332fd7217cf5b06b438503513e54e6138e0637 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Sat, 14 Dec 2013 22:58:14 +0100 +From 5bfbb46a8685de4c67f084aea983fc9a50c882ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch> +Date: Sat, 15 Feb 2014 14:02:29 +0100 Subject: [PATCH] ARM: dts: sun5i: Add support for mmc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch> Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- - arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 32 ++++++++++++++++++++++ - arch/arm/boot/dts/sun5i-a10s.dtsi | 34 ++++++++++++++++++++++++ - arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 16 +++++++++++ - arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 16 +++++++++++ - arch/arm/boot/dts/sun5i-a13.dtsi | 17 ++++++++++++ - 5 files changed, 115 insertions(+) + arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 30 ++++++++++++++++ + arch/arm/boot/dts/sun5i-a10s.dtsi | 44 ++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 15 ++++++++ + arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 15 ++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 37 ++++++++++++++++++++ + 5 files changed, 141 insertions(+) +diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +index 3c9f8b3..5c7b454 100644 --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts -@@ -34,7 +34,39 @@ +@@ -34,7 +34,37 @@ }; }; + mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; ++ pinctrl-names = "default", "default"; + pinctrl-0 = <&mmc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxino_micro>; + cd-gpios = <&pio 6 1 0>; /* PG1 */ -+ cd-mode = <1>; + status = "okay"; + }; + + mmc1: mmc@01c10000 { -+ pinctrl-names = "default"; ++ pinctrl-names = "default", "default"; + pinctrl-0 = <&mmc1_pins_a>; + pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>; + cd-gpios = <&pio 6 13 0>; /* PG13 */ -+ cd-mode = <1>; + status = "okay"; + }; + @@ -41,22 +45,24 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> + allwinner,pins = "PG1"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; -+ allwinner,pull = <0>; ++ allwinner,pull = <1>; + }; + + mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 { + allwinner,pins = "PG13"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; -+ allwinner,pull = <0>; ++ allwinner,pull = <1>; + }; + led_pins_olinuxino: led_pins@0 { allwinner,pins = "PE3"; allwinner,function = "gpio_out"; +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 3a9b33d..3a7039e 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi -@@ -293,6 +293,26 @@ +@@ -299,6 +299,36 @@ #size-cells = <0>; }; @@ -80,10 +86,20 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> + status = "disabled"; + }; + ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <34>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; -@@ -363,6 +383,20 @@ +@@ -369,6 +399,20 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; @@ -104,18 +120,19 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> }; timer@01c20c00 { +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +index fe2ce0a..2f08bb2 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts -@@ -20,7 +20,23 @@ +@@ -20,7 +20,22 @@ compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13"; soc@01c00000 { + mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; ++ pinctrl-names = "default", "default"; + pinctrl-0 = <&mmc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxinom>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ -+ cd-mode = <1>; + status = "okay"; + }; + @@ -124,24 +141,25 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; -+ allwinner,pull = <0>; ++ allwinner,pull = <1>; + }; + led_pins_olinuxinom: led_pins@0 { allwinner,pins = "PG9"; allwinner,function = "gpio_out"; +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +index a4ba5ff..a7280f5 100644 --- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts -@@ -23,7 +23,23 @@ - }; +@@ -19,7 +19,22 @@ + compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13"; soc@01c00000 { + mmc0: mmc@01c0f000 { -+ pinctrl-names = "default"; ++ pinctrl-names = "default", "default"; + pinctrl-0 = <&mmc0_pins_a>; + pinctrl-1 = <&mmc0_cd_pin_olinuxino>; + cd-gpios = <&pio 6 0 0>; /* PG0 */ -+ cd-mode = <1>; + status = "okay"; + }; + @@ -150,15 +168,17 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> + allwinner,pins = "PG0"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; -+ allwinner,pull = <0>; ++ allwinner,pull = <1>; + }; + led_pins_olinuxino: led_pins@0 { allwinner,pins = "PG9"; allwinner,function = "gpio_out"; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 9612c52..63a35b8 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi -@@ -274,6 +274,16 @@ +@@ -281,6 +281,36 @@ #size-cells = <1>; ranges; @@ -172,10 +192,30 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> + status = "disabled"; + }; + ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <33>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <34>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; -@@ -326,6 +336,13 @@ +@@ -333,6 +363,13 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; @@ -189,3 +229,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> }; timer@01c20c00 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch b/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch deleted file mode 100644 index 7b7daa7..0000000 --- a/target/linux/sunxi/patches-3.13/173-3-dt-sun4i-add-ehci-cubieboard.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 875bbd46c296e4b9ed130848bc64be5cf39669c8 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Wed, 18 Sep 2013 22:45:06 +0200 -Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to Cubieboard-A10 - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> - -Conflicts: - arch/arm/boot/dts/sun4i-a10-cubieboard.dts ---- - arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 46 ++++++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -@@ -77,6 +77,20 @@ - allwinner,drive = <1>; - allwinner,pull = <0>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PH6"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; -+ -+ usb2_vbus_pin: usb2_vbus_pin@0 { -+ allwinner,pins = "PH3"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart0: serial@01c28000 { -@@ -96,6 +110,16 @@ - pinctrl-0 = <&i2c1_pins_a>; - status = "okay"; - }; -+ -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ vbus-supply = <®_usb2_vbus>; -+ status = "okay"; -+ }; - }; - - leds { -@@ -128,5 +152,27 @@ - gpio = <&pio 1 8 0>; - enable-active-high; - }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 6 0>; -+ }; -+ -+ reg_usb2_vbus: usb2-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb2_vbus_pin>; -+ regulator-name = "usb2-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 3 0>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch b/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch new file mode 100644 index 0000000..3fb2c6f --- /dev/null +++ b/target/linux/sunxi/patches-3.13/173-3-dt-sun7i-add-mmc.patch @@ -0,0 +1,160 @@ +From a3bddfdd19c49f0bde7aa2ff496773c575763d07 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch> +Date: Sat, 15 Feb 2014 14:02:01 +0100 +Subject: [PATCH] ARM: dts: sun7i: Add support for mmc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++ + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++ + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++++ + arch/arm/boot/dts/sun7i-a20.dtsi | 61 +++++++++++++++++++++++++ + 4 files changed, 100 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index 07823c2..a8186f5 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -20,6 +20,14 @@ + compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index 403bd2e..6cd7cca 100644 +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index d5c6799..d4e2355 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -20,12 +20,35 @@ + compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc3_pins_a>; ++ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>; ++ cd-gpios = <&pio 7 11 0>; /* PH11 */ ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; + }; + + pinctrl@01c20800 { ++ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { ++ allwinner,pins = "PH11"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <0>; ++ allwinner,pull = <1>; ++ }; ++ + led_pins_olinuxino: led_pins@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 3385994..3bc6ac5 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -392,6 +392,46 @@ + #size-cells = <0>; + }; + ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&ahb_gates 8>, <&mmc0_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <0 32 4>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&ahb_gates 9>, <&mmc1_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <0 33 4>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&ahb_gates 10>, <&mmc2_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <0 34 4>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@01c12000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c12000 0x1000>; ++ clocks = <&ahb_gates 11>, <&mmc3_clk>; ++ clock-names = "ahb", "mod"; ++ interrupts = <0 35 4>; ++ bus-width = <4>; ++ status = "disabled"; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -510,6 +550,27 @@ + allwinner,drive = <3>; + allwinner,pull = <0>; + }; ++ ++ mmc0_pins_a: mmc0@0 { ++ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; ++ allwinner,function = "mmc0"; ++ allwinner,drive = <3>; ++ allwinner,pull = <0>; ++ }; ++ ++ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 { ++ allwinner,pins = "PH1"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = <0>; ++ allwinner,pull = <1>; ++ }; ++ ++ mmc3_pins_a: mmc3@0 { ++ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9"; ++ allwinner,function = "mmc3"; ++ allwinner,drive = <3>; ++ allwinner,pull = <0>; ++ }; + }; + + timer@01c20c00 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch deleted file mode 100644 index c1b2505..0000000 --- a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-add-ehci-a1000.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 9a86b6c16abc11b1090fbf4e102b4eed1d474d96 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Wed, 18 Sep 2013 00:30:40 +0200 -Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to the Mele A1000 - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun4i-a10-a1000.dts | 46 +++++++++++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts -+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts -@@ -73,6 +73,20 @@ - allwinner,drive = <0>; - allwinner,pull = <0>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PH6"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; -+ -+ usb2_vbus_pin: usb2_vbus_pin@0 { -+ allwinner,pins = "PH3"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart0: serial@01c28000 { -@@ -86,6 +100,16 @@ - pinctrl-0 = <&i2c0_pins_a>; - status = "okay"; - }; -+ -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ vbus-supply = <®_usb2_vbus>; -+ status = "okay"; -+ }; - }; - - leds { -@@ -117,5 +141,27 @@ - enable-active-high; - gpio = <&pio 7 15 0>; - }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 6 0>; -+ }; -+ -+ reg_usb2_vbus: usb2-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb2_vbus_pin>; -+ regulator-name = "usb2-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 3 0>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch new file mode 100644 index 0000000..e9e209b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/173-4-dt-sun4i-fixup-mmc.patch @@ -0,0 +1,64 @@ +From 11347c2a116f36b95d6cc3b315a1f269da6d42a0 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 17:20:21 +0100 +Subject: [PATCH] ARM: sun4i: dt: Fixup mmc bindings + +1) Now that we're no longer overriding the caps set by mmc_of_parse we need +to set cd-inverted for our card detection to work. + +2) Now that we no longer claim UHS modes support we will never use any DDR +modes, so drive-strength 2 is enough for the mmc data pins. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index a8e0df3..ba05e6e 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -345,6 +345,7 @@ + clock-names = "ahb", "mod"; + interrupts = <32>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -355,6 +356,7 @@ + clock-names = "ahb", "mod"; + interrupts = <33>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -365,6 +367,7 @@ + clock-names = "ahb", "mod"; + interrupts = <34>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -375,6 +378,7 @@ + clock-names = "ahb", "mod"; + interrupts = <35>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -460,7 +464,7 @@ + mmc0_pins_a: mmc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch new file mode 100644 index 0000000..7bbe566 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/173-5-dt-sun5i-fixup-mmc.patch @@ -0,0 +1,107 @@ +From 1fa41bc5a6659e453ca19086f195b02a23dc3bbe Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 17:25:54 +0100 +Subject: [PATCH] ARM: sun5i: dt: Fixup mmc bindings + +1) Now that we're no longer overriding the caps set by mmc_of_parse we need +to set cd-inverted for our card detection to work. + +2) Now that we no longer claim UHS modes support we will never use any DDR +modes, so drive-strength 2 is enough for the mmc data pins. + +3) mmc1 on the A13 is not routed to any pins, and thus unusable, remove it +from the dtsi + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++-- + arch/arm/boot/dts/sun5i-a13.dtsi | 14 +++----------- + 2 files changed, 8 insertions(+), 13 deletions(-) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 3a7039e..15dfa9a 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -306,6 +306,7 @@ + clock-names = "ahb", "mod"; + interrupts = <32>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -316,6 +317,7 @@ + clock-names = "ahb", "mod"; + interrupts = <33>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -326,6 +328,7 @@ + clock-names = "ahb", "mod"; + interrupts = <34>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -403,14 +406,14 @@ + mmc0_pins_a: mmc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + + mmc1_pins_a: mmc1@0 { + allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8"; + allwinner,function = "mmc1"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + }; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 63a35b8..14a99d0 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -288,16 +288,7 @@ + clock-names = "ahb", "mod"; + interrupts = <32>; + bus-width = <4>; +- status = "disabled"; +- }; +- +- mmc1: mmc@01c10000 { +- compatible = "allwinner,sun5i-a13-mmc"; +- reg = <0x01c10000 0x1000>; +- clocks = <&ahb_gates 9>, <&mmc1_clk>; +- clock-names = "ahb", "mod"; +- interrupts = <33>; +- bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -308,6 +299,7 @@ + clock-names = "ahb", "mod"; + interrupts = <34>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -367,7 +359,7 @@ + mmc0_pins_a: mmc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch b/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch new file mode 100644 index 0000000..c1784e3 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/173-6-dt-sun7i-fixup-mmc.patch @@ -0,0 +1,73 @@ +From e48e7ba7f97e883a24036df04cb474cf7cd22574 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 17:16:08 +0100 +Subject: [PATCH] ARM: sun7i: dt: Fixup mmc bindings + +1) Now that we're no longer overriding the caps set by mmc_of_parse we need +to set cd-inverted for our card detection to work. + +2) Now that we no longer claim UHS modes support we will never use any DDR +modes, so drive-strength 2 is enough for the mmc data pins. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 3bc6ac5..f4ecd79 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -399,6 +399,7 @@ + clock-names = "ahb", "mod"; + interrupts = <0 32 4>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -409,6 +410,7 @@ + clock-names = "ahb", "mod"; + interrupts = <0 33 4>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -419,6 +421,7 @@ + clock-names = "ahb", "mod"; + interrupts = <0 34 4>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -429,6 +432,7 @@ + clock-names = "ahb", "mod"; + interrupts = <0 35 4>; + bus-width = <4>; ++ cd-inverted; + status = "disabled"; + }; + +@@ -554,7 +558,7 @@ + mmc0_pins_a: mmc0@0 { + allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5"; + allwinner,function = "mmc0"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + +@@ -568,7 +572,7 @@ + mmc3_pins_a: mmc3@0 { + allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9"; + allwinner,function = "mmc3"; +- allwinner,drive = <3>; ++ allwinner,drive = <2>; + allwinner,pull = <0>; + }; + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch deleted file mode 100644 index 2ecd8d7..0000000 --- a/target/linux/sunxi/patches-3.13/174-1-dt-sun7i-add-usbclock-nodes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From b7739d837e1176b2206ee541075c9eba0a263695 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Thu, 19 Sep 2013 21:24:20 +0200 -Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -89,6 +89,14 @@ - clock-output-names = "pll6_sata", "pll6_other", "pll6"; - }; - -+ usb:usb@0x01c200cc { -+ #clock-cells = <1>; -+ compatible = "allwinner,sun47i-usb-gates-clk"; -+ reg = <0x01c200cc 0x4>; -+ clocks = <&pll6 1>; -+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy"; -+ }; -+ - cpu: cpu@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-cpu-clk"; diff --git a/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch deleted file mode 100644 index 4b2f9c2..0000000 --- a/target/linux/sunxi/patches-3.13/174-2-dt-sun7i-add-ehci-bindings.patch +++ /dev/null @@ -1,58 +0,0 @@ -From a82eb088ea3fa4c25b256400690a30f4b0392e91 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Thu, 19 Sep 2013 21:36:10 +0200 -Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> - -Conflicts: - arch/arm/boot/dts/sun7i-a20.dtsi ---- - arch/arm/boot/dts/sun7i-a20.dtsi | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -18,6 +18,8 @@ - - aliases { - ethernet0 = &gmac; -+ ehci1 = &ehci0; -+ ehci2 = &ehci1; - }; - - cpus { -@@ -623,5 +625,33 @@ - #interrupt-cells = <3>; - interrupts = <1 9 0xf04>; - }; -+ -+ usb_rst: reset@0x01c200cc { -+ #reset-cells = <1>; -+ compatible = "allwinner,sun4i-clock-reset"; -+ reg = <0x01c200cc 0x4>; -+ }; -+ -+ ehci0: ehci0@0x01c14000 { -+ compatible = "allwinner,sunxi-ehci"; -+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>; -+ interrupts = <0 39 1>; -+ resets = <&usb_rst 1>; -+ reset-names = "ehci_reset"; -+ clocks = <&usb 8>, <&ahb_gates 1>; -+ clock-names = "usb_phy", "ahb_ehci"; -+ status = "disabled"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ compatible = "allwinner,sunxi-ehci"; -+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>; -+ interrupts = <0 40 1>; -+ resets = <&usb_rst 2>; -+ reset-names = "ehci_reset"; -+ clocks = <&usb 8>, <&ahb_gates 3>; -+ clock-names = "usb_phy", "ahb_ehci"; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch b/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch deleted file mode 100644 index 2c6164e..0000000 --- a/target/linux/sunxi/patches-3.13/174-3-dt-sun7i-add-ehci-cubieboard2.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 8ba068f40cce9612d2ac0879b6978274ab497d31 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Thu, 19 Sep 2013 21:29:45 +0200 -Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings for Cubieboard2 - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> - -Conflicts: - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ---- - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 45 +++++++++++++++++++++++++++++ - 1 file changed, 45 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -@@ -69,6 +69,20 @@ - allwinner,drive = <0>; - allwinner,pull = <0>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PH6"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; -+ -+ usb2_vbus_pin: usb2_vbus_pin@0 { -+ allwinner,pins = "PH3"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart0: serial@01c28000 { -@@ -86,6 +100,15 @@ - i2c1: i2c@01c2b000 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins_a>; -+ }; -+ -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ vbus-supply = <®_usb2_vbus>; - status = "okay"; - }; - }; -@@ -119,5 +142,27 @@ - gpio = <&pio 1 8 0>; - enable-active-high; - }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 6 0>; -+ }; -+ -+ reg_usb2_vbus: usb2-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb2_vbus_pin>; -+ regulator-name = "usb2-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 7 3 0>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch b/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch deleted file mode 100644 index 1df7e5e..0000000 --- a/target/linux/sunxi/patches-3.13/174-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 5031cb9d88fe9ea4a37fe342ec5f8e2f0f930e00 Mon Sep 17 00:00:00 2001 -From: Zalan Blenessy <zalan.blenessy@gmail.com> -Date: Sun, 22 Dec 2013 17:08:10 +0100 -Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to Olinuxino A20 Micro dts - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 47 +++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts -@@ -85,6 +85,20 @@ - allwinner,drive = <1>; - allwinner,pull = <0>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PH6"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; -+ -+ usb2_vbus_pin: usb2_vbus_pin@0 { -+ allwinner,pins = "PH3"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart0: serial@01c28000 { -@@ -122,6 +136,16 @@ - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; -+ -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; -+ -+ ehci1: ehci1@0x01c1c000 { -+ vbus-supply = <®_usb2_vbus>; -+ status = "okay"; -+ }; - }; - - leds { -@@ -138,6 +162,7 @@ - - regulators { - compatible = "simple-bus"; -+ pinctrl-names = "default"; - - reg_ahci_5v: ahci-5v { - compatible = "regulator-fixed"; -@@ -148,5 +173,27 @@ - gpio = <&pio 1 8 0>; - enable-active-high; - }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&pio 7 6 0>; -+ }; -+ -+ reg_usb2_vbus: usb2-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb2_vbus_pin>; -+ regulator-name = "usb2-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&pio 7 3 0>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch b/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch deleted file mode 100644 index f95833e..0000000 --- a/target/linux/sunxi/patches-3.13/174-5-dt-sun7i-add-ehci-cubietruck.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 90cab9a5e7c43bfbda25dd114a838f4e4b50b6ff Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 17 Dec 2013 23:04:57 +0100 -Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to cubietruck dts - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 46 ++++++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -@@ -43,11 +43,21 @@ - status = "okay"; - }; - -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; -+ - sata: ahci@01c18000 { - pwr-supply = <®_ahci_5v>; - status = "okay"; - }; - -+ ehci1: ehci1@0x01c1c000 { -+ vbus-supply = <®_usb2_vbus>; -+ status = "okay"; -+ }; -+ - pinctrl@01c20800 { - mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 { - allwinner,pins = "PH1"; -@@ -90,6 +100,20 @@ - allwinner,drive = <0>; - allwinner,pull = <2>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PH6"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; -+ -+ usb2_vbus_pin: usb2_vbus_pin@0 { -+ allwinner,pins = "PH3"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart0: serial@01c28000 { -@@ -175,5 +199,27 @@ - gpio = <&pio 7 12 0>; - enable-active-high; - }; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&pio 7 6 0>; -+ }; -+ -+ reg_usb2_vbus: usb2-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb2_vbus_pin>; -+ regulator-name = "usb2-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&pio 7 3 0>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch deleted file mode 100644 index eb706c7..0000000 --- a/target/linux/sunxi/patches-3.13/175-1-dt-sun5i-add-usbclock-nodes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From f017ea35bd87e7935fbf5a03bc016d8b1efa03c0 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Tue, 24 Sep 2013 20:02:39 +0200 -Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB Host clocks - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/sun5i-a13.dtsi -+++ b/arch/arm/boot/dts/sun5i-a13.dtsi -@@ -90,6 +90,14 @@ - clock-output-names = "pll6_sata", "pll6_other", "pll6"; - }; - -+ usb:usb@0x01c200cc { -+ #clock-cells = <1>; -+ compatible = "allwinner,sun5i-usb-gates-clk"; -+ reg = <0x01c200cc 0x4>; -+ clocks = <&pll6 1>; -+ clock-output-names = "usb_ohci0", "usb_phy"; -+ }; -+ - /* dummy is 200M */ - cpu: cpu@01c20054 { - #clock-cells = <0>; diff --git a/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch b/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch deleted file mode 100644 index 0dff48f..0000000 --- a/target/linux/sunxi/patches-3.13/175-2-dt-sun5i-add-ehci-bindings.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 3d3aa5f5c67d3f860b68def6a0ffce5e7175f85e Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Tue, 24 Sep 2013 20:03:40 +0200 -Subject: [PATCH] ARM: sun5i: dt: Add USB EHCI bindings - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun5i-a13.dtsi | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - ---- a/arch/arm/boot/dts/sun5i-a13.dtsi -+++ b/arch/arm/boot/dts/sun5i-a13.dtsi -@@ -16,6 +16,10 @@ - / { - interrupt-parent = <&intc>; - -+ aliases { -+ ehci1 = &ehci0; -+ }; -+ - cpus { - #address-cells = <1>; - #size-cells = <0>; -@@ -423,5 +427,22 @@ - interrupts = <82>, <83>; - clocks = <&ahb_gates 28>; - }; -+ -+ usb_rst: reset@0x01c200cc { -+ #reset-cells = <1>; -+ compatible = "allwinner,sun4i-clock-reset"; -+ reg = <0x01c200cc 0x4>; -+ }; -+ -+ ehci0: ehci0@0x01c14000 { -+ compatible = "allwinner,sunxi-ehci"; -+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>; -+ interrupts = <39>; -+ resets = <&usb_rst 1>; -+ reset-names = "ehci_reset"; -+ clocks = <&usb 8>, <&ahb_gates 1>; -+ clock-names = "usb_phy", "ahb_ehci"; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch b/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch deleted file mode 100644 index 05a7981..0000000 --- a/target/linux/sunxi/patches-3.13/175-3-dt-sun5i-add-ehci-a13.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 586c4aa0aeb07dacccb25a419a7b6625521ddea8 Mon Sep 17 00:00:00 2001 -From: arokux <arokux@gmail.com> -Date: Tue, 24 Sep 2013 20:07:53 +0200 -Subject: [PATCH] ARM: sun5i: dt: Add EHCI bindings to A13-Olinuxino - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts -+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts -@@ -46,6 +46,13 @@ - allwinner,drive = <1>; - allwinner,pull = <0>; - }; -+ -+ usb1_vbus_pin: usb1_vbus_pin@0 { -+ allwinner,pins = "PG11"; -+ allwinner,function = "gpio_out"; -+ allwinner,drive = <0>; -+ allwinner,pull = <2>; -+ }; - }; - - uart1: serial@01c28400 { -@@ -71,6 +78,11 @@ - pinctrl-0 = <&i2c2_pins_a>; - status = "okay"; - }; -+ -+ ehci0: ehci0@0x01c14000 { -+ vbus-supply = <®_usb1_vbus>; -+ status = "okay"; -+ }; - }; - - leds { -@@ -83,4 +95,19 @@ - default-state = "on"; - }; - }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_usb1_vbus: usb1-vbus { -+ compatible = "regulator-fixed"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usb1_vbus_pin>; -+ regulator-name = "usb1-vbus"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpio = <&pio 6 11 0>; -+ }; -+ }; - }; diff --git a/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch b/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch new file mode 100644 index 0000000..dc69d17 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/175-lradc-add-driver.patch @@ -0,0 +1,339 @@ +From 14cf22b1db1b6e6b7333e8a7245055966f5497e3 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Wed, 1 Jan 2014 19:44:49 +0100 +Subject: [PATCH] input: Add new sun4i-lradc-keys driver + +Allwinnner sunxi SoCs have a low resolution adc (called lradc) which is +specifically designed to have various (tablet) keys (ie home, back, search, +etc). attached to it using a resistor network. This adds a driver for this. + +There are 2 channels, currently this driver only supports chan0 since there +are no boards known to use chan1. The devicetree properties are already +prefixed with chan0 as preparation for chan1 support in the future. + +This has been tested on an olimex a10s-olinuxino-micro, a13-olinuxino, and +a20-olinuxino-micro. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../devicetree/bindings/input/sun4i-lradc-keys.txt | 22 ++ + drivers/input/keyboard/Kconfig | 10 + + drivers/input/keyboard/Makefile | 1 + + drivers/input/keyboard/sun4i-lradc-keys.c | 243 +++++++++++++++++++++ + 4 files changed, 276 insertions(+) + create mode 100644 Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt + create mode 100644 drivers/input/keyboard/sun4i-lradc-keys.c + +diff --git a/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt +new file mode 100644 +index 0000000..7801264 +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt +@@ -0,0 +1,22 @@ ++Allwinner sun4i low res adc attached tablet keys ++------------------------------------------------ ++ ++Required properties: ++ - compatible: "allwinner,sun4i-lradc-keys" ++ - reg: mmio address range of the chip ++ - interrupts: interrupt to which the chip is connected ++ - allwinner,chan0-step: step in mV between keys must be 150 or 200 ++ - linux,chan0-keycodes: array of dt-bindings/input/input.h KEY_ codes ++ ++Example: ++ ++#include <dt-bindings/input/input.h> ++ ++ lradc: lradc@01c22800 { ++ compatible = "allwinner,sun4i-lradc-keys"; ++ reg = <0x01c22800 0x100>; ++ interrupts = <31>; ++ allwinner,chan0-step = <200>; ++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN ++ KEY_MENU KEY_ENTER KEY_HOME>; ++ }; +diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig +index a673c9f..d8a51cd 100644 +--- a/drivers/input/keyboard/Kconfig ++++ b/drivers/input/keyboard/Kconfig +@@ -544,6 +544,16 @@ config KEYBOARD_STMPE + To compile this driver as a module, choose M here: the module will be + called stmpe-keypad. + ++config KEYBOARD_SUN4I_LRADC ++ tristate "Allwinner sun4i low res adc attached tablet keys support" ++ depends on ARCH_SUNXI ++ help ++ This selects support for the Allwinner low res adc attached tablet ++ keys found on Allwinner sunxi SoCs. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called sun4i-lradc-keys. ++ + config KEYBOARD_DAVINCI + tristate "TI DaVinci Key Scan" + depends on ARCH_DAVINCI_DM365 +diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile +index a699b61..f3265bd 100644 +--- a/drivers/input/keyboard/Makefile ++++ b/drivers/input/keyboard/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o + obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o + obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o + obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o ++obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o + obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o + obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o + obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o +diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c +new file mode 100644 +index 0000000..5c55e17 +--- /dev/null ++++ b/drivers/input/keyboard/sun4i-lradc-keys.c +@@ -0,0 +1,243 @@ ++/* ++ * Allwinner sun4i low res adc attached tablet keys driver ++ * ++ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * Allwinnner sunxi SoCs have a lradc which is specifically designed to have ++ * various (tablet) keys (ie home, back, search, etc). attached to it using ++ * a resistor network. This driver is for the keys on such boards. ++ * ++ * There are 2 channels, currently this driver only supports chan0 since there ++ * are no boards known to use chan1. The devicetree properties are already ++ * prefixed with chan0 as preparation for chan1 support in the future. ++ */ ++ ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/input.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/of_platform.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#define LRADC_CTRL 0x00 ++#define LRADC_INTC 0x04 ++#define LRADC_INTS 0x08 ++#define LRADC_DATA0 0x0c ++#define LRADC_DATA1 0x10 ++ ++/* LRADC_CTRL bits */ ++#define FIRST_CONVERT_DLY(x) ((x) << 24) /* 8 bits */ ++#define CHAN_SELECT(x) ((x) << 22) /* 2 bits */ ++#define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */ ++#define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */ ++#define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */ ++#define HOLD_EN(x) ((x) << 6) ++#define LEVELB_VOL(x) ((x) << 4) /* 2 bits */ ++#define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */ ++#define ENABLE(x) ((x) << 0) ++ ++/* LRADC_INTC and LRADC_INTS bits */ ++#define CHAN1_KEYUP_IRQ BIT(12) ++#define CHAN1_ALRDY_HOLD_IRQ BIT(11) ++#define CHAN1_HOLD_IRQ BIT(10) ++#define CHAN1_KEYDOWN_IRQ BIT(9) ++#define CHAN1_DATA_IRQ BIT(8) ++#define CHAN0_KEYUP_IRQ BIT(4) ++#define CHAN0_ALRDY_HOLD_IRQ BIT(3) ++#define CHAN0_HOLD_IRQ BIT(2) ++#define CHAN0_KEYDOWN_IRQ BIT(1) ++#define CHAN0_DATA_IRQ BIT(0) ++ ++#define MAX_KEYS 13 ++ ++/* Lookup table to map the adc val to a keycode index for 150 mv step size */ ++static const u8 adc_val_to_key_index_step150[64] = { ++ 0, 0, 0, ++ 1, 1, 1, 1, 1, ++ 2, 2, 2, 2, 2, ++ 3, 3, 3, 3, ++ 4, 4, 4, 4, 4, ++ 5, 5, 5, 5, 5, ++ 6, 6, 6, 6, 6, ++ 7, 7, 7, 7, ++ 8, 8, 8, 8, 8, ++ 9, 9, 9, 9, 9, ++ 10, 10, 10, 10, ++ 11, 11, 11, 11, ++ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ++}; ++ ++/* Lookup table to map the adc val to a keycode index for 200 mv step size */ ++static const u8 adc_val_to_key_index_step200[64] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 1, 1, 1, 1, 1, 1, 1, ++ 2, 2, 2, 2, 2, 2, 2, ++ 3, 3, 3, 3, 3, 3, ++ 4, 4, 4, 4, 4, 4, ++ 5, 5, 5, 5, 5, 5, ++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, ++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 ++}; ++ ++struct sun4i_lradc_data { ++ struct device *dev; ++ struct input_dev *input; ++ void __iomem *base; ++ u32 chan0_step; ++ u32 chan0_keycode; ++ u32 chan0_keycodes[MAX_KEYS]; ++}; ++ ++static irqreturn_t sun4i_lradc_irq(int irq, void *dev_id) ++{ ++ struct sun4i_lradc_data *lradc = dev_id; ++ u32 ints, val; ++ ++ ints = readl(lradc->base + LRADC_INTS); ++ ++ /* ++ * lradc supports only one keypress at a time, release does not give ++ * any info as to which key was released, so we cache the keycode. ++ */ ++ if ((ints & CHAN0_KEYDOWN_IRQ) && lradc->chan0_keycode == 0) { ++ val = readl(lradc->base + LRADC_DATA0); ++ if (lradc->chan0_step == 150) ++ val = adc_val_to_key_index_step150[val]; ++ else ++ val = adc_val_to_key_index_step200[val]; ++ ++ lradc->chan0_keycode = lradc->chan0_keycodes[val]; ++ input_report_key(lradc->input, lradc->chan0_keycode, 1); ++ } ++ ++ if (ints & CHAN0_KEYUP_IRQ) { ++ input_report_key(lradc->input, lradc->chan0_keycode, 0); ++ lradc->chan0_keycode = 0; ++ } ++ ++ input_sync(lradc->input); ++ ++ writel(ints, lradc->base + LRADC_INTS); ++ ++ return IRQ_HANDLED; ++} ++ ++static int sun4i_lradc_open(struct input_dev *dev) ++{ ++ struct sun4i_lradc_data *lradc = input_get_drvdata(dev); ++ ++ /* ++ * Set sample time to 16 ms / 62.5 Hz. Wait 2 * 16 ms for key to ++ * stabilize on press, wait (1 + 1) * 16 ms for key release ++ */ ++ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) | ++ SAMPLE_RATE(2) | ENABLE(1), lradc->base + LRADC_CTRL); ++ ++ writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC); ++ ++ return 0; ++} ++ ++static void sun4i_lradc_close(struct input_dev *dev) ++{ ++ struct sun4i_lradc_data *lradc = input_get_drvdata(dev); ++ ++ /* Disable lradc, leave other settings unchanged */ ++ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) | ++ SAMPLE_RATE(2), lradc->base + LRADC_CTRL); ++ writel(0, lradc->base + LRADC_INTC); ++} ++ ++static int sun4i_lradc_probe(struct platform_device *pdev) ++{ ++ struct sun4i_lradc_data *lradc; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ int i, ret; ++ ++ lradc = devm_kzalloc(dev, sizeof(struct sun4i_lradc_data), GFP_KERNEL); ++ if (!lradc) ++ return -ENOMEM; ++ ++ ret = of_property_read_u32(np, "allwinner,chan0-step", ++ &lradc->chan0_step); ++ if (ret || (lradc->chan0_step != 150 && lradc->chan0_step != 200)) { ++ dev_err(dev, "Invalid allwinner,chan0-step dt-property\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < MAX_KEYS; i++) ++ of_property_read_u32_index(np, "linux,chan0-keycodes", ++ i, &lradc->chan0_keycodes[i]); ++ ++ lradc->dev = dev; ++ lradc->input = devm_input_allocate_device(dev); ++ if (!lradc->input) ++ return -ENOMEM; ++ ++ lradc->input->name = pdev->name; ++ lradc->input->phys = "sun4i_lradc/input0"; ++ lradc->input->open = sun4i_lradc_open; ++ lradc->input->close = sun4i_lradc_close; ++ lradc->input->id.bustype = BUS_HOST; ++ lradc->input->id.vendor = 0x0001; ++ lradc->input->id.product = 0x0001; ++ lradc->input->id.version = 0x0100; ++ lradc->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY); ++ for (i = 0; i < MAX_KEYS; i++) ++ set_bit(lradc->chan0_keycodes[i], lradc->input->keybit); ++ input_set_drvdata(lradc->input, lradc); ++ ++ lradc->base = devm_ioremap_resource(dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ if (IS_ERR(lradc->base)) ++ return PTR_ERR(lradc->base); ++ ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), sun4i_lradc_irq, ++ 0, "sun4i-lradc-keys", lradc); ++ if (ret) ++ return ret; ++ ++ ret = input_register_device(lradc->input); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, lradc); ++ return 0; ++} ++ ++static const struct of_device_id sun4i_lradc_of_match[] = { ++ { .compatible = "allwinner,sun4i-lradc-keys", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match); ++ ++static struct platform_driver sun4i_lradc_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sun4i-lradc-keys", ++ .of_match_table = of_match_ptr(sun4i_lradc_of_match), ++ }, ++ .probe = sun4i_lradc_probe, ++}; ++ ++module_platform_driver(sun4i_lradc_driver); ++ ++MODULE_DESCRIPTION("Allwinner sun4i low res adc attached tablet keys driver"); ++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch new file mode 100644 index 0000000..f23ad66 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/176-1-dt-sun7i-add-lradc.patch @@ -0,0 +1,59 @@ +From 0b35a283be3dcd9495bb7c0e13ef2cd58a5d2afc Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Wed, 1 Jan 2014 20:26:21 +0100 +Subject: [PATCH] ARM: dts: sun7i: Add lradc node + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 9 +++++++++ + arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++ + 2 files changed, 16 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index d4e2355..aef289f 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -14,6 +14,7 @@ + /dts-v1/; + /include/ "sun7i-a20.dtsi" + /include/ "sunxi-ahci-reg.dtsi" ++#include <dt-bindings/input/input.h> + + / { + model = "Olimex A20-Olinuxino Micro"; +@@ -57,6 +58,14 @@ + }; + }; + ++ lradc: lradc@01c22800 { ++ allwinner,chan0-step = <200>; ++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN ++ KEY_MENU KEY_SEARCH KEY_HOME ++ KEY_ESC KEY_ENTER>; ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index fa2ef07..b58ce25 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -608,6 +608,13 @@ + interrupts = <0 24 1>; + }; + ++ lradc: lradc@01c22800 { ++ compatible = "allwinner,sun4i-lradc-keys"; ++ reg = <0x01c22800 0x100>; ++ interrupts = <0 31 4>; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun7i-a20-sid"; + reg = <0x01c23800 0x200>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch new file mode 100644 index 0000000..9183d9c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/176-2-dt-sun4i-add-lradc.patch @@ -0,0 +1,31 @@ +From 7d6d16c0c9b96695cd0f5e5845ac192209f0811d Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Wed, 1 Jan 2014 19:51:36 +0100 +Subject: [PATCH] ARM: dts: sun4i: Add lradc node + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index ba05e6e..1a9ab7e 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -494,6 +494,13 @@ + interrupts = <24>; + }; + ++ lradc: lradc@01c22800 { ++ compatible = "allwinner,sun4i-lradc-keys"; ++ reg = <0x01c22800 0x100>; ++ interrupts = <31>; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-sid"; + reg = <0x01c23800 0x10>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch b/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch new file mode 100644 index 0000000..c73b52b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/176-3-dt-sun5i-add-lradc.patch @@ -0,0 +1,104 @@ +From 23f834fe6efd9f97e9b336cc53d902e6a0158cc5 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Wed, 1 Jan 2014 19:50:33 +0100 +Subject: [PATCH] ARM: dts: sun5i: Add lradc node + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 8 ++++++++ + arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++ + arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 8 ++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++ + 4 files changed, 30 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +index 5c7b454..2cbca7b 100644 +--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts +@@ -13,6 +13,7 @@ + + /dts-v1/; + /include/ "sun5i-a10s.dtsi" ++#include <dt-bindings/input/input.h> + + / { + model = "Olimex A10s-Olinuxino Micro"; +@@ -73,6 +74,13 @@ + }; + }; + ++ lradc: lradc@01c22800 { ++ allwinner,chan0-step = <200>; ++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN ++ KEY_MENU KEY_ENTER KEY_HOME>; ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 15dfa9a..95cb245 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -430,6 +430,13 @@ + reg = <0x01c20c90 0x10>; + }; + ++ lradc: lradc@01c22800 { ++ compatible = "allwinner,sun4i-lradc-keys"; ++ reg = <0x01c22800 0x100>; ++ interrupts = <31>; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-sid"; + reg = <0x01c23800 0x10>; +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +index a7280f5..ba32a41 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +@@ -13,6 +13,7 @@ + + /dts-v1/; + /include/ "sun5i-a13.dtsi" ++#include <dt-bindings/input/input.h> + + / { + model = "Olimex A13-Olinuxino"; +@@ -43,6 +44,13 @@ + }; + }; + ++ lradc: lradc@01c22800 { ++ allwinner,chan0-step = <200>; ++ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN ++ KEY_MENU KEY_ENTER KEY_HOME>; ++ status = "okay"; ++ }; ++ + uart1: serial@01c28400 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_b>; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 14a99d0..bae0f5f 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -376,6 +376,13 @@ + reg = <0x01c20c90 0x10>; + }; + ++ lradc: lradc@01c22800 { ++ compatible = "allwinner,sun4i-lradc-keys"; ++ reg = <0x01c22800 0x100>; ++ interrupts = <31>; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-sid"; + reg = <0x01c23800 0x10>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch b/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch deleted file mode 100644 index f4014bd..0000000 --- a/target/linux/sunxi/patches-3.13/176-dt-sunxi-update-usb-regulator.patch +++ /dev/null @@ -1,98 +0,0 @@ -From b0a614458fb67fdb53e1b5518dabb85d688b196e Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 17 Dec 2013 22:59:17 +0100 -Subject: [PATCH] ARM: dts: sunxi: usb Vbus is 5v not 3.3v - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 ++++---- - arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 ++++---- - arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 4 ++-- - arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++---- - 4 files changed, 14 insertions(+), 14 deletions(-) - ---- a/arch/arm/boot/dts/sun4i-a10-a1000.dts -+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts -@@ -147,8 +147,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; -@@ -158,8 +158,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; ---- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts -@@ -158,8 +158,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; -@@ -169,8 +169,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; ---- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts -+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts -@@ -104,8 +104,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 6 11 0>; - }; ---- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts -@@ -148,8 +148,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb1_vbus_pin>; - regulator-name = "usb1-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 6 0>; - }; -@@ -159,8 +159,8 @@ - pinctrl-names = "default"; - pinctrl-0 = <&usb2_vbus_pin>; - regulator-name = "usb2-vbus"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&pio 7 3 0>; - }; diff --git a/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch b/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch deleted file mode 100644 index b2ee150..0000000 --- a/target/linux/sunxi/patches-3.13/177-dt-sun7i-fix-ehci-irqtypes.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 06285d1c64552291f136eb197b6f05bc9d9c1d0e Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 17 Dec 2013 23:26:45 +0100 -Subject: [PATCH] ARM: dts: sun7i: Fix ehci interrupt types - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -635,7 +635,7 @@ - ehci0: ehci0@0x01c14000 { - compatible = "allwinner,sunxi-ehci"; - reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>; -- interrupts = <0 39 1>; -+ interrupts = <0 39 4>; - resets = <&usb_rst 1>; - reset-names = "ehci_reset"; - clocks = <&usb 8>, <&ahb_gates 1>; -@@ -646,7 +646,7 @@ - ehci1: ehci1@0x01c1c000 { - compatible = "allwinner,sunxi-ehci"; - reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>; -- interrupts = <0 40 1>; -+ interrupts = <0 40 4>; - resets = <&usb_rst 2>; - reset-names = "ehci_reset"; - clocks = <&usb 8>, <&ahb_gates 3>; diff --git a/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch b/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch deleted file mode 100644 index 20779a5..0000000 --- a/target/linux/sunxi/patches-3.13/178-sunxi-ehci-fix-resource-check.patch +++ /dev/null @@ -1,22 +0,0 @@ -From e772c9c2f552740ae735328cbd06b1d7f8e9d885 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 17 Dec 2013 23:27:03 +0100 -Subject: [PATCH] ARM: sunxi-ehci: Fix resource check - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/usb/host/ehci-sunxi.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/usb/host/ehci-sunxi.c -+++ b/drivers/usb/host/ehci-sunxi.c -@@ -332,7 +332,8 @@ static int sunxi_ehci_probe(struct platf - if (pdev->resource[0].flags != IORESOURCE_MEM - || pdev->resource[1].flags != IORESOURCE_MEM - || pdev->resource[2].flags != IORESOURCE_MEM -- || pdev->resource[3].flags != IORESOURCE_IRQ) { -+ || (pdev->resource[3].flags & IORESOURCE_TYPE_BITS) -+ != IORESOURCE_IRQ) { - dev_err(&pdev->dev, "invalid resource type\n"); - return -ENODEV; - } diff --git a/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch b/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch new file mode 100644 index 0000000..5ae391a --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-0-usb-backport-device_wakeup_enable.patch @@ -0,0 +1,896 @@ +From 3c9740a117d40a74412775b5d3fe2b88a7635a0e Mon Sep 17 00:00:00 2001 +From: Peter Chen <peter.chen@freescale.com> +Date: Tue, 5 Nov 2013 10:46:02 +0800 +Subject: [PATCH] usb: hcd: move controller wakeup setting initialization to + individual driver + +Individual controller driver has different requirement for wakeup +setting, so move it from core to itself. In order to align with +current etting the default wakeup setting is enabled (except for +chipidea host). + +Pass compile test with below commands: + make O=outout/all allmodconfig + make -j$CPU_NUM O=outout/all drivers/usb + +Signed-off-by: Peter Chen <peter.chen@freescale.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/staging/dwc2/hcd.c | 2 ++ + drivers/staging/octeon-usb/octeon-hcd.c | 1 + + drivers/staging/ozwpan/ozhcd.c | 2 ++ + drivers/usb/c67x00/c67x00-hcd.c | 2 ++ + drivers/usb/core/hcd-pci.c | 1 + + drivers/usb/core/hcd.c | 6 ------ + drivers/usb/host/ehci-atmel.c | 1 + + drivers/usb/host/ehci-exynos.c | 1 + + drivers/usb/host/ehci-fsl.c | 1 + + drivers/usb/host/ehci-grlib.c | 1 + + drivers/usb/host/ehci-mv.c | 1 + + drivers/usb/host/ehci-mxc.c | 1 + + drivers/usb/host/ehci-octeon.c | 1 + + drivers/usb/host/ehci-omap.c | 1 + + drivers/usb/host/ehci-orion.c | 1 + + drivers/usb/host/ehci-platform.c | 1 + + drivers/usb/host/ehci-pmcmsp.c | 4 +++- + drivers/usb/host/ehci-ppc-of.c | 1 + + drivers/usb/host/ehci-ps3.c | 1 + + drivers/usb/host/ehci-sead3.c | 1 + + drivers/usb/host/ehci-sh.c | 1 + + drivers/usb/host/ehci-spear.c | 1 + + drivers/usb/host/ehci-tegra.c | 1 + + drivers/usb/host/ehci-tilegx.c | 1 + + drivers/usb/host/ehci-w90x900.c | 1 + + drivers/usb/host/ehci-xilinx-of.c | 4 +++- + drivers/usb/host/fhci-hcd.c | 2 ++ + drivers/usb/host/fotg210-hcd.c | 1 + + drivers/usb/host/fusbh200-hcd.c | 1 + + drivers/usb/host/hwa-hc.c | 1 + + drivers/usb/host/imx21-hcd.c | 1 + + drivers/usb/host/isp116x-hcd.c | 2 ++ + drivers/usb/host/isp1362-hcd.c | 2 ++ + drivers/usb/host/isp1760-hcd.c | 1 + + drivers/usb/host/ohci-at91.c | 4 +++- + drivers/usb/host/ohci-da8xx.c | 2 ++ + drivers/usb/host/ohci-exynos.c | 1 + + drivers/usb/host/ohci-jz4740.c | 1 + + drivers/usb/host/ohci-nxp.c | 4 +++- + drivers/usb/host/ohci-octeon.c | 2 ++ + drivers/usb/host/ohci-omap.c | 1 + + drivers/usb/host/ohci-omap3.c | 1 + + drivers/usb/host/ohci-platform.c | 2 ++ + drivers/usb/host/ohci-ppc-of.c | 4 +++- + drivers/usb/host/ohci-ps3.c | 1 + + drivers/usb/host/ohci-pxa27x.c | 4 +++- + drivers/usb/host/ohci-s3c2410.c | 1 + + drivers/usb/host/ohci-sa1111.c | 4 +++- + drivers/usb/host/ohci-sm501.c | 1 + + drivers/usb/host/ohci-spear.c | 4 +++- + drivers/usb/host/ohci-tilegx.c | 1 + + drivers/usb/host/ohci-tmio.c | 1 + + drivers/usb/host/oxu210hp-hcd.c | 1 + + drivers/usb/host/r8a66597-hcd.c | 1 + + drivers/usb/host/sl811-hcd.c | 2 ++ + drivers/usb/host/u132-hcd.c | 1 + + drivers/usb/host/uhci-grlib.c | 1 + + drivers/usb/host/uhci-platform.c | 1 + + drivers/usb/host/whci/hcd.c | 1 + + drivers/usb/host/xhci-plat.c | 1 + + drivers/usb/musb/musb_host.c | 1 + + drivers/usb/phy/phy-msm-usb.c | 1 + + drivers/usb/phy/phy-mv-usb.c | 6 ++++-- + drivers/usb/renesas_usbhs/mod_host.c | 1 + + 64 files changed, 92 insertions(+), 16 deletions(-) + +diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c +index 3cfd2d5..078cd91 100644 +--- a/drivers/staging/dwc2/hcd.c ++++ b/drivers/staging/dwc2/hcd.c +@@ -2921,6 +2921,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, + if (retval < 0) + goto error3; + ++ device_wakeup_enable(hcd->self.controller); ++ + dwc2_hcd_dump_state(hsotg); + + dwc2_enable_global_interrupts(hsotg); +diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c +index d118952..47e0a91 100644 +--- a/drivers/staging/octeon-usb/octeon-hcd.c ++++ b/drivers/staging/octeon-usb/octeon-hcd.c +@@ -3498,6 +3498,7 @@ static int octeon_usb_driver_probe(struct device *dev) + kfree(hcd); + return -1; + } ++ device_wakeup_enable(hcd->self.controller); + + dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); + +diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c +index d9c43c3..efaf26f 100644 +--- a/drivers/staging/ozwpan/ozhcd.c ++++ b/drivers/staging/ozwpan/ozhcd.c +@@ -2270,6 +2270,8 @@ static int oz_plat_probe(struct platform_device *dev) + usb_put_hcd(hcd); + return -1; + } ++ device_wakeup_enable(hcd->self.controller); ++ + spin_lock_bh(&g_hcdlock); + g_ozhcd = ozhcd; + spin_unlock_bh(&g_hcdlock); +diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c +index 75e47b8..20ec4ee 100644 +--- a/drivers/usb/c67x00/c67x00-hcd.c ++++ b/drivers/usb/c67x00/c67x00-hcd.c +@@ -384,6 +384,8 @@ int c67x00_hcd_probe(struct c67x00_sie *sie) + goto err2; + } + ++ device_wakeup_enable(hcd->self.controller); ++ + spin_lock_irqsave(&sie->lock, flags); + sie->private_data = c67x00; + sie->irq = c67x00_hcd_irq; +diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c +index dfe9d0f..d59d993 100644 +--- a/drivers/usb/core/hcd-pci.c ++++ b/drivers/usb/core/hcd-pci.c +@@ -282,6 +282,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + + if (retval != 0) + goto unmap_registers; ++ device_wakeup_enable(hcd->self.controller); + + if (pci_dev_run_wake(dev)) + pm_runtime_put_noidle(&dev->dev); +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index d3a9bcd..6297c9e 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -2712,12 +2712,6 @@ int usb_add_hcd(struct usb_hcd *hcd, + if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) + usb_hcd_poll_rh_status(hcd); + +- /* +- * Host controllers don't generate their own wakeup requests; +- * they only forward requests from the root hub. Therefore +- * controllers should always be enabled for remote wakeup. +- */ +- device_wakeup_enable(hcd->self.controller); + return retval; + + error_create_attr_group: +diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c +index 284f841..ec9f7b7 100644 +--- a/drivers/usb/host/ehci-atmel.c ++++ b/drivers/usb/host/ehci-atmel.c +@@ -153,6 +153,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval) + goto fail_add_hcd; ++ device_wakeup_enable(hcd->self.controller); + + return retval; + +diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c +index e97c198..d1d8c47 100644 +--- a/drivers/usb/host/ehci-exynos.c ++++ b/drivers/usb/host/ehci-exynos.c +@@ -166,6 +166,7 @@ static int exynos_ehci_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto fail_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + platform_set_drvdata(pdev, hcd); + +diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c +index 87a7426..854a68f 100644 +--- a/drivers/usb/host/ehci-fsl.c ++++ b/drivers/usb/host/ehci-fsl.c +@@ -138,6 +138,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval != 0) + goto err4; ++ device_wakeup_enable(hcd->self.controller); + + #ifdef CONFIG_USB_OTG + if (pdata->operating_mode == FSL_USB2_DR_OTG) { +diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c +index b52a66c..054792c 100644 +--- a/drivers/usb/host/ehci-grlib.c ++++ b/drivers/usb/host/ehci-grlib.c +@@ -140,6 +140,7 @@ static int ehci_hcd_grlib_probe(struct platform_device *op) + if (rv) + goto err_ioremap; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_ioremap: +diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c +index 6e8afca..bd61612 100644 +--- a/drivers/usb/host/ehci-mv.c ++++ b/drivers/usb/host/ehci-mv.c +@@ -257,6 +257,7 @@ static int mv_ehci_probe(struct platform_device *pdev) + "failed to add hcd with err %d\n", retval); + goto err_set_vbus; + } ++ device_wakeup_enable(hcd->self.controller); + } + + if (pdata->private_init) +diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c +index 0528dc4..dbe5e4e 100644 +--- a/drivers/usb/host/ehci-mxc.c ++++ b/drivers/usb/host/ehci-mxc.c +@@ -155,6 +155,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) + if (ret) + goto err_add; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_add: +diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c +index 4c528b2..c4ad7ed 100644 +--- a/drivers/usb/host/ehci-octeon.c ++++ b/drivers/usb/host/ehci-octeon.c +@@ -158,6 +158,7 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) + dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); + goto err3; + } ++ device_wakeup_enable(hcd->self.controller); + + platform_set_drvdata(pdev, hcd); + +diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c +index 6fa82d6..a24720b 100644 +--- a/drivers/usb/host/ehci-omap.c ++++ b/drivers/usb/host/ehci-omap.c +@@ -215,6 +215,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) + dev_err(dev, "failed to add hcd with err %d\n", ret); + goto err_pm_runtime; + } ++ device_wakeup_enable(hcd->self.controller); + + /* + * Bring PHYs out of reset for non PHY modes. +diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c +index 2ba7673..aa8b92b 100644 +--- a/drivers/usb/host/ehci-orion.c ++++ b/drivers/usb/host/ehci-orion.c +@@ -252,6 +252,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) + if (err) + goto err4; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err4: +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 7f30b71..01536cf 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -132,6 +132,7 @@ static int ehci_platform_probe(struct platform_device *dev) + if (err) + goto err_put_hcd; + ++ device_wakeup_enable(hcd->self.controller); + platform_set_drvdata(dev, hcd); + + return err; +diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c +index 893b707f..af3974a 100644 +--- a/drivers/usb/host/ehci-pmcmsp.c ++++ b/drivers/usb/host/ehci-pmcmsp.c +@@ -210,8 +210,10 @@ int usb_hcd_msp_probe(const struct hc_driver *driver, + + + retval = usb_add_hcd(hcd, res->start, IRQF_SHARED); +- if (retval == 0) ++ if (retval == 0) { ++ device_wakeup_enable(hcd->self.controller); + return 0; ++ } + + usb_remove_hcd(hcd); + err3: +diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c +index 875d2fc..b0965eb 100644 +--- a/drivers/usb/host/ehci-ppc-of.c ++++ b/drivers/usb/host/ehci-ppc-of.c +@@ -169,6 +169,7 @@ static int ehci_hcd_ppc_of_probe(struct platform_device *op) + if (rv) + goto err_ioremap; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_ioremap: +diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c +index 8188542..7934ff9 100644 +--- a/drivers/usb/host/ehci-ps3.c ++++ b/drivers/usb/host/ehci-ps3.c +@@ -189,6 +189,7 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev) + goto fail_add_hcd; + } + ++ device_wakeup_enable(hcd->self.controller); + return result; + + fail_add_hcd: +diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c +index 8a73449..cf12676 100644 +--- a/drivers/usb/host/ehci-sead3.c ++++ b/drivers/usb/host/ehci-sead3.c +@@ -126,6 +126,7 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) + IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); ++ device_wakeup_enable(hcd->self.controller); + return ret; + } + +diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c +index dc899eb..9b9b9f5 100644 +--- a/drivers/usb/host/ehci-sh.c ++++ b/drivers/usb/host/ehci-sh.c +@@ -151,6 +151,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add hcd"); + goto fail_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + priv->hcd = hcd; + platform_set_drvdata(pdev, priv); +diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c +index ee6f9ff..8bd915b 100644 +--- a/drivers/usb/host/ehci-spear.c ++++ b/drivers/usb/host/ehci-spear.c +@@ -130,6 +130,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) + if (retval) + goto err_stop_ehci; + ++ device_wakeup_enable(hcd->self.controller); + return retval; + + err_stop_ehci: +diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c +index b9fd039..a8f4471 100644 +--- a/drivers/usb/host/ehci-tegra.c ++++ b/drivers/usb/host/ehci-tegra.c +@@ -455,6 +455,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto cleanup_otg_set_host; + } ++ device_wakeup_enable(hcd->self.controller); + + return err; + +diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c +index 67026ff..f3713d3 100644 +--- a/drivers/usb/host/ehci-tilegx.c ++++ b/drivers/usb/host/ehci-tilegx.c +@@ -170,6 +170,7 @@ static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) + ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); ++ device_wakeup_enable(hcd->self.controller); + return ret; + } + +diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c +index cdad843..12c1a56 100644 +--- a/drivers/usb/host/ehci-w90x900.c ++++ b/drivers/usb/host/ehci-w90x900.c +@@ -94,6 +94,7 @@ static int usb_w90x900_probe(const struct hc_driver *driver, + if (retval != 0) + goto err4; + ++ device_wakeup_enable(hcd->self.controller); + return retval; + err4: + iounmap(hcd->regs); +diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c +index 95979f9..3cd2efa 100644 +--- a/drivers/usb/host/ehci-xilinx-of.c ++++ b/drivers/usb/host/ehci-xilinx-of.c +@@ -191,8 +191,10 @@ static int ehci_hcd_xilinx_of_probe(struct platform_device *op) + ehci->caps = hcd->regs + 0x100; + + rv = usb_add_hcd(hcd, irq, 0); +- if (rv == 0) ++ if (rv == 0) { ++ device_wakeup_enable(hcd->self.controller); + return 0; ++ } + + err_irq: + usb_put_hcd(hcd); +diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c +index 0551c0a..1cf68ea 100644 +--- a/drivers/usb/host/fhci-hcd.c ++++ b/drivers/usb/host/fhci-hcd.c +@@ -754,6 +754,8 @@ static int of_fhci_probe(struct platform_device *ofdev) + if (ret < 0) + goto err_add_hcd; + ++ device_wakeup_enable(hcd->self.controller); ++ + fhci_dfs_create(fhci); + + return 0; +diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c +index 97d6939..98a89d1 100644 +--- a/drivers/usb/host/fotg210-hcd.c ++++ b/drivers/usb/host/fotg210-hcd.c +@@ -5889,6 +5889,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev) + dev_err(dev, "failed to add hcd with err %d\n", retval); + goto fail_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + return retval; + +diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c +index 9ea85b6..ba94990 100644 +--- a/drivers/usb/host/fusbh200-hcd.c ++++ b/drivers/usb/host/fusbh200-hcd.c +@@ -5798,6 +5798,7 @@ static int fusbh200_hcd_probe(struct platform_device *pdev) + dev_err(dev, "failed to add hcd with err %d\n", retval); + goto fail_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + return retval; + +diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c +index a4ec9e6..7fd3f9b 100644 +--- a/drivers/usb/host/hwa-hc.c ++++ b/drivers/usb/host/hwa-hc.c +@@ -791,6 +791,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, + dev_err(dev, "Cannot add HCD: %d\n", result); + goto error_add_hcd; + } ++ device_wakeup_enable(usb_hcd->self.controller); + result = wusbhc_b_create(&hwahc->wusbhc); + if (result < 0) { + dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); +diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c +index 0122624..207bad9 100644 +--- a/drivers/usb/host/imx21-hcd.c ++++ b/drivers/usb/host/imx21-hcd.c +@@ -1910,6 +1910,7 @@ static int imx21_probe(struct platform_device *pdev) + dev_err(imx21->dev, "usb_add_hcd() returned %d\n", ret); + goto failed_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + return 0; + +diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c +index 7722ec6..2740f65 100644 +--- a/drivers/usb/host/isp116x-hcd.c ++++ b/drivers/usb/host/isp116x-hcd.c +@@ -1645,6 +1645,8 @@ static int isp116x_probe(struct platform_device *pdev) + if (ret) + goto err6; + ++ device_wakeup_enable(hcd->self.controller); ++ + ret = create_debug_file(isp116x); + if (ret) { + ERR("Couldn't create debugfs entry\n"); +diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c +index cd94b10..34645ae 100644 +--- a/drivers/usb/host/isp1362-hcd.c ++++ b/drivers/usb/host/isp1362-hcd.c +@@ -2746,6 +2746,8 @@ static int isp1362_probe(struct platform_device *pdev) + retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_SHARED); + if (retval != 0) + goto err6; ++ device_wakeup_enable(hcd->self.controller); ++ + pr_info("%s, irq %d\n", hcd->product_desc, irq); + + create_debug_file(isp1362_hcd); +diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c +index 2facee5..51a0ae9 100644 +--- a/drivers/usb/host/isp1760-hcd.c ++++ b/drivers/usb/host/isp1760-hcd.c +@@ -2250,6 +2250,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + ret = usb_add_hcd(hcd, irq, irqflags); + if (ret) + goto err_unmap; ++ device_wakeup_enable(hcd->self.controller); + + return hcd; + +diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c +index cc9462f..29d2093 100644 +diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c +index 71dbd85..f0fe0d2 100644 +--- a/drivers/usb/host/ohci-da8xx.c ++++ b/drivers/usb/host/ohci-da8xx.c +@@ -348,6 +348,8 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, + if (error) + goto err4; + ++ device_wakeup_enable(hcd->self.controller); ++ + if (hub->ocic_notify) { + error = hub->ocic_notify(ohci_da8xx_ocic_handler); + if (!error) +diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c +index 9897d70..68588d8 100644 +--- a/drivers/usb/host/ohci-exynos.c ++++ b/drivers/usb/host/ohci-exynos.c +@@ -146,6 +146,7 @@ static int exynos_ohci_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto fail_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + return 0; + + fail_add_hcd: +diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c +index d4ef539..efe31f3 100644 +--- a/drivers/usb/host/ohci-jz4740.c ++++ b/drivers/usb/host/ohci-jz4740.c +@@ -217,6 +217,7 @@ static int jz4740_ohci_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret); + goto err_disable; + } ++ device_wakeup_enable(hcd->self.controller); + + return 0; + +diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c +index e99db8a..719f28e 100644 +--- a/drivers/usb/host/ohci-nxp.c ++++ b/drivers/usb/host/ohci-nxp.c +@@ -274,8 +274,10 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev) + + dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq); + ret = usb_add_hcd(hcd, irq, 0); +- if (ret == 0) ++ if (ret == 0) { ++ device_wakeup_enable(hcd->self.controller); + return ret; ++ } + + ohci_nxp_stop_hc(); + fail_resource: +diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c +index 6c16dce..49b220d 100644 +--- a/drivers/usb/host/ohci-octeon.c ++++ b/drivers/usb/host/ohci-octeon.c +@@ -171,6 +171,8 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev) + goto err3; + } + ++ device_wakeup_enable(hcd->self.controller); ++ + platform_set_drvdata(pdev, hcd); + + return 0; +diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c +index f253214..a44a4fe 100644 +--- a/drivers/usb/host/ohci-omap.c ++++ b/drivers/usb/host/ohci-omap.c +@@ -367,6 +367,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, + if (retval) + goto err3; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + err3: + iounmap(hcd->regs); +diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c +index 2145741..ec15aeb 100644 +--- a/drivers/usb/host/ohci-omap3.c ++++ b/drivers/usb/host/ohci-omap3.c +@@ -130,6 +130,7 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) + dev_dbg(dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } ++ device_wakeup_enable(hcd->self.controller); + + return 0; + +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index f351ff5..68f674c 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -108,6 +108,8 @@ static int ohci_platform_probe(struct platform_device *dev) + if (err) + goto err_put_hcd; + ++ device_wakeup_enable(hcd->self.controller); ++ + platform_set_drvdata(dev, hcd); + + return err; +diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c +index 81f3eba..83e33d4 100644 +--- a/drivers/usb/host/ohci-ppc-of.c ++++ b/drivers/usb/host/ohci-ppc-of.c +@@ -147,8 +147,10 @@ static int ohci_hcd_ppc_of_probe(struct platform_device *op) + ohci_hcd_init(ohci); + + rv = usb_add_hcd(hcd, irq, 0); +- if (rv == 0) ++ if (rv == 0) { ++ device_wakeup_enable(hcd->self.controller); + return 0; ++ } + + /* by now, 440epx is known to show usb_23 erratum */ + np = of_find_compatible_node(NULL, NULL, "ibm,usb-ehci-440epx"); +diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c +index 7d35cd9..71d8bc4 100644 +--- a/drivers/usb/host/ohci-ps3.c ++++ b/drivers/usb/host/ohci-ps3.c +@@ -173,6 +173,7 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev) + goto fail_add_hcd; + } + ++ device_wakeup_enable(hcd->self.controller); + return result; + + fail_add_hcd: +diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c +index e89ac4d..5343ecf 100644 +--- a/drivers/usb/host/ohci-pxa27x.c ++++ b/drivers/usb/host/ohci-pxa27x.c +@@ -442,8 +442,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device + ohci->num_ports = 3; + + retval = usb_add_hcd(hcd, irq, 0); +- if (retval == 0) ++ if (retval == 0) { ++ device_wakeup_enable(hcd->self.controller); + return retval; ++ } + + pxa27x_stop_hc(pxa_ohci, &pdev->dev); + err3: +diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c +index 83cd1dc..ff7c8f1 100644 +--- a/drivers/usb/host/ohci-s3c2410.c ++++ b/drivers/usb/host/ohci-s3c2410.c +@@ -395,6 +395,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, + if (retval != 0) + goto err_ioremap; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_ioremap: +diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c +index aa9e127..2ac266d 100644 +--- a/drivers/usb/host/ohci-sa1111.c ++++ b/drivers/usb/host/ohci-sa1111.c +@@ -211,8 +211,10 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev) + goto err2; + + ret = usb_add_hcd(hcd, dev->irq[1], 0); +- if (ret == 0) ++ if (ret == 0) { ++ device_wakeup_enable(hcd->self.controller); + return ret; ++ } + + sa1111_stop_hc(dev); + err2: +diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c +index 2a5de5f..4e81c80 100644 +--- a/drivers/usb/host/ohci-sm501.c ++++ b/drivers/usb/host/ohci-sm501.c +@@ -168,6 +168,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval) + goto err5; ++ device_wakeup_enable(hcd->self.controller); + + /* enable power and unmask interrupts */ + +diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c +index e418c19..4cb98ab 100644 +--- a/drivers/usb/host/ohci-spear.c ++++ b/drivers/usb/host/ohci-spear.c +@@ -103,8 +103,10 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) + ohci = hcd_to_ohci(hcd); + + retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); +- if (retval == 0) ++ if (retval == 0) { ++ device_wakeup_enable(hcd->self.controller); + return retval; ++ } + + clk_disable_unprepare(sohci_p->clk); + err_put_hcd: +diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c +index 22540ab..0b183e0 100644 +--- a/drivers/usb/host/ohci-tilegx.c ++++ b/drivers/usb/host/ohci-tilegx.c +@@ -159,6 +159,7 @@ static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) + ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); + if (ret == 0) { + platform_set_drvdata(pdev, hcd); ++ device_wakeup_enable(hcd->self.controller); + return ret; + } + +diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c +index ecb09a5..9c44093 100644 +--- a/drivers/usb/host/ohci-tmio.c ++++ b/drivers/usb/host/ohci-tmio.c +@@ -250,6 +250,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev) + if (ret) + goto err_add_hcd; + ++ device_wakeup_enable(hcd->self.controller); + if (ret == 0) + return ret; + +diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c +index 4a05148..778eeaf 100644 +--- a/drivers/usb/host/oxu210hp-hcd.c ++++ b/drivers/usb/host/oxu210hp-hcd.c +@@ -3751,6 +3751,7 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev, + if (ret < 0) + return ERR_PTR(ret); + ++ device_wakeup_enable(hcd->self.controller); + return hcd; + } + +diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c +index 3bddfcf..47b1322 100644 +--- a/drivers/usb/host/r8a66597-hcd.c ++++ b/drivers/usb/host/r8a66597-hcd.c +@@ -2514,6 +2514,7 @@ static int r8a66597_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "Failed to add hcd\n"); + goto clean_up3; + } ++ device_wakeup_enable(hcd->self.controller); + + return 0; + +diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c +index 79620c3..0115e7f 100644 +--- a/drivers/usb/host/sl811-hcd.c ++++ b/drivers/usb/host/sl811-hcd.c +@@ -1732,6 +1732,8 @@ static void remove_debug_file(struct sl811 *sl811) + if (retval != 0) + goto err6; + ++ device_wakeup_enable(hcd->self.controller); ++ + create_debug_file(sl811); + return retval; + +diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c +index 46236e9..c067175 100644 +--- a/drivers/usb/host/u132-hcd.c ++++ b/drivers/usb/host/u132-hcd.c +@@ -3133,6 +3133,7 @@ static int u132_probe(struct platform_device *pdev) + u132_u132_put_kref(u132); + return retval; + } else { ++ device_wakeup_enable(hcd->self.controller); + u132_monitor_queue_work(u132, 100); + return 0; + } +diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c +index 53c23ff..ab25dc3 100644 +--- a/drivers/usb/host/uhci-grlib.c ++++ b/drivers/usb/host/uhci-grlib.c +@@ -141,6 +141,7 @@ static int uhci_hcd_grlib_probe(struct platform_device *op) + if (rv) + goto err_uhci; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_uhci: +diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c +index 3003fef..44e6c9d 100644 +--- a/drivers/usb/host/uhci-platform.c ++++ b/drivers/usb/host/uhci-platform.c +@@ -108,6 +108,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev) + if (ret) + goto err_uhci; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + + err_uhci: +diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c +index 1b0888f..d7b363a 100644 +--- a/drivers/usb/host/whci/hcd.c ++++ b/drivers/usb/host/whci/hcd.c +@@ -293,6 +293,7 @@ static int whc_probe(struct umc_dev *umc) + dev_err(dev, "cannot add HCD: %d\n", ret); + goto error_usb_add_hcd; + } ++ device_wakeup_enable(usb_hcd->self.controller); + + ret = wusbhc_b_create(wusbhc); + if (ret) { +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index d9c169f..9d29aa1 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -139,6 +139,7 @@ static int xhci_plat_probe(struct platform_device *pdev) + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) + goto unmap_registers; ++ device_wakeup_enable(hcd->self.controller); + + /* USB 2.0 roothub is stored in the platform_device now. */ + hcd = platform_get_drvdata(pdev); +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 6582a20..e208375 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -2657,6 +2657,7 @@ int musb_host_setup(struct musb *musb, int power_budget) + if (ret < 0) + return ret; + ++ device_wakeup_enable(hcd->self.controller); + return 0; + } + +diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c +index e9d4cd9..3775283 100644 +--- a/drivers/usb/phy/phy-msm-usb.c ++++ b/drivers/usb/phy/phy-msm-usb.c +@@ -669,6 +669,7 @@ static void msm_otg_start_host(struct usb_phy *phy, int on) + pdata->setup_gpio(OTG_STATE_A_HOST); + #ifdef CONFIG_USB + usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); ++ device_wakeup_enable(hcd->self.controller); + #endif + } else { + dev_dbg(phy->dev, "host off\n"); +diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c +index 98f6ac6..44f316e 100644 +--- a/drivers/usb/phy/phy-mv-usb.c ++++ b/drivers/usb/phy/phy-mv-usb.c +@@ -213,10 +213,12 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) + + hcd = bus_to_hcd(otg->host); + +- if (on) ++ if (on) { + usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); +- else ++ device_wakeup_enable(hcd->self.controller); ++ } else { + usb_remove_hcd(hcd); ++ } + #endif /* CONFIG_USB */ + } + +diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c +index e40f565..10e1ded 100644 +--- a/drivers/usb/renesas_usbhs/mod_host.c ++++ b/drivers/usb/renesas_usbhs/mod_host.c +@@ -1469,6 +1469,7 @@ static int usbhsh_start(struct usbhs_priv *priv) + ret = usb_add_hcd(hcd, 0, 0); + if (ret < 0) + return 0; ++ device_wakeup_enable(hcd->self.controller); + + /* + * pipe initialize and enable DCP +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch b/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch new file mode 100644 index 0000000..070f4f4 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-1-usb-ohci-platform-dt-instantiation.patch @@ -0,0 +1,322 @@ +From 6b63b9b2093258541dd79a3ed311cd1d0412b846 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 5 Jan 2014 14:42:39 +0100 +Subject: [PATCH] ohci-platform: Add support for devicetree instantiation + +Add support for ohci-platform instantiation from devicetree, including +optionally getting clks and a phy from devicetree, and enabling / disabling +those on power_on / off. + +This should allow using ohci-platform from devicetree in various cases. +Specifically after this commit it can be used for the ohci controller found +on Allwinner sunxi SoCs. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +--- + Documentation/devicetree/bindings/usb/usb-ohci.txt | 22 +++ + drivers/usb/host/ohci-platform.c | 162 ++++++++++++++++++--- + 2 files changed, 162 insertions(+), 22 deletions(-) + create mode 100644 Documentation/devicetree/bindings/usb/usb-ohci.txt + +diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt +new file mode 100644 +index 0000000..6ba38d9 +--- /dev/null ++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt +@@ -0,0 +1,22 @@ ++USB OHCI controllers ++ ++Required properties: ++- compatible : "usb-ohci" ++- reg : ohci controller register range (address and length) ++- interrupts : ohci controller interrupt ++ ++Optional properties: ++- clocks : a list of phandle + clock specifier pairs ++- phys : phandle + phy specifier pair ++- phy-names : "usb" ++ ++Example: ++ ++ ohci0: usb@01c14400 { ++ compatible = "allwinner,sun4i-a10-ohci", "usb-ohci"; ++ reg = <0x01c14400 0x100>; ++ interrupts = <64>; ++ clocks = <&usb_clk 6>, <&ahb_gates 2>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ }; +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index 68f674c..49304dd 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -3,6 +3,7 @@ + * + * Copyright 2007 Michael Buesch <m@bues.ch> + * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> + * + * Derived from the OCHI-SSB driver + * Derived from the OHCI-PCI driver +@@ -14,11 +15,14 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + ++#include <linux/clk.h> ++#include <linux/dma-mapping.h> + #include <linux/hrtimer.h> + #include <linux/io.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/err.h> ++#include <linux/phy/phy.h> + #include <linux/platform_device.h> + #include <linux/usb/ohci_pdriver.h> + #include <linux/usb.h> +@@ -27,6 +31,13 @@ + #include "ohci.h" + + #define DRIVER_DESC "OHCI generic platform driver" ++#define OHCI_MAX_CLKS 3 ++#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv) ++ ++struct ohci_platform_priv { ++ struct clk *clks[OHCI_MAX_CLKS]; ++ struct phy *phy; ++}; + + static const char hcd_name[] = "ohci-platform"; + +@@ -48,11 +59,67 @@ static int ohci_platform_reset(struct usb_hcd *hcd) + return ohci_setup(hcd); + } + ++static int ohci_platform_power_on(struct platform_device *dev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(dev); ++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd); ++ int clk, ret; ++ ++ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) { ++ ret = clk_prepare_enable(priv->clks[clk]); ++ if (ret) ++ goto err_disable_clks; ++ } ++ ++ if (priv->phy) { ++ ret = phy_init(priv->phy); ++ if (ret) ++ goto err_disable_clks; ++ ++ ret = phy_power_on(priv->phy); ++ if (ret) ++ goto err_exit_phy; ++ } ++ ++ return 0; ++ ++err_exit_phy: ++ phy_exit(priv->phy); ++err_disable_clks: ++ while (--clk >= 0) ++ clk_disable_unprepare(priv->clks[clk]); ++ ++ return ret; ++} ++ ++static void ohci_platform_power_off(struct platform_device *dev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(dev); ++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd); ++ int clk; ++ ++ if (priv->phy) { ++ phy_power_off(priv->phy); ++ phy_exit(priv->phy); ++ } ++ ++ for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--) ++ if (priv->clks[clk]) ++ clk_disable_unprepare(priv->clks[clk]); ++} ++ + static struct hc_driver __read_mostly ohci_platform_hc_driver; + + static const struct ohci_driver_overrides platform_overrides __initconst = { +- .product_desc = "Generic Platform OHCI controller", +- .reset = ohci_platform_reset, ++ .product_desc = "Generic Platform OHCI controller", ++ .reset = ohci_platform_reset, ++ .extra_priv_size = sizeof(struct ohci_platform_priv), ++}; ++ ++static struct usb_ohci_pdata ohci_platform_defaults = { ++ .power_on = ohci_platform_power_on, ++ .power_suspend = ohci_platform_power_off, ++ .power_off = ohci_platform_power_off, + }; + + static int ohci_platform_probe(struct platform_device *dev) +@@ -60,17 +127,23 @@ static int ohci_platform_probe(struct platform_device *dev) + struct usb_hcd *hcd; + struct resource *res_mem; + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); +- int irq; +- int err = -ENOMEM; +- +- if (!pdata) { +- WARN_ON(1); +- return -ENODEV; +- } ++ struct ohci_platform_priv *priv; ++ int err, irq, clk = 0; + + if (usb_disabled()) + return -ENODEV; + ++ /* ++ * Use reasonable defaults so platforms don't have to provide these ++ * with DT probing on ARM. ++ */ ++ if (!pdata) ++ pdata = &ohci_platform_defaults; ++ ++ err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)); ++ if (err) ++ return err; ++ + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "no irq provided"); +@@ -83,17 +156,40 @@ static int ohci_platform_probe(struct platform_device *dev) + return -ENXIO; + } + ++ hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, ++ dev_name(&dev->dev)); ++ if (!hcd) ++ return -ENOMEM; ++ ++ platform_set_drvdata(dev, hcd); ++ dev->dev.platform_data = pdata; ++ priv = hcd_to_ohci_priv(hcd); ++ ++ if (pdata == &ohci_platform_defaults && dev->dev.of_node) { ++ priv->phy = devm_phy_get(&dev->dev, "usb"); ++ if (IS_ERR(priv->phy)) { ++ err = PTR_ERR(priv->phy); ++ if (err == -EPROBE_DEFER) ++ goto err_put_hcd; ++ priv->phy = NULL; ++ } ++ ++ for (clk = 0; clk < OHCI_MAX_CLKS; clk++) { ++ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); ++ if (IS_ERR(priv->clks[clk])) { ++ err = PTR_ERR(priv->clks[clk]); ++ if (err == -EPROBE_DEFER) ++ goto err_put_clks; ++ priv->clks[clk] = NULL; ++ break; ++ } ++ } ++ } ++ + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) +- return err; +- } +- +- hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, +- dev_name(&dev->dev)); +- if (!hcd) { +- err = -ENOMEM; +- goto err_power; ++ goto err_put_clks; + } + + hcd->rsrc_start = res_mem->start; +@@ -102,11 +198,11 @@ static int ohci_platform_probe(struct platform_device *dev) + hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); +- goto err_put_hcd; ++ goto err_power; + } + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) +- goto err_put_hcd; ++ goto err_power; + + device_wakeup_enable(hcd->self.controller); + +@@ -114,11 +210,17 @@ static int ohci_platform_probe(struct platform_device *dev) + + return err; + +-err_put_hcd: +- usb_put_hcd(hcd); + err_power: + if (pdata->power_off) + pdata->power_off(dev); ++err_put_clks: ++ while (--clk >= 0) ++ clk_put(priv->clks[clk]); ++err_put_hcd: ++ if (pdata == &ohci_platform_defaults) ++ dev->dev.platform_data = NULL; ++ ++ usb_put_hcd(hcd); + + return err; + } +@@ -127,13 +229,22 @@ static int ohci_platform_remove(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); ++ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd); ++ int clk; + + usb_remove_hcd(hcd); +- usb_put_hcd(hcd); + + if (pdata->power_off) + pdata->power_off(dev); + ++ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) ++ clk_put(priv->clks[clk]); ++ ++ usb_put_hcd(hcd); ++ ++ if (pdata == &ohci_platform_defaults) ++ dev->dev.platform_data = NULL; ++ + return 0; + } + +@@ -180,6 +291,12 @@ static int ohci_platform_resume(struct device *dev) + #define ohci_platform_resume NULL + #endif /* CONFIG_PM */ + ++static const struct of_device_id ohci_platform_ids[] = { ++ { .compatible = "usb-ohci", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ohci_platform_ids); ++ + static const struct platform_device_id ohci_platform_table[] = { + { "ohci-platform", 0 }, + { } +@@ -200,6 +317,7 @@ static int ohci_platform_resume(struct device *dev) + .owner = THIS_MODULE, + .name = "ohci-platform", + .pm = &ohci_platform_pm_ops, ++ .of_match_table = ohci_platform_ids, + } + }; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch b/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch new file mode 100644 index 0000000..908d841 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-2-usb-ehci-platform-support-clk-phy-via-dt.patch @@ -0,0 +1,392 @@ +From 543824fa2a8a592a6eec0e0053063284980dc378 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 5 Jan 2014 00:04:02 +0100 +Subject: [PATCH] ehci-platform: Add support for clks and phy passed through + devicetree + +Currently ehci-platform is only used in combination with devicetree when used +with some Via socs. By extending it to (optionally) get clks and a phy from +devicetree, and enabling / disabling those on power_on / off, it can be used +more generically. Specifically after this commit it can be used for the +ehci controller on Allwinner sunxi SoCs. + +Since ehci-platform is intended to handle any generic enough non pci ehci +device, add a "usb-ehci" compatibility string. + +There already is a usb-ehci device-tree bindings document, update this +with clks and phy bindings info. + +Although actually quite generic so far the via,vt8500 compatibilty string +had its own bindings document. Somehow we even ended up with 2 of them. Since +these provide no extra information over the generic usb-ehci documentation, +this patch removes them. + +The ehci-ppc-of.c driver also claims the usb-ehci compatibility string, +even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is +not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid +2 drivers claiming the same compatibility string getting build on ppc. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +--- + Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++- + .../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 --- + .../devicetree/bindings/usb/vt8500-ehci.txt | 12 -- + drivers/usb/host/Kconfig | 1 + + drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++---- + 5 files changed, 142 insertions(+), 58 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt + delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt + +diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt +index fa18612..2c1aeeb 100644 +--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt +@@ -7,13 +7,14 @@ Required properties: + (debug-port or other) can be also specified here, but only after + definition of standard EHCI registers. + - interrupts : one EHCI interrupt should be described here. +-If device registers are implemented in big endian mode, the device +-node should have "big-endian-regs" property. +-If controller implementation operates with big endian descriptors, +-"big-endian-desc" property should be specified. +-If both big endian registers and descriptors are used by the controller +-implementation, "big-endian" property can be specified instead of having +-both "big-endian-regs" and "big-endian-desc". ++ ++Optional properties: ++ - big-endian-regs : boolean, set this for hcds with big-endian registers ++ - big-endian-desc : boolean, set this for hcds with big-endian descriptors ++ - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc ++ - clocks : a list of phandle + clock specifier pairs ++ - phys : phandle + phy specifier pair ++ - phy-names : "usb" + + Example (Sequoia 440EPx): + ehci@e0000300 { +@@ -23,3 +24,13 @@ Example (Sequoia 440EPx): + reg = <0 e0000300 90 0 e0000390 70>; + big-endian; + }; ++ ++Example (Allwinner sun4i A10 SoC): ++ ehci0: usb@01c14000 { ++ compatible = "allwinner,sun4i-a10-ehci", "usb-ehci"; ++ reg = <0x01c14000 0x100>; ++ interrupts = <39>; ++ clocks = <&ahb_gates 1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ }; +diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt +deleted file mode 100644 +index 17b3ad1..0000000 +--- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt ++++ /dev/null +@@ -1,15 +0,0 @@ +-VIA/Wondermedia VT8500 EHCI Controller +------------------------------------------------------ +- +-Required properties: +-- compatible : "via,vt8500-ehci" +-- reg : Should contain 1 register ranges(address and length) +-- interrupts : ehci controller interrupt +- +-Example: +- +- ehci@d8007900 { +- compatible = "via,vt8500-ehci"; +- reg = <0xd8007900 0x200>; +- interrupts = <43>; +- }; +diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt +deleted file mode 100644 +index 5fb8fd6..0000000 +--- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt ++++ /dev/null +@@ -1,12 +0,0 @@ +-VIA VT8500 and Wondermedia WM8xxx SoC USB controllers. +- +-Required properties: +- - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci". +- - reg: Address range of the ehci registers. size should be 0x200 +- - interrupts: Should contain the ehci interrupt. +- +-usb: ehci@D8007100 { +- compatible = "wm,prizm-ehci", "usb-ehci"; +- reg = <0xD8007100 0x200>; +- interrupts = <1>; +-}; +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index a9707da..e28cbe0 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -255,6 +255,7 @@ config USB_EHCI_ATH79 + + config USB_EHCI_HCD_PLATFORM + tristate "Generic EHCI driver for a platform device" ++ depends on !PPC_OF + default n + ---help--- + Adds an EHCI host driver for a generic platform device, which +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 01536cf..5ebd0b7 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -3,6 +3,7 @@ + * + * Copyright 2007 Steven Brown <sbrown@cortland.com> + * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright 2014 Hans de Goede <hdegoede@redhat.com> + * + * Derived from the ohci-ssb driver + * Copyright 2007 Michael Buesch <m@bues.ch> +@@ -18,6 +19,7 @@ + * + * Licensed under the GNU/GPL. See COPYING for details. + */ ++#include <linux/clk.h> + #include <linux/dma-mapping.h> + #include <linux/err.h> + #include <linux/kernel.h> +@@ -25,6 +27,7 @@ + #include <linux/io.h> + #include <linux/module.h> + #include <linux/of.h> ++#include <linux/phy/phy.h> + #include <linux/platform_device.h> + #include <linux/usb.h> + #include <linux/usb/hcd.h> +@@ -33,6 +36,13 @@ + #include "ehci.h" + + #define DRIVER_DESC "EHCI generic platform driver" ++#define EHCI_MAX_CLKS 3 ++#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) ++ ++struct ehci_platform_priv { ++ struct clk *clks[EHCI_MAX_CLKS]; ++ struct phy *phy; ++}; + + static const char hcd_name[] = "ehci-platform"; + +@@ -64,38 +74,90 @@ static int ehci_platform_reset(struct usb_hcd *hcd) + return 0; + } + ++static int ehci_platform_power_on(struct platform_device *dev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(dev); ++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); ++ int clk, ret; ++ ++ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) { ++ ret = clk_prepare_enable(priv->clks[clk]); ++ if (ret) ++ goto err_disable_clks; ++ } ++ ++ if (priv->phy) { ++ ret = phy_init(priv->phy); ++ if (ret) ++ goto err_disable_clks; ++ ++ ret = phy_power_on(priv->phy); ++ if (ret) ++ goto err_exit_phy; ++ } ++ ++ return 0; ++ ++err_exit_phy: ++ phy_exit(priv->phy); ++err_disable_clks: ++ while (--clk >= 0) ++ clk_disable_unprepare(priv->clks[clk]); ++ ++ return ret; ++} ++ ++static void ehci_platform_power_off(struct platform_device *dev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(dev); ++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); ++ int clk; ++ ++ if (priv->phy) { ++ phy_power_off(priv->phy); ++ phy_exit(priv->phy); ++ } ++ ++ for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) ++ if (priv->clks[clk]) ++ clk_disable_unprepare(priv->clks[clk]); ++} ++ + static struct hc_driver __read_mostly ehci_platform_hc_driver; + + static const struct ehci_driver_overrides platform_overrides __initconst = { +- .reset = ehci_platform_reset, ++ .reset = ehci_platform_reset, ++ .extra_priv_size = sizeof(struct ehci_platform_priv), + }; + +-static struct usb_ehci_pdata ehci_platform_defaults; ++static struct usb_ehci_pdata ehci_platform_defaults = { ++ .power_on = ehci_platform_power_on, ++ .power_suspend = ehci_platform_power_off, ++ .power_off = ehci_platform_power_off, ++}; + + static int ehci_platform_probe(struct platform_device *dev) + { + struct usb_hcd *hcd; + struct resource *res_mem; +- struct usb_ehci_pdata *pdata; +- int irq; +- int err; ++ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); ++ struct ehci_platform_priv *priv; ++ int err, irq, clk = 0; + + if (usb_disabled()) + return -ENODEV; + + /* +- * use reasonable defaults so platforms don't have to provide these. +- * with DT probing on ARM, none of these are set. ++ * Use reasonable defaults so platforms don't have to provide these ++ * with DT probing on ARM. + */ +- if (!dev_get_platdata(&dev->dev)) +- dev->dev.platform_data = &ehci_platform_defaults; ++ if (!pdata) ++ pdata = &ehci_platform_defaults; + + err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)); + if (err) + return err; + +- pdata = dev_get_platdata(&dev->dev); +- + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "no irq provided"); +@@ -107,17 +169,40 @@ static int ehci_platform_probe(struct platform_device *dev) + return -ENXIO; + } + ++ hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, ++ dev_name(&dev->dev)); ++ if (!hcd) ++ return -ENOMEM; ++ ++ platform_set_drvdata(dev, hcd); ++ dev->dev.platform_data = pdata; ++ priv = hcd_to_ehci_priv(hcd); ++ ++ if (pdata == &ehci_platform_defaults && dev->dev.of_node) { ++ priv->phy = devm_phy_get(&dev->dev, "usb"); ++ if (IS_ERR(priv->phy)) { ++ err = PTR_ERR(priv->phy); ++ if (err == -EPROBE_DEFER) ++ goto err_put_hcd; ++ priv->phy = NULL; ++ } ++ ++ for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { ++ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); ++ if (IS_ERR(priv->clks[clk])) { ++ err = PTR_ERR(priv->clks[clk]); ++ if (err == -EPROBE_DEFER) ++ goto err_put_clks; ++ priv->clks[clk] = NULL; ++ break; ++ } ++ } ++ } ++ + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) +- return err; +- } +- +- hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, +- dev_name(&dev->dev)); +- if (!hcd) { +- err = -ENOMEM; +- goto err_power; ++ goto err_put_clks; + } + + hcd->rsrc_start = res_mem->start; +@@ -126,22 +211,28 @@ static int ehci_platform_probe(struct platform_device *dev) + hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); +- goto err_put_hcd; ++ goto err_power; + } + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) +- goto err_put_hcd; ++ goto err_power; + + device_wakeup_enable(hcd->self.controller); + platform_set_drvdata(dev, hcd); + + return err; + +-err_put_hcd: +- usb_put_hcd(hcd); + err_power: + if (pdata->power_off) + pdata->power_off(dev); ++err_put_clks: ++ while (--clk >= 0) ++ clk_put(priv->clks[clk]); ++err_put_hcd: ++ if (pdata == &ehci_platform_defaults) ++ dev->dev.platform_data = NULL; ++ ++ usb_put_hcd(hcd); + + return err; + } +@@ -150,13 +241,19 @@ static int ehci_platform_remove(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); ++ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); ++ int clk; + + usb_remove_hcd(hcd); +- usb_put_hcd(hcd); + + if (pdata->power_off) + pdata->power_off(dev); + ++ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) ++ clk_put(priv->clks[clk]); ++ ++ usb_put_hcd(hcd); ++ + if (pdata == &ehci_platform_defaults) + dev->dev.platform_data = NULL; + +@@ -207,8 +304,10 @@ static int ehci_platform_resume(struct device *dev) + static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, + { .compatible = "wm,prizm-ehci", }, ++ { .compatible = "usb-ehci", }, + {} + }; ++MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); + + static const struct platform_device_id ehci_platform_table[] = { + { "ehci-platform", 0 }, +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch b/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch new file mode 100644 index 0000000..178bf45 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-3-usb-ohci-platform-support-bigendian.patch @@ -0,0 +1,80 @@ +From 10d7c018269928db8487057c4c143dbd014d2262 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 21 Jan 2014 16:05:47 +0100 +Subject: [PATCH] ohci-platform: Add support for controllers with big-endian + regs / descriptors + +Note this commit uses the same devicetree booleans for this as the ones +already existing in the usb-ehci bindings, see: +Documentation/devicetree/bindings/usb/usb-ehci.txt + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/usb/usb-ohci.txt | 3 +++ + drivers/usb/host/ohci-platform.c | 27 ++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt +index 6ba38d9..6933b0c 100644 +--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt +@@ -6,6 +6,9 @@ Required properties: + - interrupts : ohci controller interrupt + + Optional properties: ++- big-endian-regs : boolean, set this for hcds with big-endian registers ++- big-endian-desc : boolean, set this for hcds with big-endian descriptors ++- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc + - clocks : a list of phandle + clock specifier pairs + - phys : phandle + phy specifier pair + - phy-names : "usb" +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index 49304dd..e2c28fd 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -128,6 +128,7 @@ static int ohci_platform_probe(struct platform_device *dev) + struct resource *res_mem; + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ohci_platform_priv *priv; ++ struct ohci_hcd *ohci; + int err, irq, clk = 0; + + if (usb_disabled()) +@@ -164,8 +165,34 @@ static int ohci_platform_probe(struct platform_device *dev) + platform_set_drvdata(dev, hcd); + dev->dev.platform_data = pdata; + priv = hcd_to_ohci_priv(hcd); ++ ohci = hcd_to_ohci(hcd); + + if (pdata == &ohci_platform_defaults && dev->dev.of_node) { ++ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) ++ ohci->flags |= OHCI_QUIRK_BE_MMIO; ++ ++ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc")) ++ ohci->flags |= OHCI_QUIRK_BE_DESC; ++ ++ if (of_property_read_bool(dev->dev.of_node, "big-endian")) ++ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; ++ ++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO ++ if (ohci->flags & OHCI_QUIRK_BE_MMIO) { ++ dev_err(&dev->dev, ++ "Error big-endian-regs not compiled in\n"); ++ err = -EINVAL; ++ goto err_put_hcd; ++ } ++#endif ++#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC ++ if (ohci->flags & OHCI_QUIRK_BE_DESC) { ++ dev_err(&dev->dev, ++ "Error big-endian-desc not compiled in\n"); ++ err = -EINVAL; ++ goto err_put_hcd; ++ } ++#endif + priv->phy = devm_phy_get(&dev->dev, "usb"); + if (IS_ERR(priv->phy)) { + err = PTR_ERR(priv->phy); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch b/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch new file mode 100644 index 0000000..5f70434 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-4-usb-ehci-platform-support-bigendian.patch @@ -0,0 +1,77 @@ +From 57b5e74a0d7ba5dbf77ee05a2693635faba5fe30 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 21 Jan 2014 16:20:53 +0100 +Subject: [PATCH] ehci-platform: Add support for controllers with big-endian + regs / descriptors + +This uses the already documented devicetree booleans for this, see: +Documentation/devicetree/bindings/usb/usb-ehci.txt + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/usb/host/ehci-platform.c | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 5ebd0b7..8fde649 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -55,8 +55,10 @@ static int ehci_platform_reset(struct usb_hcd *hcd) + + hcd->has_tt = pdata->has_tt; + ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; +- ehci->big_endian_desc = pdata->big_endian_desc; +- ehci->big_endian_mmio = pdata->big_endian_mmio; ++ if (pdata->big_endian_desc) ++ ehci->big_endian_desc = 1; ++ if (pdata->big_endian_mmio) ++ ehci->big_endian_mmio = 1; + ehci->ignore_oc = pdata->ignore_oc; + + if (pdata->pre_setup) { +@@ -142,6 +144,7 @@ static int ehci_platform_probe(struct platform_device *dev) + struct resource *res_mem; + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_platform_priv *priv; ++ struct ehci_hcd *ehci; + int err, irq, clk = 0; + + if (usb_disabled()) +@@ -177,8 +180,34 @@ static int ehci_platform_probe(struct platform_device *dev) + platform_set_drvdata(dev, hcd); + dev->dev.platform_data = pdata; + priv = hcd_to_ehci_priv(hcd); ++ ehci = hcd_to_ehci(hcd); + + if (pdata == &ehci_platform_defaults && dev->dev.of_node) { ++ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) ++ ehci->big_endian_mmio = 1; ++ ++ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc")) ++ ehci->big_endian_desc = 1; ++ ++ if (of_property_read_bool(dev->dev.of_node, "big-endian")) ++ ehci->big_endian_mmio = ehci->big_endian_desc = 1; ++ ++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO ++ if (ehci->big_endian_mmio) { ++ dev_err(&dev->dev, ++ "Error big-endian-regs not compiled in\n"); ++ err = -EINVAL; ++ goto err_put_hcd; ++ } ++#endif ++#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC ++ if (ehci->big_endian_desc) { ++ dev_err(&dev->dev, ++ "Error big-endian-desc not compiled in\n"); ++ err = -EINVAL; ++ goto err_put_hcd; ++ } ++#endif + priv->phy = devm_phy_get(&dev->dev, "usb"); + if (IS_ERR(priv->phy)) { + err = PTR_ERR(priv->phy); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch new file mode 100644 index 0000000..4255a34 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-5-usb-ohci-change-compat-string.patch @@ -0,0 +1,69 @@ +From abddd82743cc2c4acdfe66a6d5e63f2085d2269b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 11 Feb 2014 11:27:29 +0100 +Subject: [PATCH] ohci-platform: Change compatible string from usb-ohci to + generic-ohci + +The initial versions of the devicetree enablement patches for ohci-platform +used "ohci-platform" as compatible string. However this was disliked by various +reviewers because the platform bus is a Linux invention and devicetree is +supposed to be OS agnostic. After much discussion I gave up and went with +the generic usb-ohci as requested. + +In retro-spect I should have chosen something different, the dts files for many +existing boards already claim to be compatible with "usb-ohci", ie they have: + + compatible = "ti,ohci-omap3", "usb-ohci"; + +In theory this should not be a problem since the "ti,ohci-omap3" entry takes +presedence, but in practice using a conflicting compatible string is an issue, +because it makes which driver gets used depend on driver registration order. + +This patch changes the compatible string claimed by ohci-platform to +"generic-ohci", avoiding the driver registration / module loading ordering +problems. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/usb/usb-ohci.txt | 4 ++-- + drivers/usb/host/ohci-platform.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt +index 6933b0c..45f67d9 100644 +--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt +@@ -1,7 +1,7 @@ + USB OHCI controllers + + Required properties: +-- compatible : "usb-ohci" ++- compatible : "generic-ohci" + - reg : ohci controller register range (address and length) + - interrupts : ohci controller interrupt + +@@ -16,7 +16,7 @@ Optional properties: + Example: + + ohci0: usb@01c14400 { +- compatible = "allwinner,sun4i-a10-ohci", "usb-ohci"; ++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; + reg = <0x01c14400 0x100>; + interrupts = <64>; + clocks = <&usb_clk 6>, <&ahb_gates 2>; +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index e2c28fd..b6ca0b2 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -319,7 +319,7 @@ static int ohci_platform_resume(struct device *dev) + #endif /* CONFIG_PM */ + + static const struct of_device_id ohci_platform_ids[] = { +- { .compatible = "usb-ohci", }, ++ { .compatible = "generic-ohci", }, + { } + }; + MODULE_DEVICE_TABLE(of, ohci_platform_ids); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch new file mode 100644 index 0000000..5222422 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-6-usb-ehci-change-compat-string.patch @@ -0,0 +1,83 @@ +From 80c544c77beeffee4e9484bf193ab391297688cd Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 11 Feb 2014 11:46:13 +0100 +Subject: [PATCH] ehci-platform: Change compatible string from usb-ehci to + generic-ehci + +The initial versions of the devicetree enablement patches for ehci-platform +used "ehci-platform" as compatible string. However this was disliked by various +reviewers because the platform bus is a Linux invention and devicetree is +supposed to be OS agnostic. After much discussion I gave up, added a: +"depends on !PPC_OF" to Kconfig to avoid a known conflict with PPC-OF platforms +and went with the generic usb-ehci as requested. + +In retro-spect I should have chosen something different, the dts files for many +existing boards already claim to be compatible with "usb-ehci", ie they have: + + compatible = "ti,ehci-omap", "usb-ehci"; + +In theory this should not be a problem since the "ti,ehci-omap" entry takes +presedence, but in practice using a conflicting compatible string is an issue, +because it makes which driver gets used depend on driver registration order. + +This patch changes the compatible string claimed by ehci-platform to +"generic-ehci", avoiding the driver registration / module loading ordering +problems, and removes the "depends on !PPC_OF" workaround. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/usb/usb-ehci.txt | 4 ++-- + drivers/usb/host/Kconfig | 1 - + drivers/usb/host/ehci-platform.c | 2 +- + 3 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt +index 2c1aeeb..ff151ec 100644 +--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt +@@ -1,7 +1,7 @@ + USB EHCI controllers + + Required properties: +- - compatible : should be "usb-ehci". ++ - compatible : should be "generic-ehci". + - reg : should contain at least address and length of the standard EHCI + register set for the device. Optional platform-dependent registers + (debug-port or other) can be also specified here, but only after +@@ -27,7 +27,7 @@ Example (Sequoia 440EPx): + + Example (Allwinner sun4i A10 SoC): + ehci0: usb@01c14000 { +- compatible = "allwinner,sun4i-a10-ehci", "usb-ehci"; ++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci"; + reg = <0x01c14000 0x100>; + interrupts = <39>; + clocks = <&ahb_gates 1>; +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index e28cbe0..a9707da 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -255,7 +255,6 @@ config USB_EHCI_ATH79 + + config USB_EHCI_HCD_PLATFORM + tristate "Generic EHCI driver for a platform device" +- depends on !PPC_OF + default n + ---help--- + Adds an EHCI host driver for a generic platform device, which +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 8fde649..1178730 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -333,7 +333,7 @@ static int ehci_platform_resume(struct device *dev) + static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, + { .compatible = "wm,prizm-ehci", }, +- { .compatible = "usb-ehci", }, ++ { .compatible = "generic-ehci", }, + {} + }; + MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch new file mode 100644 index 0000000..0b7695a --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-7-usb-uhci-change-compat-string.patch @@ -0,0 +1,83 @@ +From 3aa1e8b65b7db768fade643e26f8995860596795 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 11 Feb 2014 17:41:48 +0100 +Subject: [PATCH] uhci-platform: Change compatible string from platform-uhci to + generic-uhci + +This brings the uhci-platform bindings in sync with what we've done for +the ohci- and ehci-platform drivers. As discussed there using platform as a +prefix is a bit weird as the platform bus is a Linux specific thing and +the bindings are supposed to be OS agnostic. + +Note that the old platform-uhci compatible string is kept around for, well, +compatibility reasons. + +While at it rename the bindings txt file to match the name of all the +other ?hci-platform bindings docs. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/usb/platform-uhci.txt | 15 --------------- + Documentation/devicetree/bindings/usb/usb-uhci.txt | 15 +++++++++++++++ + drivers/usb/host/uhci-platform.c | 1 + + 3 files changed, 16 insertions(+), 15 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/usb/platform-uhci.txt + create mode 100644 Documentation/devicetree/bindings/usb/usb-uhci.txt + +diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt +deleted file mode 100644 +index a4fb071..0000000 +--- a/Documentation/devicetree/bindings/usb/platform-uhci.txt ++++ /dev/null +@@ -1,15 +0,0 @@ +-Generic Platform UHCI Controller +------------------------------------------------------ +- +-Required properties: +-- compatible : "platform-uhci" +-- reg : Should contain 1 register ranges(address and length) +-- interrupts : UHCI controller interrupt +- +-Example: +- +- uhci@d8007b00 { +- compatible = "platform-uhci"; +- reg = <0xd8007b00 0x200>; +- interrupts = <43>; +- }; +diff --git a/Documentation/devicetree/bindings/usb/usb-uhci.txt b/Documentation/devicetree/bindings/usb/usb-uhci.txt +new file mode 100644 +index 0000000..2981334 +--- /dev/null ++++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt +@@ -0,0 +1,15 @@ ++Generic Platform UHCI Controller ++----------------------------------------------------- ++ ++Required properties: ++- compatible : "generic-uhci" (deprecated: "platform-uhci") ++- reg : Should contain 1 register ranges(address and length) ++- interrupts : UHCI controller interrupt ++ ++Example: ++ ++ uhci@d8007b00 { ++ compatible = "generic-uhci"; ++ reg = <0xd8007b00 0x200>; ++ interrupts = <43>; ++ }; +diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c +index 44e6c9d..01833ab 100644 +--- a/drivers/usb/host/uhci-platform.c ++++ b/drivers/usb/host/uhci-platform.c +@@ -148,6 +148,7 @@ static void uhci_hcd_platform_shutdown(struct platform_device *op) + } + + static const struct of_device_id platform_uhci_ids[] = { ++ { .compatible = "generic-uhci", }, + { .compatible = "platform-uhci", }, + {} + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch b/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch new file mode 100644 index 0000000..03f42f8 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-8-usb-xhci-change-compat-string.patch @@ -0,0 +1,56 @@ +From 1f5109503787538c4a5deb3be7da8336951b105b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Tue, 11 Feb 2014 17:50:51 +0100 +Subject: [PATCH] xhci-platform: Change compatible string from xhci-platform to + generic-xhci + +This brings the xhci-platform bindings in sync with what we've done for +the ohci- and ehci-platform drivers. As discussed there using platform as a +postfix is a bit weird as the platform bus is a Linux specific thing and +the bindings are supposed to be OS agnostic. + +Note that the old xhci-platform compatible string is kept around for, well, +compatibility reasons. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/usb/usb-xhci.txt | 4 ++-- + drivers/usb/host/xhci-plat.c | 1 + + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt +index 5752df0..90f8f60 100644 +--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt +@@ -1,14 +1,14 @@ + USB xHCI controllers + + Required properties: +- - compatible: should be "xhci-platform". ++ - compatible: should be "generic-xhci" (deprecated: "xhci-platform"). + - reg: should contain address and length of the standard XHCI + register set for the device. + - interrupts: one XHCI interrupt should be described here. + + Example: + usb@f0931000 { +- compatible = "xhci-platform"; ++ compatible = "generic-xhci"; + reg = <0xf0931000 0x8c8>; + interrupts = <0x0 0x4e 0x0>; + }; +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 8abda5c..8affef9 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -226,6 +226,7 @@ static int xhci_plat_resume(struct device *dev) + + #ifdef CONFIG_OF + static const struct of_device_id usb_xhci_of_match[] = { ++ { .compatible = "generic-xhci" }, + { .compatible = "xhci-platform" }, + { }, + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch b/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch new file mode 100644 index 0000000..a31f16b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-9-clk-sunxi-add-usb-clockreg-reset.patch @@ -0,0 +1,127 @@ +From edb7ebba49b6946e80dfac0d13ac15028952aa29 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Thu, 9 Jan 2014 19:33:04 +0100 +Subject: [PATCH] clk: sunxi: Add support for USB clock-register reset bits + +The usb-clk register is special in that it not only contains clk gate bits, +but also has a few reset bits. This commit adds support for this by allowing +gates type sunxi clks to also register a reset controller. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + drivers/clk/sunxi/clk-sunxi.c | 71 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 46a38b4..2dbaee7 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -18,6 +18,7 @@ + #include <linux/clkdev.h> + #include <linux/of.h> + #include <linux/of_address.h> ++#include <linux/reset-controller.h> + + #include "clk-factors.h" + +@@ -852,6 +853,59 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, + + + /** ++ * sunxi_gates_reset... - reset bits in leaf gate clk registers handling ++ */ ++ ++struct gates_reset_data { ++ void __iomem *reg; ++ spinlock_t *lock; ++ struct reset_controller_dev rcdev; ++}; ++ ++static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct gates_reset_data *data = container_of(rcdev, ++ struct gates_reset_data, ++ rcdev); ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(data->lock, flags); ++ ++ reg = readl(data->reg); ++ writel(reg & ~BIT(id), data->reg); ++ ++ spin_unlock_irqrestore(data->lock, flags); ++ ++ return 0; ++} ++ ++static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct gates_reset_data *data = container_of(rcdev, ++ struct gates_reset_data, ++ rcdev); ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(data->lock, flags); ++ ++ reg = readl(data->reg); ++ writel(reg | BIT(id), data->reg); ++ ++ spin_unlock_irqrestore(data->lock, flags); ++ ++ return 0; ++} ++ ++static struct reset_control_ops sunxi_gates_reset_ops = { ++ .assert = sunxi_gates_reset_assert, ++ .deassert = sunxi_gates_reset_deassert, ++}; ++ ++/** + * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks + */ + +@@ -859,6 +913,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, + + struct gates_data { + DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); ++ u32 reset_mask; + }; + + static const struct gates_data sun4i_axi_gates_data __initconst = { +@@ -929,6 +984,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, + struct gates_data *data) + { + struct clk_onecell_data *clk_data; ++ struct gates_reset_data *reset_data; + const char *clk_parent; + const char *clk_name; + void *reg; +@@ -972,6 +1028,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node, + clk_data->clk_num = i; + + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ /* Register a reset controler for gates with reset bits */ ++ if (data->reset_mask == 0) ++ return; ++ ++ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); ++ if (!reset_data) ++ return; ++ ++ reset_data->reg = reg; ++ reset_data->lock = &clk_lock; ++ reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1; ++ reset_data->rcdev.ops = &sunxi_gates_reset_ops; ++ reset_data->rcdev.of_node = node; ++ reset_controller_register(&reset_data->rcdev); + } + + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch b/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch new file mode 100644 index 0000000..4302c0e5 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/180-a-clk-sunxi-add-usb-clockreg-defs.patch @@ -0,0 +1,50 @@ +From a6459be451bc7eb541aca2be3b36b06955d06622 Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Thu, 19 Sep 2013 21:59:32 +0200 +Subject: [PATCH] clk: sunxi: Add USB clock register defintions + +Add register definitions for the usb-clk register found on sun4i, sun5i and +sun7i SoCs. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + Documentation/devicetree/bindings/clock/sunxi.txt | 5 +++++ + drivers/clk/sunxi/clk-sunxi.c | 12 ++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index 0da774c..c77a5b8 100644 +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 2dbaee7..9daa9b0 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -924,6 +924,16 @@ struct gates_data { + .mask = {0x7F77FFF, 0x14FB3F}, + }; + ++static const struct gates_data sun4i_a10_usb_gates_data __initconst = { ++ .mask = {0x1C0}, ++ .reset_mask = 0x07, ++}; ++ ++static const struct gates_data sun5i_a13_usb_gates_data __initconst = { ++ .mask = {0x140}, ++ .reset_mask = 0x03, ++}; ++ + static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = { + .mask = {0x147667e7, 0x185915}, + }; +@@ -1271,6 +1281,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, + {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, + {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, ++ {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, ++ {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, + {} + }; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch b/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch new file mode 100644 index 0000000..c3693a7 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/181-1-dt-sun4i-add-vbus-reg-dtsi.patch @@ -0,0 +1,79 @@ +From c3593cc95c240663bd9c191c1029237e467575af Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Fri, 7 Feb 2014 18:08:03 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add sun4i-a10-usb-vbus-reg dts include file + +Almost all sun4i and sun7i boards have a gpio controlled vbus for usb1 and +usb2, using gpio pin PH6 and PH3 as in the reference design. This commit adds +an include file for this, avoiding the need to copy and paste the exact same +dts code to almost all sun4i and sun7i dts files. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi | 54 +++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + create mode 100644 arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi + +diff --git a/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi +new file mode 100644 +index 0000000..803be0c +--- /dev/null ++++ b/arch/arm/boot/dts/sun4i-a10-usb-vbus-reg.dtsi +@@ -0,0 +1,54 @@ ++/* ++ * sun4i boards usb vbus supply common code ++ * ++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/ { ++ soc@01c00000 { ++ pio: pinctrl@01c20800 { ++ usb1_vbus_pin_a: usb1_vbus_pin@0 { ++ allwinner,pins = "PH6"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ ++ usb2_vbus_pin_a: usb2_vbus_pin@0 { ++ allwinner,pins = "PH3"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ }; ++ }; ++ ++ reg_usb1_vbus: usb1-vbus { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_vbus_pin_a>; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&pio 7 6 0>; ++ }; ++ ++ reg_usb2_vbus: usb2-vbus { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb2_vbus_pin_a>; ++ regulator-name = "usb2-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&pio 7 3 0>; ++ }; ++}; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch b/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch new file mode 100644 index 0000000..e6d4f27 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/181-2-dt-sun5i-add-vbus-reg-dtsi.patch @@ -0,0 +1,95 @@ +From d11b47592e6af40fff595900c2af30774ee0b88e Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sun, 9 Feb 2014 14:17:28 +0100 +Subject: [PATCH] ARM: sun5i: dt: Add sun5i-a1*-usb-vbus-reg dts include files + +Almost all sun5i-a10s boards have a gpio controlled vbus for usb1 using gpio +pin PB10 as in the reference design. This commit adds an include file for this, +avoiding the need to copy and paste the dts code. + +For sun5i-a13 based board the reference design uses a gpio on the pmic, which +we don't support yet. Still for consistency with all the other dts files also +add a sun5i-a13-usb-vbus-reg.dtsi files, without a gpio reference for now. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi | 36 ++++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi | 23 ++++++++++++++++ + 2 files changed, 59 insertions(+) + create mode 100644 arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi + create mode 100644 arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi + +diff --git a/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi +new file mode 100644 +index 0000000..bb1a693 +--- /dev/null ++++ b/arch/arm/boot/dts/sun5i-a10s-usb-vbus-reg.dtsi +@@ -0,0 +1,36 @@ ++/* ++ * sun5i a10s boards usb vbus supply common code ++ * ++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/ { ++ soc@01c00000 { ++ pio: pinctrl@01c20800 { ++ usb1_vbus_pin_a: usb1_vbus_pin@0 { ++ allwinner,pins = "PB10"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ }; ++ }; ++ ++ reg_usb1_vbus: usb1-vbus { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_vbus_pin_a>; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&pio 1 10 0>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi b/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi +new file mode 100644 +index 0000000..4d70b9a +--- /dev/null ++++ b/arch/arm/boot/dts/sun5i-a13-usb-vbus-reg.dtsi +@@ -0,0 +1,23 @@ ++/* ++ * sun5i a13 boards usb vbus supply common code ++ * ++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/ { ++ reg_usb1_vbus: usb1-vbus { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ }; ++}; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch b/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch new file mode 100644 index 0000000..4c62640 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/182-usb-add-ehci-driver.patch @@ -0,0 +1,420 @@ +From ac74dd1167924c412498a651edda63df49941f10 Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sat, 4 Jan 2014 23:56:17 +0100 +Subject: [PATCH] ARM: sunxi: Add driver for sunxi usb phy + +The Allwinner A1x / A2x SoCs have 2 or 3 usb phys which are all accessed +through a single set of registers. Besides this there are also some other +phy related bits which need poking, which are per phy, but shared between the +ohci and ehci controllers, so these are also controlled from this new phy +driver. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../devicetree/bindings/phy/sun4i-usb-phy.txt | 26 ++ + drivers/phy/Kconfig | 11 + + drivers/phy/Makefile | 1 + + drivers/phy/phy-sun4i-usb.c | 329 +++++++++++++++++++++ + 4 files changed, 367 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt + create mode 100644 drivers/phy/phy-sun4i-usb.c + +diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +new file mode 100644 +index 0000000..a82361b +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +@@ -0,0 +1,26 @@ ++Allwinner sun4i USB PHY ++----------------------- ++ ++Required properties: ++- compatible : should be one of "allwinner,sun4i-a10-usb-phy", ++ "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy" ++- reg : a list of offset + length pairs ++- reg-names : "phy_ctrl", "pmu1" and for sun4i or sun7i "pmu2" ++- #phy-cells : from the generic phy bindings, must be 1 ++- clocks : phandle + clock specifier for the phy clock ++- clock-names : "usb_phy" ++- resets : a list of phandle + reset specifier pairs ++- reset-names : "usb0_reset", "usb1_reset" and for sun4i or sun7i "usb2_reset" ++ ++Example: ++ usbphy: phy@0x01c13400 { ++ #phy-cells = <1>; ++ compatible = "allwinner,sun4i-a10-usb-phy"; ++ /* phy base regs, phy1 pmu reg, phy2 pmu reg */ ++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; ++ reg-names = "phy_ctrl", "pmu1", "pmu2"; ++ clocks = <&usb_clk 8>; ++ clock-names = "usb_phy"; ++ resets = <&usb_clk 1>, <&usb_clk 2>; ++ reset-names = "usb1_reset", "usb2_reset"; ++ }; +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index 4ef8755..6e336b4 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -64,4 +64,15 @@ config BCM_KONA_USB2_PHY + help + Enable this to support the Broadcom Kona USB 2.0 PHY. + ++config PHY_SUN4I_USB ++ tristate "Allwinner sunxi SoC USB PHY driver" ++ depends on ARCH_SUNXI ++ select GENERIC_PHY ++ help ++ Enable this to support the transceiver that is part of Allwinner ++ sunxi SoCs. ++ ++ This driver controls the entire USB PHY block, both the USB OTG ++ parts, as well as the 2 regular USB 2 host PHYs. ++ + endmenu +diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile +index b57c253..9d4f8bb 100644 +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o + obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o + obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o + obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o ++obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o +diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c +new file mode 100644 +index 0000000..31c4611 +--- /dev/null ++++ b/drivers/phy/phy-sun4i-usb.c +@@ -0,0 +1,329 @@ ++/* ++ * Allwinner sun4i USB phy driver ++ * ++ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com> ++ * ++ * Based on code from ++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com> ++ * ++ * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver ++ * Copyright (C) 2013 Samsung Electronics Co., Ltd. ++ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/mutex.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/phy/phy.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/reset.h> ++ ++#define REG_ISCR 0x00 ++#define REG_PHYCTL 0x04 ++#define REG_PHYBIST 0x08 ++#define REG_PHYTUNE 0x0c ++ ++#define SUNXI_AHB_ICHR8_EN BIT(10) ++#define SUNXI_AHB_INCR4_BURST_EN BIT(9) ++#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) ++#define SUNXI_ULPI_BYPASS_EN BIT(0) ++ ++/* Common Control Bits for Both PHYs */ ++#define PHY_PLL_BW 0x03 ++#define PHY_RES45_CAL_EN 0x0c ++ ++/* Private Control Bits for Each PHY */ ++#define PHY_TX_AMPLITUDE_TUNE 0x20 ++#define PHY_TX_SLEWRATE_TUNE 0x22 ++#define PHY_VBUSVALID_TH_SEL 0x25 ++#define PHY_PULLUP_RES_SEL 0x27 ++#define PHY_OTG_FUNC_EN 0x28 ++#define PHY_VBUS_DET_EN 0x29 ++#define PHY_DISCON_TH_SEL 0x2a ++ ++#define MAX_PHYS 3 ++ ++struct sun4i_usb_phy_data { ++ struct clk *clk; ++ void __iomem *base; ++ struct mutex mutex; ++ int num_phys; ++ u32 disc_thresh; ++ struct sun4i_usb_phy { ++ struct phy *phy; ++ void __iomem *pmu; ++ struct regulator *vbus; ++ struct reset_control *reset; ++ int index; ++ } phys[MAX_PHYS]; ++}; ++ ++#define to_sun4i_usb_phy_data(phy) \ ++ container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index]) ++ ++static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, ++ int len) ++{ ++ struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); ++ u32 temp, usbc_bit = BIT(phy->index * 2); ++ int i; ++ ++ mutex_lock(&phy_data->mutex); ++ ++ for (i = 0; i < len; i++) { ++ temp = readl(phy_data->base + REG_PHYCTL); ++ ++ /* clear the address portion */ ++ temp &= ~(0xff << 8); ++ ++ /* set the address */ ++ temp |= ((addr + i) << 8); ++ writel(temp, phy_data->base + REG_PHYCTL); ++ ++ /* set the data bit and clear usbc bit*/ ++ temp = readb(phy_data->base + REG_PHYCTL); ++ if (data & 0x1) ++ temp |= BIT(7); ++ else ++ temp &= ~BIT(7); ++ temp &= ~usbc_bit; ++ writeb(temp, phy_data->base + REG_PHYCTL); ++ ++ /* pulse usbc_bit */ ++ temp = readb(phy_data->base + REG_PHYCTL); ++ temp |= usbc_bit; ++ writeb(temp, phy_data->base + REG_PHYCTL); ++ ++ temp = readb(phy_data->base + REG_PHYCTL); ++ temp &= ~usbc_bit; ++ writeb(temp, phy_data->base + REG_PHYCTL); ++ ++ data >>= 1; ++ } ++ mutex_unlock(&phy_data->mutex); ++} ++ ++static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable) ++{ ++ u32 bits, reg_value; ++ ++ if (!phy->pmu) ++ return; ++ ++ bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN | ++ SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN; ++ ++ reg_value = readl(phy->pmu); ++ ++ if (enable) ++ reg_value |= bits; ++ else ++ reg_value &= ~bits; ++ ++ writel(reg_value, phy->pmu); ++} ++ ++static int sun4i_usb_phy_init(struct phy *_phy) ++{ ++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); ++ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); ++ int ret; ++ ++ ret = clk_prepare_enable(data->clk); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_deassert(phy->reset); ++ if (ret) { ++ clk_disable_unprepare(data->clk); ++ return ret; ++ } ++ ++ /* Adjust PHY's magnitude and rate */ ++ sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); ++ ++ /* Disconnect threshold adjustment */ ++ sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2); ++ ++ sun4i_usb_phy_passby(phy, 1); ++ ++ return 0; ++} ++ ++static int sun4i_usb_phy_exit(struct phy *_phy) ++{ ++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); ++ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); ++ ++ sun4i_usb_phy_passby(phy, 0); ++ reset_control_assert(phy->reset); ++ clk_disable_unprepare(data->clk); ++ ++ return 0; ++} ++ ++static int sun4i_usb_phy_power_on(struct phy *_phy) ++{ ++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); ++ int ret = 0; ++ ++ if (phy->vbus) ++ ret = regulator_enable(phy->vbus); ++ ++ return ret; ++} ++ ++static int sun4i_usb_phy_power_off(struct phy *_phy) ++{ ++ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ if (phy->vbus) ++ regulator_disable(phy->vbus); ++ ++ return 0; ++} ++ ++static struct phy_ops sun4i_usb_phy_ops = { ++ .init = sun4i_usb_phy_init, ++ .exit = sun4i_usb_phy_exit, ++ .power_on = sun4i_usb_phy_power_on, ++ .power_off = sun4i_usb_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *sun4i_usb_phy_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); ++ ++ if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys)) ++ return ERR_PTR(-ENODEV); ++ ++ return data->phys[args->args[0]].phy; ++} ++ ++static int sun4i_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct sun4i_usb_phy_data *data; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ void __iomem *pmu = NULL; ++ struct phy_provider *phy_provider; ++ struct reset_control *reset; ++ struct regulator *vbus; ++ struct resource *res; ++ struct phy *phy; ++ char name[16]; ++ int i; ++ ++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ mutex_init(&data->mutex); ++ ++ if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy")) ++ data->num_phys = 2; ++ else ++ data->num_phys = 3; ++ ++ if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy")) ++ data->disc_thresh = 3; ++ else ++ data->disc_thresh = 2; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); ++ data->base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(data->base)) ++ return PTR_ERR(data->base); ++ ++ data->clk = devm_clk_get(dev, "usb_phy"); ++ if (IS_ERR(data->clk)) { ++ dev_err(dev, "could not get usb_phy clock\n"); ++ return PTR_ERR(data->clk); ++ } ++ ++ /* Skip 0, 0 is the phy for otg which is not yet supported. */ ++ for (i = 1; i < data->num_phys; i++) { ++ snprintf(name, sizeof(name), "usb%d_vbus", i); ++ vbus = devm_regulator_get_optional(dev, name); ++ if (IS_ERR(vbus)) { ++ if (PTR_ERR(vbus) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ vbus = NULL; ++ } ++ ++ snprintf(name, sizeof(name), "usb%d_reset", i); ++ reset = devm_reset_control_get(dev, name); ++ if (IS_ERR(reset)) { ++ dev_err(dev, "failed to get reset %s\n", name); ++ return PTR_ERR(phy); ++ } ++ ++ if (i) { /* No pmu for usbc0 */ ++ snprintf(name, sizeof(name), "pmu%d", i); ++ res = platform_get_resource_byname(pdev, ++ IORESOURCE_MEM, name); ++ pmu = devm_ioremap_resource(dev, res); ++ if (IS_ERR(pmu)) ++ return PTR_ERR(pmu); ++ } ++ ++ phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create PHY %d\n", i); ++ return PTR_ERR(phy); ++ } ++ ++ data->phys[i].phy = phy; ++ data->phys[i].pmu = pmu; ++ data->phys[i].vbus = vbus; ++ data->phys[i].reset = reset; ++ data->phys[i].index = i; ++ phy_set_drvdata(phy, &data->phys[i]); ++ } ++ ++ dev_set_drvdata(dev, data); ++ phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ return 0; ++} ++ ++static const struct of_device_id sun4i_usb_phy_of_match[] = { ++ { .compatible = "allwinner,sun4i-a10-usb-phy" }, ++ { .compatible = "allwinner,sun5i-a13-usb-phy" }, ++ { .compatible = "allwinner,sun7i-a20-usb-phy" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); ++ ++static struct platform_driver sun4i_usb_phy_driver = { ++ .probe = sun4i_usb_phy_probe, ++ .driver = { ++ .of_match_table = sun4i_usb_phy_of_match, ++ .name = "sun4i-usb-phy", ++ .owner = THIS_MODULE, ++ } ++}; ++module_platform_driver(sun4i_usb_phy_driver); ++ ++MODULE_DESCRIPTION("Allwinner sun4i USB phy driver"); ++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); ++MODULE_LICENSE("GPL v2"); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch new file mode 100644 index 0000000..f0f5b92 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/183-1-dt-sun4i-add-usbclock-nodes.patch @@ -0,0 +1,34 @@ +From a6ff9c88c09c81cb612f2588a5bfbde21bdcbf7b Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Thu, 19 Sep 2013 21:58:47 +0200 +Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 1a9ab7e..7550c4e 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -307,6 +307,15 @@ + clock-output-names = "ir1"; + }; + ++ usb_clk: clk@01c200cc { ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ compatible = "allwinner,sun4i-a10-usb-clk"; ++ reg = <0x01c200cc 0x4>; ++ clocks = <&pll6 1>; ++ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy"; ++ }; ++ + spi3_clk: clk@01c200d4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch new file mode 100644 index 0000000..6a0a1cf --- /dev/null +++ b/target/linux/sunxi/patches-3.13/183-2-dt-sun4i-add-usb-bindings.patch @@ -0,0 +1,86 @@ +From f1a981bd49f310775780c221fe92f6861c5e8f3f Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Wed, 18 Sep 2013 00:30:04 +0200 +Subject: [PATCH] ARM: sun4i: dt: Add USB host bindings + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 7550c4e..80bbdeb 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -391,6 +391,38 @@ + status = "disabled"; + }; + ++ usbphy: phy@01c13400 { ++ #phy-cells = <1>; ++ compatible = "allwinner,sun4i-a10-usb-phy"; ++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; ++ reg-names = "phy_ctrl", "pmu1", "pmu2"; ++ clocks = <&usb_clk 8>; ++ clock-names = "usb_phy"; ++ resets = <&usb_clk 1>, <&usb_clk 2>; ++ reset-names = "usb1_reset", "usb2_reset"; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci"; ++ reg = <0x01c14000 0x100>; ++ interrupts = <39>; ++ clocks = <&ahb_gates 1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; ++ reg = <0x01c14400 0x100>; ++ interrupts = <64>; ++ clocks = <&usb_clk 6>, <&ahb_gates 2>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -399,6 +431,26 @@ + status = "disabled"; + }; + ++ ehci1: usb@01c1c000 { ++ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci"; ++ reg = <0x01c1c000 0x100>; ++ interrupts = <40>; ++ clocks = <&ahb_gates 3>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci"; ++ reg = <0x01c1c400 0x100>; ++ interrupts = <65>; ++ clocks = <&usb_clk 7>, <&ahb_gates 4>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch b/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch new file mode 100644 index 0000000..85483f2 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/183-3-dt-sun4i-add-ehci-cubieboard.patch @@ -0,0 +1,62 @@ +From d2afb2629087ab17d87d605d4b7f49da3a85f1b1 Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Wed, 18 Sep 2013 22:45:06 +0200 +Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to cubieboard dts + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index ef85b8e..57d2c9c 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -13,6 +13,7 @@ + /dts-v1/; + /include/ "sun4i-a10.dtsi" + /include/ "sunxi-ahci-reg.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" + + / { + model = "Cubietech Cubieboard"; +@@ -42,11 +43,33 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; + }; + ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + led_pins_cubieboard: led_pins@0 { + allwinner,pins = "PH20", "PH21"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch b/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch new file mode 100644 index 0000000..bd85989 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/183-4-dt-sun4i-add-ehci-a1000.patch @@ -0,0 +1,61 @@ +From dee94e49177c0bac675d543b16de0f354b0f476a Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Wed, 18 Sep 2013 00:30:40 +0200 +Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to Mele A1000 dts + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index 4b2a694..144b8e6 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -13,6 +13,7 @@ + + /dts-v1/; + /include/ "sun4i-a10.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" + + / { + model = "Mele A1000"; +@@ -43,10 +44,32 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + status = "okay"; + }; + ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + emac_power_pin_a1000: emac_power_pin@0 { + allwinner,pins = "PH15"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch new file mode 100644 index 0000000..2bb2a90 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/184-1-dt-sun7i-add-usbclock-nodes.patch @@ -0,0 +1,34 @@ +From ebac8eac9b49c914a975c04a62ea5cfc058d958d Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Thu, 19 Sep 2013 21:24:20 +0200 +Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index b58ce25..ed9b8cc 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -297,6 +297,15 @@ + clock-output-names = "ir1"; + }; + ++ usb_clk: clk@01c200cc { ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ compatible = "allwinner,sun4i-a10-usb-clk"; ++ reg = <0x01c200cc 0x4>; ++ clocks = <&pll6 1>; ++ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy"; ++ }; ++ + spi3_clk: clk@01c200d4 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch new file mode 100644 index 0000000..1c5ef8b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/184-2-dt-sun7i-add-usb-bindings.patch @@ -0,0 +1,86 @@ +From bc68c927139d1cac9647c8bcd3e8cea1cac9eaef Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Thu, 19 Sep 2013 21:36:10 +0200 +Subject: [PATCH] ARM: sun7i: dt: Add USB host bindings + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index ed9b8cc..bdfa594 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -453,6 +453,38 @@ + status = "disabled"; + }; + ++ usbphy: phy@01c13400 { ++ #phy-cells = <1>; ++ compatible = "allwinner,sun7i-a20-usb-phy"; ++ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; ++ reg-names = "phy_ctrl", "pmu1", "pmu2"; ++ clocks = <&usb_clk 8>; ++ clock-names = "usb_phy"; ++ resets = <&usb_clk 1>, <&usb_clk 2>; ++ reset-names = "usb1_reset", "usb2_reset"; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci"; ++ reg = <0x01c14000 0x100>; ++ interrupts = <0 39 4>; ++ clocks = <&ahb_gates 1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci"; ++ reg = <0x01c14400 0x100>; ++ interrupts = <0 64 4>; ++ clocks = <&usb_clk 6>, <&ahb_gates 2>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -461,6 +493,26 @@ + status = "disabled"; + }; + ++ ehci1: usb@01c1c000 { ++ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci"; ++ reg = <0x01c1c000 0x100>; ++ interrupts = <0 40 4>; ++ clocks = <&ahb_gates 3>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci"; ++ reg = <0x01c1c400 0x100>; ++ interrupts = <0 65 4>; ++ clocks = <&usb_clk 7>, <&ahb_gates 4>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + pio: pinctrl@01c20800 { + compatible = "allwinner,sun7i-a20-pinctrl"; + reg = <0x01c20800 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch b/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch new file mode 100644 index 0000000..7ca9d8a --- /dev/null +++ b/target/linux/sunxi/patches-3.13/184-3-dt-sun7i-add-ehci-cubieboard2.patch @@ -0,0 +1,62 @@ +From 5b820d3062a436cf36ddf2fecc88524b9adf7b6e Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Thu, 19 Sep 2013 21:29:45 +0200 +Subject: [PATCH] ARM: sun7i: dt: Add USB host nodes to cubieboard2 dts + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index a8186f5..9fa1d85 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -14,6 +14,7 @@ + /dts-v1/; + /include/ "sun7i-a20.dtsi" + /include/ "sunxi-ahci-reg.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" + + / { + model = "Cubietech Cubieboard2"; +@@ -28,11 +29,33 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; + }; + ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + led_pins_cubieboard2: led_pins@0 { + allwinner,pins = "PH20", "PH21"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch b/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch new file mode 100644 index 0000000..11d0936 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/184-4-dt-sun7i-add-ehci-olinuxino-a20-micro.patch @@ -0,0 +1,61 @@ +From 2f2ffd5ea0174434c8214722127e5e977dcecf32 Mon Sep 17 00:00:00 2001 +From: Zalan Blenessy <zalan.blenessy@gmail.com> +Date: Sun, 22 Dec 2013 17:08:10 +0100 +Subject: [PATCH] ARM: sun7i: dt: Add USB host nodes to a20-olinuxino-micro dts + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index aef289f..824ce0a 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -14,6 +14,7 @@ + /dts-v1/; + /include/ "sun7i-a20.dtsi" + /include/ "sunxi-ahci-reg.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" + #include <dt-bindings/input/input.h> + + / { +@@ -37,11 +38,33 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ + ahci: sata@01c18000 { + target-supply = <®_ahci_5v>; + status = "okay"; + }; + ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 { + allwinner,pins = "PH11"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch b/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch new file mode 100644 index 0000000..ef7323b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/185-1-dt-sun5i-add-usbclock-nodes.patch @@ -0,0 +1,55 @@ +From 84e5402d6755b0563cfbe1b6b930b13b1c10d56c Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Tue, 24 Sep 2013 20:02:39 +0200 +Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB clocks + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 9 +++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 9 +++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 95cb245..0565040 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -268,6 +268,15 @@ + clock-output-names = "ir0"; + }; + ++ usb_clk: clk@01c200cc { ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ compatible = "allwinner,sun5i-a13-usb-clk"; ++ reg = <0x01c200cc 0x4>; ++ clocks = <&pll6 1>; ++ clock-output-names = "usb_ohci0", "usb_phy"; ++ }; ++ + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index bae0f5f..785dea5 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -266,6 +266,15 @@ + clock-output-names = "ir0"; + }; + ++ usb_clk: clk@01c200cc { ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ compatible = "allwinner,sun5i-a13-usb-clk"; ++ reg = <0x01c200cc 0x4>; ++ clocks = <&pll6 1>; ++ clock-output-names = "usb_ohci0", "usb_phy"; ++ }; ++ + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-mod0-clk"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch b/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch new file mode 100644 index 0000000..50dc201 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/185-2-dt-sun5i-add-usb-bindings.patch @@ -0,0 +1,103 @@ +From 22f661c548042565ffa32e468267f94cadafe144 Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Tue, 24 Sep 2013 20:03:40 +0200 +Subject: [PATCH] ARM: sun5i: dt: Add USB host bindings + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 32 ++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/sun5i-a13.dtsi | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 0565040..a5431ed 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -341,6 +341,38 @@ + status = "disabled"; + }; + ++ usbphy: phy@01c13400 { ++ #phy-cells = <1>; ++ compatible = "allwinner,sun5i-a13-usb-phy"; ++ reg = <0x01c13400 0x10 0x01c14800 0x4>; ++ reg-names = "phy_ctrl", "pmu1"; ++ clocks = <&usb_clk 8>; ++ clock-names = "usb_phy"; ++ resets = <&usb_clk 1>; ++ reset-names = "usb1_reset"; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ compatible = "allwinner,sun5i-a10s-ehci", "generic-ehci"; ++ reg = <0x01c14000 0x100>; ++ interrupts = <39>; ++ clocks = <&ahb_gates 1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ compatible = "allwinner,sun5i-a10s-ohci", "generic-ohci"; ++ reg = <0x01c14400 0x100>; ++ interrupts = <40>; ++ clocks = <&usb_clk 6>, <&ahb_gates 2>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 785dea5..7fe9cdc 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -312,6 +312,38 @@ + status = "disabled"; + }; + ++ usbphy: phy@01c13400 { ++ #phy-cells = <1>; ++ compatible = "allwinner,sun5i-a13-usb-phy"; ++ reg = <0x01c13400 0x10 0x01c14800 0x4>; ++ reg-names = "phy_ctrl", "pmu1"; ++ clocks = <&usb_clk 8>; ++ clock-names = "usb_phy"; ++ resets = <&usb_clk 1>; ++ reset-names = "usb1_reset"; ++ status = "disabled"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ compatible = "allwinner,sun5i-a13-ehci", "generic-ehci"; ++ reg = <0x01c14000 0x100>; ++ interrupts = <39>; ++ clocks = <&ahb_gates 1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ compatible = "allwinner,sun5i-a13-ohci", "generic-ohci"; ++ reg = <0x01c14400 0x100>; ++ interrupts = <40>; ++ clocks = <&usb_clk 6>, <&ahb_gates 2>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch b/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch new file mode 100644 index 0000000..a664bc0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/185-3-dt-sun5i-add-ehci-a13.patch @@ -0,0 +1,72 @@ +From 8bf60620f751f93157c81038527b03716c8aeede Mon Sep 17 00:00:00 2001 +From: Roman Byshko <rbyshko@gmail.com> +Date: Tue, 24 Sep 2013 20:07:53 +0200 +Subject: [PATCH] ARM: sun5i: dt: Add USB host nodes to A13-Olinuxino + +Add nodes for the usb-phy and ehci- and ohci-usb-host controllers. + +Signed-off-by: Roman Byshko <rbyshko@gmail.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +index ba32a41..39556d1 100644 +--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts ++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts +@@ -13,6 +13,7 @@ + + /dts-v1/; + /include/ "sun5i-a13.dtsi" ++/include/ "sun5i-a13-usb-vbus-reg.dtsi" + #include <dt-bindings/input/input.h> + + / { +@@ -28,6 +29,19 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { + mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 { + allwinner,pins = "PG0"; +@@ -42,6 +56,13 @@ + allwinner,drive = <1>; + allwinner,pull = <0>; + }; ++ ++ usb1_vbus_pin_olinuxino: usb1_vbus_pin@0 { ++ allwinner,pins = "PG11"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; + }; + + lradc: lradc@01c22800 { +@@ -86,4 +107,9 @@ + default-state = "on"; + }; + }; ++ ++ reg_usb1_vbus: usb1-vbus { ++ pinctrl-0 = <&usb1_vbus_pin_olinuxino>; ++ gpio = <&pio 6 11 0>; ++ }; + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch b/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch deleted file mode 100644 index 3035a49..0000000 --- a/target/linux/sunxi/patches-3.13/190-stmmac-enable-main-clock-when-probing.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 133a9b75e2b0c48cd1d8f93b0ee61089821c32d9 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:34 +0800 -Subject: [PATCH] net: stmmac: Enable stmmac main clock when probing hardware - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 24 +++++++++++++---------- - 1 file changed, 14 insertions(+), 10 deletions(-) - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2680,10 +2680,17 @@ struct stmmac_priv *stmmac_dvr_probe(str - if ((phyaddr >= 0) && (phyaddr <= 31)) - priv->plat->phy_addr = phyaddr; - -+ priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); -+ if (IS_ERR(priv->stmmac_clk)) { -+ pr_warn("%s: warning: cannot get CSR clock\n", __func__); -+ goto error_clk_get; -+ } -+ clk_prepare_enable(priv->stmmac_clk); -+ - /* Init MAC and get the capabilities */ - ret = stmmac_hw_init(priv); - if (ret) -- goto error_free_netdev; -+ goto error_hw_init; - - ndev->netdev_ops = &stmmac_netdev_ops; - -@@ -2721,12 +2728,6 @@ struct stmmac_priv *stmmac_dvr_probe(str - goto error_netdev_register; - } - -- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME); -- if (IS_ERR(priv->stmmac_clk)) { -- pr_warn("%s: warning: cannot get CSR clock\n", __func__); -- goto error_clk_get; -- } -- - /* If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be - * changed at run-time and it is fixed. Viceversa the driver'll try to -@@ -2751,15 +2752,18 @@ struct stmmac_priv *stmmac_dvr_probe(str - } - } - -+ clk_disable_unprepare(priv->stmmac_clk); -+ - return priv; - - error_mdio_register: -- clk_put(priv->stmmac_clk); --error_clk_get: - unregister_netdev(ndev); - error_netdev_register: - netif_napi_del(&priv->napi); --error_free_netdev: -+error_hw_init: -+ clk_disable_unprepare(priv->stmmac_clk); -+ clk_put(priv->stmmac_clk); -+error_clk_get: - free_netdev(ndev); - - return NULL; diff --git a/target/linux/sunxi/patches-3.13/180-sunxi-select-PSCI.patch b/target/linux/sunxi/patches-3.13/190-sunxi-select-PSCI.patch index a634240..a634240 100644 --- a/target/linux/sunxi/patches-3.13/180-sunxi-select-PSCI.patch +++ b/target/linux/sunxi/patches-3.13/190-sunxi-select-PSCI.patch diff --git a/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch b/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch deleted file mode 100644 index 5c4f40d..0000000 --- a/target/linux/sunxi/patches-3.13/191-stmmac-honor-DT-params.patch +++ /dev/null @@ -1,24 +0,0 @@ -From a2acf761e37031737300c47284181a21b6bc0cc2 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:35 +0800 -Subject: [PATCH] net: stmmac: Honor DT parameter to force DMA store and - forward mode - -"snps,force_sf_dma_mode" is documented in stmmac device tree bindings, -but is never handled by the driver. - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -47,6 +47,7 @@ static int stmmac_probe_config_dt(struct - plat->bus_id = 0; - - of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr); -+ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode"); - - plat->mdio_bus_data = devm_kzalloc(&pdev->dev, - sizeof(struct stmmac_mdio_bus_data), diff --git a/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch b/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch deleted file mode 100644 index 409f93a..0000000 --- a/target/linux/sunxi/patches-3.13/192-stmmac-use-platform-data-with-compat.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 34722924d416c3521de2bc8d10dfcd07a55135ea Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:36 +0800 -Subject: [PATCH] net: stmmac: Use platform data tied with compatible strings - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 29 ++++++++++++++-------- - 1 file changed, 19 insertions(+), 10 deletions(-) - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -26,8 +26,19 @@ - #include <linux/io.h> - #include <linux/of.h> - #include <linux/of_net.h> -+#include <linux/of_device.h> - #include "stmmac.h" - -+static const struct of_device_id stmmac_dt_ids[] = { -+ { .compatible = "st,spear600-gmac"}, -+ { .compatible = "snps,dwmac-3.610"}, -+ { .compatible = "snps,dwmac-3.70a"}, -+ { .compatible = "snps,dwmac-3.710"}, -+ { .compatible = "snps,dwmac"}, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, stmmac_dt_ids); -+ - #ifdef CONFIG_OF - static int stmmac_probe_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat, -@@ -35,10 +46,18 @@ static int stmmac_probe_config_dt(struct - { - struct device_node *np = pdev->dev.of_node; - struct stmmac_dma_cfg *dma_cfg; -+ const struct of_device_id *device; - - if (!np) - return -ENODEV; - -+ device = of_match_device(stmmac_dt_ids, &pdev->dev); -+ if (!device) -+ return -ENODEV; -+ -+ if (device->data) -+ memcpy(plat, device->data, sizeof(*plat)); -+ - *mac = of_get_mac_address(np); - plat->interface = of_get_phy_mode(np); - -@@ -257,16 +276,6 @@ static const struct dev_pm_ops stmmac_pl - static const struct dev_pm_ops stmmac_pltfr_pm_ops; - #endif /* CONFIG_PM */ - --static const struct of_device_id stmmac_dt_ids[] = { -- { .compatible = "st,spear600-gmac"}, -- { .compatible = "snps,dwmac-3.610"}, -- { .compatible = "snps,dwmac-3.70a"}, -- { .compatible = "snps,dwmac-3.710"}, -- { .compatible = "snps,dwmac"}, -- { /* sentinel */ } --}; --MODULE_DEVICE_TABLE(of, stmmac_dt_ids); -- - struct platform_driver stmmac_pltfr_driver = { - .probe = stmmac_pltfr_probe, - .remove = stmmac_pltfr_remove, diff --git a/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch b/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch deleted file mode 100644 index 6bc409e..0000000 --- a/target/linux/sunxi/patches-3.13/193-stmmac-platform-ext-for-a20.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 3c6560eccfeee3a93d57c3b2206abfbe06459015 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:37 +0800 -Subject: [PATCH] net: stmmac: sunxi platfrom extensions for GMAC in Allwinner - A20 SoC's - -The Allwinner A20 has an ethernet controller that seems to be -an early version of Synopsys DesignWare MAC 10/100/1000 Universal, -which is supported by the stmmac driver. - -Allwinner's GMAC requires setting additional registers in the SoC's -clock control unit. - -The exact version of the DWMAC IP that Allwinner uses is unknown, -thus the exact feature set is unknown. - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - .../bindings/net/allwinner,sun7i-gmac.txt | 22 +++++++ - drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++++ - drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + - drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 76 ++++++++++++++++++++++ - drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 + - .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 + - 6 files changed, 117 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-gmac.txt - create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-gmac.txt -@@ -0,0 +1,22 @@ -+* Allwinner GMAC ethernet controller -+ -+This device is a platform glue layer for stmmac. -+Please see stmmac.txt for the other unchanged properties. -+ -+Required properties: -+ - compatible: Should be "allwinner,sun7i-gmac" -+ - reg: Address and length of register set for the device and corresponding -+ clock control -+ -+Examples: -+ -+ gmac: ethernet@01c50000 { -+ compatible = "allwinner,sun7i-gmac"; -+ reg = <0x01c50000 0x10000>, -+ <0x01c20164 0x4>; -+ interrupts = <0 85 1>; -+ interrupt-names = "macirq"; -+ clocks = <&ahb_gates 49>; -+ clock-names = "stmmaceth"; -+ phy-mode = "mii"; -+ }; ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -25,6 +25,18 @@ config STMMAC_PLATFORM - - If unsure, say N. - -+config DWMAC_SUNXI -+ bool "Allwinner GMAC support" -+ depends on STMMAC_PLATFORM -+ depends on ARCH_SUNXI -+ default y -+ ---help--- -+ Support for Allwinner A20 GMAC ethernet driver. -+ -+ This selects Allwinner SoC glue layer support for the -+ stmmac device driver. This driver is used for A20 GMAC -+ ethernet controller. -+ - config STMMAC_PCI - bool "STMMAC PCI bus support" - depends on STMMAC_ETH && PCI ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -1,6 +1,7 @@ - obj-$(CONFIG_STMMAC_ETH) += stmmac.o - stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o - stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o -+stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o - stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ - chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ - dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c -@@ -0,0 +1,76 @@ -+/** -+ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer -+ * -+ * Copyright (C) 2013 Chen-Yu Tsai -+ * -+ * Chen-Yu Tsai <wens@csie.org> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/clk.h> -+#include <linux/phy.h> -+#include <linux/stmmac.h> -+ -+#define GMAC_IF_TYPE_RGMII 0x4 -+ -+#define GMAC_TX_CLK_MASK 0x3 -+#define GMAC_TX_CLK_MII 0x0 -+#define GMAC_TX_CLK_RGMII_INT 0x2 -+ -+static int sun7i_gmac_init(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct device *dev = &pdev->dev; -+ void __iomem *addr = NULL; -+ struct plat_stmmacenet_data *plat_dat = NULL; -+ u32 priv_clk_reg; -+ -+ plat_dat = dev_get_platdata(&pdev->dev); -+ if (!plat_dat) -+ return -EINVAL; -+ -+ /* Get GMAC clock register in CCU */ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ addr = devm_ioremap_resource(dev, res); -+ if (IS_ERR(addr)) -+ return PTR_ERR(addr); -+ -+ priv_clk_reg = readl(addr); -+ -+ /* Set GMAC interface port mode */ -+ if (plat_dat->interface == PHY_INTERFACE_MODE_RGMII) -+ priv_clk_reg |= GMAC_IF_TYPE_RGMII; -+ else -+ priv_clk_reg &= ~GMAC_IF_TYPE_RGMII; -+ -+ /* Set GMAC transmit clock source. */ -+ priv_clk_reg &= ~GMAC_TX_CLK_MASK; -+ if (plat_dat->interface == PHY_INTERFACE_MODE_RGMII -+ || plat_dat->interface == PHY_INTERFACE_MODE_GMII) -+ priv_clk_reg |= GMAC_TX_CLK_RGMII_INT; -+ else -+ priv_clk_reg |= GMAC_TX_CLK_MII; -+ -+ writel(priv_clk_reg, addr); -+ -+ /* mask out phy addr 0x0 */ -+ plat_dat->mdio_bus_data->phy_mask = 0x1; -+ -+ return 0; -+} -+ -+const struct plat_stmmacenet_data sun7i_gmac_data = { -+ .has_gmac = 1, -+ .tx_coe = 1, -+ .init = sun7i_gmac_init, -+}; -+ ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -130,6 +130,9 @@ void stmmac_disable_eee_mode(struct stmm - bool stmmac_eee_init(struct stmmac_priv *priv); - - #ifdef CONFIG_STMMAC_PLATFORM -+#ifdef CONFIG_DWMAC_SUNXI -+extern const struct plat_stmmacenet_data sun7i_gmac_data; -+#endif - extern struct platform_driver stmmac_pltfr_driver; - static inline int stmmac_register_platform(void) - { ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -35,6 +35,9 @@ static const struct of_device_id stmmac_ - { .compatible = "snps,dwmac-3.70a"}, - { .compatible = "snps,dwmac-3.710"}, - { .compatible = "snps,dwmac"}, -+#ifdef CONFIG_DWMAC_SUNXI -+ { .compatible = "allwinner,sun7i-gmac", .data = &sun7i_gmac_data}, -+#endif - { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, stmmac_dt_ids); diff --git a/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch b/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch deleted file mode 100644 index 0b65dac..0000000 --- a/target/linux/sunxi/patches-3.13/194-dt-sun7i-add-gmac-ctrler.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a07eeb627d300da0dee8cb39b59173332be8e4bb Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:38 +0800 -Subject: [PATCH] ARM: dts: sun7i: Add GMAC controller node to sun7i DTSI - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20.dtsi -+++ b/arch/arm/boot/dts/sun7i-a20.dtsi -@@ -605,6 +605,20 @@ - status = "disabled"; - }; - -+ gmac: ethernet@01c50000 { -+ compatible = "allwinner,sun7i-gmac", "snps,dwmac"; -+ reg = <0x01c50000 0x10000>, -+ <0x01c20164 0x4>; -+ interrupts = <0 85 1>; -+ interrupt-names = "macirq"; -+ clocks = <&ahb_gates 49>; -+ clock-names = "stmmaceth"; -+ snps,pbl = <2>; -+ snps,fixed-burst; -+ snps,force_sf_dma_mode; -+ status = "disabled"; -+ }; -+ - hstimer@01c60000 { - compatible = "allwinner,sun7i-a20-hstimer"; - reg = <0x01c60000 0x1000>; diff --git a/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch b/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch deleted file mode 100644 index e781d0f..0000000 --- a/target/linux/sunxi/patches-3.13/196-1-dt-sun7i-enable-gmac-cubietruck.patch +++ /dev/null @@ -1,29 +0,0 @@ -From a94741174cdc6bd29c56c5aa1a225ac6e7f4ebde Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai <wens@csie.org> -Date: Sat, 7 Dec 2013 01:29:40 +0800 -Subject: [PATCH] ARM: dts: sun7i: cubietruck: Enable the GMAC - -The CubieTruck uses the GMAC with an RGMII phy. - -Signed-off-by: Chen-Yu Tsai <wens@csie.org> ---- - arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -@@ -121,6 +121,14 @@ - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; -+ -+ gmac: ethernet@01c50000 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&gmac_pins_rgmii>; -+ snps,phy-addr = <1>; -+ phy-mode = "rgmii"; -+ status = "okay"; -+ }; - }; - - leds { diff --git a/target/linux/sunxi/patches-3.13/212-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch b/target/linux/sunxi/patches-3.13/211-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch index feb736a..feb736a 100644 --- a/target/linux/sunxi/patches-3.13/212-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch +++ b/target/linux/sunxi/patches-3.13/211-pinctrl-sunxi-add-a20-output-clkpin-funcs.patch diff --git a/target/linux/sunxi/patches-3.13/213-dt-sun7i-add-external-clk-outputs.patch b/target/linux/sunxi/patches-3.13/212-dt-sun7i-add-pinmuxing-for-extclocks.patch index 3dda294..3dda294 100644 --- a/target/linux/sunxi/patches-3.13/213-dt-sun7i-add-external-clk-outputs.patch +++ b/target/linux/sunxi/patches-3.13/212-dt-sun7i-add-pinmuxing-for-extclocks.patch diff --git a/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch b/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch new file mode 100644 index 0000000..6dc1f1c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/220-dt-sun4i-move-aliases-to-dtsi.patch @@ -0,0 +1,62 @@ +From 10b302a297aee952949423aaec0749b757f34950 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 17 Nov 2013 10:03:04 +0100 +Subject: [PATCH] ARM: sun4i: dt: Move the aliases to the DTSI + +The aliases are shared across boards are really belong to the DTSI. +Move them there. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ---- + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 5 ----- + arch/arm/boot/dts/sun4i-a10.dtsi | 2 ++ + 3 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index eb4d73b..d4b081d 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -18,10 +18,6 @@ + model = "Mele A1000"; + compatible = "mele,a1000", "allwinner,sun4i-a10"; + +- aliases { +- serial0 = &uart0; +- }; +- + soc@01c00000 { + emac: ethernet@01c0b000 { + pinctrl-names = "default"; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index 425a7db..f1c77e0 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -17,11 +17,6 @@ + model = "Cubietech Cubieboard"; + compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10"; + +- aliases { +- serial0 = &uart0; +- serial1 = &uart1; +- }; +- + chosen { + bootargs = "earlyprintk console=ttyS0,115200"; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 3ba2b46..0adbbe3 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -17,6 +17,8 @@ + + aliases { + ethernet0 = &emac; ++ serial0 = &uart0; ++ serial1 = &uart1; + }; + + cpus { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch b/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch deleted file mode 100644 index ee19c29..0000000 --- a/target/linux/sunxi/patches-3.13/230-dt-add-pcduino.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -253,6 +253,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ - sun4i-a10-cubieboard.dtb \ - sun4i-a10-mini-xplus.dtb \ - sun4i-a10-hackberry.dtb \ -+ sun4i-a10-pcduino.dtb \ - sun5i-a10s-olinuxino-micro.dtb \ - sun5i-a13-olinuxino.dtb \ - sun5i-a13-olinuxino-micro.dtb \ diff --git a/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch b/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch new file mode 100644 index 0000000..e54627d --- /dev/null +++ b/target/linux/sunxi/patches-3.13/230-dt-sunxi-change-emac-to-new-compats.patch @@ -0,0 +1,57 @@ +From 4dae1686782d52084893421b89ff1aa61e223aaf Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:49:11 +0100 +Subject: [PATCH] net: ethernet: sunxi: Add new compatibles + +The Allwinner A10 compatibles were following a slightly different compatible +patterns than the rest of the SoCs for historical reasons. Add compatibles +matching the other pattern to the ethernet driver for consistency, and keep the +older one for backward compatibility. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt | 5 +++-- + drivers/net/ethernet/allwinner/sun4i-emac.c | 3 +++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt +index b90bfcd..863d5b81 100644 +--- a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt ++++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt +@@ -1,7 +1,8 @@ + * Allwinner EMAC ethernet controller + + Required properties: +-- compatible: should be "allwinner,sun4i-emac". ++- compatible: should be "allwinner,sun4i-a10-emac" (Deprecated: ++ "allwinner,sun4i-emac") + - reg: address and length of the register set for the device. + - interrupts: interrupt for the device + - phy: A phandle to a phy node defining the PHY address (as the reg +@@ -14,7 +15,7 @@ Optional properties: + Example: + + emac: ethernet@01c0b000 { +- compatible = "allwinner,sun4i-emac"; ++ compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <55>; + clocks = <&ahb_gates 17>; +diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c +index 0cc2143..511f6ee 100644 +--- a/drivers/net/ethernet/allwinner/sun4i-emac.c ++++ b/drivers/net/ethernet/allwinner/sun4i-emac.c +@@ -929,6 +929,9 @@ static int emac_resume(struct platform_device *dev) + } + + static const struct of_device_id emac_of_match[] = { ++ {.compatible = "allwinner,sun4i-a10-emac",}, ++ ++ /* Deprecated */ + {.compatible = "allwinner,sun4i-emac",}, + {}, + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch b/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch deleted file mode 100644 index 8292840..0000000 --- a/target/linux/sunxi/patches-3.13/231-dt-add-a10-olinuxino-lime.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -254,6 +254,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ - sun4i-a10-mini-xplus.dtb \ - sun4i-a10-hackberry.dtb \ - sun4i-a10-pcduino.dtb \ -+ sun4i-a10-olinuxino-lime.dtb \ - sun5i-a10s-olinuxino-micro.dtb \ - sun5i-a13-olinuxino.dtb \ - sun5i-a13-olinuxino-micro.dtb \ diff --git a/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch b/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch new file mode 100644 index 0000000..fe1b436 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/231-dt-sunxi-net-phy-add-new-compats.patch @@ -0,0 +1,57 @@ +From efe205704fa8435b7bca495138dd2dbd973e0c28 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:49:12 +0100 +Subject: [PATCH] net: phy: sunxi: Add new compatibles + +The Allwinner A10 compatibles were following a slightly different compatible +patterns than the rest of the SoCs for historical reasons. Add compatibles +matching the other pattern to the mdio driver for consistency, and keep the +older one for backward compatibility. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt | 5 +++-- + drivers/net/phy/mdio-sun4i.c | 3 +++ + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt +index 00b9f9a..4ec5641 100644 +--- a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt ++++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt +@@ -1,7 +1,8 @@ + * Allwinner A10 MDIO Ethernet Controller interface + + Required properties: +-- compatible: should be "allwinner,sun4i-mdio". ++- compatible: should be "allwinner,sun4i-a10-mdio" ++ (Deprecated: "allwinner,sun4i-mdio"). + - reg: address and length of the register set for the device. + + Optional properties: +@@ -9,7 +10,7 @@ Optional properties: + + Example at the SoC level: + mdio@01c0b080 { +- compatible = "allwinner,sun4i-mdio"; ++ compatible = "allwinner,sun4i-a10-mdio"; + reg = <0x01c0b080 0x14>; + #address-cells = <1>; + #size-cells = <0>; +diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c +index bb88bc7..9367acc 100644 +--- a/drivers/net/phy/mdio-sun4i.c ++++ b/drivers/net/phy/mdio-sun4i.c +@@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev) + } + + static const struct of_device_id sun4i_mdio_dt_ids[] = { ++ { .compatible = "allwinner,sun4i-a10-mdio" }, ++ ++ /* Deprecated */ + { .compatible = "allwinner,sun4i-mdio" }, + { } + }; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch deleted file mode 100644 index 3583966..0000000 --- a/target/linux/sunxi/patches-3.13/232-dt-pcduino-update-mmc-entry.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts -+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts -@@ -42,9 +42,9 @@ - }; - }; - -- sdc0: sdc@01c0f000 { -+ mmc0: mmc@01c0f000 { - pinctrl-names = "default"; -- pinctrl-0 = <&sdc0_pins_a>; -+ pinctrl-0 = <&mmc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_pcduino>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; diff --git a/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch b/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch new file mode 100644 index 0000000..83b6702 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/232-dt-sunxi-change-to-new-net-compats.patch @@ -0,0 +1,85 @@ +From 1c70e099ac80ee779ffac66a6169ad936425fe41 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:49:13 +0100 +Subject: [PATCH] ARM: sunxi: dt: Convert to the new net compatibles + +Switch the device tree to the new compatibles introduced in the ethernet and +mdio drivers to have a common pattern accross all Allwinner SoCs. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 4 ++-- + arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++-- + arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 040bb0e..10666ca 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -315,7 +315,7 @@ + ranges; + + emac: ethernet@01c0b000 { +- compatible = "allwinner,sun4i-emac"; ++ compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <55>; + clocks = <&ahb_gates 17>; +@@ -323,7 +323,7 @@ + }; + + mdio@01c0b080 { +- compatible = "allwinner,sun4i-mdio"; ++ compatible = "allwinner,sun4i-a10-mdio"; + reg = <0x01c0b080 0x14>; + status = "disabled"; + #address-cells = <1>; +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index ea16054..6496159 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -278,7 +278,7 @@ + ranges; + + emac: ethernet@01c0b000 { +- compatible = "allwinner,sun4i-emac"; ++ compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <55>; + clocks = <&ahb_gates 17>; +@@ -286,7 +286,7 @@ + }; + + mdio@01c0b080 { +- compatible = "allwinner,sun4i-mdio"; ++ compatible = "allwinner,sun4i-a10-mdio"; + reg = <0x01c0b080 0x14>; + status = "disabled"; + #address-cells = <1>; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 119f066..9ff0948 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -340,7 +340,7 @@ + ranges; + + emac: ethernet@01c0b000 { +- compatible = "allwinner,sun4i-emac"; ++ compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <0 55 4>; + clocks = <&ahb_gates 17>; +@@ -348,7 +348,7 @@ + }; + + mdio@01c0b080 { +- compatible = "allwinner,sun4i-mdio"; ++ compatible = "allwinner,sun4i-a10-mdio"; + reg = <0x01c0b080 0x14>; + status = "disabled"; + #address-cells = <1>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch deleted file mode 100644 index 2812a22..0000000 --- a/target/linux/sunxi/patches-3.13/233-dt-lime-update-mmc-entry.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts -+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts -@@ -33,9 +33,9 @@ - }; - }; - -- sdc0: sdc@01c0f000 { -+ mmc0: mmc@01c0f000 { - pinctrl-names = "default"; -- pinctrl-0 = <&sdc0_pins_a>; -+ pinctrl-0 = <&mmc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_olinuxino>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; diff --git a/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch b/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch deleted file mode 100644 index b998f11..0000000 --- a/target/linux/sunxi/patches-3.13/234-dt-cubietruck-update-mmc-entry.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts -@@ -19,9 +19,9 @@ - compatible = "cubietech,cubietruck", "allwinner,sun7i-a20"; - - soc@01c00000 { -- sdc0: sdc@01c0f000 { -+ mmc0: mmc@01c0f000 { - pinctrl-names = "default"; -- pinctrl-0 = <&sdc0_pins_a>; -+ pinctrl-0 = <&mmc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_cubietruck>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-mode = <1>; diff --git a/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch new file mode 100644 index 0000000..b4bc637 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/240-1-dt-sun4i-add-missing-serial-aliases.patch @@ -0,0 +1,33 @@ +From 791f631bb8f3feb10871b82015a25a7f40ce68e7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 2 Jan 2014 22:05:04 +0100 +Subject: [PATCH] ARM: sun4i: a10: Add missing serial aliases + +Some UART aliases have been defined, but not all of them. Add the remaining +ones to be consistent and to ease the parsing of the DT by the bootloaders. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 10666ca..d9c097c 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -19,6 +19,12 @@ + ethernet0 = &emac; + serial0 = &uart0; + serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial5 = &uart5; ++ serial6 = &uart6; ++ serial7 = &uart7; + }; + + cpus { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch new file mode 100644 index 0000000..3f63485 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/240-2-dt-sun5i-a10s-add-missing-serial-aliases.patch @@ -0,0 +1,31 @@ +From 64c3866d232e6b29862f4773ea97b16f4dad6950 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 2 Jan 2014 22:05:04 +0100 +Subject: [PATCH] ARM: sun5i: a10s: Add missing serial aliases + +Some UART aliases have been defined, but not all of them. Add the remaining +ones to be consistent and to ease the parsing of the DT by the bootloaders. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 6496159..e00f292 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -18,6 +18,10 @@ + + aliases { + ethernet0 = &emac; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; + }; + + cpus { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch new file mode 100644 index 0000000..a60e497 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/240-3-dt-sun5i-a13-add-missing-serial-aliases.patch @@ -0,0 +1,32 @@ +From 0cc774ef2524ec54e9d2db8771ba3739cb8ebc99 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Mon, 13 Jan 2014 11:08:47 +0100 +Subject: [PATCH] ARM: sun5i: a13: Add missing serial aliases + +Some UART aliases have been defined, but not all of them. Add the remaining +ones to be consistent and to ease the parsing of the DT by the bootloaders. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun5i-a13.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 320335a..6de40b6 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -16,6 +16,11 @@ + / { + interrupt-parent = <&intc>; + ++ aliases { ++ serial0 = &uart1; ++ serial1 = &uart3; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch b/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch new file mode 100644 index 0000000..5a1f25c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/240-4-dt-sun6i-add-missing-serial-aliases.patch @@ -0,0 +1,37 @@ +From 27fb9d199aa3d2f89b4d0b1930062bb1a5a69a57 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 2 Jan 2014 22:05:04 +0100 +Subject: [PATCH] ARM: sun6i: Add missing serial aliases + +Some UART aliases have been defined, but not all of them. Add the remaining +ones to be consistent and to ease the parsing of the DT by the bootloaders. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index 5256ad9..092bf97 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -16,6 +16,16 @@ + / { + interrupt-parent = <&gic>; + ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial5 = &uart5; ++ }; ++ ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch b/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch new file mode 100644 index 0000000..2e64dd8 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/241-dt-sun7i-add-pinmuxing-for-uart2.patch @@ -0,0 +1,35 @@ +From 4261ec43b199a214f6b0ae5fefefff2e524f8977 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Tue, 14 Jan 2014 22:49:50 +0800 +Subject: [PATCH] ARM: dts: sun7i: add pin muxing options for UART2 + +UART2 is used on CubieTruck to connect to the Bluetooth module. +Add the pin set used in this case. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index b476855..bfb2cf2 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -381,6 +381,13 @@ + allwinner,pull = <0>; + }; + ++ uart2_pins_a: uart2@0 { ++ allwinner,pins = "PI16", "PI17", "PI18", "PI19"; ++ allwinner,function = "uart2"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + uart6_pins_a: uart6@0 { + allwinner,pins = "PI12", "PI13"; + allwinner,function = "uart6"; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch b/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch new file mode 100644 index 0000000..4496437 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/250-clk-sunxi-get-divs-parent-clkname.patch @@ -0,0 +1,45 @@ +From 97e36b3ce3106988b82e1ca53b1d1c872bde855a Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:40 +0800 +Subject: [PATCH] clk: sunxi: get divs parent clock name from parent factor + clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Divs clocks consist of a parent factor clock with multiple outputs, +and seperate clocks for each output. Get the name of the parent +clock from the parent factor clock, instead of the DT node name. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Acked-by: Mike Turquette <mturquette@linaro.org> +Signed-off-by: Emilio López <emilio@elopez.com.ar> +--- + drivers/clk/sunxi/clk-sunxi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 7a2ed98..736fb60 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -869,7 +869,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + struct divs_data *data) + { + struct clk_onecell_data *clk_data; +- const char *parent = node->name; ++ const char *parent; + const char *clk_name; + struct clk **clks, *pclk; + struct clk_hw *gate_hw, *rate_hw; +@@ -883,6 +883,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + + /* Set up factor clock that we will be dividing */ + pclk = sunxi_factors_clk_setup(node, data->factors); ++ parent = __clk_get_name(pclk); + + reg = of_iomap(node, 0); + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch b/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch new file mode 100644 index 0000000..7c49d0f --- /dev/null +++ b/target/linux/sunxi/patches-3.13/251-clk-sunxi-add-clk-output-names-dt-prop.patch @@ -0,0 +1,55 @@ +From f64111ebaf6776558f0e60d0ea8c7a9c579b9436 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:37 +0800 +Subject: [PATCH] clk: sunxi: add clock-output-names dt property support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sunxi clock drivers use dt node name as clock name, but clock +nodes should be named clk@X, so the names would be the same. +Let the drivers read clock names from dt clock-output-names +property. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Acked-by: Mike Turquette <mturquette@linaro.org> +Signed-off-by: Emilio López <emilio@elopez.com.ar> +--- + drivers/clk/sunxi/clk-sunxi.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index abb6c5a..0ed9794 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -51,6 +51,8 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) + if (!gate) + goto err_free_fixed; + ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ + /* set up gate and fixed rate properties */ + gate->reg = of_iomap(node, 0); + gate->bit_idx = SUNXI_OSC24M_GATE; +@@ -601,6 +603,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node, + (parents[i] = of_clk_get_parent_name(node, i)) != NULL) + i++; + ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ + clk = clk_register_mux(NULL, clk_name, parents, i, + CLK_SET_RATE_NO_REPARENT, reg, + data->shift, SUNXI_MUX_GATE_WIDTH, +@@ -660,6 +664,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, + + clk_parent = of_clk_get_parent_name(node, 0); + ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ + clk = clk_register_divider(NULL, clk_name, clk_parent, 0, + reg, data->shift, data->width, + data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch b/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch new file mode 100644 index 0000000..f89e97a --- /dev/null +++ b/target/linux/sunxi/patches-3.13/252-clk-sunxi-add-names-for-pll5-6-into-factors_data.patch @@ -0,0 +1,83 @@ +From 667f542db542fddc62d1299b17451d7cae84f6e1 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 3 Feb 2014 09:51:39 +0800 +Subject: [PATCH] clk: sunxi: add names for pll5, pll6 parent clocks to + factors_data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some factor clocks, such as the parent clock of pll5 and pll6, have +multiple output names. Add the corresponding names to factors_data +tied to compatible string. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Acked-by: Mike Turquette <mturquette@linaro.org> +Signed-off-by: Emilio López <emilio@elopez.com.ar> +--- + drivers/clk/sunxi/clk-sunxi.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 0ed9794..7a2ed98 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -389,6 +389,7 @@ struct factors_data { + int mux; + struct clk_factors_config *table; + void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); ++ const char *name; + }; + + static struct clk_factors_config sun4i_pll1_config = { +@@ -457,6 +458,14 @@ struct factors_data { + .enable = 31, + .table = &sun4i_pll5_config, + .getter = sun4i_get_pll5_factors, ++ .name = "pll5", ++}; ++ ++static const struct factors_data sun4i_pll6_data __initconst = { ++ .enable = 31, ++ .table = &sun4i_pll5_config, ++ .getter = sun4i_get_pll5_factors, ++ .name = "pll6", + }; + + static const struct factors_data sun4i_apb1_data __initconst = { +@@ -499,14 +508,14 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, + (parents[i] = of_clk_get_parent_name(node, i)) != NULL) + i++; + +- /* Nodes should be providing the name via clock-output-names +- * but originally our dts didn't, and so we used node->name. +- * The new, better nodes look like clk@deadbeef, so we pull the +- * name just in this case */ +- if (!strcmp("clk", clk_name)) { +- of_property_read_string_index(node, "clock-output-names", +- 0, &clk_name); +- } ++ /* ++ * some factor clocks, such as pll5 and pll6, may have multiple ++ * outputs, and have their name designated in factors_data ++ */ ++ if (data->name) ++ clk_name = data->name; ++ else ++ of_property_read_string(node, "clock-output-names", &clk_name); + + factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); + if (!factors) +@@ -838,7 +847,7 @@ struct divs_data { + }; + + static const struct divs_data pll6_divs_data __initconst = { +- .factors = &sun4i_pll5_data, ++ .factors = &sun4i_pll6_data, + .div = { + { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ + { .fixed = 2 }, /* P, other */ +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch b/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch new file mode 100644 index 0000000..ce5a070 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/253-clk-sunxi-add-a20a31-gmac-clock.patch @@ -0,0 +1,177 @@ +From 967f938d4b16233fd7596e94803a36161847c6a8 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Mon, 10 Feb 2014 18:35:47 +0800 +Subject: [PATCH] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit + +The Allwinner A20/A31 clock module controls the transmit clock source +and interface type of the GMAC ethernet controller. Model this as +a single clock for GMAC drivers to use. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +--- + Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++ + drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++ + 2 files changed, 126 insertions(+) + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index 93d003c..0da774c 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -37,6 +37,7 @@ Required properties: + "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 + "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks + "allwinner,sun7i-a20-out-clk" - for the external output clocks ++ "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 + + Required properties for all clocks: + - reg : shall be the control register address for the clock. +@@ -50,6 +51,9 @@ Required properties for all clocks: + If the clock module only has one output, the name shall be the + module name. + ++For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate ++dummy clocks at 25 MHz and 125 MHz, respectively. See example. ++ + Clock consumers should specify the desired clocks they use with a + "clocks" phandle cell. Consumers that are using a gated clock should + provide an additional ID in their clock property. This ID is the +@@ -96,3 +100,29 @@ mmc0_clk: clk@01c20088 { + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0"; + }; ++ ++mii_phy_tx_clk: clk@2 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++ clock-output-names = "mii_phy_tx"; ++}; ++ ++gmac_int_tx_clk: clk@3 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_int_tx"; ++}; ++ ++gmac_clk: clk@01c20164 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun7i-a20-gmac-clk"; ++ reg = <0x01c20164 0x4>; ++ /* ++ * The first clock must be fixed at 25MHz; ++ * the second clock must be fixed at 125MHz ++ */ ++ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; ++ clock-output-names = "gmac"; ++}; +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 0dce6fd..3283179 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -404,6 +404,102 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, + + + /** ++ * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module ++ * ++ * This clock looks something like this ++ * ________________________ ++ * MII TX clock from PHY >-----|___________ _________|----> to GMAC core ++ * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY ++ * Ext. 125MHz RGMII TX clk >--|__divider__/ | ++ * |________________________| ++ * ++ * The external 125 MHz reference is optional, i.e. GMAC can use its ++ * internal TX clock just fine. The A31 GMAC clock module does not have ++ * the divider controls for the external reference. ++ * ++ * To keep it simple, let the GMAC use either the MII TX clock for MII mode, ++ * and its internal TX clock for GMII and RGMII modes. The GMAC driver should ++ * select the appropriate source and gate/ungate the output to the PHY. ++ * ++ * Only the GMAC should use this clock. Altering the clock so that it doesn't ++ * match the GMAC's operation parameters will result in the GMAC not being ++ * able to send traffic out. The GMAC driver should set the clock rate and ++ * enable/disable this clock to configure the required state. The clock ++ * driver then responds by auto-reparenting the clock. ++ */ ++ ++#define SUN7I_A20_GMAC_GPIT 2 ++#define SUN7I_A20_GMAC_MASK 0x3 ++#define SUN7I_A20_GMAC_PARENTS 2 ++ ++static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ struct clk_mux *mux; ++ struct clk_gate *gate; ++ const char *clk_name = node->name; ++ const char *parents[SUN7I_A20_GMAC_PARENTS]; ++ void *reg; ++ ++ if (of_property_read_string(node, "clock-output-names", &clk_name)) ++ return; ++ ++ /* allocate mux and gate clock structs */ ++ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); ++ if (!mux) ++ return; ++ ++ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); ++ if (!gate) ++ goto free_mux; ++ ++ /* gmac clock requires exactly 2 parents */ ++ parents[0] = of_clk_get_parent_name(node, 0); ++ parents[1] = of_clk_get_parent_name(node, 1); ++ if (!parents[0] || !parents[1]) ++ goto free_gate; ++ ++ reg = of_iomap(node, 0); ++ if (!reg) ++ goto free_gate; ++ ++ /* set up gate and fixed rate properties */ ++ gate->reg = reg; ++ gate->bit_idx = SUN7I_A20_GMAC_GPIT; ++ gate->lock = &clk_lock; ++ mux->reg = reg; ++ mux->mask = SUN7I_A20_GMAC_MASK; ++ mux->flags = CLK_MUX_INDEX_BIT; ++ mux->lock = &clk_lock; ++ ++ clk = clk_register_composite(NULL, clk_name, ++ parents, SUN7I_A20_GMAC_PARENTS, ++ &mux->hw, &clk_mux_ops, ++ NULL, NULL, ++ &gate->hw, &clk_gate_ops, ++ 0); ++ ++ if (IS_ERR(clk)) ++ goto iounmap_reg; ++ ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ clk_register_clkdev(clk, clk_name, NULL); ++ ++ return; ++ ++iounmap_reg: ++ iounmap(reg); ++free_gate: ++ kfree(gate); ++free_mux: ++ kfree(mux); ++} ++CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", ++ sun7i_a20_gmac_clk_setup); ++ ++ ++ ++/** + * sunxi_factors_clk_setup() - Setup function for factor clocks + */ + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch b/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch new file mode 100644 index 0000000..5238534 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/254-dt-sun7i-change-32k-osc-nodename.patch @@ -0,0 +1,36 @@ +From 673fac742946bcb7cc43b9e67459862d6c4a8a6c Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai <wens@csie.org> +Date: Wed, 1 Jan 2014 10:30:47 +0800 +Subject: [PATCH] ARM: dts: sun7i: Change 32768 Hz oscillator node name to + clk@N style + +Device tree naming conventions state that node names should match +the nodes function. Change external low speed oscillator node name +to match. + +Signed-off-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 898b021..edad6f1 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -53,10 +53,11 @@ + clock-frequency = <24000000>; + }; + +- osc32k: osc32k { ++ osc32k: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; ++ clock-output-names = "osc32k"; + }; + + pll1: pll1@01c20000 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch b/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch new file mode 100644 index 0000000..6e220e9 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/255-clk-sunxi-add-a31-pll6.patch @@ -0,0 +1,111 @@ +From 92ef67c53ad92487c3c8de75e7940384c2edd793 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Wed, 5 Feb 2014 14:05:03 +0100 +Subject: [PATCH] clk: sunxi: Add support for PLL6 on the A31 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The A31 has a slightly different PLL6 clock. Add support for this new clock in +our driver. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Signed-off-by: Emilio López <emilio@elopez.com.ar> +--- + Documentation/devicetree/bindings/clock/sunxi.txt | 1 + + drivers/clk/sunxi/clk-sunxi.c | 45 +++++++++++++++++++++++ + 2 files changed, 46 insertions(+) + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index ca2b692..c37c764 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -11,6 +11,7 @@ Required properties: + "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 + "allwinner,sun4i-pll5-clk" - for the PLL5 clock + "allwinner,sun4i-pll6-clk" - for the PLL6 clock ++ "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 + "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock + "allwinner,sun4i-axi-clk" - for the AXI clock + "allwinner,sun4i-axi-gates-clk" - for the AXI gates +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index a779c31..d4cf297 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -252,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate, + *n = DIV_ROUND_UP(div, (*k+1)); + } + ++/** ++ * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 ++ * PLL6 rate is calculated as follows ++ * rate = parent_rate * n * (k + 1) / 2 ++ * parent_rate is always 24Mhz ++ */ ++ ++static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate, ++ u8 *n, u8 *k, u8 *m, u8 *p) ++{ ++ u8 div; ++ ++ /* ++ * We always have 24MHz / 2, so we can just say that our ++ * parent clock is 12MHz. ++ */ ++ parent_rate = parent_rate / 2; ++ ++ /* Normalize value to a parent_rate multiple (24M / 2) */ ++ div = *freq / parent_rate; ++ *freq = parent_rate * div; ++ ++ /* we were called to round the frequency, we can now return */ ++ if (n == NULL) ++ return; ++ ++ *k = div / 32; ++ if (*k > 3) ++ *k = 3; + ++ *n = DIV_ROUND_UP(div, (*k+1)); ++} + + /** + * sun4i_get_apb1_factors() - calculates m, p factors for APB1 +@@ -420,6 +451,13 @@ struct factors_data { + .kwidth = 2, + }; + ++static struct clk_factors_config sun6i_a31_pll6_config = { ++ .nshift = 8, ++ .nwidth = 5, ++ .kshift = 4, ++ .kwidth = 2, ++}; ++ + static struct clk_factors_config sun4i_apb1_config = { + .mshift = 0, + .mwidth = 5, +@@ -469,6 +507,12 @@ struct factors_data { + .name = "pll6", + }; + ++static const struct factors_data sun6i_a31_pll6_data __initconst = { ++ .enable = 31, ++ .table = &sun6i_a31_pll6_config, ++ .getter = sun6i_a31_get_pll6_factors, ++}; ++ + static const struct factors_data sun4i_apb1_data __initconst = { + .table = &sun4i_apb1_config, + .getter = sun4i_get_apb1_factors, +@@ -1069,6 +1113,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + static const struct of_device_id clk_factors_match[] __initconst = { + {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,}, + {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, ++ {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,}, + {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,}, + {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,}, + {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch b/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch new file mode 100644 index 0000000..8941125 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/260-spi-add-a31-spi-driver.patch @@ -0,0 +1,599 @@ +From 3558fe900e8af6c3bfadeff24a12ffb19ac9b108 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Wed, 5 Feb 2014 14:05:05 +0100 +Subject: [PATCH 1/2] spi: sunxi: Add Allwinner A31 SPI controller driver + +The Allwinner A31 has a new SPI controller IP compared to the older Allwinner +SoCs. + +It supports DMA, but the driver only does PIO for now, and DMA will be +supported eventually. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Signed-off-by: Mark Brown <broonie@linaro.org> +--- + .../devicetree/bindings/spi/spi-sun6i.txt | 24 + + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-sun6i.c | 483 +++++++++++++++++++++ + 4 files changed, 514 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt + create mode 100644 drivers/spi/spi-sun6i.c + +diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt b/Documentation/devicetree/bindings/spi/spi-sun6i.txt +new file mode 100644 +index 0000000..21de73d +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt +@@ -0,0 +1,24 @@ ++Allwinner A31 SPI controller ++ ++Required properties: ++- compatible: Should be "allwinner,sun6i-a31-spi". ++- reg: Should contain register location and length. ++- interrupts: Should contain interrupt. ++- clocks: phandle to the clocks feeding the SPI controller. Two are ++ needed: ++ - "ahb": the gated AHB parent clock ++ - "mod": the parent module clock ++- clock-names: Must contain the clock names described just above ++- resets: phandle to the reset controller asserting this device in ++ reset ++ ++Example: ++ ++spi1: spi@01c69000 { ++ compatible = "allwinner,sun6i-a31-spi"; ++ reg = <0x01c69000 0x1000>; ++ interrupts = <0 66 4>; ++ clocks = <&ahb1_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ resets = <&ahb1_rst 21>; ++}; +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index ba9310b..7cfe0ee 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -446,6 +446,12 @@ config SPI_SIRF + help + SPI driver for CSR SiRFprimaII SoCs + ++config SPI_SUN6I ++ tristate "Allwinner A31 SPI controller" ++ depends on ARCH_SUNXI || COMPILE_TEST ++ help ++ This enables using the SPI controller on the Allwinner A31 SoCs. ++ + config SPI_MXS + tristate "Freescale MXS SPI controller" + depends on ARCH_MXS +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 95af48d..13b6ccf 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -70,6 +70,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o + obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o + obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o + obj-$(CONFIG_SPI_SIRF) += spi-sirf.o ++obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o + obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o + obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o + obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o +diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c +new file mode 100644 +index 0000000..94d38d0 +--- /dev/null ++++ b/drivers/spi/spi-sun6i.c +@@ -0,0 +1,483 @@ ++/* ++ * Copyright (C) 2012 - 2014 Allwinner Tech ++ * Pan Nan <pannan@allwinnertech.com> ++ * ++ * Copyright (C) 2014 Maxime Ripard ++ * Maxime Ripard <maxime.ripard@free-electrons.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/device.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/reset.h> ++#include <linux/workqueue.h> ++ ++#include <linux/spi/spi.h> ++ ++#define SUN6I_FIFO_DEPTH 128 ++ ++#define SUN6I_GBL_CTL_REG 0x04 ++#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0) ++#define SUN6I_GBL_CTL_MASTER BIT(1) ++#define SUN6I_GBL_CTL_TP BIT(7) ++#define SUN6I_GBL_CTL_RST BIT(31) ++ ++#define SUN6I_TFR_CTL_REG 0x08 ++#define SUN6I_TFR_CTL_CPHA BIT(0) ++#define SUN6I_TFR_CTL_CPOL BIT(1) ++#define SUN6I_TFR_CTL_SPOL BIT(2) ++#define SUN6I_TFR_CTL_CS_MASK 0x3 ++#define SUN6I_TFR_CTL_CS(cs) (((cs) & SUN6I_TFR_CTL_CS_MASK) << 4) ++#define SUN6I_TFR_CTL_CS_MANUAL BIT(6) ++#define SUN6I_TFR_CTL_CS_LEVEL BIT(7) ++#define SUN6I_TFR_CTL_DHB BIT(8) ++#define SUN6I_TFR_CTL_FBS BIT(12) ++#define SUN6I_TFR_CTL_XCH BIT(31) ++ ++#define SUN6I_INT_CTL_REG 0x10 ++#define SUN6I_INT_CTL_RF_OVF BIT(8) ++#define SUN6I_INT_CTL_TC BIT(12) ++ ++#define SUN6I_INT_STA_REG 0x14 ++ ++#define SUN6I_FIFO_CTL_REG 0x18 ++#define SUN6I_FIFO_CTL_RF_RST BIT(15) ++#define SUN6I_FIFO_CTL_TF_RST BIT(31) ++ ++#define SUN6I_FIFO_STA_REG 0x1c ++#define SUN6I_FIFO_STA_RF_CNT_MASK 0x7f ++#define SUN6I_FIFO_STA_RF_CNT_BITS 0 ++#define SUN6I_FIFO_STA_TF_CNT_MASK 0x7f ++#define SUN6I_FIFO_STA_TF_CNT_BITS 16 ++ ++#define SUN6I_CLK_CTL_REG 0x24 ++#define SUN6I_CLK_CTL_CDR2_MASK 0xff ++#define SUN6I_CLK_CTL_CDR2(div) (((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0) ++#define SUN6I_CLK_CTL_CDR1_MASK 0xf ++#define SUN6I_CLK_CTL_CDR1(div) (((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8) ++#define SUN6I_CLK_CTL_DRS BIT(12) ++ ++#define SUN6I_BURST_CNT_REG 0x30 ++#define SUN6I_BURST_CNT(cnt) ((cnt) & 0xffffff) ++ ++#define SUN6I_XMIT_CNT_REG 0x34 ++#define SUN6I_XMIT_CNT(cnt) ((cnt) & 0xffffff) ++ ++#define SUN6I_BURST_CTL_CNT_REG 0x38 ++#define SUN6I_BURST_CTL_CNT_STC(cnt) ((cnt) & 0xffffff) ++ ++#define SUN6I_TXDATA_REG 0x200 ++#define SUN6I_RXDATA_REG 0x300 ++ ++struct sun6i_spi { ++ struct spi_master *master; ++ void __iomem *base_addr; ++ struct clk *hclk; ++ struct clk *mclk; ++ struct reset_control *rstc; ++ ++ struct completion done; ++ ++ const u8 *tx_buf; ++ u8 *rx_buf; ++ int len; ++}; ++ ++static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) ++{ ++ return readl(sspi->base_addr + reg); ++} ++ ++static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value) ++{ ++ writel(value, sspi->base_addr + reg); ++} ++ ++static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len) ++{ ++ u32 reg, cnt; ++ u8 byte; ++ ++ /* See how much data is available */ ++ reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG); ++ reg &= SUN6I_FIFO_STA_RF_CNT_MASK; ++ cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS; ++ ++ if (len > cnt) ++ len = cnt; ++ ++ while (len--) { ++ byte = readb(sspi->base_addr + SUN6I_RXDATA_REG); ++ if (sspi->rx_buf) ++ *sspi->rx_buf++ = byte; ++ } ++} ++ ++static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len) ++{ ++ u8 byte; ++ ++ if (len > sspi->len) ++ len = sspi->len; ++ ++ while (len--) { ++ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0; ++ writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG); ++ sspi->len--; ++ } ++} ++ ++static void sun6i_spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct sun6i_spi *sspi = spi_master_get_devdata(spi->master); ++ u32 reg; ++ ++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); ++ reg &= ~SUN6I_TFR_CTL_CS_MASK; ++ reg |= SUN6I_TFR_CTL_CS(spi->chip_select); ++ ++ if (enable) ++ reg |= SUN6I_TFR_CTL_CS_LEVEL; ++ else ++ reg &= ~SUN6I_TFR_CTL_CS_LEVEL; ++ ++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); ++} ++ ++ ++static int sun6i_spi_transfer_one(struct spi_master *master, ++ struct spi_device *spi, ++ struct spi_transfer *tfr) ++{ ++ struct sun6i_spi *sspi = spi_master_get_devdata(master); ++ unsigned int mclk_rate, div, timeout; ++ unsigned int tx_len = 0; ++ int ret = 0; ++ u32 reg; ++ ++ /* We don't support transfer larger than the FIFO */ ++ if (tfr->len > SUN6I_FIFO_DEPTH) ++ return -EINVAL; ++ ++ reinit_completion(&sspi->done); ++ sspi->tx_buf = tfr->tx_buf; ++ sspi->rx_buf = tfr->rx_buf; ++ sspi->len = tfr->len; ++ ++ /* Clear pending interrupts */ ++ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0); ++ ++ /* Reset FIFO */ ++ sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, ++ SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST); ++ ++ /* ++ * Setup the transfer control register: Chip Select, ++ * polarities, etc. ++ */ ++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); ++ ++ if (spi->mode & SPI_CPOL) ++ reg |= SUN6I_TFR_CTL_CPOL; ++ else ++ reg &= ~SUN6I_TFR_CTL_CPOL; ++ ++ if (spi->mode & SPI_CPHA) ++ reg |= SUN6I_TFR_CTL_CPHA; ++ else ++ reg &= ~SUN6I_TFR_CTL_CPHA; ++ ++ if (spi->mode & SPI_LSB_FIRST) ++ reg |= SUN6I_TFR_CTL_FBS; ++ else ++ reg &= ~SUN6I_TFR_CTL_FBS; ++ ++ /* ++ * If it's a TX only transfer, we don't want to fill the RX ++ * FIFO with bogus data ++ */ ++ if (sspi->rx_buf) ++ reg &= ~SUN6I_TFR_CTL_DHB; ++ else ++ reg |= SUN6I_TFR_CTL_DHB; ++ ++ /* We want to control the chip select manually */ ++ reg |= SUN6I_TFR_CTL_CS_MANUAL; ++ ++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); ++ ++ /* Ensure that we have a parent clock fast enough */ ++ mclk_rate = clk_get_rate(sspi->mclk); ++ if (mclk_rate < (2 * spi->max_speed_hz)) { ++ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); ++ mclk_rate = clk_get_rate(sspi->mclk); ++ } ++ ++ /* ++ * Setup clock divider. ++ * ++ * We have two choices there. Either we can use the clock ++ * divide rate 1, which is calculated thanks to this formula: ++ * SPI_CLK = MOD_CLK / (2 ^ cdr) ++ * Or we can use CDR2, which is calculated with the formula: ++ * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) ++ * Wether we use the former or the latter is set through the ++ * DRS bit. ++ * ++ * First try CDR2, and if we can't reach the expected ++ * frequency, fall back to CDR1. ++ */ ++ div = mclk_rate / (2 * spi->max_speed_hz); ++ if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { ++ if (div > 0) ++ div--; ++ ++ reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS; ++ } else { ++ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); ++ reg = SUN6I_CLK_CTL_CDR1(div); ++ } ++ ++ sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); ++ ++ /* Setup the transfer now... */ ++ if (sspi->tx_buf) ++ tx_len = tfr->len; ++ ++ /* Setup the counters */ ++ sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len)); ++ sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len)); ++ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, ++ SUN6I_BURST_CTL_CNT_STC(tx_len)); ++ ++ /* Fill the TX FIFO */ ++ sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH); ++ ++ /* Enable the interrupts */ ++ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC); ++ ++ /* Start the transfer */ ++ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); ++ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH); ++ ++ timeout = wait_for_completion_timeout(&sspi->done, ++ msecs_to_jiffies(1000)); ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH); ++ ++out: ++ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); ++ ++ return ret; ++} ++ ++static irqreturn_t sun6i_spi_handler(int irq, void *dev_id) ++{ ++ struct sun6i_spi *sspi = dev_id; ++ u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG); ++ ++ /* Transfer complete */ ++ if (status & SUN6I_INT_CTL_TC) { ++ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC); ++ complete(&sspi->done); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static int sun6i_spi_runtime_resume(struct device *dev) ++{ ++ struct spi_master *master = dev_get_drvdata(dev); ++ struct sun6i_spi *sspi = spi_master_get_devdata(master); ++ int ret; ++ ++ ret = clk_prepare_enable(sspi->hclk); ++ if (ret) { ++ dev_err(dev, "Couldn't enable AHB clock\n"); ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(sspi->mclk); ++ if (ret) { ++ dev_err(dev, "Couldn't enable module clock\n"); ++ goto err; ++ } ++ ++ ret = reset_control_deassert(sspi->rstc); ++ if (ret) { ++ dev_err(dev, "Couldn't deassert the device from reset\n"); ++ goto err2; ++ } ++ ++ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, ++ SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP); ++ ++ return 0; ++ ++err2: ++ clk_disable_unprepare(sspi->mclk); ++err: ++ clk_disable_unprepare(sspi->hclk); ++out: ++ return ret; ++} ++ ++static int sun6i_spi_runtime_suspend(struct device *dev) ++{ ++ struct spi_master *master = dev_get_drvdata(dev); ++ struct sun6i_spi *sspi = spi_master_get_devdata(master); ++ ++ reset_control_assert(sspi->rstc); ++ clk_disable_unprepare(sspi->mclk); ++ clk_disable_unprepare(sspi->hclk); ++ ++ return 0; ++} ++ ++static int sun6i_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct sun6i_spi *sspi; ++ struct resource *res; ++ int ret = 0, irq; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi)); ++ if (!master) { ++ dev_err(&pdev->dev, "Unable to allocate SPI Master\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, master); ++ sspi = spi_master_get_devdata(master); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(sspi->base_addr)) { ++ ret = PTR_ERR(sspi->base_addr); ++ goto err_free_master; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "No spi IRQ specified\n"); ++ ret = -ENXIO; ++ goto err_free_master; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler, ++ 0, "sun6i-spi", sspi); ++ if (ret) { ++ dev_err(&pdev->dev, "Cannot request IRQ\n"); ++ goto err_free_master; ++ } ++ ++ sspi->master = master; ++ master->set_cs = sun6i_spi_set_cs; ++ master->transfer_one = sun6i_spi_transfer_one; ++ master->num_chipselect = 4; ++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; ++ master->dev.of_node = pdev->dev.of_node; ++ master->auto_runtime_pm = true; ++ ++ sspi->hclk = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(sspi->hclk)) { ++ dev_err(&pdev->dev, "Unable to acquire AHB clock\n"); ++ ret = PTR_ERR(sspi->hclk); ++ goto err_free_master; ++ } ++ ++ sspi->mclk = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(sspi->mclk)) { ++ dev_err(&pdev->dev, "Unable to acquire module clock\n"); ++ ret = PTR_ERR(sspi->mclk); ++ goto err_free_master; ++ } ++ ++ init_completion(&sspi->done); ++ ++ sspi->rstc = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(sspi->rstc)) { ++ dev_err(&pdev->dev, "Couldn't get reset controller\n"); ++ ret = PTR_ERR(sspi->rstc); ++ goto err_free_master; ++ } ++ ++ /* ++ * This wake-up/shutdown pattern is to be able to have the ++ * device woken up, even if runtime_pm is disabled ++ */ ++ ret = sun6i_spi_runtime_resume(&pdev->dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't resume the device\n"); ++ goto err_free_master; ++ } ++ ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_idle(&pdev->dev); ++ ++ ret = devm_spi_register_master(&pdev->dev, master); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot register SPI master\n"); ++ goto err_pm_disable; ++ } ++ ++ return 0; ++ ++err_pm_disable: ++ pm_runtime_disable(&pdev->dev); ++ sun6i_spi_runtime_suspend(&pdev->dev); ++err_free_master: ++ spi_master_put(master); ++ return ret; ++} ++ ++static int sun6i_spi_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id sun6i_spi_match[] = { ++ { .compatible = "allwinner,sun6i-a31-spi", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sun6i_spi_match); ++ ++static const struct dev_pm_ops sun6i_spi_pm_ops = { ++ .runtime_resume = sun6i_spi_runtime_resume, ++ .runtime_suspend = sun6i_spi_runtime_suspend, ++}; ++ ++static struct platform_driver sun6i_spi_driver = { ++ .probe = sun6i_spi_probe, ++ .remove = sun6i_spi_remove, ++ .driver = { ++ .name = "sun6i-spi", ++ .owner = THIS_MODULE, ++ .of_match_table = sun6i_spi_match, ++ .pm = &sun6i_spi_pm_ops, ++ }, ++}; ++module_platform_driver(sun6i_spi_driver); ++ ++MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>"); ++MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); ++MODULE_DESCRIPTION("Allwinner A31 SPI controller driver"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.5 + + +From 7961656a6f11b69966500d7bd25273203fd930da Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@linaro.org> +Date: Thu, 6 Feb 2014 10:53:51 +0000 +Subject: [PATCH 2/2] spi/sunxi: Add missing dependency on RESET_CONTROLLER + +Signed-off-by: Mark Brown <broonie@linaro.org> +--- + drivers/spi/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 7cfe0ee..0ec4641 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -449,6 +449,7 @@ config SPI_SIRF + config SPI_SUN6I + tristate "Allwinner A31 SPI controller" + depends on ARCH_SUNXI || COMPILE_TEST ++ depends on RESET_CONTROLLER + help + This enables using the SPI controller on the Allwinner A31 SoCs. + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch b/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch new file mode 100644 index 0000000..78475fc --- /dev/null +++ b/target/linux/sunxi/patches-3.13/261-dt-sun6i-add-pll6-and-spi.patch @@ -0,0 +1,82 @@ +From b0a09c756bf6e0b89d6b88a7620ba4cd86b1895b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Wed, 5 Feb 2014 14:05:04 +0100 +Subject: [PATCH] ARM: sun6i: dt: Add PLL6 and SPI module clocks + +The module clocks in the A31 are still compatible with the A10 one. Add the SPI +module clocks and the PLL6 in the device tree to allow their use by the SPI +controllers. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 46 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 37 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index 092bf97..93d7bb6 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -83,16 +83,12 @@ + clocks = <&osc24M>; + }; + +- /* +- * This is a dummy clock, to be used as placeholder on +- * other mux clocks when a specific parent clock is not +- * yet implemented. It should be dropped when the driver +- * is complete. +- */ +- pll6: pll6 { ++ pll6: clk@01c20028 { + #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <0>; ++ compatible = "allwinner,sun6i-a31-pll6-clk"; ++ reg = <0x01c20028 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll6"; + }; + + cpu: cpu@01c20050 { +@@ -192,6 +188,38 @@ + "apb2_uart1", "apb2_uart2", "apb2_uart3", + "apb2_uart4", "apb2_uart5"; + }; ++ ++ spi0_clk: clk@01c200a0 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a0 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "spi0"; ++ }; ++ ++ spi1_clk: clk@01c200a4 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a4 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "spi1"; ++ }; ++ ++ spi2_clk: clk@01c200a8 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200a8 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "spi2"; ++ }; ++ ++ spi3_clk: clk@01c200ac { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-mod0-clk"; ++ reg = <0x01c200ac 0x4>; ++ clocks = <&osc24M>, <&pll6>; ++ clock-output-names = "spi3"; ++ }; + }; + + soc@01c00000 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch b/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch new file mode 100644 index 0000000..be2cce5 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/262-spi-add-a10-spi-driver.patch @@ -0,0 +1,571 @@ +From 67e7ba38902a28679bf6ee8fd82952ae6795f5f5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:53 +0100 +Subject: [PATCH] spi: sunxi: Add Allwinner A10 SPI controller driver + +The older Allwinner SoCs (A10, A13, A10s and A20) all have the same SPI +controller. + +Unfortunately, this SPI controller, even though quite similar, is significantly +different from the recently supported A31 SPI controller (different registers +offset, split/merged registers, etc.). Supporting both controllers in a single +driver would be unreasonable, hence the addition of a new driver. + +Like its more recent counterpart, it supports DMA, but the driver only does PIO +until we have a dmaengine driver for this platform. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + .../devicetree/bindings/spi/spi-sun4i.txt | 24 ++ + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-sun4i.c | 477 +++++++++++++++++++++ + 4 files changed, 508 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/spi-sun4i.txt + create mode 100644 drivers/spi/spi-sun4i.c + +diff --git a/Documentation/devicetree/bindings/spi/spi-sun4i.txt b/Documentation/devicetree/bindings/spi/spi-sun4i.txt +new file mode 100644 +index 0000000..de827f5 +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-sun4i.txt +@@ -0,0 +1,24 @@ ++Allwinner A10 SPI controller ++ ++Required properties: ++- compatible: Should be "allwinner,sun4-a10-spi". ++- reg: Should contain register location and length. ++- interrupts: Should contain interrupt. ++- clocks: phandle to the clocks feeding the SPI controller. Two are ++ needed: ++ - "ahb": the gated AHB parent clock ++ - "mod": the parent module clock ++- clock-names: Must contain the clock names described just above ++ ++Example: ++ ++spi1: spi@01c06000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c06000 0x1000>; ++ interrupts = <11>; ++ clocks = <&ahb_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++}; +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 58530d3..78adfae 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -446,6 +446,12 @@ config SPI_SIRF + help + SPI driver for CSR SiRFprimaII SoCs + ++config SPI_SUN4I ++ tristate "Allwinner A10 SoCs SPI controller" ++ depends on ARCH_SUNXI || COMPILE_TEST ++ help ++ SPI driver for Allwinner sun4i, sun5i and sun7i SoCs ++ + config SPI_SUN6I + tristate "Allwinner A31 SPI controller" + depends on ARCH_SUNXI || COMPILE_TEST +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 13b6ccf..65f4993 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -70,6 +70,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o + obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o + obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o + obj-$(CONFIG_SPI_SIRF) += spi-sirf.o ++obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o + obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o + obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o + obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o +diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c +new file mode 100644 +index 0000000..3f82705 +--- /dev/null ++++ b/drivers/spi/spi-sun4i.c +@@ -0,0 +1,477 @@ ++/* ++ * Copyright (C) 2012 - 2014 Allwinner Tech ++ * Pan Nan <pannan@allwinnertech.com> ++ * ++ * Copyright (C) 2014 Maxime Ripard ++ * Maxime Ripard <maxime.ripard@free-electrons.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/device.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/workqueue.h> ++ ++#include <linux/spi/spi.h> ++ ++#define SUN4I_FIFO_DEPTH 64 ++ ++#define SUN4I_RXDATA_REG 0x00 ++ ++#define SUN4I_TXDATA_REG 0x04 ++ ++#define SUN4I_CTL_REG 0x08 ++#define SUN4I_CTL_ENABLE BIT(0) ++#define SUN4I_CTL_MASTER BIT(1) ++#define SUN4I_CTL_CPHA BIT(2) ++#define SUN4I_CTL_CPOL BIT(3) ++#define SUN4I_CTL_CS_ACTIVE_LOW BIT(4) ++#define SUN4I_CTL_LMTF BIT(6) ++#define SUN4I_CTL_TF_RST BIT(8) ++#define SUN4I_CTL_RF_RST BIT(9) ++#define SUN4I_CTL_XCH BIT(10) ++#define SUN4I_CTL_CS_MASK 0x3000 ++#define SUN4I_CTL_CS(cs) (((cs) << 12) & SUN4I_CTL_CS_MASK) ++#define SUN4I_CTL_DHB BIT(15) ++#define SUN4I_CTL_CS_MANUAL BIT(16) ++#define SUN4I_CTL_CS_LEVEL BIT(17) ++#define SUN4I_CTL_TP BIT(18) ++ ++#define SUN4I_INT_CTL_REG 0x0c ++#define SUN4I_INT_CTL_TC BIT(16) ++ ++#define SUN4I_INT_STA_REG 0x10 ++ ++#define SUN4I_DMA_CTL_REG 0x14 ++ ++#define SUN4I_WAIT_REG 0x18 ++ ++#define SUN4I_CLK_CTL_REG 0x1c ++#define SUN4I_CLK_CTL_CDR2_MASK 0xff ++#define SUN4I_CLK_CTL_CDR2(div) ((div) & SUN4I_CLK_CTL_CDR2_MASK) ++#define SUN4I_CLK_CTL_CDR1_MASK 0xf ++#define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8) ++#define SUN4I_CLK_CTL_DRS BIT(12) ++ ++#define SUN4I_BURST_CNT_REG 0x20 ++#define SUN4I_BURST_CNT(cnt) ((cnt) & 0xffffff) ++ ++#define SUN4I_XMIT_CNT_REG 0x24 ++#define SUN4I_XMIT_CNT(cnt) ((cnt) & 0xffffff) ++ ++#define SUN4I_FIFO_STA_REG 0x28 ++#define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f ++#define SUN4I_FIFO_STA_RF_CNT_BITS 0 ++#define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f ++#define SUN4I_FIFO_STA_TF_CNT_BITS 16 ++ ++struct sun4i_spi { ++ struct spi_master *master; ++ void __iomem *base_addr; ++ struct clk *hclk; ++ struct clk *mclk; ++ ++ struct completion done; ++ ++ const u8 *tx_buf; ++ u8 *rx_buf; ++ int len; ++}; ++ ++static inline u32 sun4i_spi_read(struct sun4i_spi *sspi, u32 reg) ++{ ++ return readl(sspi->base_addr + reg); ++} ++ ++static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value) ++{ ++ writel(value, sspi->base_addr + reg); ++} ++ ++static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len) ++{ ++ u32 reg, cnt; ++ u8 byte; ++ ++ /* See how much data is available */ ++ reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG); ++ reg &= SUN4I_FIFO_STA_RF_CNT_MASK; ++ cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS; ++ ++ if (len > cnt) ++ len = cnt; ++ ++ while (len--) { ++ byte = readb(sspi->base_addr + SUN4I_RXDATA_REG); ++ if (sspi->rx_buf) ++ *sspi->rx_buf++ = byte; ++ } ++} ++ ++static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len) ++{ ++ u8 byte; ++ ++ if (len > sspi->len) ++ len = sspi->len; ++ ++ while (len--) { ++ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0; ++ writeb(byte, sspi->base_addr + SUN4I_TXDATA_REG); ++ sspi->len--; ++ } ++} ++ ++static void sun4i_spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct sun4i_spi *sspi = spi_master_get_devdata(spi->master); ++ u32 reg; ++ ++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); ++ ++ reg &= ~SUN4I_CTL_CS_MASK; ++ reg |= SUN4I_CTL_CS(spi->chip_select); ++ ++ if (enable) ++ reg |= SUN4I_CTL_CS_LEVEL; ++ else ++ reg &= ~SUN4I_CTL_CS_LEVEL; ++ ++ /* ++ * Even though this looks irrelevant since we are supposed to ++ * be controlling the chip select manually, this bit also ++ * controls the levels of the chip select for inactive ++ * devices. ++ * ++ * If we don't set it, the chip select level will go low by ++ * default when the device is idle, which is not really ++ * expected in the common case where the chip select is active ++ * low. ++ */ ++ if (spi->mode & SPI_CS_HIGH) ++ reg &= ~SUN4I_CTL_CS_ACTIVE_LOW; ++ else ++ reg |= SUN4I_CTL_CS_ACTIVE_LOW; ++ ++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); ++} ++ ++static int sun4i_spi_transfer_one(struct spi_master *master, ++ struct spi_device *spi, ++ struct spi_transfer *tfr) ++{ ++ struct sun4i_spi *sspi = spi_master_get_devdata(master); ++ unsigned int mclk_rate, div, timeout; ++ unsigned int tx_len = 0; ++ int ret = 0; ++ u32 reg; ++ ++ /* We don't support transfer larger than the FIFO */ ++ if (tfr->len > SUN4I_FIFO_DEPTH) ++ return -EINVAL; ++ ++ reinit_completion(&sspi->done); ++ sspi->tx_buf = tfr->tx_buf; ++ sspi->rx_buf = tfr->rx_buf; ++ sspi->len = tfr->len; ++ ++ /* Clear pending interrupts */ ++ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0); ++ ++ ++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); ++ ++ /* Reset FIFOs */ ++ sun4i_spi_write(sspi, SUN4I_CTL_REG, ++ reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST); ++ ++ /* ++ * Setup the transfer control register: Chip Select, ++ * polarities, etc. ++ */ ++ if (spi->mode & SPI_CPOL) ++ reg |= SUN4I_CTL_CPOL; ++ else ++ reg &= ~SUN4I_CTL_CPOL; ++ ++ if (spi->mode & SPI_CPHA) ++ reg |= SUN4I_CTL_CPHA; ++ else ++ reg &= ~SUN4I_CTL_CPHA; ++ ++ if (spi->mode & SPI_LSB_FIRST) ++ reg |= SUN4I_CTL_LMTF; ++ else ++ reg &= ~SUN4I_CTL_LMTF; ++ ++ ++ /* ++ * If it's a TX only transfer, we don't want to fill the RX ++ * FIFO with bogus data ++ */ ++ if (sspi->rx_buf) ++ reg &= ~SUN4I_CTL_DHB; ++ else ++ reg |= SUN4I_CTL_DHB; ++ ++ /* We want to control the chip select manually */ ++ reg |= SUN4I_CTL_CS_MANUAL; ++ ++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); ++ ++ /* Ensure that we have a parent clock fast enough */ ++ mclk_rate = clk_get_rate(sspi->mclk); ++ if (mclk_rate < (2 * spi->max_speed_hz)) { ++ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); ++ mclk_rate = clk_get_rate(sspi->mclk); ++ } ++ ++ /* ++ * Setup clock divider. ++ * ++ * We have two choices there. Either we can use the clock ++ * divide rate 1, which is calculated thanks to this formula: ++ * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) ++ * Or we can use CDR2, which is calculated with the formula: ++ * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) ++ * Wether we use the former or the latter is set through the ++ * DRS bit. ++ * ++ * First try CDR2, and if we can't reach the expected ++ * frequency, fall back to CDR1. ++ */ ++ div = mclk_rate / (2 * spi->max_speed_hz); ++ if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { ++ if (div > 0) ++ div--; ++ ++ reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; ++ } else { ++ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); ++ reg = SUN4I_CLK_CTL_CDR1(div); ++ } ++ ++ sun4i_spi_write(sspi, SUN4I_CLK_CTL_REG, reg); ++ ++ /* Setup the transfer now... */ ++ if (sspi->tx_buf) ++ tx_len = tfr->len; ++ ++ /* Setup the counters */ ++ sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len)); ++ sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len)); ++ ++ /* Fill the TX FIFO */ ++ sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH); ++ ++ /* Enable the interrupts */ ++ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC); ++ ++ /* Start the transfer */ ++ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); ++ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH); ++ ++ timeout = wait_for_completion_timeout(&sspi->done, ++ msecs_to_jiffies(1000)); ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); ++ ++out: ++ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); ++ ++ return ret; ++} ++ ++static irqreturn_t sun4i_spi_handler(int irq, void *dev_id) ++{ ++ struct sun4i_spi *sspi = dev_id; ++ u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG); ++ ++ /* Transfer complete */ ++ if (status & SUN4I_INT_CTL_TC) { ++ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC); ++ complete(&sspi->done); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static int sun4i_spi_runtime_resume(struct device *dev) ++{ ++ struct spi_master *master = dev_get_drvdata(dev); ++ struct sun4i_spi *sspi = spi_master_get_devdata(master); ++ int ret; ++ ++ ret = clk_prepare_enable(sspi->hclk); ++ if (ret) { ++ dev_err(dev, "Couldn't enable AHB clock\n"); ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(sspi->mclk); ++ if (ret) { ++ dev_err(dev, "Couldn't enable module clock\n"); ++ goto err; ++ } ++ ++ sun4i_spi_write(sspi, SUN4I_CTL_REG, ++ SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP); ++ ++ return 0; ++ ++err: ++ clk_disable_unprepare(sspi->hclk); ++out: ++ return ret; ++} ++ ++static int sun4i_spi_runtime_suspend(struct device *dev) ++{ ++ struct spi_master *master = dev_get_drvdata(dev); ++ struct sun4i_spi *sspi = spi_master_get_devdata(master); ++ ++ clk_disable_unprepare(sspi->mclk); ++ clk_disable_unprepare(sspi->hclk); ++ ++ return 0; ++} ++ ++static int sun4i_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct sun4i_spi *sspi; ++ struct resource *res; ++ int ret = 0, irq; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi)); ++ if (!master) { ++ dev_err(&pdev->dev, "Unable to allocate SPI Master\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, master); ++ sspi = spi_master_get_devdata(master); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(sspi->base_addr)) { ++ ret = PTR_ERR(sspi->base_addr); ++ goto err_free_master; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "No spi IRQ specified\n"); ++ ret = -ENXIO; ++ goto err_free_master; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler, ++ 0, "sun4i-spi", sspi); ++ if (ret) { ++ dev_err(&pdev->dev, "Cannot request IRQ\n"); ++ goto err_free_master; ++ } ++ ++ sspi->master = master; ++ master->set_cs = sun4i_spi_set_cs; ++ master->transfer_one = sun4i_spi_transfer_one; ++ master->num_chipselect = 4; ++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; ++ master->dev.of_node = pdev->dev.of_node; ++ master->auto_runtime_pm = true; ++ ++ sspi->hclk = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(sspi->hclk)) { ++ dev_err(&pdev->dev, "Unable to acquire AHB clock\n"); ++ ret = PTR_ERR(sspi->hclk); ++ goto err_free_master; ++ } ++ ++ sspi->mclk = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(sspi->mclk)) { ++ dev_err(&pdev->dev, "Unable to acquire module clock\n"); ++ ret = PTR_ERR(sspi->mclk); ++ goto err_free_master; ++ } ++ ++ init_completion(&sspi->done); ++ ++ /* ++ * This wake-up/shutdown pattern is to be able to have the ++ * device woken up, even if runtime_pm is disabled ++ */ ++ ret = sun4i_spi_runtime_resume(&pdev->dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't resume the device\n"); ++ goto err_free_master; ++ } ++ ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_idle(&pdev->dev); ++ ++ ret = devm_spi_register_master(&pdev->dev, master); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot register SPI master\n"); ++ goto err_pm_disable; ++ } ++ ++ return 0; ++ ++err_pm_disable: ++ pm_runtime_disable(&pdev->dev); ++ sun4i_spi_runtime_suspend(&pdev->dev); ++err_free_master: ++ spi_master_put(master); ++ return ret; ++} ++ ++static int sun4i_spi_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id sun4i_spi_match[] = { ++ { .compatible = "allwinner,sun4i-a10-spi", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sun4i_spi_match); ++ ++static const struct dev_pm_ops sun4i_spi_pm_ops = { ++ .runtime_resume = sun4i_spi_runtime_resume, ++ .runtime_suspend = sun4i_spi_runtime_suspend, ++}; ++ ++static struct platform_driver sun4i_spi_driver = { ++ .probe = sun4i_spi_probe, ++ .remove = sun4i_spi_remove, ++ .driver = { ++ .name = "sun4i-spi", ++ .owner = THIS_MODULE, ++ .of_match_table = sun4i_spi_match, ++ .pm = &sun4i_spi_pm_ops, ++ }, ++}; ++module_platform_driver(sun4i_spi_driver); ++ ++MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>"); ++MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); ++MODULE_DESCRIPTION("Allwinner A1X/A20 SPI controller driver"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch b/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch new file mode 100644 index 0000000..8d43f62 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/263-1-dt-sun7i-add-a20-spi.patch @@ -0,0 +1,85 @@ +From 3fff6e0d2bdd3b3f999a9dfcc8432ecba56eaad8 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:54 +0100 +Subject: [PATCH] ARM: dt: sun7i: Add A20 SPI controller nodes + +The A20 has 4 SPI controllers compatible with the one found in the A10. Add +them in the DT. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 1961751..bcea04a 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -393,6 +393,28 @@ + #size-cells = <1>; + ranges; + ++ spi0: spi@01c05000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c05000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&ahb_gates 20>, <&spi0_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@01c06000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c06000 0x1000>; ++ interrupts = <0 11 4>; ++ clocks = <&ahb_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + emac: ethernet@01c0b000 { + compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; +@@ -485,6 +507,17 @@ + status = "disabled"; + }; + ++ spi2: spi@01c17000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c17000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&ahb_gates 22>, <&spi2_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -513,6 +546,17 @@ + status = "disabled"; + }; + ++ spi3: spi@01c1f000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c1f000 0x1000>; ++ interrupts = <0 50 4>; ++ clocks = <&ahb_gates 23>, <&spi3_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + pio: pinctrl@01c20800 { + compatible = "allwinner,sun7i-a20-pinctrl"; + reg = <0x01c20800 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch new file mode 100644 index 0000000..4848688 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/263-2-dt-sun4i-add-a10-spi.patch @@ -0,0 +1,84 @@ +From f21f034bd5b288068e1fa35c28d5e48e9ae8cbf5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:55 +0100 +Subject: [PATCH] ARM: dt: sun4i: Add A10 SPI controller nodes + +The A10 has 4 SPI controllers that are now supported. Add them in the DT. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 3a5775c..cdd5b72 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -331,6 +331,28 @@ + #size-cells = <1>; + ranges; + ++ spi0: spi@01c05000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c05000 0x1000>; ++ interrupts = <10>; ++ clocks = <&ahb_gates 20>, <&spi0_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@01c06000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c06000 0x1000>; ++ interrupts = <11>; ++ clocks = <&ahb_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + emac: ethernet@01c0b000 { + compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; +@@ -423,6 +445,17 @@ + status = "disabled"; + }; + ++ spi2: spi@01c17000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c17000 0x1000>; ++ interrupts = <12>; ++ clocks = <&ahb_gates 22>, <&spi2_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + ahci: sata@01c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; +@@ -451,6 +484,17 @@ + status = "disabled"; + }; + ++ spi3: spi@01c1f000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c1f000 0x1000>; ++ interrupts = <50>; ++ clocks = <&ahb_gates 23>, <&spi3_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch new file mode 100644 index 0000000..46ee7d2 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/263-3-dt-sun5i-a10s-add-a10-spi.patch @@ -0,0 +1,67 @@ +From f76e72a20510fa17934c82bed5e23f7c4a4f2931 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:56 +0100 +Subject: [PATCH] ARM: dt: sun5i: Add A10s SPI controller nodes + +The A10s has 3 SPI controllers compatible with the one found in the A10. Add +them in the DT. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index e5064dc..2dedb7c 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -292,6 +292,28 @@ + #size-cells = <1>; + ranges; + ++ spi0: spi@01c05000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c05000 0x1000>; ++ interrupts = <10>; ++ clocks = <&ahb_gates 20>, <&spi0_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@01c06000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c06000 0x1000>; ++ interrupts = <11>; ++ clocks = <&ahb_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + emac: ethernet@01c0b000 { + compatible = "allwinner,sun4i-a10-emac"; + reg = <0x01c0b000 0x1000>; +@@ -373,6 +395,17 @@ + status = "disabled"; + }; + ++ spi2: spi@01c17000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c17000 0x1000>; ++ interrupts = <12>; ++ clocks = <&ahb_gates 22>, <&spi2_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch b/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch new file mode 100644 index 0000000..30bec68 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/263-4-dt-sun5i-a13-add-a10-spi.patch @@ -0,0 +1,67 @@ +From a02b2ef06a3f11d2e6c20c2cdcdd6f0b4217d234 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:57 +0100 +Subject: [PATCH] ARM: dt: sun5i: Add A13 SPI controller nodes + +The A13 has 3 SPI controllers compatible with the one found in the A10. Add +them in the DT. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun5i-a13.dtsi | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index b0cc56c..1ff406b 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -290,6 +290,28 @@ + #size-cells = <1>; + ranges; + ++ spi0: spi@01c05000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c05000 0x1000>; ++ interrupts = <10>; ++ clocks = <&ahb_gates 20>, <&spi0_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@01c06000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c06000 0x1000>; ++ interrupts = <11>; ++ clocks = <&ahb_gates 21>, <&spi1_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + mmc0: mmc@01c0f000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c0f000 0x1000>; +@@ -344,6 +366,17 @@ + status = "disabled"; + }; + ++ spi2: spi@01c17000 { ++ compatible = "allwinner,sun4i-a10-spi"; ++ reg = <0x01c17000 0x1000>; ++ interrupts = <12>; ++ clocks = <&ahb_gates 22>, <&spi2_clk>; ++ clock-names = "ahb", "mod"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch b/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch new file mode 100644 index 0000000..9d2543c --- /dev/null +++ b/target/linux/sunxi/patches-3.13/263-5-dt-sun7i-add-spi-muxing.patch @@ -0,0 +1,38 @@ +From eb9180f426a7da1da5ed0f3aa13b92609c869fc0 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:58 +0100 +Subject: [PATCH] ARM: dt: sun7i: Add SPI muxing options + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index bcea04a..9f57035 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -688,6 +688,20 @@ + allwinner,drive = <2>; + allwinner,pull = <0>; + }; ++ ++ spi1_pins_a: spi1@0 { ++ allwinner,pins = "PI16", "PI17", "PI18", "PI19"; ++ allwinner,function = "spi1"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ ++ spi2_pins_a: spi2@0 { ++ allwinner,pins = "PC19", "PC20", "PC21", "PC22"; ++ allwinner,function = "spi2"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; + }; + + timer@01c20c00 { +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch b/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch new file mode 100644 index 0000000..bebcbd0 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/264-5-dt-sun7i-enable-spi-on-a20micro.patch @@ -0,0 +1,46 @@ +From 5c5ac3fb749c64e7c1e6e3208fcabab065359f56 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sat, 22 Feb 2014 22:35:59 +0100 +Subject: [PATCH] ARM: dts: sun7i: Enable the SPI controllers of the + A20-olinuxino-micro + +The A20-Olinuxino-micro has two SPI bus exposed on its UEXT connectors, enable +them. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index 824ce0a..68cedf3 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -21,7 +21,24 @@ + model = "Olimex A20-Olinuxino Micro"; + compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20"; + ++ aliases { ++ spi0 = &spi1; ++ spi1 = &spi2; ++ }; ++ + soc@01c00000 { ++ spi1: spi@01c06000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pins_a>; ++ status = "okay"; ++ }; ++ ++ spi2: spi@01c17000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_pins_a>; ++ status = "okay"; ++ }; ++ + mmc0: mmc@01c0f000 { + pinctrl-names = "default", "default"; + pinctrl-0 = <&mmc0_pins_a>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch b/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch new file mode 100644 index 0000000..7a4498b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/270-1-wdt-sunxi-introduce-new-compat.patch @@ -0,0 +1,53 @@ +From 111579574584c73a91c2b1bf8657c3691cc22409 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:55:23 +0100 +Subject: [PATCH] wdt: sunxi: Introduce a new compatible for the A10 and A31 + +For historical reasons, the Allwinner A10 compatibles are not following the +patterns used for this other Allwinner SoCs. + +Introduce a new compatible following the usual pattern, and deprecate the olders. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt | 7 ++++--- + drivers/watchdog/sunxi_wdt.c | 1 + + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt +index e39cb26..6e8c937 100644 +--- a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt ++++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt +@@ -2,13 +2,14 @@ Allwinner SoCs Watchdog timer + + Required properties: + +-- compatible : should be "allwinner,<soc-family>-wdt", the currently supported +- SoC families being sun4i and sun6i ++- compatible : should be either "allwinner,sun4i-a10-wdt" or ++ "allwinner,sun6i-a31-wdt" (deprecated: ++ "allwinner,sun4i-wdt", "allwinner,sun6i-wdt") + - reg : Specifies base physical address and size of the registers. + + Example: + + wdt: watchdog@01c20c90 { +- compatible = "allwinner,sun4i-wdt"; ++ compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; +diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c +index 76332d89..7c8923d 100644 +--- a/drivers/watchdog/sunxi_wdt.c ++++ b/drivers/watchdog/sunxi_wdt.c +@@ -206,6 +206,7 @@ static void sunxi_wdt_shutdown(struct platform_device *pdev) + + static const struct of_device_id sunxi_wdt_dt_ids[] = { + { .compatible = "allwinner,sun4i-wdt" }, ++ { .compatible = "allwinner,sun4i-a10-wdt" }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch b/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch new file mode 100644 index 0000000..0150dfa --- /dev/null +++ b/target/linux/sunxi/patches-3.13/270-2-wdt-sunxi-add-new-wdt-compats-into-reboot-code.patch @@ -0,0 +1,31 @@ +From b50ff681c8e3e9e408ee1fb6c6317bc8da653a01 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:55:24 +0100 +Subject: [PATCH] ARM: sunxi: Add the new watchog compatibles to the reboot + code + +Now that the watchdog driver has new compatibles, we need to support them in +the machine reboot code too. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/mach-sunxi/sunxi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c +index aeea6ce..c310df6 100644 +--- a/arch/arm/mach-sunxi/sunxi.c ++++ b/arch/arm/mach-sunxi/sunxi.c +@@ -95,7 +95,9 @@ static void sun6i_restart(enum reboot_mode mode, const char *cmd) + + static struct of_device_id sunxi_restart_ids[] = { + { .compatible = "allwinner,sun4i-wdt" }, ++ { .compatible = "allwinner,sun4i-a10-wdt" }, + { .compatible = "allwinner,sun6i-wdt" }, ++ { .compatible = "allwinner,sun6i-a31-wdt" }, + { /*sentinel*/ } + }; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch b/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch new file mode 100644 index 0000000..843d0d6 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/270-3-dt-sunxi-watchdog-update-compats.patch @@ -0,0 +1,86 @@ +From 0dba36162dffdee935287645d515f53057de3537 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Sun, 2 Feb 2014 14:55:25 +0100 +Subject: [PATCH] ARM: sunxi: dt: Update the watchdog compatibles + +The watchdog compatibles were following a different pattern than the one found +in the other devices. Now that the driver supports the right pattern, switch to +it in the DT. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 2 +- + arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +- + arch/arm/boot/dts/sun5i-a13.dtsi | 2 +- + arch/arm/boot/dts/sun6i-a31.dtsi | 2 +- + arch/arm/boot/dts/sun7i-a20.dtsi | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 80bbdeb..3a5775c 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -545,7 +545,7 @@ + }; + + wdt: watchdog@01c20c90 { +- compatible = "allwinner,sun4i-wdt"; ++ compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index a5431ed..e5064dc 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -467,7 +467,7 @@ + }; + + wdt: watchdog@01c20c90 { +- compatible = "allwinner,sun4i-wdt"; ++ compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; + +diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi +index 7fe9cdc..b0cc56c 100644 +--- a/arch/arm/boot/dts/sun5i-a13.dtsi ++++ b/arch/arm/boot/dts/sun5i-a13.dtsi +@@ -413,7 +413,7 @@ + }; + + wdt: watchdog@01c20c90 { +- compatible = "allwinner,sun4i-wdt"; ++ compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index b4407f17..c15f30e 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -289,7 +289,7 @@ + }; + + wdt1: watchdog@01c20ca0 { +- compatible = "allwinner,sun6i-wdt"; ++ compatible = "allwinner,sun6i-a31-wdt"; + reg = <0x01c20ca0 0x20>; + }; + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index e67924a..1961751 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -659,7 +659,7 @@ + }; + + wdt: watchdog@01c20c90 { +- compatible = "allwinner,sun4i-wdt"; ++ compatible = "allwinner,sun4i-a10-wdt"; + reg = <0x01c20c90 0x10>; + }; + +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch b/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch new file mode 100644 index 0000000..e42f0fe --- /dev/null +++ b/target/linux/sunxi/patches-3.13/280-input-add-sun4i-ts-driver.patch @@ -0,0 +1,354 @@ +From 328d21d9c56ddca56ed80b1595066b1621f6926b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 23 Dec 2013 16:21:02 +0100 +Subject: [PATCH] input: Add new sun4i-ts driver for Allwinner sunxi SoC's rtp + controller + +Note the sun4i-ts controller is capable of detecting a second touch, but when +a second touch is present then the accuracy becomes so bad the reported touch +location is not useable. + +The original android driver contains some complicated heuristics using the +aprox. distance between the 2 touches to see if the user is making a pinch +open / close movement, and then reports emulated multi-touch events around +the last touch coordinate (as the dual-touch coordinates are worthless). + +These kinds of heuristics are just asking for trouble (and don't belong +in the kernel). So this driver offers straight forward, reliable single +touch functionality only. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + .../bindings/input/touchscreen/sun4i.txt | 15 ++ + drivers/input/touchscreen/Kconfig | 10 + + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/sun4i-ts.c | 262 +++++++++++++++++++++ + 4 files changed, 288 insertions(+) + create mode 100644 Documentation/devicetree/bindings/input/touchscreen/sun4i.txt + create mode 100644 drivers/input/touchscreen/sun4i-ts.c + +diff --git a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt +new file mode 100644 +index 0000000..e45927e +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt +@@ -0,0 +1,15 @@ ++sun4i resistive touchscreen controller ++-------------------------------------- ++ ++Required properties: ++ - compatible: "allwinner,sun4i-ts" ++ - reg: mmio address range of the chip ++ - interrupts: interrupt to which the chip is connected ++ ++Example: ++ ++ rtp: rtp@01c25000 { ++ compatible = "allwinner,sun4i-ts"; ++ reg = <0x01c25000 0x100>; ++ interrupts = <29>; ++ }; +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 07e9e82..f4c5ca3 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -906,6 +906,16 @@ config TOUCHSCREEN_STMPE + To compile this driver as a module, choose M here: the + module will be called stmpe-ts. + ++config TOUCHSCREEN_SUN4I ++ tristate "Allwinner sun4i resistive touchscreen controller support" ++ depends on ARCH_SUNXI ++ help ++ This selects support for the resistive touchscreen controller ++ found on Allwinner sunxi SoCs. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called sun4i-ts. ++ + config TOUCHSCREEN_SUR40 + tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen" + depends on USB +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 62801f2..c8f7375 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o + obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o + obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o + obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o ++obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o + obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o + obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o + obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o +diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c +new file mode 100644 +index 0000000..5945219 +--- /dev/null ++++ b/drivers/input/touchscreen/sun4i-ts.c +@@ -0,0 +1,262 @@ ++/* ++ * Allwinner sunxi resistive touchscreen controller driver ++ * ++ * Copyright (C) 2013 - 2014 Hans de Goede <hdegoede@redhat.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * The sun4i-ts controller is capable of detecting a second touch, but when a ++ * second touch is present then the accuracy becomes so bad the reported touch ++ * location is not useable. ++ * ++ * The original android driver contains some complicated heuristics using the ++ * aprox. distance between the 2 touches to see if the user is making a pinch ++ * open / close movement, and then reports emulated multi-touch events around ++ * the last touch coordinate (as the dual-touch coordinates are worthless). ++ * ++ * These kinds of heuristics are just asking for trouble (and don't belong ++ * in the kernel). So this driver offers straight forward, reliable single ++ * touch functionality only. ++ */ ++ ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/input.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/of_platform.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#define TP_CTRL0 0x00 ++#define TP_CTRL1 0x04 ++#define TP_CTRL2 0x08 ++#define TP_CTRL3 0x0c ++#define TP_INT_FIFOC 0x10 ++#define TP_INT_FIFOS 0x14 ++#define TP_TPR 0x18 ++#define TP_CDAT 0x1c ++#define TEMP_DATA 0x20 ++#define TP_DATA 0x24 ++ ++/* TP_CTRL0 bits */ ++#define ADC_FIRST_DLY(x) ((x) << 24) /* 8 bits */ ++#define ADC_FIRST_DLY_MODE(x) ((x) << 23) ++#define ADC_CLK_SEL(x) ((x) << 22) ++#define ADC_CLK_DIV(x) ((x) << 20) /* 3 bits */ ++#define FS_DIV(x) ((x) << 16) /* 4 bits */ ++#define T_ACQ(x) ((x) << 0) /* 16 bits */ ++ ++/* TP_CTRL1 bits */ ++#define STYLUS_UP_DEBOUN(x) ((x) << 12) /* 8 bits */ ++#define STYLUS_UP_DEBOUN_EN(x) ((x) << 9) ++#define TOUCH_PAN_CALI_EN(x) ((x) << 6) ++#define TP_DUAL_EN(x) ((x) << 5) ++#define TP_MODE_EN(x) ((x) << 4) ++#define TP_ADC_SELECT(x) ((x) << 3) ++#define ADC_CHAN_SELECT(x) ((x) << 0) /* 3 bits */ ++ ++/* TP_CTRL2 bits */ ++#define TP_SENSITIVE_ADJUST(x) ((x) << 28) /* 4 bits */ ++#define TP_MODE_SELECT(x) ((x) << 26) /* 2 bits */ ++#define PRE_MEA_EN(x) ((x) << 24) ++#define PRE_MEA_THRE_CNT(x) ((x) << 0) /* 24 bits */ ++ ++/* TP_CTRL3 bits */ ++#define FILTER_EN(x) ((x) << 2) ++#define FILTER_TYPE(x) ((x) << 0) /* 2 bits */ ++ ++/* TP_INT_FIFOC irq and fifo mask / control bits */ ++#define TEMP_IRQ_EN(x) ((x) << 18) ++#define OVERRUN_IRQ_EN(x) ((x) << 17) ++#define DATA_IRQ_EN(x) ((x) << 16) ++#define TP_DATA_XY_CHANGE(x) ((x) << 13) ++#define FIFO_TRIG(x) ((x) << 8) /* 5 bits */ ++#define DATA_DRQ_EN(x) ((x) << 7) ++#define FIFO_FLUSH(x) ((x) << 4) ++#define TP_UP_IRQ_EN(x) ((x) << 1) ++#define TP_DOWN_IRQ_EN(x) ((x) << 0) ++ ++/* TP_INT_FIFOS irq and fifo status bits */ ++#define TEMP_DATA_PENDING BIT(18) ++#define FIFO_OVERRUN_PENDING BIT(17) ++#define FIFO_DATA_PENDING BIT(16) ++#define TP_IDLE_FLG BIT(2) ++#define TP_UP_PENDING BIT(1) ++#define TP_DOWN_PENDING BIT(0) ++ ++/* TP_TPR bits */ ++#define TEMP_ENABLE(x) ((x) << 16) ++#define TEMP_PERIOD(x) ((x) << 0) /* t = x * 256 * 16 / clkin */ ++ ++struct sun4i_ts_data { ++ struct device *dev; ++ struct input_dev *input; ++ void __iomem *base; ++ unsigned int irq; ++ bool ignore_fifo_data; ++}; ++ ++static irqreturn_t sun4i_ts_irq(int irq, void *dev_id) ++{ ++ struct sun4i_ts_data *ts = dev_id; ++ u32 reg_val, x, y; ++ ++ reg_val = readl(ts->base + TP_INT_FIFOS); ++ ++ if (reg_val & FIFO_DATA_PENDING) { ++ x = readl(ts->base + TP_DATA); ++ y = readl(ts->base + TP_DATA); ++ /* The 1st location reported after an up event is unreliable */ ++ if (!ts->ignore_fifo_data) { ++ input_report_abs(ts->input, ABS_X, x); ++ input_report_abs(ts->input, ABS_Y, y); ++ /* ++ * The hardware has a separate down status bit, but ++ * that gets set before we get the first location, ++ * resulting in reporting a click on the old location. ++ */ ++ input_report_key(ts->input, BTN_TOUCH, 1); ++ input_sync(ts->input); ++ } else { ++ ts->ignore_fifo_data = false; ++ } ++ } ++ ++ if (reg_val & TP_UP_PENDING) { ++ ts->ignore_fifo_data = true; ++ input_report_key(ts->input, BTN_TOUCH, 0); ++ input_sync(ts->input); ++ } ++ ++ writel(reg_val, ts->base + TP_INT_FIFOS); ++ ++ return IRQ_HANDLED; ++} ++ ++static int sun4i_ts_open(struct input_dev *dev) ++{ ++ struct sun4i_ts_data *ts = input_get_drvdata(dev); ++ ++ /* Flush, set trig level to 1, enable data and up irqs */ ++ writel(DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) | TP_UP_IRQ_EN(1), ++ ts->base + TP_INT_FIFOC); ++ ++ return 0; ++} ++ ++static void sun4i_ts_close(struct input_dev *dev) ++{ ++ struct sun4i_ts_data *ts = input_get_drvdata(dev); ++ ++ /* Deactivate all IRQs */ ++ writel(0, ts->base + TP_INT_FIFOC); ++} ++ ++static int sun4i_ts_probe(struct platform_device *pdev) ++{ ++ struct sun4i_ts_data *ts; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); ++ if (!ts) ++ return -ENOMEM; ++ ++ ts->dev = dev; ++ ts->ignore_fifo_data = true; ++ ++ ts->input = devm_input_allocate_device(dev); ++ if (!ts->input) ++ return -ENOMEM; ++ ++ ts->input->name = pdev->name; ++ ts->input->phys = "sun4i_ts/input0"; ++ ts->input->open = sun4i_ts_open; ++ ts->input->close = sun4i_ts_close; ++ ts->input->id.bustype = BUS_HOST; ++ ts->input->id.vendor = 0x0001; ++ ts->input->id.product = 0x0001; ++ ts->input->id.version = 0x0100; ++ ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); ++ set_bit(BTN_TOUCH, ts->input->keybit); ++ input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0); ++ input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0); ++ input_set_drvdata(ts->input, ts); ++ ++ ts->base = devm_ioremap_resource(dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ if (IS_ERR(ts->base)) ++ return PTR_ERR(ts->base); ++ ++ ts->irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts); ++ if (ret) ++ return ret; ++ ++ /* ++ * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192, ++ * t_acq = clkin / (16 * 64) ++ */ ++ writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63), ++ ts->base + TP_CTRL0); ++ ++ /* ++ * sensitive_adjust = 15 : max, which is not all that sensitive, ++ * tp_mode = 0 : only x and y coordinates, as we don't use dual touch ++ */ ++ writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0), ++ ts->base + TP_CTRL2); ++ ++ /* Enable median filter, type 1 : 5/3 */ ++ writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3); ++ ++ /* Enable temperature measurement, period 1953 (2 seconds) */ ++ writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); ++ ++ /* ++ * Set stylus up debounce to aprox 10 ms, enable debounce, and ++ * finally enable tp mode. ++ */ ++ writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1), ++ ts->base + TP_CTRL1); ++ ++ ret = input_register_device(ts->input); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, ts); ++ return 0; ++} ++ ++static const struct of_device_id sun4i_ts_of_match[] = { ++ { .compatible = "allwinner,sun4i-ts", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, sun4i_ts_of_match); ++ ++static struct platform_driver sun4i_ts_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "sun4i-ts", ++ .of_match_table = of_match_ptr(sun4i_ts_of_match), ++ }, ++ .probe = sun4i_ts_probe, ++}; ++ ++module_platform_driver(sun4i_ts_driver); ++ ++MODULE_DESCRIPTION("Allwinner sun4i resistive touchscreen controller driver"); ++MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch b/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch new file mode 100644 index 0000000..cca20c3 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/301-1-dt-sun4i-add-pcduino.patch @@ -0,0 +1,86 @@ +From 248529e6c78ba746988f1313f7bfb7ae74eae785 Mon Sep 17 00:00:00 2001 +From: Zoltan HERPAI <wigyori@uid0.hu> +Date: Mon, 13 Jan 2014 14:15:01 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add basic board support for LinkSprite + pcDuino + +This patch will add a basic board support DT for the +LinkSprite pcDuino board. + +Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu> +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/sun4i-a10-pcduino.dts | 48 +++++++++++++++++++++++++++++++++ + 2 files changed, 49 insertions(+) + create mode 100644 arch/arm/boot/dts/sun4i-a10-pcduino.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 6d1e43d..0b127db 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -283,6 +283,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ + sun4i-a10-cubieboard.dtb \ + sun4i-a10-mini-xplus.dtb \ + sun4i-a10-hackberry.dtb \ ++ sun4i-a10-pcduino.dtb \ + sun5i-a10s-olinuxino-micro.dtb \ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ +diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +new file mode 100644 +index 0000000..f5692a3 +--- /dev/null ++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +@@ -0,0 +1,48 @@ ++/* ++ * Copyright 2014 Zoltan HERPAI ++ * Zoltan HERPAI <wigyori@uid0.hu> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/dts-v1/; ++/include/ "sun4i-a10.dtsi" ++ ++/ { ++ model = "LinkSprite pcDuino"; ++ compatible = "linksprite,a10-pcduino", "allwinner,sun4i-a10"; ++ ++ soc@01c00000 { ++ emac: ethernet@01c0b000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emac_pins_a>; ++ phy = <&phy1>; ++ status = "okay"; ++ }; ++ ++ mdio@01c0b080 { ++ status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; ++ ++ uart0: serial@01c28000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++ }; ++ ++ i2c0: i2c@01c2ac00 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins_a>; ++ status = "okay"; ++ }; ++ }; ++}; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch b/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch new file mode 100644 index 0000000..e028d12 --- /dev/null +++ b/target/linux/sunxi/patches-3.13/301-2-dt-sun4i-pcduino-add-mmc.patch @@ -0,0 +1,73 @@ +From 54b9b9ab635ed8e643784402096524768f490f5d Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Sat, 11 Jan 2014 04:33:23 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add mmc node to a few more boards + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-hackberry.dts | 9 +++++++++ + arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 8 ++++++++ + arch/arm/boot/dts/sun4i-a10-pcduino.dts | 8 ++++++++ + 3 files changed, 25 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +index 6692d336..2eb30d0 100644 +--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts ++++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts +@@ -35,6 +35,15 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-mode = <1>; ++ status = "okay"; ++ }; ++ + pio: pinctrl@01c20800 { + pinctrl-names = "default"; + pinctrl-0 = <&hackberry_hogs>; +diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +index 70b3323..6dbe53c 100644 +--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts ++++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts +@@ -19,6 +19,14 @@ + compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10"; + + soc@01c00000 { ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +index f5692a3..87f7742 100644 +--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts ++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +@@ -33,6 +33,14 @@ + }; + }; + ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch b/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch new file mode 100644 index 0000000..c81008f --- /dev/null +++ b/target/linux/sunxi/patches-3.13/301-3-dt-sun4i-pcduino-add-usb.patch @@ -0,0 +1,58 @@ +From 713c2957f8b9e49b2170c9e546d705c9c358faee Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Mon, 17 Feb 2014 20:41:04 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to pcduino.dts + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/sun4i-a10-pcduino.dts | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +index 87f7742..3ccd357 100644 +--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts ++++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts +@@ -12,6 +12,7 @@ + + /dts-v1/; + /include/ "sun4i-a10.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" + + / { + model = "LinkSprite pcDuino"; +@@ -41,6 +42,32 @@ + status = "okay"; + }; + ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ ++ ahci: sata@01c18000 { ++ status = "okay"; ++ }; ++ ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +-- +1.8.5.5 + diff --git a/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch b/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch new file mode 100644 index 0000000..f6cbf1b --- /dev/null +++ b/target/linux/sunxi/patches-3.13/302-dt-sun4i-add-lime.patch @@ -0,0 +1,150 @@ +From 75e7218e107016a4baae26c70a81b1111fc8c70b Mon Sep 17 00:00:00 2001 +From: Hans de Goede <hdegoede@redhat.com> +Date: Fri, 10 Jan 2014 23:23:06 +0100 +Subject: [PATCH] ARM: sun4i: dt: Add sun4i-a10-olinuxino-lime.dtb + +This add support for the A10-OLinuXino-LIME: +https://www.olimex.com/Products/OLinuXino/A10/A10-OLinuXino-LIME + +A low cost Allwinner A10 based dev-board, with sata, ethernet, hdmi and 2x USB. + +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 112 +++++++++++++++++++++++++ + 2 files changed, 113 insertions(+) + create mode 100644 arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 0b127db..c576de8 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -283,6 +283,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \ + sun4i-a10-cubieboard.dtb \ + sun4i-a10-mini-xplus.dtb \ + sun4i-a10-hackberry.dtb \ ++ sun4i-a10-olinuxino-lime.dtb \ + sun4i-a10-pcduino.dtb \ + sun5i-a10s-olinuxino-micro.dtb \ + sun5i-a13-olinuxino.dtb \ +diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +new file mode 100644 +index 0000000..3c076f2 +--- /dev/null ++++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts +@@ -0,0 +1,112 @@ ++/* ++ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com> ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/dts-v1/; ++/include/ "sun4i-a10.dtsi" ++/include/ "sunxi-ahci-reg.dtsi" ++/include/ "sun4i-a10-usb-vbus-reg.dtsi" ++ ++/ { ++ model = "Olimex A10-OLinuXino-LIME"; ++ compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10"; ++ ++ soc@01c00000 { ++ emac: ethernet@01c0b000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emac_pins_a>; ++ phy = <&phy1>; ++ status = "okay"; ++ }; ++ ++ mdio@01c0b080 { ++ status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; ++ ++ mmc0: mmc@01c0f000 { ++ pinctrl-names = "default", "default"; ++ pinctrl-0 = <&mmc0_pins_a>; ++ pinctrl-1 = <&mmc0_cd_pin_reference_design>; ++ cd-gpios = <&pio 7 1 0>; /* PH1 */ ++ cd-mode = <1>; ++ status = "okay"; ++ }; ++ ++ usbphy: phy@01c13400 { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ usb2_vbus-supply = <®_usb2_vbus>; ++ status = "okay"; ++ }; ++ ++ ehci0: usb@01c14000 { ++ status = "okay"; ++ }; ++ ++ ohci0: usb@01c14400 { ++ status = "okay"; ++ }; ++ ++ ahci: sata@01c18000 { ++ target-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ ++ ehci1: usb@01c1c000 { ++ status = "okay"; ++ }; ++ ++ ohci1: usb@01c1c400 { ++ status = "okay"; ++ }; ++ ++ pinctrl@01c20800 { ++ ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 { ++ allwinner,pins = "PC3"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ ++ led_pins_olinuxinolime: led_pins@0 { ++ allwinner,pins = "PH2"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <1>; ++ allwinner,pull = <0>; ++ }; ++ }; ++ ++ uart0: serial@01c28000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&led_pins_olinuxinolime>; ++ ++ green { ++ label = "a10-olinuxino-lime:green:usr"; ++ gpios = <&pio 7 2 0>; ++ default-state = "on"; ++ }; ++ }; ++ ++ reg_ahci_5v: ahci-5v { ++ pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>; ++ gpio = <&pio 2 3 0>; ++ }; ++}; +-- +1.8.5.5 + |