-# 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
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
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
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
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
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
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
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
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
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
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
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
# 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
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
+++ /dev/null
-/*
- * 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;
- };
- };
-};
+++ /dev/null
-/*
- * 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;
- };
- };
-};
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";
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>;
- };
- };
};
+++ /dev/null
-/*
- * 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");
+++ /dev/null
-/*
- * 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
+++ /dev/null
-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,},
- {}
--- /dev/null
+From 820a121fdef79cc1293e6fee2fbe8156d9e8a75a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 11 Dec 2013 15:07:52 +0100
+Subject: [PATCH] regulator_get_optional: don't print an error when no
+ regulator is found
+
+Only print an error when _regulator_get() is expected to return a valid
+regulator, that is when _regulator_get() is called from regulator_get() and
+we're not using the dummy because we don't have full-constraints, or when
+_regulator_get() is called from regulator_get_exclusive() in which case
+returning a dummy is not allowed.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ drivers/regulator/core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -1351,7 +1351,8 @@ static struct regulator *_regulator_get(
+
+ rdev = dummy_regulator_rdev;
+ goto found;
+- } else {
++ /* Don't log an error when called from regulator_get_optional() */
++ } else if (!have_full_constraints() || exclusive) {
+ dev_err(dev, "dummy supplies not allowed\n");
+ }
+
--- /dev/null
+From d3861805e84e1b54073e20dc499b9380b38bb7ab Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 3 Nov 2013 10:30:12 +0100
+Subject: [PATCH] ARM: sun6i: dt: Add IP needed to bring up the additional
+ cores
+
+Add the PRCM and CPU configuration units needed for SMP in the A31 DTSI.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun6i-a31.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -322,5 +322,15 @@
+ #interrupt-cells = <3>;
+ interrupts = <1 9 0xf04>;
+ };
++
++ cpucfg@01f01c00 {
++ compatible = "allwinner,sun6i-a31-cpuconfig";
++ reg = <0x01f01c00 0x300>;
++ };
++
++ prcm@01f01c00 {
++ compatible = "allwinner,sun6i-a31-prcm";
++ reg = <0x01f01400 0x200>;
++ };
+ };
+ };
+++ /dev/null
-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 {
--- /dev/null
+From 0aff0370cbffeadc14456556b904c80e30b3717e Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+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
+its device tree. A dummy fixed factor clock is also added to serve as
+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 | 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
+@@ -303,6 +303,34 @@
+ clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
+ clock-output-names = "mbus";
+ };
++
++ /*
++ * Dummy clock used by output clocks
++ */
++ 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 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun7i-a20-out-clk";
++ reg = <0x01c201f0 0x4>;
++ clocks = <&osc24M_32k>, <&osc32k>, <&osc24M>;
++ clock-output-names = "clk_out_a";
++ };
++
++ clk_out_b: clk@01c201f4 {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun7i-a20-out-clk";
++ reg = <0x01c201f4 0x4>;
++ clocks = <&osc24M_32k>, <&osc32k>, <&osc24M>;
++ clock-output-names = "clk_out_b";
++ };
+ };
+
+ soc@01c00000 {
+--
+1.8.5.5
+
+++ /dev/null
-From 820a121fdef79cc1293e6fee2fbe8156d9e8a75a Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Wed, 11 Dec 2013 15:07:52 +0100
-Subject: [PATCH] regulator_get_optional: don't print an error when no
- regulator is found
-
-Only print an error when _regulator_get() is expected to return a valid
-regulator, that is when _regulator_get() is called from regulator_get() and
-we're not using the dummy because we don't have full-constraints, or when
-_regulator_get() is called from regulator_get_exclusive() in which case
-returning a dummy is not allowed.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/regulator/core.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/regulator/core.c
-+++ b/drivers/regulator/core.c
-@@ -1351,7 +1351,8 @@ static struct regulator *_regulator_get(
-
- rdev = dummy_regulator_rdev;
- goto found;
-- } else {
-+ /* Don't log an error when called from regulator_get_optional() */
-+ } else if (!have_full_constraints() || exclusive) {
- dev_err(dev, "dummy supplies not allowed\n");
- }
-
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
+++ /dev/null
-From d3861805e84e1b54073e20dc499b9380b38bb7ab Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@free-electrons.com>
-Date: Sun, 3 Nov 2013 10:30:12 +0100
-Subject: [PATCH] ARM: sun6i: dt: Add IP needed to bring up the additional
- cores
-
-Add the PRCM and CPU configuration units needed for SMP in the A31 DTSI.
-
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- arch/arm/boot/dts/sun6i-a31.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/arm/boot/dts/sun6i-a31.dtsi
-+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
-@@ -322,5 +322,15 @@
- #interrupt-cells = <3>;
- interrupts = <1 9 0xf04>;
- };
-+
-+ cpucfg@01f01c00 {
-+ compatible = "allwinner,sun6i-a31-cpuconfig";
-+ reg = <0x01f01c00 0x300>;
-+ };
-+
-+ prcm@01f01c00 {
-+ compatible = "allwinner,sun6i-a31-prcm";
-+ reg = <0x01f01400 0x200>;
-+ };
- };
- };
--- /dev/null
+From 538d4a6ca5f41039d906f28be82e0f4d26ec8ac9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Mon, 23 Dec 2013 00:32:44 -0300
+Subject: [PATCH] ARM: sunxi: dt: add nodes for the mbus clock
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+mbus is the memory bus clock, and it is present on both sun5i and sun7i
+machines. Its register layout is compatible with the mod0 one.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 8 ++++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
+ 3 files changed, 24 insertions(+)
+
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -257,6 +257,14 @@
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ clock-output-names = "ir0";
+ };
++
++ mbus_clk: clk@01c2015c {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c2015c 0x4>;
++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
++ clock-output-names = "mbus";
++ };
+ };
+
+ soc@01c00000 {
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -258,6 +258,14 @@
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ clock-output-names = "ir0";
+ };
++
++ mbus_clk: clk@01c2015c {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c2015c 0x4>;
++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
++ clock-output-names = "mbus";
++ };
+ };
+
+ soc@01c00000 {
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -290,6 +290,14 @@
+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
+ clock-output-names = "spi3";
+ };
++
++ mbus_clk: clk@01c2015c {
++ #clock-cells = <0>;
++ compatible = "allwinner,sun4i-mod0-clk";
++ reg = <0x01c2015c 0x4>;
++ clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
++ clock-output-names = "mbus";
++ };
+ };
+
+ soc@01c00000 {
--- /dev/null
+From 2af807481169af627dc63f98b773c33d85020658 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Fri, 15 Nov 2013 15:26:44 -0300
+Subject: [PATCH] ARM: sunxi: dt: add EMAC aliases
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+U-Boot uses the ethernet0 alias to locate the right node to fill in
+the MAC address of the first ethernet interface. This patch adds the
+alias on all the sunxi SoCs with EMAC. In this way, people using
+ethernet in U-Boot (eg, for tftp) can keep a consistent address on both
+U-Boot and Linux with no additional effort.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ 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, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -15,6 +15,10 @@
+ / {
+ interrupt-parent = <&intc>;
+
++ aliases {
++ ethernet0 = &emac;
++ };
++
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -16,6 +16,10 @@
+ / {
+ interrupt-parent = <&intc>;
+
++ aliases {
++ ethernet0 = &emac;
++ };
++
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -16,6 +16,10 @@
+ / {
+ interrupt-parent = <&gic>;
+
++ aliases {
++ ethernet0 = &emac;
++ };
++
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
--- /dev/null
+From dfd4430579f5e53324c00e9e21fb0929bb46542c Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+Date: Sat, 7 Dec 2013 01:29:43 +0800
+Subject: [PATCH] ARM: dts: sun7i: Add ethernet alias for GMAC
+
+U-Boot will insert MAC address into the device tree image.
+It looks up ethernet[0-5] aliases to find the ethernet nodes.
+Alias GMAC as ethernet0, as it is the only ethernet controller used.
+
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -17,7 +17,7 @@
+ interrupt-parent = <&gic>;
+
+ aliases {
+- ethernet0 = &emac;
++ ethernet0 = &gmac;
+ };
+
+ cpus {
+++ /dev/null
-From 538d4a6ca5f41039d906f28be82e0f4d26ec8ac9 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
-Date: Mon, 23 Dec 2013 00:32:44 -0300
-Subject: [PATCH] ARM: sunxi: dt: add nodes for the mbus clock
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-mbus is the memory bus clock, and it is present on both sun5i and sun7i
-machines. Its register layout is compatible with the mod0 one.
-
-Signed-off-by: Emilio López <emilio@elopez.com.ar>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- arch/arm/boot/dts/sun5i-a10s.dtsi | 8 ++++++++
- arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++
- arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
- 3 files changed, 24 insertions(+)
-
---- a/arch/arm/boot/dts/sun5i-a10s.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -257,6 +257,14 @@
- clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "ir0";
- };
-+
-+ mbus_clk: clk@01c2015c {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-mod0-clk";
-+ reg = <0x01c2015c 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mbus";
-+ };
- };
-
- soc@01c00000 {
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -258,6 +258,14 @@
- clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "ir0";
- };
-+
-+ mbus_clk: clk@01c2015c {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-mod0-clk";
-+ reg = <0x01c2015c 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mbus";
-+ };
- };
-
- soc@01c00000 {
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -290,6 +290,14 @@
- clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "spi3";
- };
-+
-+ mbus_clk: clk@01c2015c {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-mod0-clk";
-+ reg = <0x01c2015c 0x4>;
-+ clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
-+ clock-output-names = "mbus";
-+ };
- };
-
- soc@01c00000 {
--- /dev/null
+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
+
+Note this requires a new enough uboot, otherwise things won't work, ie:
+
+https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-next
+or:
+http://xenbits.xen.org/gitweb/?p=people/ianc/u-boot.git;a=shortlog;h=refs/heads/devel/sunxi-psci
+
+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
+@@ -370,6 +370,14 @@
+ };
+ };
+
++ timer {
++ compatible = "arm,armv7-timer";
++ interrupts = <1 13 0xf08>,
++ <1 14 0xf08>,
++ <1 11 0xf08>,
++ <1 10 0xf08>;
++ };
++
+ soc@01c00000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+--
+1.8.5.5
+
+++ /dev/null
-From 2af807481169af627dc63f98b773c33d85020658 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
-Date: Fri, 15 Nov 2013 15:26:44 -0300
-Subject: [PATCH] ARM: sunxi: dt: add EMAC aliases
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-U-Boot uses the ethernet0 alias to locate the right node to fill in
-the MAC address of the first ethernet interface. This patch adds the
-alias on all the sunxi SoCs with EMAC. In this way, people using
-ethernet in U-Boot (eg, for tftp) can keep a consistent address on both
-U-Boot and Linux with no additional effort.
-
-Signed-off-by: Emilio López <emilio@elopez.com.ar>
----
- 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, 12 insertions(+)
-
---- a/arch/arm/boot/dts/sun4i-a10.dtsi
-+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
-@@ -15,6 +15,10 @@
- / {
- interrupt-parent = <&intc>;
-
-+ aliases {
-+ ethernet0 = &emac;
-+ };
-+
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
---- a/arch/arm/boot/dts/sun5i-a10s.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -16,6 +16,10 @@
- / {
- interrupt-parent = <&intc>;
-
-+ aliases {
-+ ethernet0 = &emac;
-+ };
-+
- cpus {
- cpu@0 {
- compatible = "arm,cortex-a8";
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -16,6 +16,10 @@
- / {
- interrupt-parent = <&gic>;
-
-+ aliases {
-+ ethernet0 = &emac;
-+ };
-+
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
--- /dev/null
+From aad62992a2921436ec7c054f8b80bc916b8cc9d7 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 14 Dec 2013 16:26:17 +0100
+Subject: [PATCH] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board
+
+The A13-OLinuXino-MICRO is a small dev-board with the Allwinner A13 SoC:
+https://www.olimex.com/Products/OLinuXino/A13/A13-OLinuXino-MICRO/
+
+Features:
+A13 Cortex A8 processor at 1GHz, 3D Mali400 GPU
+256 MB RAM (128Mbit x 16)
+5VDC input power supply with own ICs, noise immune design
+1 USB host
+1 USB OTG which can power the board
+SD-card connector for booting the Linux image
+VGA video output
+LCD signals available on connector so you still can use LCD if you disable VGA/HDMI
+Audio output
+Microphone input pads (no connector)
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 68 +++++++++++++++++++++++++
+ 2 files changed, 69 insertions(+)
+ create mode 100644 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -255,6 +255,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
+ sun4i-a10-hackberry.dtb \
+ sun5i-a10s-olinuxino-micro.dtb \
+ sun5i-a13-olinuxino.dtb \
++ sun5i-a13-olinuxino-micro.dtb \
+ sun6i-a31-colombus.dtb \
+ sun7i-a20-cubieboard2.dtb \
+ sun7i-a20-cubietruck.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+@@ -0,0 +1,68 @@
++/*
++ * Copyright 2012 Maxime Ripard
++ * Copyright 2013 Hans de Goede <hdegoede@redhat.com>
++ *
++ * Maxime Ripard <maxime.ripard@free-electrons.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/ "sun5i-a13.dtsi"
++
++/ {
++ model = "Olimex A13-Olinuxino Micro";
++ compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
++
++ soc@01c00000 {
++ pinctrl@01c20800 {
++ led_pins_olinuxinom: led_pins@0 {
++ allwinner,pins = "PG9";
++ allwinner,function = "gpio_out";
++ allwinner,drive = <1>;
++ allwinner,pull = <0>;
++ };
++ };
++
++ uart1: serial@01c28400 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart1_pins_b>;
++ 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";
++ };
++
++ i2c2: i2c@01c2b400 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c2_pins_a>;
++ status = "okay";
++ };
++ };
++
++ leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&led_pins_olinuxinom>;
++
++ power {
++ label = "a13-olinuxino-micro:green:power";
++ gpios = <&pio 6 9 0>;
++ default-state = "on";
++ };
++ };
++};
+++ /dev/null
-From dfd4430579f5e53324c00e9e21fb0929bb46542c Mon Sep 17 00:00:00 2001
-From: Chen-Yu Tsai <wens@csie.org>
-Date: Sat, 7 Dec 2013 01:29:43 +0800
-Subject: [PATCH] ARM: dts: sun7i: Add ethernet alias for GMAC
-
-U-Boot will insert MAC address into the device tree image.
-It looks up ethernet[0-5] aliases to find the ethernet nodes.
-Alias GMAC as ethernet0, as it is the only ethernet controller used.
-
-Signed-off-by: Chen-Yu Tsai <wens@csie.org>
----
- arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/sun7i-a20.dtsi
-+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
-@@ -17,7 +17,7 @@
- interrupt-parent = <&gic>;
-
- aliases {
-- ethernet0 = &emac;
-+ ethernet0 = &gmac;
- };
-
- cpus {
+++ /dev/null
-From 26523a27f47828e50212201ba25862fe1e2b845c 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
-
-Note this requires a new enough uboot, otherwise things won't work, ie:
-
-https://github.com/jwrdegoede/u-boot-sunxi/commits/sunxi-next
-or:
-http://xenbits.xen.org/gitweb/?p=people/ianc/u-boot.git;a=shortlog;h=refs/heads/devel/sunxi-psci
-
-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
-@@ -304,6 +304,14 @@
- };
- };
-
-+ timer {
-+ compatible = "arm,armv7-timer";
-+ interrupts = <1 13 0xf08>,
-+ <1 14 0xf08>,
-+ <1 11 0xf08>,
-+ <1 10 0xf08>;
-+ };
-+
- soc@01c00000 {
- compatible = "simple-bus";
- #address-cells = <1>;
+++ /dev/null
-From aad62992a2921436ec7c054f8b80bc916b8cc9d7 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sat, 14 Dec 2013 16:26:17 +0100
-Subject: [PATCH] ARM: dts: sun5i: Add new sun5i-a13-olinuxino-micro board
-
-The A13-OLinuXino-MICRO is a small dev-board with the Allwinner A13 SoC:
-https://www.olimex.com/Products/OLinuXino/A13/A13-OLinuXino-MICRO/
-
-Features:
-A13 Cortex A8 processor at 1GHz, 3D Mali400 GPU
-256 MB RAM (128Mbit x 16)
-5VDC input power supply with own ICs, noise immune design
-1 USB host
-1 USB OTG which can power the board
-SD-card connector for booting the Linux image
-VGA video output
-LCD signals available on connector so you still can use LCD if you disable VGA/HDMI
-Audio output
-Microphone input pads (no connector)
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- arch/arm/boot/dts/Makefile | 1 +
- arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 68 +++++++++++++++++++++++++
- 2 files changed, 69 insertions(+)
- create mode 100644 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -255,6 +255,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
- sun4i-a10-hackberry.dtb \
- sun5i-a10s-olinuxino-micro.dtb \
- sun5i-a13-olinuxino.dtb \
-+ sun5i-a13-olinuxino-micro.dtb \
- sun6i-a31-colombus.dtb \
- sun7i-a20-cubieboard2.dtb \
- sun7i-a20-cubietruck.dtb \
---- /dev/null
-+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
-@@ -0,0 +1,68 @@
-+/*
-+ * Copyright 2012 Maxime Ripard
-+ * Copyright 2013 Hans de Goede <hdegoede@redhat.com>
-+ *
-+ * Maxime Ripard <maxime.ripard@free-electrons.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/ "sun5i-a13.dtsi"
-+
-+/ {
-+ model = "Olimex A13-Olinuxino Micro";
-+ compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
-+
-+ soc@01c00000 {
-+ pinctrl@01c20800 {
-+ led_pins_olinuxinom: led_pins@0 {
-+ allwinner,pins = "PG9";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <1>;
-+ allwinner,pull = <0>;
-+ };
-+ };
-+
-+ uart1: serial@01c28400 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart1_pins_b>;
-+ 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";
-+ };
-+
-+ i2c2: i2c@01c2b400 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c2_pins_a>;
-+ status = "okay";
-+ };
-+ };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&led_pins_olinuxinom>;
-+
-+ power {
-+ label = "a13-olinuxino-micro:green:power";
-+ gpios = <&pio 6 9 0>;
-+ default-state = "on";
-+ };
-+ };
-+};
+++ /dev/null
-From 4f43ab43125a12dbc23e352ac0eb4fd80a876fb5 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
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Emilio López <emilio@elopez.com.ar>
----
- drivers/clk/sunxi/clk-sunxi.c | 35 +++++++++++++++++++++++++++++++++++
- 1 file changed, 35 insertions(+)
-
---- 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 *
-
-
- /**
-+ * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
-+ */
-+
-+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output)
-+{
-+ #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
-+ #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
-+
-+ struct clk_composite *composite = to_clk_composite(hw);
-+ struct clk_hw *rate_hw = composite->rate_hw;
-+ struct clk_factors *factors = to_clk_factors(rate_hw);
-+ unsigned long flags = 0;
-+ u32 reg;
-+
-+ if (factors->lock)
-+ spin_lock_irqsave(factors->lock, flags);
-+
-+ reg = readl(factors->reg);
-+
-+ /* set sample clock phase control */
-+ reg &= ~(0x7 << 20);
-+ reg |= ((sample & 0x7) << 20);
-+
-+ /* set output clock phase control */
-+ reg &= ~(0x7 << 8);
-+ reg |= ((output & 0x7) << 8);
-+
-+ writel(reg, factors->reg);
-+
-+ if (factors->lock)
-+ spin_unlock_irqrestore(factors->lock, flags);
-+}
-+
-+
-+/**
- * sunxi_factors_clk_setup() - Setup function for factor clocks
- */
-
--- /dev/null
+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
+
+++ /dev/null
-From a8cfe8ebdb18e6724b6520e08602b8e72e762ab9 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
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- include/linux/clk/sunxi.h | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
- create mode 100644 include/linux/clk/sunxi.h
-
---- /dev/null
-+++ b/include/linux/clk/sunxi.h
-@@ -0,0 +1,22 @@
-+/*
-+ * Copyright 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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __LINUX_CLK_SUNXI_H_
-+#define __LINUX_CLK_SUNXI_H_
-+
-+#include <linux/clk.h>
-+
-+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
-+
-+#endif
--- /dev/null
+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
+
--- /dev/null
+From 249ac8d24efdc07f521b796b96796ffa55abe0a5 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+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.
+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 | 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
+@@ -484,6 +484,32 @@
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
++
++ 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 = <0>;
++ allwinner,pull = <0>;
++ };
++
++ 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>;
++ };
+ };
+
+ timer@01c20c00 {
+--
+1.8.5.5
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
+++ /dev/null
-From 33b0123664b627005728cfe7b1967b790392ceec 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
-
-The correct value for selecting the mmc0 function on port F pins is 2 not 4,
-as per the data-sheet:
-http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- drivers/pinctrl/pinctrl-sunxi-pins.h | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- 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
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* D1 */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* D1 */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* D0 */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* D0 */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* CLK */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* CLK */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* CMD */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* CMD */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* D3 */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* D3 */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION(0x4, "mmc0")), /* D2 */
-+ SUNXI_FUNCTION(0x2, "mmc0")), /* D2 */
- /* Hole */
- SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
- SUNXI_FUNCTION(0x0, "gpio_in"),
--- /dev/null
+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
+
--- /dev/null
+From 7405ae68d251191677e51aadb4308d6ce5212bbe Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+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.
+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 | 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 @@
+ compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
+
+ 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>;
+- };
+- };
+-
+ 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_a>;
++ phy = <&phy1>;
++ phy-mode = "mii";
++ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
++ };
+ };
+
+ leds {
+--
+1.8.5.5
+
--- /dev/null
+From e401b86036245d2d62d825f0e3e12286c111b281 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wens@csie.org>
+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 | 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 @@
+ compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
+
+ 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>;
+- };
+- };
+-
+ 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_a>;
++ phy = <&phy1>;
++ phy-mode = "mii";
++ status = "okay";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ };
++ };
+ };
+
+ leds {
+--
+1.8.5.5
+
+++ /dev/null
-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
+++ /dev/null
-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 {
--- /dev/null
+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
+
+++ /dev/null
-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
-Subject: [PATCH] ARM: dts: sun5i: Add support for mmc
-
-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(+)
-
---- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
-+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
-@@ -34,7 +34,39 @@
- };
- };
-
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "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-0 = <&mmc1_pins_a>;
-+ pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>;
-+ cd-gpios = <&pio 6 13 0>; /* PG13 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin@0 {
-+ allwinner,pins = "PG1";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
-+ mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 {
-+ allwinner,pins = "PG13";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_olinuxino: led_pins@0 {
- allwinner,pins = "PE3";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun5i-a10s.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
-@@ -293,6 +293,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 = <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";
-+ };
-+
- intc: interrupt-controller@01c20400 {
- compatible = "allwinner,sun4i-ic";
- reg = <0x01c20400 0x400>;
-@@ -363,6 +383,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>;
-+ };
-+
-+ mmc1_pins_a: mmc1@0 {
-+ allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8";
-+ allwinner,function = "mmc1";
-+ allwinner,drive = <3>;
-+ allwinner,pull = <0>;
-+ };
- };
-
- timer@01c20c00 {
---- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
-+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
-@@ -20,7 +20,23 @@
- compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
-
- soc@01c00000 {
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
-+ cd-gpios = <&pio 6 0 0>; /* PG0 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
-+ allwinner,pins = "PG0";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_olinuxinom: led_pins@0 {
- allwinner,pins = "PG9";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
-@@ -23,7 +23,23 @@
- };
-
- soc@01c00000 {
-+ mmc0: mmc@01c0f000 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
-+ cd-gpios = <&pio 6 0 0>; /* PG0 */
-+ cd-mode = <1>;
-+ status = "okay";
-+ };
-+
- pinctrl@01c20800 {
-+ mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
-+ allwinner,pins = "PG0";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <0>;
-+ allwinner,pull = <0>;
-+ };
-+
- led_pins_olinuxino: led_pins@0 {
- allwinner,pins = "PG9";
- allwinner,function = "gpio_out";
---- a/arch/arm/boot/dts/sun5i-a13.dtsi
-+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
-@@ -274,6 +274,16 @@
- #size-cells = <1>;
- ranges;
-
-+ 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";
-+ };
-+
- intc: interrupt-controller@01c20400 {
- compatible = "allwinner,sun4i-ic";
- reg = <0x01c20400 0x400>;
-@@ -326,6 +336,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 {
--- /dev/null
+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
+
+++ /dev/null
-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 {
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
+++ /dev/null
---- 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;
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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: