sunxi: driver refresh for 3.13 - update gmac / mmc / usb / ahci drivers to follow mainline dev trees - add driver for spi - update clock support - update a31 support - move to new DT compats where appropriate - re-order patchqueue where needed - verified working a20 smp - move most DTSes off files/ - update defconfig

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>

SVN-Revision: 39782
This commit is contained in:
Zoltan Herpai 2014-03-06 00:09:30 +00:00
parent 2c771cc71f
commit ac4b9dbb3c
179 changed files with 14841 additions and 4719 deletions

View file

@ -1,4 +1,4 @@
# CONFIG_AHCI_SUNXI is not set
CONFIG_AHCI_SUNXI=y
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
@ -47,6 +47,7 @@ CONFIG_AUDIT=y
CONFIG_AUDIT_GENERIC=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_AVERAGE=y
CONFIG_BCH=y
CONFIG_BINFMT_MISC=y
CONFIG_BLK_CGROUP=y
CONFIG_BLK_DEV_SD=y
@ -139,6 +140,7 @@ CONFIG_EXT4_FS=y
CONFIG_FRAME_POINTER=y
CONFIG_FRAME_WARN=2048
CONFIG_FREEZER=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_GARP=y
CONFIG_GENERIC_ACL=y
@ -152,6 +154,7 @@ CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
@ -225,6 +228,7 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_IOSCHED_CFQ=y
CONFIG_IPC_NS=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@ -236,7 +240,6 @@ CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
# CONFIG_JFFS2_CMODE_PRIORITY is not set
CONFIG_KALLSYMS=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
@ -260,7 +263,6 @@ CONFIG_MMC_BLOCK=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MODULES_USE_ELF_REL=y
# CONFIG_MTD is not set
CONFIG_MULTI_IRQ_HANDLER=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
@ -284,6 +286,7 @@ CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
@ -294,6 +297,7 @@ CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PID_NS=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_SINGLE is not set
@ -340,7 +344,6 @@ CONFIG_RESOURCE_COUNTERS=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_SATA_AHCI_PLATFORM=y
# CONFIG_SATA_RCAR is not set
CONFIG_SCHED_HRTICK=y
CONFIG_SCSI=y
CONFIG_SECURITYFS=y
@ -360,6 +363,10 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_SUN4I=y
# CONFIG_SPI_SUN6I is not set
# CONFIG_STAGING is not set
# CONFIG_STMMAC_DA is not set
# CONFIG_STMMAC_DEBUG_FS is not set
@ -371,6 +378,7 @@ CONFIG_STRICT_DEVMEM=y
CONFIG_SUN4I_TIMER=y
CONFIG_SUN5I_HSTIMER=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_SWIOTLB=y
CONFIG_SWP_EMULATE=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TASKSTATS=y
@ -381,6 +389,7 @@ CONFIG_TASK_XACCT=y
# CONFIG_THUMB2_KERNEL is not set
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TOUCHSCREEN_SUN4I=y
CONFIG_TREE_PREEMPT_RCU=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UID16=y
@ -390,9 +399,8 @@ CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_HCD_PLATFORM is not set
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_SUNXI_EHCI=y
CONFIG_USB_SUPPORT=y
# CONFIG_USER_NS is not set
CONFIG_USE_OF=y

View file

@ -1,168 +0,0 @@
/*
* Copyright 2012 Stefan Roese
* Stefan Roese <sr@denx.de>
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
/include/ "sun4i-a10.dtsi"
/ {
model = "Olimex A10-Olinuxino LIME";
compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10";
soc@01c00000 {
emac: ethernet@01c0b000 {
pinctrl-names = "default";
pinctrl-0 = <&emac_pins_a>;
phy = <&phy1>;
status = "okay";
};
mdio@01c0b080 {
status = "okay";
phy1: ethernet-phy@1 {
reg = <1>;
};
};
sdc0: sdc@01c0f000 {
pinctrl-names = "default";
pinctrl-0 = <&sdc0_pins_a>;
pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
cd-gpios = <&pio 7 1 0>; /* PH1 */
cd-mode = <1>;
status = "okay";
};
sata: ahci@01c18000 {
pwr-supply = <&reg_ahci_5v>;
status = "okay";
};
pinctrl@01c20800 {
ahci_pwr_pin: ahci_pwr_pin@0 {
allwinner,pins = "PC3";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
allwinner,function = "gpio_out";
allwinner,drive = <1>;
allwinner,pull = <0>;
};
usb1_vbus_pin: usb1_vbus_pin@0 {
allwinner,pins = "PH6";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <2>;
};
usb2_vbus_pin: usb2_vbus_pin@0 {
allwinner,pins = "PH3";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <2>;
};
};
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
i2c0: i2c@01c2ac00 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
};
i2c1: i2c@01c2b000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
ehci0: ehci0@0x01c14000 {
vbus-supply = <&reg_usb1_vbus>;
status = "okay";
};
ehci1: ehci1@0x01c1c000 {
vbus-supply = <&reg_usb2_vbus>;
status = "okay";
};
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins_olinuxino>;
green {
label = "a10-olinuxino-lime:green:usr";
gpios = <&pio 7 2 0>;
default-state = "on";
};
};
regulators {
compatible = "simple-bus";
reg_usb1_vbus: usb1-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb1_vbus_pin>;
regulator-name = "usb1-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 6 0>;
};
reg_usb2_vbus: usb2-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb2_vbus_pin>;
regulator-name = "usb2-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 3 0>;
};
};
regulators {
compatible = "simple-bus";
pinctrl-names = "default";
reg_ahci_5v: ahci-5v {
compatible = "regulator-fixed";
regulator-name = "ahci-5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
pinctrl-0 = <&ahci_pwr_pin>;
gpio = <&pio 2 3 0>;
enable-active-high;
};
};
};

View file

@ -1,168 +0,0 @@
/*
* Copyright 2012 Stefan Roese
* Stefan Roese <sr@denx.de>
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
/include/ "sun4i-a10.dtsi"
/ {
model = "pcDuino";
compatible = "pcduino,a10-pcduino", "allwinner,sun4i-a10";
aliases {
serial0 = &uart0;
serial1 = &uart1;
};
chosen {
bootargs = "earlyprintk console=ttyS0,115200";
};
soc@01c00000 {
emac: ethernet@01c0b000 {
pinctrl-names = "default";
pinctrl-0 = <&emac_pins_a>;
phy = <&phy1>;
status = "okay";
};
mdio@01c0b080 {
status = "okay";
phy1: ethernet-phy@1 {
reg = <1>;
};
};
sdc0: sdc@01c0f000 {
pinctrl-names = "default";
pinctrl-0 = <&sdc0_pins_a>;
pinctrl-1 = <&mmc0_cd_pin_pcduino>;
cd-gpios = <&pio 7 1 0>; /* PH1 */
cd-mode = <1>;
status = "okay";
};
pinctrl@01c20800 {
mmc0_cd_pin_pcduino: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
led_pins_pcduino: led_pins@0 {
allwinner,pins = "PH20", "PH21";
allwinner,function = "gpio_out";
allwinner,drive = <1>;
allwinner,pull = <0>;
};
usb1_vbus_pin: usb1_vbus_pin@0 {
allwinner,pins = "PH6";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <2>;
};
usb2_vbus_pin: usb2_vbus_pin@0 {
allwinner,pins = "PH3";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <2>;
};
};
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
i2c0: i2c@01c2ac00 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
};
i2c1: i2c@01c2b000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
ehci0: ehci0@0x01c14000 {
vbus-supply = <&reg_usb1_vbus>;
status = "okay";
};
ehci1: ehci1@0x01c1c000 {
vbus-supply = <&reg_usb2_vbus>;
status = "okay";
};
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins_pcduino>;
blue {
label = "pcduino:blue:usr";
gpios = <&pio 7 21 0>; /* LED1 */
};
green {
label = "pcduino:green:usr";
gpios = <&pio 7 20 0>; /* LED2 */
linux,default-trigger = "heartbeat";
};
};
regulators {
compatible = "simple-bus";
reg_usb1_vbus: usb1-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb1_vbus_pin>;
regulator-name = "usb1-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 6 0>;
};
reg_usb2_vbus: usb2-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb2_vbus_pin>;
regulator-name = "usb2-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 3 0>;
};
};
regulators {
compatible = "simple-bus";
pinctrl-names = "default";
vcc_3v3_reg: regulator@0 {
compatible = "regulator-fixed";
regulator-name = "vcc_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};

View file

@ -19,45 +19,7 @@
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
soc@01c00000 {
sdc0: sdc@01c0f000 {
pinctrl-names = "default";
pinctrl-0 = <&sdc0_pins_a>;
pinctrl-1 = <&mmc0_cd_pin_cubietruck>;
cd-gpios = <&pio 7 1 0>; /* PH1 */
cd-mode = <1>;
status = "okay";
};
ehci0: ehci0@0x01c14000 {
vbus-supply = <&reg_usb1_vbus>;
status = "okay";
};
sata: ahci@01c18000 {
pwr-supply = <&reg_ahci_5v>;
status = "okay";
};
ehci1: ehci1@0x01c1c000 {
vbus-supply = <&reg_usb2_vbus>;
status = "okay";
};
pinctrl@01c20800 {
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
allwinner,pins = "PH12";
allwinner,function = "gpio_out";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
led_pins_cubietruck: led_pins@0 {
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
allwinner,function = "gpio_out";
@ -112,41 +74,4 @@
gpios = <&pio 7 7 0>;
};
};
regulators {
compatible = "simple-bus";
pinctrl-names = "default";
reg_ahci_5v: ahci-5v {
compatible = "regulator-fixed";
regulator-name = "ahci-5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
gpio = <&pio 7 12 0>;
enable-active-high;
};
reg_usb1_vbus: usb1-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb1_vbus_pin>;
regulator-name = "usb1-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 6 0>;
};
reg_usb2_vbus: usb2-vbus {
compatible = "regulator-fixed";
pinctrl-names = "default";
pinctrl-0 = <&usb2_vbus_pin>;
regulator-name = "usb2-vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
gpio = <&pio 7 3 0>;
};
};
};

View file

@ -1,908 +0,0 @@
/*
* Driver for sunxi SD/MMC host controllers
* (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
* (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
* (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
* (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
* (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/clk-private.h>
#include <linux/clk/sunxi.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sd.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include "sunxi-mci.h"
static void sunxi_mmc_init_host(struct mmc_host *mmc)
{
u32 rval;
struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
/* reset controller */
rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset;
mci_writel(smc_host, REG_GCTRL, rval);
mci_writel(smc_host, REG_FTRGL, 0x20070008);
mci_writel(smc_host, REG_TMOUT, 0xffffffff);
mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask);
mci_writel(smc_host, REG_RINTR, 0xffffffff);
mci_writel(smc_host, REG_DBGC, 0xdeb);
mci_writel(smc_host, REG_FUNS, 0xceaa0000);
mci_writel(smc_host, REG_DLBA, smc_host->sg_dma);
rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb;
rval &= ~SDXC_AccessDoneDirect;
mci_writel(smc_host, REG_GCTRL, rval);
}
static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host)
{
mci_writel(smc_host, REG_GCTRL, SDXC_HWReset);
}
/* /\* UHS-I Operation Modes */
/* * DS 25MHz 12.5MB/s 3.3V */
/* * HS 50MHz 25MB/s 3.3V */
/* * SDR12 25MHz 12.5MB/s 1.8V */
/* * SDR25 50MHz 25MB/s 1.8V */
/* * SDR50 100MHz 50MB/s 1.8V */
/* * SDR104 208MHz 104MB/s 1.8V */
/* * DDR50 50MHz 50MB/s 1.8V */
/* * MMC Operation Modes */
/* * DS 26MHz 26MB/s 3/1.8/1.2V */
/* * HS 52MHz 52MB/s 3/1.8/1.2V */
/* * HSDDR 52MHz 104MB/s 3/1.8/1.2V */
/* * HS200 200MHz 200MB/s 1.8/1.2V */
/* * */
/* * Spec. Timing */
/* * SD3.0 */
/* * Fcclk Tcclk Fsclk Tsclk Tis Tih odly RTis RTih */
/* * 400K 2.5us 24M 41ns 5ns 5ns 1 2209ns 41ns */
/* * 25M 40ns 600M 1.67ns 5ns 5ns 3 14.99ns 5.01ns */
/* * 50M 20ns 600M 1.67ns 6ns 2ns 3 14.99ns 5.01ns */
/* * 50MDDR 20ns 600M 1.67ns 6ns 0.8ns 2 6.67ns 3.33ns */
/* * 104M 9.6ns 600M 1.67ns 3ns 0.8ns 1 7.93ns 1.67ns */
/* * 208M 4.8ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
/* * 25M 40ns 300M 3.33ns 5ns 5ns 2 13.34ns 6.66ns */
/* * 50M 20ns 300M 3.33ns 6ns 2ns 2 13.34ns 6.66ns */
/* * 50MDDR 20ns 300M 3.33ns 6ns 0.8ns 1 6.67ns 3.33ns */
/* * 104M 9.6ns 300M 3.33ns 3ns 0.8ns 0 7.93ns 1.67ns */
/* * 208M 4.8ns 300M 3.33ns 1.4ns 0.8ns 0 3.13ns 1.67ns */
/* * eMMC4.5 */
/* * 400K 2.5us 24M 41ns 3ns 3ns 1 2209ns 41ns */
/* * 25M 40ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
/* * 50M 20ns 600M 1.67ns 3ns 3ns 3 14.99ns 5.01ns */
/* * 50MDDR 20ns 600M 1.67ns 2.5ns 2.5ns 2 6.67ns 3.33ns */
/* * 200M 5ns 600M 1.67ns 1.4ns 0.8ns 1 3.33ns 1.67ns */
/* *\/ */
static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
struct mmc_data *data)
{
struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
int i, max_len = (1 << host->idma_des_size_bits);
for (i = 0; i < data->sg_len; i++) {
pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN |
SDXC_IDMAC_DES0_DIC;
if (data->sg[i].length == max_len)
pdes[i].buf_size = 0; /* 0 == max_len */
else
pdes[i].buf_size = data->sg[i].length;
pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
}
pdes[0].config |= SDXC_IDMAC_DES0_FD;
pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD;
wmb(); /* Ensure idma_des hit main mem before we start the idmac */
}
static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data)
{
if (data->flags & MMC_DATA_WRITE)
return DMA_TO_DEVICE;
else
return DMA_FROM_DEVICE;
}
static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host,
struct mmc_data *data)
{
u32 dma_len;
u32 i;
u32 temp;
struct scatterlist *sg;
dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len,
sunxi_mmc_get_dma_dir(data));
if (dma_len == 0) {
dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n");
return -ENOMEM;
}
for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->offset & 3 || sg->length & 3) {
dev_err(mmc_dev(smc_host->mmc),
"unaligned scatterlist: os %x length %d\n",
sg->offset, sg->length);
return -EINVAL;
}
}
sunxi_mmc_init_idma_des(smc_host, data);
temp = mci_readl(smc_host, REG_GCTRL);
temp |= SDXC_DMAEnb;
mci_writel(smc_host, REG_GCTRL, temp);
temp |= SDXC_DMAReset;
mci_writel(smc_host, REG_GCTRL, temp);
mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST);
if (!(data->flags & MMC_DATA_WRITE))
mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt);
mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn);
return 0;
}
static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
struct mmc_request *req)
{
u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD
| SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION;
u32 ri = 0;
unsigned long expire = jiffies + msecs_to_jiffies(1000);
mci_writel(host, REG_CARG, 0);
mci_writel(host, REG_CMDR, cmd_val);
do {
ri = mci_readl(host, REG_RINTR);
} while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) &&
time_before(jiffies, expire));
if (ri & SDXC_IntErrBit) {
dev_err(mmc_dev(host->mmc), "send stop command failed\n");
if (req->stop)
req->stop->resp[0] = -ETIMEDOUT;
} else {
if (req->stop)
req->stop->resp[0] = mci_readl(host, REG_RESP0);
}
mci_writel(host, REG_RINTR, 0xffff);
}
static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host)
{
struct mmc_command *cmd = smc_host->mrq->cmd;
struct mmc_data *data = smc_host->mrq->data;
/* For some cmds timeout is normal with sd/mmc cards */
if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout &&
(cmd->opcode == 5 || cmd->opcode == 52))
return;
dev_err(mmc_dev(smc_host->mmc),
"smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
smc_host->mmc->index, cmd->opcode,
data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
smc_host->int_sum & SDXC_RespErr ? " RE" : "",
smc_host->int_sum & SDXC_RespCRCErr ? " RCE" : "",
smc_host->int_sum & SDXC_DataCRCErr ? " DCE" : "",
smc_host->int_sum & SDXC_RespTimeout ? " RTO" : "",
smc_host->int_sum & SDXC_DataTimeout ? " DTO" : "",
smc_host->int_sum & SDXC_FIFORunErr ? " FE" : "",
smc_host->int_sum & SDXC_HardWLocked ? " HL" : "",
smc_host->int_sum & SDXC_StartBitErr ? " SBE" : "",
smc_host->int_sum & SDXC_EndBitErr ? " EBE" : ""
);
}
static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host)
{
struct mmc_request *mrq;
unsigned long iflags;
spin_lock_irqsave(&host->lock, iflags);
mrq = host->mrq;
if (!mrq) {
spin_unlock_irqrestore(&host->lock, iflags);
dev_err(mmc_dev(host->mmc), "no request to finalize\n");
return;
}
if (host->int_sum & SDXC_IntErrBit) {
sunxi_mmc_dump_errinfo(host);
mrq->cmd->error = -ETIMEDOUT;
if (mrq->data)
mrq->data->error = -ETIMEDOUT;
if (mrq->stop)
mrq->stop->error = -ETIMEDOUT;
} else {
if (mrq->cmd->flags & MMC_RSP_136) {
mrq->cmd->resp[0] = mci_readl(host, REG_RESP3);
mrq->cmd->resp[1] = mci_readl(host, REG_RESP2);
mrq->cmd->resp[2] = mci_readl(host, REG_RESP1);
mrq->cmd->resp[3] = mci_readl(host, REG_RESP0);
} else {
mrq->cmd->resp[0] = mci_readl(host, REG_RESP0);
}
if (mrq->data)
mrq->data->bytes_xfered =
mrq->data->blocks * mrq->data->blksz;
}
if (mrq->data) {
struct mmc_data *data = mrq->data;
u32 temp;
mci_writel(host, REG_IDST, 0x337);
mci_writel(host, REG_DMAC, 0);
temp = mci_readl(host, REG_GCTRL);
mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset);
temp &= ~SDXC_DMAEnb;
mci_writel(host, REG_GCTRL, temp);
temp |= SDXC_FIFOReset;
mci_writel(host, REG_GCTRL, temp);
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
sunxi_mmc_get_dma_dir(data));
}
mci_writel(host, REG_RINTR, 0xffff);
dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n",
mrq->cmd->resp[0], mrq->cmd->resp[1],
mrq->cmd->resp[2], mrq->cmd->resp[3]);
host->mrq = NULL;
host->int_sum = 0;
host->wait_dma = 0;
spin_unlock_irqrestore(&host->lock, iflags);
if (mrq->data && mrq->data->error) {
dev_err(mmc_dev(host->mmc),
"data error, sending stop command\n");
sunxi_mmc_send_manual_stop(host, mrq);
}
mmc_request_done(host->mmc, mrq);
}
static s32 sunxi_mmc_get_ro(struct mmc_host *mmc)
{
struct sunxi_mmc_host *host = mmc_priv(mmc);
int read_only = 0;
if (gpio_is_valid(host->wp_pin)) {
pinctrl_request_gpio(host->wp_pin);
read_only = gpio_get_value(host->wp_pin);
}
return read_only;
}
static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id)
{
struct sunxi_mmc_host *host = dev_id;
u32 finalize = 0;
u32 sdio_int = 0;
u32 msk_int;
u32 idma_int;
spin_lock(&host->lock);
idma_int = mci_readl(host, REG_IDST);
msk_int = mci_readl(host, REG_MISTA);
dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n",
host->mrq, msk_int, idma_int);
if (host->mrq) {
if (idma_int & SDXC_IDMACReceiveInt)
host->wait_dma = 0;
host->int_sum |= msk_int;
/* Wait for CmdDone on RespTimeout before finishing the req */
if ((host->int_sum & SDXC_RespTimeout) &&
!(host->int_sum & SDXC_CmdDone))
mci_writel(host, REG_IMASK,
host->sdio_imask | SDXC_CmdDone);
else if (host->int_sum & SDXC_IntErrBit)
finalize = 1; /* Don't wait for dma on error */
else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma)
finalize = 1; /* Done */
if (finalize) {
mci_writel(host, REG_IMASK, host->sdio_imask);
mci_writel(host, REG_IDIE, 0);
}
}
if (msk_int & SDXC_SDIOInt)
sdio_int = 1;
mci_writel(host, REG_RINTR, msk_int);
mci_writel(host, REG_IDST, idma_int);
spin_unlock(&host->lock);
if (finalize)
tasklet_schedule(&host->tasklet);
if (sdio_int)
mmc_signal_sdio_irq(host->mmc);
return IRQ_HANDLED;
}
static void sunxi_mmc_tasklet(unsigned long data)
{
struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data;
sunxi_mmc_finalize_request(smc_host);
}
static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
{
unsigned long expire = jiffies + msecs_to_jiffies(2000);
u32 rval;
rval = mci_readl(host, REG_CLKCR);
rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn);
if (oclk_en)
rval |= SDXC_CardClkOn;
if (!host->io_flag)
rval |= SDXC_LowPowerOn;
mci_writel(host, REG_CLKCR, rval);
rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver;
if (host->voltage_switching)
rval |= SDXC_VolSwitch;
mci_writel(host, REG_CMDR, rval);
do {
rval = mci_readl(host, REG_CMDR);
} while (time_before(jiffies, expire) && (rval & SDXC_Start));
if (rval & SDXC_Start) {
dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
host->ferror = 1;
}
}
static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
u32 oclk_dly, u32 sclk_dly)
{
unsigned long iflags;
struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
spin_lock_irqsave(&smc_host->lock, iflags);
clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
spin_unlock_irqrestore(&smc_host->lock, iflags);
}
struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
{ MMC_CLK_400K, 0, 7 },
{ MMC_CLK_25M, 0, 5 },
{ MMC_CLK_50M, 3, 5 },
{ MMC_CLK_50MDDR, 2, 4 },
{ MMC_CLK_50MDDR_8BIT, 2, 4 },
{ MMC_CLK_100M, 1, 4 },
{ MMC_CLK_200M, 1, 4 },
};
static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
unsigned int rate)
{
u32 newrate;
u32 src_clk;
u32 oclk_dly;
u32 sclk_dly;
u32 temp;
struct sunxi_mmc_clk_dly *dly = NULL;
newrate = clk_round_rate(smc_host->clk_mod, rate);
if (smc_host->clk_mod_rate == newrate) {
dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n",
rate, newrate);
return;
}
dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n",
rate, newrate);
/* setting clock rate */
clk_disable(smc_host->clk_mod);
clk_set_rate(smc_host->clk_mod, newrate);
clk_enable(smc_host->clk_mod);
smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod);
dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate);
sunxi_mmc_oclk_onoff(smc_host, 0);
/* clear internal divider */
temp = mci_readl(smc_host, REG_CLKCR);
temp &= ~0xff;
mci_writel(smc_host, REG_CLKCR, temp);
/* determine delays */
if (rate <= 400000) {
dly = &mmc_clk_dly[MMC_CLK_400K];
} else if (rate <= 25000000) {
dly = &mmc_clk_dly[MMC_CLK_25M];
} else if (rate <= 50000000) {
if (smc_host->ddr) {
if (smc_host->bus_width == 8)
dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT];
else
dly = &mmc_clk_dly[MMC_CLK_50MDDR];
} else {
dly = &mmc_clk_dly[MMC_CLK_50M];
}
} else if (rate <= 104000000) {
dly = &mmc_clk_dly[MMC_CLK_100M];
} else if (rate <= 208000000) {
dly = &mmc_clk_dly[MMC_CLK_200M];
} else
dly = &mmc_clk_dly[MMC_CLK_50M];
oclk_dly = dly->oclk_dly;
sclk_dly = dly->sclk_dly;
src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod));
if (src_clk >= 300000000 && src_clk <= 400000000) {
if (oclk_dly)
oclk_dly--;
if (sclk_dly)
sclk_dly--;
}
sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
sunxi_mmc_oclk_onoff(smc_host, 1);
/* oclk_onoff sets various irq status bits, clear these */
mci_writel(smc_host, REG_RINTR,
mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt);
}
static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sunxi_mmc_host *host = mmc_priv(mmc);
u32 temp;
s32 err;
/* Set the power state */
switch (ios->power_mode) {
case MMC_POWER_ON:
break;
case MMC_POWER_UP:
if (!IS_ERR(host->vmmc)) {
mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd);
udelay(200);
}
err = clk_prepare_enable(host->clk_ahb);
if (err) {
dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err);
host->ferror = 1;
return;
}
err = clk_prepare_enable(host->clk_mod);
if (err) {
dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err);
host->ferror = 1;
return;
}
sunxi_mmc_init_host(mmc);
enable_irq(host->irq);
dev_dbg(mmc_dev(host->mmc), "power on!\n");
host->ferror = 0;
break;
case MMC_POWER_OFF:
dev_dbg(mmc_dev(host->mmc), "power off!\n");
disable_irq(host->irq);
sunxi_mmc_exit_host(host);
clk_disable_unprepare(host->clk_ahb);
clk_disable_unprepare(host->clk_mod);
if (!IS_ERR(host->vmmc))
mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
host->ferror = 0;
break;
}
/* set bus width */
switch (ios->bus_width) {
case MMC_BUS_WIDTH_1:
mci_writel(host, REG_WIDTH, SDXC_WIDTH1);
host->bus_width = 1;
break;
case MMC_BUS_WIDTH_4:
mci_writel(host, REG_WIDTH, SDXC_WIDTH4);
host->bus_width = 4;
break;
case MMC_BUS_WIDTH_8:
mci_writel(host, REG_WIDTH, SDXC_WIDTH8);
host->bus_width = 8;
break;
}
/* set ddr mode */
temp = mci_readl(host, REG_GCTRL);
if (ios->timing == MMC_TIMING_UHS_DDR50) {
temp |= SDXC_DDR_MODE;
host->ddr = 1;
} else {
temp &= ~SDXC_DDR_MODE;
host->ddr = 0;
}
mci_writel(host, REG_GCTRL, temp);
/* set up clock */
if (ios->clock && ios->power_mode) {
dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock);
sunxi_mmc_clk_set_rate(host, ios->clock);
usleep_range(50000, 55000);
}
}
static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
unsigned long flags;
u32 imask;
spin_lock_irqsave(&smc_host->lock, flags);
imask = mci_readl(smc_host, REG_IMASK);
if (enable) {
smc_host->sdio_imask = SDXC_SDIOInt;
imask |= SDXC_SDIOInt;
} else {
smc_host->sdio_imask = 0;
imask &= ~SDXC_SDIOInt;
}
mci_writel(smc_host, REG_IMASK, imask);
spin_unlock_irqrestore(&smc_host->lock, flags);
}
static void sunxi_mmc_hw_reset(struct mmc_host *mmc)
{
struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
mci_writel(smc_host, REG_HWRST, 0);
udelay(10);
mci_writel(smc_host, REG_HWRST, 1);
udelay(300);
}
static int sunxi_mmc_card_present(struct mmc_host *mmc)
{
struct sunxi_mmc_host *host = mmc_priv(mmc);
switch (host->cd_mode) {
case CARD_DETECT_BY_GPIO_POLL:
return !gpio_get_value(host->cd_pin); /* Signal inverted */
case CARD_ALWAYS_PRESENT:
return 1;
}
return 0; /* Never reached */
}
static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sunxi_mmc_host *host = mmc_priv(mmc);
struct mmc_command *cmd = mrq->cmd;
struct mmc_data *data = mrq->data;
unsigned long iflags;
u32 imask = SDXC_IntErrBit;
u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f);
u32 byte_cnt = 0;
int ret;
if (!sunxi_mmc_card_present(mmc) || host->ferror) {
dev_dbg(mmc_dev(host->mmc), "no medium present\n");
mrq->cmd->error = -ENOMEDIUM;
mmc_request_done(mmc, mrq);
return;
}
if (data) {
byte_cnt = data->blksz * data->blocks;
mci_writel(host, REG_BLKSZ, data->blksz);
mci_writel(host, REG_BCNTR, byte_cnt);
ret = sunxi_mmc_prepare_dma(host, data);
if (ret < 0) {
dev_err(mmc_dev(host->mmc), "prepare DMA failed\n");
cmd->error = ret;
cmd->data->error = ret;
mmc_request_done(host->mmc, mrq);
return;
}
}
if (cmd->opcode == MMC_GO_IDLE_STATE) {
cmd_val |= SDXC_SendInitSeq;
imask |= SDXC_CmdDone;
}
if (cmd->opcode == SD_SWITCH_VOLTAGE) {
cmd_val |= SDXC_VolSwitch;
imask |= SDXC_VolChgDone;
host->voltage_switching = 1;
sunxi_mmc_oclk_onoff(host, 1);
}
if (cmd->flags & MMC_RSP_PRESENT) {
cmd_val |= SDXC_RspExp;
if (cmd->flags & MMC_RSP_136)
cmd_val |= SDXC_LongRsp;
if (cmd->flags & MMC_RSP_CRC)
cmd_val |= SDXC_CheckRspCRC;
if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) {
cmd_val |= SDXC_DataExp | SDXC_WaitPreOver;
if (cmd->data->flags & MMC_DATA_STREAM) {
imask |= SDXC_AutoCMDDone;
cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop;
}
if (cmd->data->stop) {
imask |= SDXC_AutoCMDDone;
cmd_val |= SDXC_SendAutoStop;
} else
imask |= SDXC_DataOver;
if (cmd->data->flags & MMC_DATA_WRITE)
cmd_val |= SDXC_Write;
else
host->wait_dma = 1;
} else
imask |= SDXC_CmdDone;
} else
imask |= SDXC_CmdDone;
dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n",
cmd_val & 0x3f, cmd_val, cmd->arg, imask,
mrq->data ? mrq->data->blksz * mrq->data->blocks : 0);
spin_lock_irqsave(&host->lock, iflags);
host->mrq = mrq;
mci_writel(host, REG_IMASK, host->sdio_imask | imask);
spin_unlock_irqrestore(&host->lock, iflags);
mci_writel(host, REG_CARG, cmd->arg);
mci_writel(host, REG_CMDR, cmd_val);
}
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-mmc", },
{ .compatible = "allwinner,sun5i-mmc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
static struct mmc_host_ops sunxi_mmc_ops = {
.request = sunxi_mmc_request,
.set_ios = sunxi_mmc_set_ios,
.get_ro = sunxi_mmc_get_ro,
.get_cd = sunxi_mmc_card_present,
.enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
.hw_reset = sunxi_mmc_hw_reset,
};
static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int ret;
if (of_device_is_compatible(np, "allwinner,sun4i-mmc"))
host->idma_des_size_bits = 13;
else
host->idma_des_size_bits = 16;
host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc");
if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
host->reg_base = devm_ioremap_resource(&pdev->dev,
platform_get_resource(pdev, IORESOURCE_MEM, 0));
if (IS_ERR(host->reg_base))
return PTR_ERR(host->reg_base);
host->irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0,
"sunxi-mci", host);
if (ret)
return ret;
disable_irq(host->irq);
host->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(host->clk_ahb)) {
dev_err(&pdev->dev, "Could not get ahb clock\n");
return PTR_ERR(host->clk_ahb);
}
host->clk_mod = devm_clk_get(&pdev->dev, "mod");
if (IS_ERR(host->clk_mod)) {
dev_err(&pdev->dev, "Could not get mod clock\n");
return PTR_ERR(host->clk_mod);
}
of_property_read_u32(np, "bus-width", &host->bus_width);
if (host->bus_width != 1 && host->bus_width != 4) {
dev_err(&pdev->dev, "Invalid bus-width %d\n", host->bus_width);
return -EINVAL;
}
of_property_read_u32(np, "cd-mode", &host->cd_mode);
switch (host->cd_mode) {
case CARD_DETECT_BY_GPIO_POLL:
host->cd_pin = of_get_named_gpio(np, "cd-gpios", 0);
if (!gpio_is_valid(host->cd_pin)) {
dev_err(&pdev->dev, "Invalid cd-gpios\n");
return -EINVAL;
}
ret = devm_gpio_request(&pdev->dev, host->cd_pin, "mmc_cd");
if (ret) {
dev_err(&pdev->dev, "Could not get cd-gpios\n");
return ret;
}
gpio_direction_input(host->cd_pin);
break;
case CARD_ALWAYS_PRESENT:
break;
default:
dev_err(&pdev->dev, "Invalid cd-mode %d\n", host->cd_mode);
return -EINVAL;
}
host->wp_pin = of_get_named_gpio(np, "wp-gpios", 0);
if (gpio_is_valid(host->wp_pin)) {
ret = devm_gpio_request(&pdev->dev, host->wp_pin, "mmc_wp");
if (ret) {
dev_err(&pdev->dev, "Could not get wp-gpios\n");
return ret;
}
gpio_direction_input(host->wp_pin);
}
return 0;
}
static int sunxi_mmc_probe(struct platform_device *pdev)
{
struct sunxi_mmc_host *host;
struct mmc_host *mmc;
int ret;
mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
if (!mmc) {
dev_err(&pdev->dev, "mmc alloc host failed\n");
return -ENOMEM;
}
host = mmc_priv(mmc);
host->mmc = mmc;
spin_lock_init(&host->lock);
tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host);
ret = sunxi_mmc_resource_request(host, pdev);
if (ret)
goto error_free_host;
host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
if (!host->sg_cpu) {
dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n");
ret = -ENOMEM;
goto error_free_host;
}
mmc->ops = &sunxi_mmc_ops;
mmc->max_blk_count = 8192;
mmc->max_blk_size = 4096;
mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des);
mmc->max_seg_size = (1 << host->idma_des_size_bits);
mmc->max_req_size = mmc->max_seg_size * mmc->max_segs;
/* 400kHz ~ 50MHz */
mmc->f_min = 400000;
mmc->f_max = 50000000;
/* available voltages */
if (!IS_ERR(host->vmmc))
mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc);
else
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL |
MMC_CAP_DRIVER_TYPE_A;
if (host->bus_width == 4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
ret = mmc_add_host(mmc);
if (ret)
goto error_free_dma;
dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq);
platform_set_drvdata(pdev, mmc);
return 0;
error_free_dma:
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
error_free_host:
mmc_free_host(mmc);
return ret;
}
static int sunxi_mmc_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct sunxi_mmc_host *host = mmc_priv(mmc);
mmc_remove_host(mmc);
sunxi_mmc_exit_host(host);
tasklet_disable(&host->tasklet);
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
mmc_free_host(mmc);
return 0;
}
static struct platform_driver sunxi_mmc_driver = {
.driver = {
.name = "sunxi-mci",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(sunxi_mmc_of_match),
},
.probe = sunxi_mmc_probe,
.remove = sunxi_mmc_remove,
};
module_platform_driver(sunxi_mmc_driver);
MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("David Lanzendörfer <david.lanzendoerfer@o2s.ch>");
MODULE_ALIAS("platform:sunxi-mmc");

View file

@ -1,246 +0,0 @@
/*
* Driver for sunxi SD/MMC host controllers
* (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
* (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
* (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
* (C) Copyright 2013-2013 David Lanzendörfer <david.lanzendoerfer@o2s.ch>
* (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
#ifndef __SUNXI_MCI_H__
#define __SUNXI_MCI_H__
/* register offset define */
#define SDXC_REG_GCTRL (0x00) /* SMC Global Control Register */
#define SDXC_REG_CLKCR (0x04) /* SMC Clock Control Register */
#define SDXC_REG_TMOUT (0x08) /* SMC Time Out Register */
#define SDXC_REG_WIDTH (0x0C) /* SMC Bus Width Register */
#define SDXC_REG_BLKSZ (0x10) /* SMC Block Size Register */
#define SDXC_REG_BCNTR (0x14) /* SMC Byte Count Register */
#define SDXC_REG_CMDR (0x18) /* SMC Command Register */
#define SDXC_REG_CARG (0x1C) /* SMC Argument Register */
#define SDXC_REG_RESP0 (0x20) /* SMC Response Register 0 */
#define SDXC_REG_RESP1 (0x24) /* SMC Response Register 1 */
#define SDXC_REG_RESP2 (0x28) /* SMC Response Register 2 */
#define SDXC_REG_RESP3 (0x2C) /* SMC Response Register 3 */
#define SDXC_REG_IMASK (0x30) /* SMC Interrupt Mask Register */
#define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */
#define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */
#define SDXC_REG_STAS (0x3C) /* SMC Status Register */
#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */
#define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */
#define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */
#define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */
#define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */
#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */
#define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */
#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */
#define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */
#define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */
#define SDXC_REG_CHDA (0x90)
#define SDXC_REG_CBDA (0x94)
#define mci_readl(host, reg) \
__raw_readl((host)->reg_base + SDXC_##reg)
#define mci_writel(host, reg, value) \
__raw_writel((value), (host)->reg_base + SDXC_##reg)
/* global control register bits */
#define SDXC_SoftReset BIT(0)
#define SDXC_FIFOReset BIT(1)
#define SDXC_DMAReset BIT(2)
#define SDXC_HWReset (SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset)
#define SDXC_INTEnb BIT(4)
#define SDXC_DMAEnb BIT(5)
#define SDXC_DebounceEnb BIT(8)
#define SDXC_PosedgeLatchData BIT(9)
#define SDXC_DDR_MODE BIT(10)
#define SDXC_MemAccessDone BIT(29)
#define SDXC_AccessDoneDirect BIT(30)
#define SDXC_ACCESS_BY_AHB BIT(31)
#define SDXC_ACCESS_BY_DMA (0U << 31)
/* clock control bits */
#define SDXC_CardClkOn BIT(16)
#define SDXC_LowPowerOn BIT(17)
/* bus width */
#define SDXC_WIDTH1 (0)
#define SDXC_WIDTH4 (1)
#define SDXC_WIDTH8 (2)
/* smc command bits */
#define SDXC_RspExp BIT(6)
#define SDXC_LongRsp BIT(7)
#define SDXC_CheckRspCRC BIT(8)
#define SDXC_DataExp BIT(9)
#define SDXC_Write BIT(10)
#define SDXC_Seqmod BIT(11)
#define SDXC_SendAutoStop BIT(12)
#define SDXC_WaitPreOver BIT(13)
#define SDXC_StopAbortCMD BIT(14)
#define SDXC_SendInitSeq BIT(15)
#define SDXC_UPCLKOnly BIT(21)
#define SDXC_RdCEATADev BIT(22)
#define SDXC_CCSExp BIT(23)
#define SDXC_EnbBoot BIT(24)
#define SDXC_AltBootOpt BIT(25)
#define SDXC_BootACKExp BIT(26)
#define SDXC_BootAbort BIT(27)
#define SDXC_VolSwitch BIT(28)
#define SDXC_UseHoldReg BIT(29)
#define SDXC_Start BIT(31)
/* interrupt bits */
#define SDXC_RespErr BIT(1)
#define SDXC_CmdDone BIT(2)
#define SDXC_DataOver BIT(3)
#define SDXC_TxDataReq BIT(4)
#define SDXC_RxDataReq BIT(5)
#define SDXC_RespCRCErr BIT(6)
#define SDXC_DataCRCErr BIT(7)
#define SDXC_RespTimeout BIT(8)
#define SDXC_DataTimeout BIT(9)
#define SDXC_VolChgDone BIT(10)
#define SDXC_FIFORunErr BIT(11)
#define SDXC_HardWLocked BIT(12)
#define SDXC_StartBitErr BIT(13)
#define SDXC_AutoCMDDone BIT(14)
#define SDXC_EndBitErr BIT(15)
#define SDXC_SDIOInt BIT(16)
#define SDXC_CardInsert BIT(30)
#define SDXC_CardRemove BIT(31)
#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | \
SDXC_DataCRCErr | SDXC_RespTimeout | \
SDXC_DataTimeout | SDXC_FIFORunErr | \
SDXC_HardWLocked | SDXC_StartBitErr | \
SDXC_EndBitErr) /* 0xbbc2 */
#define SDXC_IntDoneBit (SDXC_AutoCMDDone | SDXC_DataOver | \
SDXC_CmdDone | SDXC_VolChgDone)
/* status */
#define SDXC_RXWLFlag BIT(0)
#define SDXC_TXWLFlag BIT(1)
#define SDXC_FIFOEmpty BIT(2)
#define SDXC_FIFOFull BIT(3)
#define SDXC_CardPresent BIT(8)
#define SDXC_CardDataBusy BIT(9)
#define SDXC_DataFSMBusy BIT(10)
#define SDXC_DMAReq BIT(31)
#define SDXC_FIFO_SIZE (16)
/* Function select */
#define SDXC_CEATAOn (0xceaaU << 16)
#define SDXC_SendIrqRsp BIT(0)
#define SDXC_SDIORdWait BIT(1)
#define SDXC_AbtRdData BIT(2)
#define SDXC_SendCCSD BIT(8)
#define SDXC_SendAutoStopCCSD BIT(9)
#define SDXC_CEATADevIntEnb BIT(10)
/* IDMA controller bus mod bit field */
#define SDXC_IDMACSoftRST BIT(0)
#define SDXC_IDMACFixBurst BIT(1)
#define SDXC_IDMACIDMAOn BIT(7)
#define SDXC_IDMACRefetchDES BIT(31)
/* IDMA status bit field */
#define SDXC_IDMACTransmitInt BIT(0)
#define SDXC_IDMACReceiveInt BIT(1)
#define SDXC_IDMACFatalBusErr BIT(2)
#define SDXC_IDMACDesInvalid BIT(4)
#define SDXC_IDMACCardErrSum BIT(5)
#define SDXC_IDMACNormalIntSum BIT(8)
#define SDXC_IDMACAbnormalIntSum BIT(9)
#define SDXC_IDMACHostAbtInTx BIT(10)
#define SDXC_IDMACHostAbtInRx BIT(10)
#define SDXC_IDMACIdle (0U << 13)
#define SDXC_IDMACSuspend (1U << 13)
#define SDXC_IDMACDESCRd (2U << 13)
#define SDXC_IDMACDESCCheck (3U << 13)
#define SDXC_IDMACRdReqWait (4U << 13)
#define SDXC_IDMACWrReqWait (5U << 13)
#define SDXC_IDMACRd (6U << 13)
#define SDXC_IDMACWr (7U << 13)
#define SDXC_IDMACDESCClose (8U << 13)
struct sunxi_idma_des {
u32 config;
#define SDXC_IDMAC_DES0_DIC BIT(1) /* disable interrupt on completion */
#define SDXC_IDMAC_DES0_LD BIT(2) /* last descriptor */
#define SDXC_IDMAC_DES0_FD BIT(3) /* first descriptor */
#define SDXC_IDMAC_DES0_CH BIT(4) /* chain mode */
#define SDXC_IDMAC_DES0_ER BIT(5) /* end of ring */
#define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */
#define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */
/*
* If the idma-des-size-bits of property is ie 13, bufsize bits are:
* Bits 0-12: buf1 size
* Bits 13-25: buf2 size
* Bits 26-31: not used
* Since we only ever set buf1 size, we can simply store it directly.
*/
u32 buf_size;
u32 buf_addr_ptr1;
u32 buf_addr_ptr2;
};
struct sunxi_mmc_host {
struct mmc_host *mmc;
struct regulator *vmmc;
/* IO mapping base */
void __iomem *reg_base;
spinlock_t lock;
struct tasklet_struct tasklet;
/* clock management */
struct clk *clk_ahb;
struct clk *clk_mod;
/* indicator pins */
int wp_pin;
int cd_pin;
int cd_mode;
#define CARD_DETECT_BY_GPIO_POLL (1) /* mmc detected by gpio check */
#define CARD_ALWAYS_PRESENT (2) /* mmc always present */
/* ios information */
u32 clk_mod_rate;
u32 bus_width;
u32 idma_des_size_bits;
u32 ddr;
u32 voltage_switching;
/* irq */
int irq;
u32 int_sum;
u32 sdio_imask;
/* flags */
u32 power_on:1;
u32 io_flag:1;
u32 wait_dma:1;
dma_addr_t sg_dma;
void *sg_cpu;
struct mmc_request *mrq;
u32 ferror;
};
#define MMC_CLK_400K 0
#define MMC_CLK_25M 1
#define MMC_CLK_50M 2
#define MMC_CLK_50MDDR 3
#define MMC_CLK_50MDDR_8BIT 4
#define MMC_CLK_100M 5
#define MMC_CLK_200M 6
#define MMC_CLK_MOD_NUM 7
struct sunxi_mmc_clk_dly {
u32 mode;
u32 oclk_dly;
u32 sclk_dly;
};
#endif

View file

@ -1,95 +0,0 @@
From 9490107c16c8eaa35b07794e19d5d2eddea8e44b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Sat, 14 Sep 2013 20:48:40 -0300
Subject: [PATCH] clk: sunxi: Implement muxable AHB clock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
sun5i and sun7i have a mux to change the AHB clock parent, this commit
adds support for it on the driver.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
drivers/clk/sunxi/clk-sunxi.c | 37 +++++++++++++++++++++++
2 files changed, 38 insertions(+)
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -15,6 +15,7 @@ Required properties:
"allwinner,sun4i-axi-clk" - for the AXI clock
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-ahb-clk" - for the AHB clock
+ "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
"allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -249,7 +249,32 @@ static void sun4i_get_pll5_factors(u32 *
*n = DIV_ROUND_UP(div, (*k+1));
}
+/**
+ * sun5i_get_ahb_factors() - calculates p factor for AHB
+ * AHB rate is calculated as follows
+ * rate = parent_rate >> p
+ */
+
+static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /* This clock can only divide, so we will never achieve a higher
+ * rate than the parent's */
+ if (*freq > parent_rate)
+ *freq = parent_rate;
+
+ /* Normalize value to a parent multiple */
+ div = *freq / parent_rate;
+ *freq = parent_rate * div;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+ *p = div;
+}
/**
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
@@ -375,6 +400,11 @@ static struct clk_factors_config sun4i_p
.kwidth = 2,
};
+static struct clk_factors_config sun5i_a13_ahb_config = {
+ .pshift = 4,
+ .pwidth = 2,
+};
+
static struct clk_factors_config sun4i_apb1_config = {
.mshift = 0,
.mwidth = 5,
@@ -408,6 +438,12 @@ static const struct factors_data sun4i_p
.getter = sun4i_get_pll5_factors,
};
+static const struct factors_data sun5i_a13_ahb_data __initconst = {
+ .mux = 6,
+ .table = &sun5i_a13_ahb_config,
+ .getter = sun5i_a13_get_ahb_factors,
+};
+
static const struct factors_data sun4i_apb1_data __initconst = {
.table = &sun4i_apb1_config,
.getter = sun4i_get_apb1_factors,
@@ -916,6 +952,7 @@ free_clkdata:
static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+ {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,},
{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
{.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
{}

View file

@ -1,60 +0,0 @@
From c8fe5648aff581545ce5744f73ee1312080b8ef4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Sat, 14 Sep 2013 20:44:03 -0300
Subject: [PATCH] ARM: sunxi: dt: Update AHB clock to be muxable on sun[57]i
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
sun5i and sun7i have a mux to select the parent clock for AHB. This
commit implements the required changes on the device trees.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 4 ++--
arch/arm/boot/dts/sun5i-a13.dtsi | 4 ++--
arch/arm/boot/dts/sun7i-a20.dtsi | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -111,9 +111,9 @@
ahb: ahb@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-ahb-clk";
+ compatible = "allwinner,sun5i-a13-ahb-clk";
reg = <0x01c20054 0x4>;
- clocks = <&axi>;
+ clocks = <&axi>, <&cpu>, <&pll6 1>;
};
ahb_gates: ahb_gates@01c20060 {
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -115,9 +115,9 @@
ahb: ahb@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-ahb-clk";
+ compatible = "allwinner,sun5i-a13-ahb-clk";
reg = <0x01c20054 0x4>;
- clocks = <&axi>;
+ clocks = <&axi>, <&cpu>, <&pll6 1>;
};
ahb_gates: ahb_gates@01c20060 {
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -101,9 +101,9 @@
ahb: ahb@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-ahb-clk";
+ compatible = "allwinner,sun5i-a13-ahb-clk";
reg = <0x01c20054 0x4>;
- clocks = <&axi>;
+ clocks = <&axi>, <&pll6 1>, <&pll6 2>;
};
ahb_gates: ahb_gates@01c20060 {

View file

@ -1,6 +1,6 @@
From 6dd612e3d7e0c76f863efaddae4738fadc461f72 Mon Sep 17 00:00:00 2001
From 0aff0370cbffeadc14456556b904c80e30b3717e Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 24 Dec 2013 21:26:18 +0800
Date: Wed, 1 Jan 2014 10:30:48 +0800
Subject: [PATCH] ARM: dts: sun7i: external clock outputs
This commit adds the two external clock outputs available on A20 to
@ -9,13 +9,16 @@ the first input of the clock outputs, which according to AW's A20 user
manual, is the 24MHz oscillator divided by 750.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index edad6f1..0d54998 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -312,6 +312,33 @@
@@ -303,6 +303,34 @@
clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
clock-output-names = "mbus";
};
@ -23,12 +26,13 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+ /*
+ * Dummy clock used by output clocks
+ */
+ osc24M_32k: osc24M_32k {
+ osc24M_32k: clk@1 {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clock-div = <750>;
+ clock-mult = <1>;
+ clocks = <&osc24M>;
+ clock-output-names = "osc24M_32k";
+ };
+
+ clk_out_a: clk@01c201f0 {
@ -48,4 +52,7 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+ };
};
timer {
soc@01c00000 {
--
1.8.5.5

View file

@ -0,0 +1,139 @@
From dfb12c0c35b6cca5e55f40870b65af87988adb3e Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:41 +0800
Subject: [PATCH] ARM: dts: sun4i: rename clock node names to clk@N
Device tree naming conventions state that node names should match
node function. Change fully functioning clock nodes to match and
add clock-output-names to all sunxi clock nodes.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 28273f9..26cf191 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -58,34 +58,38 @@
clock-frequency = <0>;
};
- osc24M: osc24M@01c20050 {
+ osc24M: clk@01c20050 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-osc-clk";
reg = <0x01c20050 0x4>;
clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
};
- osc32k: osc32k {
+ osc32k: clk@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
+ clock-output-names = "osc32k";
};
- pll1: pll1@01c20000 {
+ pll1: clk@01c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll1";
};
- pll4: pll4@01c20018 {
+ pll4: clk@01c20018 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20018 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll4";
};
- pll5: pll5@01c20020 {
+ pll5: clk@01c20020 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll5-clk";
reg = <0x01c20020 0x4>;
@@ -93,7 +97,7 @@
clock-output-names = "pll5_ddr", "pll5_other";
};
- pll6: pll6@01c20028 {
+ pll6: clk@01c20028 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll6-clk";
reg = <0x01c20028 0x4>;
@@ -107,6 +111,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -114,9 +119,10 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20054 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
- axi_gates: axi_gates@01c2005c {
+ axi_gates: clk@01c2005c {
#clock-cells = <1>;
compatible = "allwinner,sun4i-axi-gates-clk";
reg = <0x01c2005c 0x4>;
@@ -129,9 +135,10 @@
compatible = "allwinner,sun4i-ahb-clk";
reg = <0x01c20054 0x4>;
clocks = <&axi>;
+ clock-output-names = "ahb";
};
- ahb_gates: ahb_gates@01c20060 {
+ ahb_gates: clk@01c20060 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-ahb-gates-clk";
reg = <0x01c20060 0x8>;
@@ -154,9 +161,10 @@
compatible = "allwinner,sun4i-apb0-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb>;
+ clock-output-names = "apb0";
};
- apb0_gates: apb0_gates@01c20068 {
+ apb0_gates: clk@01c20068 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-apb0-gates-clk";
reg = <0x01c20068 0x4>;
@@ -171,6 +179,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -178,9 +187,10 @@
compatible = "allwinner,sun4i-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
+ clock-output-names = "apb1";
};
- apb1_gates: apb1_gates@01c2006c {
+ apb1_gates: clk@01c2006c {
#clock-cells = <1>;
compatible = "allwinner,sun4i-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
--
1.8.5.5

View file

@ -0,0 +1,261 @@
From 3dce8324949eaa1ab4b750e8422ce78ddceb7aa4 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:42 +0800
Subject: [PATCH] ARM: dts: sun5i: rename clock node names to clk@N
Device tree naming conventions state that node names should match
node function. Change fully functioning clock nodes to match and
add clock-output-names to all sunxi clock nodes.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 30 ++++++++++++++++++++----------
arch/arm/boot/dts/sun5i-a13.dtsi | 30 ++++++++++++++++++++----------
2 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 2318082..b114be7 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -51,34 +51,38 @@
clock-frequency = <0>;
};
- osc24M: osc24M@01c20050 {
+ osc24M: clk@01c20050 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-osc-clk";
reg = <0x01c20050 0x4>;
clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
};
- osc32k: osc32k {
+ osc32k: clk@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
+ clock-output-names = "osc32k";
};
- pll1: pll1@01c20000 {
+ pll1: clk@01c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll1";
};
- pll4: pll4@01c20018 {
+ pll4: clk@01c20018 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20018 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll4";
};
- pll5: pll5@01c20020 {
+ pll5: clk@01c20020 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll5-clk";
reg = <0x01c20020 0x4>;
@@ -86,7 +90,7 @@
clock-output-names = "pll5_ddr", "pll5_other";
};
- pll6: pll6@01c20028 {
+ pll6: clk@01c20028 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll6-clk";
reg = <0x01c20028 0x4>;
@@ -100,6 +104,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -107,9 +112,10 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20054 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
- axi_gates: axi_gates@01c2005c {
+ axi_gates: clk@01c2005c {
#clock-cells = <1>;
compatible = "allwinner,sun4i-axi-gates-clk";
reg = <0x01c2005c 0x4>;
@@ -122,9 +128,10 @@
compatible = "allwinner,sun4i-ahb-clk";
reg = <0x01c20054 0x4>;
clocks = <&axi>;
+ clock-output-names = "ahb";
};
- ahb_gates: ahb_gates@01c20060 {
+ ahb_gates: clk@01c20060 {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a10s-ahb-gates-clk";
reg = <0x01c20060 0x8>;
@@ -143,9 +150,10 @@
compatible = "allwinner,sun4i-apb0-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb>;
+ clock-output-names = "apb0";
};
- apb0_gates: apb0_gates@01c20068 {
+ apb0_gates: clk@01c20068 {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a10s-apb0-gates-clk";
reg = <0x01c20068 0x4>;
@@ -159,6 +167,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -166,9 +175,10 @@
compatible = "allwinner,sun4i-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
+ clock-output-names = "apb1";
};
- apb1_gates: apb1_gates@01c2006c {
+ apb1_gates: clk@01c2006c {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a10s-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 6de40b6..5c121fc 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -52,34 +52,38 @@
clock-frequency = <0>;
};
- osc24M: osc24M@01c20050 {
+ osc24M: clk@01c20050 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-osc-clk";
reg = <0x01c20050 0x4>;
clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
};
- osc32k: osc32k {
+ osc32k: clk@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
+ clock-output-names = "osc32k";
};
- pll1: pll1@01c20000 {
+ pll1: clk@01c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll1";
};
- pll4: pll4@01c20018 {
+ pll4: clk@01c20018 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20018 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll4";
};
- pll5: pll5@01c20020 {
+ pll5: clk@01c20020 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll5-clk";
reg = <0x01c20020 0x4>;
@@ -87,7 +91,7 @@
clock-output-names = "pll5_ddr", "pll5_other";
};
- pll6: pll6@01c20028 {
+ pll6: clk@01c20028 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll6-clk";
reg = <0x01c20028 0x4>;
@@ -101,6 +105,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -108,9 +113,10 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20054 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
- axi_gates: axi_gates@01c2005c {
+ axi_gates: clk@01c2005c {
#clock-cells = <1>;
compatible = "allwinner,sun4i-axi-gates-clk";
reg = <0x01c2005c 0x4>;
@@ -123,9 +129,10 @@
compatible = "allwinner,sun4i-ahb-clk";
reg = <0x01c20054 0x4>;
clocks = <&axi>;
+ clock-output-names = "ahb";
};
- ahb_gates: ahb_gates@01c20060 {
+ ahb_gates: clk@01c20060 {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a13-ahb-gates-clk";
reg = <0x01c20060 0x8>;
@@ -143,9 +150,10 @@
compatible = "allwinner,sun4i-apb0-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb>;
+ clock-output-names = "apb0";
};
- apb0_gates: apb0_gates@01c20068 {
+ apb0_gates: clk@01c20068 {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a13-apb0-gates-clk";
reg = <0x01c20068 0x4>;
@@ -158,6 +166,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -165,9 +174,10 @@
compatible = "allwinner,sun4i-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
+ clock-output-names = "apb1";
};
- apb1_gates: apb1_gates@01c2006c {
+ apb1_gates: clk@01c2006c {
#clock-cells = <1>;
compatible = "allwinner,sun5i-a13-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
--
1.8.5.5

View file

@ -0,0 +1,112 @@
From 5cd0fa24e51d342f175d31ecb72c2e957a6bd0af Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:43 +0800
Subject: [PATCH] ARM: dts: sun6i: rename clock node names to clk@N
Device tree naming conventions state that node names should match
node function. Change fully functioning clock nodes to match and
add clock-output-names to all sunxi clock nodes.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index fc07f70..d3f1995 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -70,17 +70,19 @@
clock-frequency = <24000000>;
};
- osc32k: osc32k {
+ osc32k: clk@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
+ clock-output-names = "osc32k";
};
- pll1: pll1@01c20000 {
+ pll1: clk@01c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun6i-a31-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll1";
};
pll6: clk@01c20028 {
@@ -103,6 +105,7 @@
* Allwinner.
*/
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
+ clock-output-names = "cpu";
};
axi: axi@01c20050 {
@@ -110,6 +113,7 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20050 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
ahb1_mux: ahb1_mux@01c20054 {
@@ -117,6 +121,7 @@
compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
+ clock-output-names = "ahb1_mux";
};
ahb1: ahb1@01c20054 {
@@ -124,9 +129,10 @@
compatible = "allwinner,sun4i-ahb-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb1_mux>;
+ clock-output-names = "ahb1";
};
- ahb1_gates: ahb1_gates@01c20060 {
+ ahb1_gates: clk@01c20060 {
#clock-cells = <1>;
compatible = "allwinner,sun6i-a31-ahb1-gates-clk";
reg = <0x01c20060 0x8>;
@@ -152,9 +158,10 @@
compatible = "allwinner,sun4i-apb0-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb1>;
+ clock-output-names = "apb1";
};
- apb1_gates: apb1_gates@01c20060 {
+ apb1_gates: clk@01c20068 {
#clock-cells = <1>;
compatible = "allwinner,sun6i-a31-apb1-gates-clk";
reg = <0x01c20068 0x4>;
@@ -169,6 +176,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+ clock-output-names = "apb2_mux";
};
apb2: apb2@01c20058 {
@@ -176,9 +184,10 @@
compatible = "allwinner,sun6i-a31-apb2-div-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb2_mux>;
+ clock-output-names = "apb2";
};
- apb2_gates: apb2_gates@01c2006c {
+ apb2_gates: clk@01c2006c {
#clock-cells = <1>;
compatible = "allwinner,sun6i-a31-apb2-gates-clk";
reg = <0x01c2006c 0x4>;
--
1.8.5.5

View file

@ -0,0 +1,132 @@
From cb6050998de262d5acf2207c5451d4f5995a5bff Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:44 +0800
Subject: [PATCH] ARM: dts: sun7i: rename clock node names to clk@N
Device tree naming conventions state that node names should match
node function. Change fully functioning clock nodes to match and
add clock-output-names to all sunxi clock nodes.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index fe0fe47..cefd7ac 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -54,11 +54,12 @@
#size-cells = <1>;
ranges;
- osc24M: osc24M@01c20050 {
+ osc24M: clk@01c20050 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-osc-clk";
reg = <0x01c20050 0x4>;
clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
};
osc32k: clk@0 {
@@ -68,21 +69,23 @@
clock-output-names = "osc32k";
};
- pll1: pll1@01c20000 {
+ pll1: clk@01c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll1";
};
- pll4: pll4@01c20018 {
+ pll4: clk@01c20018 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-pll1-clk";
reg = <0x01c20018 0x4>;
clocks = <&osc24M>;
+ clock-output-names = "pll4";
};
- pll5: pll5@01c20020 {
+ pll5: clk@01c20020 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll5-clk";
reg = <0x01c20020 0x4>;
@@ -90,7 +93,7 @@
clock-output-names = "pll5_ddr", "pll5_other";
};
- pll6: pll6@01c20028 {
+ pll6: clk@01c20028 {
#clock-cells = <1>;
compatible = "allwinner,sun4i-pll6-clk";
reg = <0x01c20028 0x4>;
@@ -103,6 +106,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -110,6 +114,7 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20054 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
ahb: ahb@01c20054 {
@@ -117,9 +122,10 @@
compatible = "allwinner,sun4i-ahb-clk";
reg = <0x01c20054 0x4>;
clocks = <&axi>;
+ clock-output-names = "ahb";
};
- ahb_gates: ahb_gates@01c20060 {
+ ahb_gates: clk@01c20060 {
#clock-cells = <1>;
compatible = "allwinner,sun7i-a20-ahb-gates-clk";
reg = <0x01c20060 0x8>;
@@ -144,9 +150,10 @@
compatible = "allwinner,sun4i-apb0-clk";
reg = <0x01c20054 0x4>;
clocks = <&ahb>;
+ clock-output-names = "apb0";
};
- apb0_gates: apb0_gates@01c20068 {
+ apb0_gates: clk@01c20068 {
#clock-cells = <1>;
compatible = "allwinner,sun7i-a20-apb0-gates-clk";
reg = <0x01c20068 0x4>;
@@ -162,6 +169,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -169,9 +177,10 @@
compatible = "allwinner,sun4i-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
+ clock-output-names = "apb1";
};
- apb1_gates: apb1_gates@01c2006c {
+ apb1_gates: clk@01c2006c {
#clock-cells = <1>;
compatible = "allwinner,sun7i-a20-apb1-gates-clk";
reg = <0x01c2006c 0x4>;
--
1.8.5.5

View file

@ -1,4 +1,4 @@
From 26523a27f47828e50212201ba25862fe1e2b845c Mon Sep 17 00:00:00 2001
From fdc4530902ed845fc0f31b9bbcc45e05fefe21da Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 1 Dec 2013 22:40:34 +0100
Subject: [PATCH] ARM: dts: sun7i: Add arch timers
@ -14,9 +14,11 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index f4ecd79..fa2ef07 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -304,6 +304,14 @@
@@ -370,6 +370,14 @@
};
};
@ -31,3 +33,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
soc@01c00000 {
compatible = "simple-bus";
#address-cells = <1>;
--
1.8.5.5

View file

@ -0,0 +1,56 @@
From bc7a0478e6dac1304fdfdb6f3056f438b632da62 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:48 +0800
Subject: [PATCH] ARM: dts: sun7i: Add GMAC clock node to sun7i DTSI
The GMAC uses 1 of 2 sources for its transmit clock, depending on the
PHY interface mode. Add both sources as dummy clocks, and as parents
to the GMAC clock node.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index cefd7ac..7d98edc 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -322,6 +322,34 @@
};
/*
+ * The following two are dummy clocks, placeholders used in the gmac_tx
+ * clock. The gmac driver will choose one parent depending on the PHY
+ * interface mode, using clk_set_rate auto-reparenting.
+ * The actual TX clock rate is not controlled by the gmac_tx clock.
+ */
+ mii_phy_tx_clk: clk@2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ clock-output-names = "mii_phy_tx";
+ };
+
+ gmac_int_tx_clk: clk@3 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_int_tx";
+ };
+
+ gmac_tx_clk: clk@01c20164 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun7i-a20-gmac-clk";
+ reg = <0x01c20164 0x4>;
+ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
+ clock-output-names = "gmac_tx";
+ };
+
+ /*
* Dummy clock used by output clocks
*/
osc24M_32k: clk@1 {
--
1.8.5.5

View file

@ -0,0 +1,39 @@
From 7584e81f6d9fecf0ad6e2854654b183432adb918 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:49 +0800
Subject: [PATCH] ARM: dts: sun7i: Add GMAC controller node to sun7i DTSI
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 7d98edc..87eab0d 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -645,6 +645,21 @@
status = "disabled";
};
+ gmac: ethernet@01c50000 {
+ compatible = "allwinner,sun7i-a20-gmac";
+ reg = <0x01c50000 0x10000>;
+ interrupts = <0 85 4>;
+ interrupt-names = "macirq";
+ clocks = <&ahb_gates 49>, <&gmac_tx_clk>;
+ clock-names = "stmmaceth", "allwinner_gmac_tx";
+ snps,pbl = <2>;
+ snps,fixed-burst;
+ snps,force_sf_dma_mode;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
hstimer@01c60000 {
compatible = "allwinner,sun7i-a20-hstimer";
reg = <0x01c60000 0x1000>;
--
1.8.5.5

View file

@ -1,6 +1,6 @@
From 777ba9f88e1a566a6ed26fe1e8dfff4b8c1448fc Mon Sep 17 00:00:00 2001
From 249ac8d24efdc07f521b796b96796ffa55abe0a5 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Sat, 7 Dec 2013 01:29:39 +0800
Date: Mon, 10 Feb 2014 18:35:50 +0800
Subject: [PATCH] ARM: dts: sun7i: Add pin muxing options for the GMAC
The A20 has EMAC and GMAC muxed on the same pins.
@ -8,37 +8,46 @@ Add pin sets with gmac function for MII and RGMII mode to the DTSI.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
arch/arm/boot/dts/sun7i-a20.dtsi | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 87eab0d..9bb6fdf 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -428,6 +428,28 @@
@@ -484,6 +484,32 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+ gmac_pins_mii: gmac_mii {
+
+ gmac_pins_mii_a: gmac_mii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA9", "PA10",
+ "PA11", "PA12", "PA13", "PA14",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
+ allwinner,drive = <3>;
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ gmac_pins_rgmii: gmac_rgmii {
+ gmac_pins_rgmii_a: gmac_rgmii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA10",
+ "PA11", "PA12", "PA13",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
+ /*
+ * data lines in RGMII mode use DDR mode
+ * and need a higher signal drive strength
+ */
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
+
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
allwinner,function = "mmc0";
};
timer@01c20c00 {
--
1.8.5.5

View file

@ -0,0 +1,50 @@
From 33ba4079ea8c611c1aeca34f2d6d53a8214c14c5 Mon Sep 17 00:00:00 2001
From: Rashika Kheria <rashika.kheria@gmail.com>
Date: Thu, 19 Dec 2013 14:19:44 +0530
Subject: [PATCH] drivers: net: Mark functions as static in stmmac_platform.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch marks the function stmmac_pltfr_freeze() and
stmmac_pltfr_restore() in stmmac_platform.c as static because they are
not used outside this file.
Thus, it also removes the following warnings in
ethernet/stmicro/stmmac/stmmac_platform.c:
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:222:5: warning: no previous prototype for stmmac_pltfr_freeze [-Wmissing-prototypes]
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c:236:5: warning: no previous prototype for stmmac_pltfr_restore [-Wmissing-prototypes]
Signed-off-by: Rashika Kheria <rashika.kheria@gmail.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 51c9069..38bd1f4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -219,7 +219,7 @@ static int stmmac_pltfr_resume(struct device *dev)
return stmmac_resume(ndev);
}
-int stmmac_pltfr_freeze(struct device *dev)
+static int stmmac_pltfr_freeze(struct device *dev)
{
int ret;
struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
@@ -233,7 +233,7 @@ int stmmac_pltfr_freeze(struct device *dev)
return ret;
}
-int stmmac_pltfr_restore(struct device *dev)
+static int stmmac_pltfr_restore(struct device *dev)
{
struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
struct net_device *ndev = dev_get_drvdata(dev);
--
1.8.5.5

View file

@ -0,0 +1,77 @@
From 9cbadf094d9d479413dc8cfa77dff9e732184337 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:51:43 +0000
Subject: [PATCH] net: stmmac: support max-speed device tree property
This patch adds support to "max-speed" property which is a standard
Ethernet device tree property. max-speed specifies maximum speed
(specified in megabits per second) supported the device.
Depending on the clocking schemes some of the boards can only support
few link speeds, so having a way to limit the link speed in the mac
driver would allow such setups to work reliably.
Without this patch there is no way to tell the driver to limit the
link speed.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +++-
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++++
include/linux/stmmac.h | 1 +
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ecdc8ab..15192c0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -776,6 +776,7 @@ static int stmmac_init_phy(struct net_device *dev)
char phy_id_fmt[MII_BUS_ID_SIZE + 3];
char bus_id[MII_BUS_ID_SIZE];
int interface = priv->plat->interface;
+ int max_speed = priv->plat->max_speed;
priv->oldlink = 0;
priv->speed = 0;
priv->oldduplex = -1;
@@ -800,7 +801,8 @@ static int stmmac_init_phy(struct net_device *dev)
/* Stop Advertising 1000BASE Capability if interface is not GMII */
if ((interface == PHY_INTERFACE_MODE_MII) ||
- (interface == PHY_INTERFACE_MODE_RMII))
+ (interface == PHY_INTERFACE_MODE_RMII) ||
+ (max_speed < 1000 && max_speed > 0))
phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 38bd1f4..9377ee6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -42,6 +42,10 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
*mac = of_get_mac_address(np);
plat->interface = of_get_phy_mode(np);
+ /* Get max speed of operation from device tree */
+ if (of_property_read_u32(np, "max-speed", &plat->max_speed))
+ plat->max_speed = -1;
+
plat->bus_id = of_alias_get_id(np, "ethernet");
if (plat->bus_id < 0)
plat->bus_id = 0;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index bb5deb0..33ace71 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -110,6 +110,7 @@ struct plat_stmmacenet_data {
int force_sf_dma_mode;
int force_thresh_dma_mode;
int riwt_off;
+ int max_speed;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev);
--
1.8.5.5

View file

@ -0,0 +1,31 @@
From 984203ceff27e9d6d94fbae4b043fc9afb658121 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:51:58 +0000
Subject: [PATCH] net: stmmac: mdio: remove reset gpio free
This patch removes gpio_free for reset line of the phy, driver stores
the gpio number in its private data-structure to use in future. As the
driver uses this pin in future this pin should not be freed.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index fe7bc99..aab12d2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -166,7 +166,6 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
udelay(data->delays[1]);
gpio_set_value(reset_gpio, active_low ? 1 : 0);
udelay(data->delays[2]);
- gpio_free(reset_gpio);
}
}
#endif
--
1.8.5.5

View file

@ -0,0 +1,223 @@
From 09f8d6960b69e474eef9d2aebdd0d536d00af0c8 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:06 +0000
Subject: [PATCH] net: stmmac: move dma allocation to new function
This patch moves dma resource allocation to a new function
alloc_dma_desc_resources, the reason for moving this to a new function
is to keep the memory allocations in a separate function. One more reason
it to get suspend and hibernation cases working without releasing and
allocating these resources during suspend-resume and freeze-restore
cases.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 169 +++++++++++-----------
1 file changed, 85 insertions(+), 84 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 15192c0..532f2b4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -996,66 +996,6 @@ static int init_dma_desc_rings(struct net_device *dev)
pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
txsize, rxsize, bfsize);
- if (priv->extend_desc) {
- priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
- sizeof(struct
- dma_extended_desc),
- &priv->dma_rx_phy,
- GFP_KERNEL);
- if (!priv->dma_erx)
- goto err_dma;
-
- priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
- sizeof(struct
- dma_extended_desc),
- &priv->dma_tx_phy,
- GFP_KERNEL);
- if (!priv->dma_etx) {
- dma_free_coherent(priv->device, priv->dma_rx_size *
- sizeof(struct dma_extended_desc),
- priv->dma_erx, priv->dma_rx_phy);
- goto err_dma;
- }
- } else {
- priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
- sizeof(struct dma_desc),
- &priv->dma_rx_phy,
- GFP_KERNEL);
- if (!priv->dma_rx)
- goto err_dma;
-
- priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
- sizeof(struct dma_desc),
- &priv->dma_tx_phy,
- GFP_KERNEL);
- if (!priv->dma_tx) {
- dma_free_coherent(priv->device, priv->dma_rx_size *
- sizeof(struct dma_desc),
- priv->dma_rx, priv->dma_rx_phy);
- goto err_dma;
- }
- }
-
- priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
- GFP_KERNEL);
- if (!priv->rx_skbuff_dma)
- goto err_rx_skbuff_dma;
-
- priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
- GFP_KERNEL);
- if (!priv->rx_skbuff)
- goto err_rx_skbuff;
-
- priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
- GFP_KERNEL);
- if (!priv->tx_skbuff_dma)
- goto err_tx_skbuff_dma;
-
- priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
- GFP_KERNEL);
- if (!priv->tx_skbuff)
- goto err_tx_skbuff;
-
if (netif_msg_probe(priv)) {
pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
(u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
@@ -1123,30 +1063,6 @@ static int init_dma_desc_rings(struct net_device *dev)
err_init_rx_buffers:
while (--i >= 0)
stmmac_free_rx_buffers(priv, i);
- kfree(priv->tx_skbuff);
-err_tx_skbuff:
- kfree(priv->tx_skbuff_dma);
-err_tx_skbuff_dma:
- kfree(priv->rx_skbuff);
-err_rx_skbuff:
- kfree(priv->rx_skbuff_dma);
-err_rx_skbuff_dma:
- if (priv->extend_desc) {
- dma_free_coherent(priv->device, priv->dma_tx_size *
- sizeof(struct dma_extended_desc),
- priv->dma_etx, priv->dma_tx_phy);
- dma_free_coherent(priv->device, priv->dma_rx_size *
- sizeof(struct dma_extended_desc),
- priv->dma_erx, priv->dma_rx_phy);
- } else {
- dma_free_coherent(priv->device,
- priv->dma_tx_size * sizeof(struct dma_desc),
- priv->dma_tx, priv->dma_tx_phy);
- dma_free_coherent(priv->device,
- priv->dma_rx_size * sizeof(struct dma_desc),
- priv->dma_rx, priv->dma_rx_phy);
- }
-err_dma:
return ret;
}
@@ -1182,6 +1098,85 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
}
}
+static int alloc_dma_desc_resources(struct stmmac_priv *priv)
+{
+ unsigned int txsize = priv->dma_tx_size;
+ unsigned int rxsize = priv->dma_rx_size;
+ int ret = -ENOMEM;
+
+ priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
+ GFP_KERNEL);
+ if (!priv->rx_skbuff_dma)
+ return -ENOMEM;
+
+ priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
+ GFP_KERNEL);
+ if (!priv->rx_skbuff)
+ goto err_rx_skbuff;
+
+ priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+ GFP_KERNEL);
+ if (!priv->tx_skbuff_dma)
+ goto err_tx_skbuff_dma;
+
+ priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
+ GFP_KERNEL);
+ if (!priv->tx_skbuff)
+ goto err_tx_skbuff;
+
+ if (priv->extend_desc) {
+ priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
+ sizeof(struct
+ dma_extended_desc),
+ &priv->dma_rx_phy,
+ GFP_KERNEL);
+ if (!priv->dma_erx)
+ goto err_dma;
+
+ priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
+ sizeof(struct
+ dma_extended_desc),
+ &priv->dma_tx_phy,
+ GFP_KERNEL);
+ if (!priv->dma_etx) {
+ dma_free_coherent(priv->device, priv->dma_rx_size *
+ sizeof(struct dma_extended_desc),
+ priv->dma_erx, priv->dma_rx_phy);
+ goto err_dma;
+ }
+ } else {
+ priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
+ sizeof(struct dma_desc),
+ &priv->dma_rx_phy,
+ GFP_KERNEL);
+ if (!priv->dma_rx)
+ goto err_dma;
+
+ priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
+ sizeof(struct dma_desc),
+ &priv->dma_tx_phy,
+ GFP_KERNEL);
+ if (!priv->dma_tx) {
+ dma_free_coherent(priv->device, priv->dma_rx_size *
+ sizeof(struct dma_desc),
+ priv->dma_rx, priv->dma_rx_phy);
+ goto err_dma;
+ }
+ }
+
+ return 0;
+
+err_dma:
+ kfree(priv->tx_skbuff);
+err_tx_skbuff:
+ kfree(priv->tx_skbuff_dma);
+err_tx_skbuff_dma:
+ kfree(priv->rx_skbuff);
+err_rx_skbuff:
+ kfree(priv->rx_skbuff_dma);
+ return ret;
+}
+
static void free_dma_desc_resources(struct stmmac_priv *priv)
{
/* Release the DMA TX/RX socket buffers */
@@ -1623,6 +1618,12 @@ static int stmmac_open(struct net_device *dev)
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+ alloc_dma_desc_resources(priv);
+ if (ret < 0) {
+ pr_err("%s: DMA descriptors allocation failed\n", __func__);
+ goto dma_desc_error;
+ }
+
ret = init_dma_desc_rings(dev);
if (ret < 0) {
pr_err("%s: DMA descriptors initialization failed\n", __func__);
--
1.8.5.5

View file

@ -0,0 +1,214 @@
From 523f11b5d4fd72efb72b04cd7006bfd1d1d4f341 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:14 +0000
Subject: [PATCH] net: stmmac: move hardware setup for stmmac_open to new
function
This patch moves hardware setup part of the code in stmmac_open to a new
function stmmac_hw_setup, the reason for doing this is to make hw
initialization independent function so that PM functions can re-use it to
re-initialize the IP after returning from low power state.
This will also avoid code duplication across stmmac_resume/restore and
stmmac_open.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 155 ++++++++++++----------
1 file changed, 88 insertions(+), 67 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 532f2b4..341c8dc3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1586,6 +1586,86 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
}
/**
+ * stmmac_hw_setup: setup mac in a usable state.
+ * @dev : pointer to the device structure.
+ * Description:
+ * This function sets up the ip in a usable state.
+ * Return value:
+ * 0 on success and an appropriate (-)ve integer as defined in errno.h
+ * file on failure.
+ */
+static int stmmac_hw_setup(struct net_device *dev)
+{
+ struct stmmac_priv *priv = netdev_priv(dev);
+ int ret;
+
+ ret = init_dma_desc_rings(dev);
+ if (ret < 0) {
+ pr_err("%s: DMA descriptors initialization failed\n", __func__);
+ return ret;
+ }
+ /* DMA initialization and SW reset */
+ ret = stmmac_init_dma_engine(priv);
+ if (ret < 0) {
+ pr_err("%s: DMA engine initialization failed\n", __func__);
+ return ret;
+ }
+
+ /* Copy the MAC addr into the HW */
+ priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+
+ /* If required, perform hw setup of the bus. */
+ if (priv->plat->bus_setup)
+ priv->plat->bus_setup(priv->ioaddr);
+
+ /* Initialize the MAC Core */
+ priv->hw->mac->core_init(priv->ioaddr);
+
+ /* Enable the MAC Rx/Tx */
+ stmmac_set_mac(priv->ioaddr, true);
+
+ /* Set the HW DMA mode and the COE */
+ stmmac_dma_operation_mode(priv);
+
+ stmmac_mmc_setup(priv);
+
+ ret = stmmac_init_ptp(priv);
+ if (ret)
+ pr_warn("%s: failed PTP initialisation\n", __func__);
+
+#ifdef CONFIG_STMMAC_DEBUG_FS
+ ret = stmmac_init_fs(dev);
+ if (ret < 0)
+ pr_warn("%s: failed debugFS registration\n", __func__);
+#endif
+ /* Start the ball rolling... */
+ pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
+ priv->hw->dma->start_tx(priv->ioaddr);
+ priv->hw->dma->start_rx(priv->ioaddr);
+
+ /* Dump DMA/MAC registers */
+ if (netif_msg_hw(priv)) {
+ priv->hw->mac->dump_regs(priv->ioaddr);
+ priv->hw->dma->dump_regs(priv->ioaddr);
+ }
+ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
+
+ priv->eee_enabled = stmmac_eee_init(priv);
+
+ stmmac_init_tx_coalesce(priv);
+
+ if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+ priv->rx_riwt = MAX_DMA_RIWT;
+ priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
+ }
+
+ if (priv->pcs && priv->hw->mac->ctrl_ane)
+ priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+
+ return 0;
+}
+
+/**
* stmmac_open - open entry point of the driver
* @dev : pointer to the device structure.
* Description:
@@ -1613,6 +1693,10 @@ static int stmmac_open(struct net_device *dev)
}
}
+ /* Extra statistics */
+ memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
+ priv->xstats.threshold = tc;
+
/* Create and initialize the TX/RX descriptors chains. */
priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -1624,28 +1708,14 @@ static int stmmac_open(struct net_device *dev)
goto dma_desc_error;
}
- ret = init_dma_desc_rings(dev);
+ ret = stmmac_hw_setup(dev);
if (ret < 0) {
- pr_err("%s: DMA descriptors initialization failed\n", __func__);
- goto dma_desc_error;
- }
-
- /* DMA initialization and SW reset */
- ret = stmmac_init_dma_engine(priv);
- if (ret < 0) {
- pr_err("%s: DMA engine initialization failed\n", __func__);
+ pr_err("%s: Hw setup failed\n", __func__);
goto init_error;
}
- /* Copy the MAC addr into the HW */
- priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
-
- /* If required, perform hw setup of the bus. */
- if (priv->plat->bus_setup)
- priv->plat->bus_setup(priv->ioaddr);
-
- /* Initialize the MAC Core */
- priv->hw->mac->core_init(priv->ioaddr);
+ if (priv->phydev)
+ phy_start(priv->phydev);
/* Request the IRQ lines */
ret = request_irq(dev->irq, stmmac_interrupt,
@@ -1678,55 +1748,6 @@ static int stmmac_open(struct net_device *dev)
}
}
- /* Enable the MAC Rx/Tx */
- stmmac_set_mac(priv->ioaddr, true);
-
- /* Set the HW DMA mode and the COE */
- stmmac_dma_operation_mode(priv);
-
- /* Extra statistics */
- memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
- priv->xstats.threshold = tc;
-
- stmmac_mmc_setup(priv);
-
- ret = stmmac_init_ptp(priv);
- if (ret)
- pr_warn("%s: failed PTP initialisation\n", __func__);
-
-#ifdef CONFIG_STMMAC_DEBUG_FS
- ret = stmmac_init_fs(dev);
- if (ret < 0)
- pr_warn("%s: failed debugFS registration\n", __func__);
-#endif
- /* Start the ball rolling... */
- pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
- priv->hw->dma->start_tx(priv->ioaddr);
- priv->hw->dma->start_rx(priv->ioaddr);
-
- /* Dump DMA/MAC registers */
- if (netif_msg_hw(priv)) {
- priv->hw->mac->dump_regs(priv->ioaddr);
- priv->hw->dma->dump_regs(priv->ioaddr);
- }
-
- if (priv->phydev)
- phy_start(priv->phydev);
-
- priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
-
- priv->eee_enabled = stmmac_eee_init(priv);
-
- stmmac_init_tx_coalesce(priv);
-
- if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
- priv->rx_riwt = MAX_DMA_RIWT;
- priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
- }
-
- if (priv->pcs && priv->hw->mac->ctrl_ane)
- priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
-
napi_enable(&priv->napi);
netif_start_queue(dev);
--
1.8.5.5

View file

@ -0,0 +1,45 @@
From 073752aa59b3db120b2508d5bdd0598ada25fd25 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:27 +0000
Subject: [PATCH] net: stmmac: make stmmac_mdio_reset non-static
This patch promotes stmmac_mdio_reset function from static to
non-static, so that power management functions can decide to reset if
the IP comes out from lowe power state specially hibernation cases.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 92be6b3..5a568015 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -110,6 +110,7 @@ struct stmmac_priv {
int stmmac_mdio_unregister(struct net_device *ndev);
int stmmac_mdio_register(struct net_device *ndev);
+int stmmac_mdio_reset(struct mii_bus *mii);
void stmmac_set_ethtool_ops(struct net_device *netdev);
extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index aab12d2..a468eb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -128,7 +128,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
* @bus: points to the mii_bus structure
* Description: reset the MII bus
*/
-static int stmmac_mdio_reset(struct mii_bus *bus)
+int stmmac_mdio_reset(struct mii_bus *bus)
{
#if defined(CONFIG_STMMAC_PLATFORM)
struct net_device *ndev = bus->priv;
--
1.8.5.5

View file

@ -0,0 +1,57 @@
From 623997fb90eab7a135c2c68a332c8450a488baca Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:35 +0000
Subject: [PATCH] net: stmmac: fix power management suspend-resume case
The driver PM resume assumes that the IP is still powered up and the
all the register contents are not disturbed when it comes out of low
power suspend case. This assumption is wrong, basically the driver
should not consider any state of registers after it comes out of low
power. However driver can keep the part of the IP powered up if its a
wake up source. But it can not assume the register state of the IP. Also
its possible that SOC glue layer can take the power off the IP if its
not wake-up source to reduce the power consumption.
This patch re initializes hardware by calling stmmac_hw_setup function in
resume case.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 341c8dc3..742a83f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2887,18 +2887,19 @@ int stmmac_resume(struct net_device *ndev)
* this bit because it can generate problems while resuming
* from another devices (e.g. serial console).
*/
- if (device_may_wakeup(priv->device))
+ if (device_may_wakeup(priv->device)) {
priv->hw->mac->pmt(priv->ioaddr, 0);
- else
+ } else {
/* enable the clk prevously disabled */
clk_prepare_enable(priv->stmmac_clk);
+ /* reset the phy so that it's ready */
+ if (priv->mii)
+ stmmac_mdio_reset(priv->mii);
+ }
netif_device_attach(ndev);
- /* Enable the MAC and DMA */
- stmmac_set_mac(priv->ioaddr, true);
- priv->hw->dma->start_tx(priv->ioaddr);
- priv->hw->dma->start_rx(priv->ioaddr);
+ stmmac_hw_setup(ndev);
napi_enable(&priv->napi);
--
1.8.5.5

View file

@ -0,0 +1,146 @@
From 33a23e223749c45ff8099ff9baa235301a3ad07f Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:44 +0000
Subject: [PATCH] net: stmmac: use suspend functions for hibernation
In hibernation freeze case the driver just releases the resources like
dma buffers, irqs, unregisters the drivers and during restore it does
register, request the resources. This is not really necessary, as part
of power management all the data structures are intact, all the
previously allocated resources can be used after coming out of low
power.
This patch uses the suspend and resume callbacks for freeze and
restore which initializes the hardware correctly without unregistering
or releasing the resources, this should also help in reducing the time
to restore.
Also this patch fixes a bug in stmmac_pltfr_restore and
stmmac_pltfr_freeze where it tries to get hold of platform data via
dev_get_platdata call, which would return NULL in device tree cases and
the next if statement would crash as there is no NULL check.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 -
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 --------
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 ++++++----------------
3 files changed, 12 insertions(+), 50 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 5a568015..027f1dd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -117,8 +117,6 @@ struct stmmac_priv {
extern const struct stmmac_hwtimestamp stmmac_ptp;
int stmmac_ptp_register(struct stmmac_priv *priv);
void stmmac_ptp_unregister(struct stmmac_priv *priv);
-int stmmac_freeze(struct net_device *ndev);
-int stmmac_restore(struct net_device *ndev);
int stmmac_resume(struct net_device *ndev);
int stmmac_suspend(struct net_device *ndev);
int stmmac_dvr_remove(struct net_device *ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 742a83f..c1298a0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2912,22 +2912,6 @@ int stmmac_resume(struct net_device *ndev)
return 0;
}
-
-int stmmac_freeze(struct net_device *ndev)
-{
- if (!ndev || !netif_running(ndev))
- return 0;
-
- return stmmac_release(ndev);
-}
-
-int stmmac_restore(struct net_device *ndev)
-{
- if (!ndev || !netif_running(ndev))
- return 0;
-
- return stmmac_open(ndev);
-}
#endif /* CONFIG_PM */
/* Driver can be configured w/ and w/ both PCI and Platf drivers
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 9377ee6..6d0bf22 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -211,55 +211,35 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int stmmac_pltfr_suspend(struct device *dev)
{
- struct net_device *ndev = dev_get_drvdata(dev);
-
- return stmmac_suspend(ndev);
-}
-
-static int stmmac_pltfr_resume(struct device *dev)
-{
- struct net_device *ndev = dev_get_drvdata(dev);
-
- return stmmac_resume(ndev);
-}
-
-static int stmmac_pltfr_freeze(struct device *dev)
-{
int ret;
- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
- ret = stmmac_freeze(ndev);
- if (plat_dat->exit)
- plat_dat->exit(pdev);
+ ret = stmmac_suspend(ndev);
+ if (priv->plat->exit)
+ priv->plat->exit(pdev);
return ret;
}
-static int stmmac_pltfr_restore(struct device *dev)
+static int stmmac_pltfr_resume(struct device *dev)
{
- struct plat_stmmacenet_data *plat_dat = dev_get_platdata(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
- if (plat_dat->init)
- plat_dat->init(pdev);
+ if (priv->plat->init)
+ priv->plat->init(pdev);
- return stmmac_restore(ndev);
+ return stmmac_resume(ndev);
}
-static const struct dev_pm_ops stmmac_pltfr_pm_ops = {
- .suspend = stmmac_pltfr_suspend,
- .resume = stmmac_pltfr_resume,
- .freeze = stmmac_pltfr_freeze,
- .thaw = stmmac_pltfr_restore,
- .restore = stmmac_pltfr_restore,
-};
-#else
-static const struct dev_pm_ops stmmac_pltfr_pm_ops;
#endif /* CONFIG_PM */
+static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
+ stmmac_pltfr_suspend, stmmac_pltfr_resume);
+
static const struct of_device_id stmmac_dt_ids[] = {
{ .compatible = "st,spear600-gmac"},
{ .compatible = "snps,dwmac-3.610"},
--
1.8.5.5

View file

@ -0,0 +1,50 @@
From db88f10ad6a84c5bcb71bf51f0988a4bb1733bea Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:52:52 +0000
Subject: [PATCH] net: stmmac: restore pinstate in pm resume.
This patch adds code to restore default pinstate of the pins when it
comes back from low power state. Without this patch the state of the
pins would be unknown and the driver would not work.
This patch also adds code to put the pins in to sleep state when the
driver enters low power state.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c1298a0..df7d8d6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -43,6 +43,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
+#include <linux/pinctrl/consumer.h>
#ifdef CONFIG_STMMAC_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -2864,6 +2865,7 @@ int stmmac_suspend(struct net_device *ndev)
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
else {
stmmac_set_mac(priv->ioaddr, false);
+ pinctrl_pm_select_sleep_state(priv->device);
/* Disable clock in case of PWM is off */
clk_disable_unprepare(priv->stmmac_clk);
}
@@ -2890,6 +2892,7 @@ int stmmac_resume(struct net_device *ndev)
if (device_may_wakeup(priv->device)) {
priv->hw->mac->pmt(priv->ioaddr, 0);
} else {
+ pinctrl_pm_select_default_state(priv->device);
/* enable the clk prevously disabled */
clk_prepare_enable(priv->stmmac_clk);
/* reset the phy so that it's ready */
--
1.8.5.5

View file

@ -0,0 +1,73 @@
From 89f7f2cfdd7ade55d5230501c21271690790ceda Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Thu, 16 Jan 2014 10:53:00 +0000
Subject: [PATCH] net: stmmac: notify the PM core of a wakeup event.
In PM_SUSPEND_FREEZE and WOL(Wakeup On Lan) case, when the driver gets a
wakeup event, either the driver or platform specific PM code should notify
the pm core about it, so that the system can wakeup from low power.
In cases where there is no involvement of platform specific PM, it
becomes driver responsibility to notify the PM core to wakeup the
system.
Without this WOL with PM_SUSPEND_FREEZE does not work on STi based SOCs.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 9 +++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 027f1dd..73709e9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -105,6 +105,7 @@ struct stmmac_priv {
unsigned int default_addend;
u32 adv_ts;
int use_riwt;
+ int irq_wake;
spinlock_t ptp_lock;
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index df7d8d6..cddcf76 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2320,6 +2320,9 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
struct net_device *dev = (struct net_device *)dev_id;
struct stmmac_priv *priv = netdev_priv(dev);
+ if (priv->irq_wake)
+ pm_wakeup_event(priv->device, 0);
+
if (unlikely(!dev)) {
pr_err("%s: invalid dev pointer\n", __func__);
return IRQ_NONE;
@@ -2861,9 +2864,10 @@ int stmmac_suspend(struct net_device *ndev)
stmmac_clear_descriptors(priv);
/* Enable Power down mode by programming the PMT regs */
- if (device_may_wakeup(priv->device))
+ if (device_may_wakeup(priv->device)) {
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
- else {
+ priv->irq_wake = 1;
+ } else {
stmmac_set_mac(priv->ioaddr, false);
pinctrl_pm_select_sleep_state(priv->device);
/* Disable clock in case of PWM is off */
@@ -2891,6 +2895,7 @@ int stmmac_resume(struct net_device *ndev)
*/
if (device_may_wakeup(priv->device)) {
priv->hw->mac->pmt(priv->ioaddr, 0);
+ priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
/* enable the clk prevously disabled */
--
1.8.5.5

View file

@ -0,0 +1,38 @@
From 957f00fbab201f429ad81cc87ee3177e4289567d Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:51 +0800
Subject: [PATCH] ARM: dts: sun7i: cubietruck: Enable the GMAC
The CubieTruck uses the GMAC with an RGMII phy.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index f9dcb61..025ce52 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -51,6 +51,18 @@
pinctrl-0 = <&i2c2_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_rgmii_a>;
+ phy = <&phy1>;
+ phy-mode = "rgmii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
leds {
--
1.8.5.5

View file

@ -1,6 +1,6 @@
From e28b63650ff934751b9fe56415dc2491a6c6b704 Mon Sep 17 00:00:00 2001
From 7405ae68d251191677e51aadb4308d6ce5212bbe Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Sat, 7 Dec 2013 01:29:41 +0800
Date: Mon, 10 Feb 2014 18:35:52 +0800
Subject: [PATCH] ARM: dts: sun7i: cubieboard2: Enable GMAC instead of EMAC
GMAC has better performance and fewer hardware issues.
@ -8,9 +8,11 @@ Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 5c51cb8..7bf4935 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -19,21 +19,6 @@
@ -32,21 +34,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
- };
- };
-
mmc0: mmc@01c0f000 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>;
@@ -111,6 +96,14 @@
vbus-supply = <&reg_usb2_vbus>;
pinctrl@01c20800 {
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -60,6 +45,18 @@
pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_mii>;
+ snps,phy-addr = <1>;
+ pinctrl-0 = <&gmac_pins_mii_a>;
+ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
leds {
--
1.8.5.5

View file

@ -1,16 +1,19 @@
From e39d51b2236ab17628fe5d110296cd33a9c4427e Mon Sep 17 00:00:00 2001
From e401b86036245d2d62d825f0e3e12286c111b281 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Sat, 7 Dec 2013 01:29:42 +0800
Subject: [PATCH] ARM: dts: sun7i: olinuxino-micro: Enable GMAC instead of EMAC
Date: Mon, 10 Feb 2014 18:35:53 +0800
Subject: [PATCH] ARM: dts: sun7i: a20-olinuxino-micro: Enable GMAC instead of
EMAC
GMAC has better performance and fewer hardware issues.
Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 27 +++++++++++--------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index ead3013..b02a796 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -19,21 +19,6 @@
@ -32,21 +35,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
- };
- };
-
mmc0: mmc@01c0f000 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>;
@@ -146,6 +131,14 @@
vbus-supply = <&reg_usb2_vbus>;
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
@@ -78,6 +63,18 @@
pinctrl-0 = <&i2c2_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_mii>;
+ snps,phy-addr = <1>;
+ pinctrl-0 = <&gmac_pins_mii_a>;
+ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
leds {
--
1.8.5.5

View file

@ -1,41 +0,0 @@
From 447675f817b95881e9922f002de3fc7f6d6e9207 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
Date: Fri, 6 Sep 2013 22:34:33 +0200
Subject: [PATCH] ARM: sunxi-mci: Add driver for SD/MMC hosts found within
Allwinner A1X SoCs
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/Kconfig | 8 +
drivers/mmc/host/Makefile | 2 +
drivers/mmc/host/sunxi-mci.c | 1056 ++++++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/sunxi-mci.h | 334 +++++++++++++
4 files changed, 1400 insertions(+)
create mode 100644 drivers/mmc/host/sunxi-mci.c
create mode 100644 drivers/mmc/host/sunxi-mci.h
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -690,3 +690,11 @@ config MMC_REALTEK_PCI
help
Say Y here to include driver code to support SD/MMC card interface
of Realtek PCI-E card reader
+
+config MMC_SUNXI
+ tristate "Allwinner A1X SD/MMC Host Controller support"
+ depends on ARCH_SUNXI
+ default y
+ help
+ This selects support for the SD/MMC Host Controller on
+ Allwinner A1X based SoCs.
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
+obj-$(CONFIG_MMC_SUNXI) += sunxi-mci.o
+
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o

View file

@ -1,97 +0,0 @@
From 677631fa522e4ac24f636535e3abb5cd1a5ef40e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 14 Dec 2013 22:58:12 +0100
Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 16 ++++++++++++++++
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 16 ++++++++++++++++
arch/arm/boot/dts/sun4i-a10.dtsi | 17 +++++++++++++++++
3 files changed, 49 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -39,7 +39,23 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_a1000>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ mmc0_cd_pin_a1000: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
emac_power_pin_a1000: emac_power_pin@0 {
allwinner,pins = "PH15";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -42,7 +42,23 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_cubieboard>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_cubieboard: led_pins@0 {
allwinner,pins = "PH20", "PH21";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -328,6 +328,16 @@
#size-cells = <0>;
};
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun4i-a10-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <32>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
@@ -398,6 +408,13 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -0,0 +1,96 @@
From 62866e98737e77c87f9dec99edea76ab54360770 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:40 +0800
Subject: [PATCH] net: stmmac: Enable stmmac main clock when probing hardware
The stmmac driver does not enable the main clock during the probe phase.
If the clock was not enabled by the boot loader or was disabled by the
kernel, hardware features and the MDIO bus would not be probed properly.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index cddcf76..0d2c4cb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1680,8 +1680,6 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
- clk_prepare_enable(priv->stmmac_clk);
-
stmmac_check_ether_addr(priv);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
@@ -1819,7 +1817,6 @@ static int stmmac_release(struct net_device *dev)
#ifdef CONFIG_STMMAC_DEBUG_FS
stmmac_exit_fs();
#endif
- clk_disable_unprepare(priv->stmmac_clk);
stmmac_release_ptp(priv);
@@ -2727,10 +2724,18 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if ((phyaddr >= 0) && (phyaddr <= 31))
priv->plat->phy_addr = phyaddr;
+ priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_clk)) {
+ dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
+ __func__);
+ goto error_clk_get;
+ }
+ clk_prepare_enable(priv->stmmac_clk);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
- goto error_free_netdev;
+ goto error_hw_init;
ndev->netdev_ops = &stmmac_netdev_ops;
@@ -2768,12 +2773,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
goto error_netdev_register;
}
- priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);
- if (IS_ERR(priv->stmmac_clk)) {
- pr_warn("%s: warning: cannot get CSR clock\n", __func__);
- goto error_clk_get;
- }
-
/* If a specific clk_csr value is passed from the platform
* this means that the CSR Clock Range selection cannot be
* changed at run-time and it is fixed. Viceversa the driver'll try to
@@ -2801,12 +2800,12 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
return priv;
error_mdio_register:
- clk_put(priv->stmmac_clk);
-error_clk_get:
unregister_netdev(ndev);
error_netdev_register:
netif_napi_del(&priv->napi);
-error_free_netdev:
+error_hw_init:
+ clk_disable_unprepare(priv->stmmac_clk);
+error_clk_get:
free_netdev(ndev);
return NULL;
@@ -2833,6 +2832,7 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
return 0;
--
1.8.5.5

View file

@ -0,0 +1,158 @@
From c5e4ddbdfa1134a36589c1466ed4abb85fe6f976 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:41 +0800
Subject: [PATCH] net: stmmac: Add support for optional reset control
The DWMAC has a reset assert line, which is used on some SoCs. Add an
optional reset control to stmmac driver core.
To support reset control deferred probing, this patch changes the driver
probe function to return the actual error, instead of just -EINVAL.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/devicetree/bindings/net/stmmac.txt | 3 +++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 4 ++--
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 ++--
6 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index eba0e5e..d132513 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -30,6 +30,9 @@ Required properties:
Optional properties:
- mac-address: 6 bytes, mac address
+- resets: Should contain a phandle to the STMMAC reset signal, if any
+- reset-names: Should contain the reset signal name "stmmaceth", if a
+ reset phandle is given
Examples:
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 6e52c0f..b59d1ef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -5,6 +5,7 @@ config STMMAC_ETH
select PHYLIB
select CRC32
select PTP_1588_CLOCK
+ select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
Synopsys IP Core and only tested on the STMicroelectronics
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 73709e9..c1c141f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -32,6 +32,7 @@
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
+#include <linux/reset.h>
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
@@ -91,6 +92,7 @@ struct stmmac_priv {
int wolopts;
int wol_irq;
struct clk *stmmac_clk;
+ struct reset_control *stmmac_rst;
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0d2c4cb..0c5c120 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -51,6 +51,7 @@
#include <linux/net_tstamp.h>
#include "stmmac_ptp.h"
#include "stmmac.h"
+#include <linux/reset.h>
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
#define JUMBO_LEN 9000
@@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (IS_ERR(priv->stmmac_clk)) {
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
__func__);
+ ret = PTR_ERR(priv->stmmac_clk);
goto error_clk_get;
}
clk_prepare_enable(priv->stmmac_clk);
+ priv->stmmac_rst = devm_reset_control_get(priv->device,
+ STMMAC_RESOURCE_NAME);
+ if (IS_ERR(priv->stmmac_rst)) {
+ if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto error_hw_init;
+ }
+ dev_info(priv->device, "no reset control found\n");
+ priv->stmmac_rst = NULL;
+ }
+ if (priv->stmmac_rst)
+ reset_control_deassert(priv->stmmac_rst);
+
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
@@ -2808,7 +2823,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
error_clk_get:
free_netdev(ndev);
- return NULL;
+ return ERR_PTR(ret);
}
/**
@@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
+ if (priv->stmmac_rst)
+ reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 37ba2e0..2916089 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
stmmac_default_data();
priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- ret = -ENODEV;
+ ret = PTR_ERR(priv);
goto err_out;
}
priv->dev->irq = pdev->irq;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 6d0bf22..cc6b89a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
- if (!priv) {
+ if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
- return -ENODEV;
+ return PTR_ERR(priv);
}
/* Get MAC address if available (DT) */
--
1.8.5.5

View file

@ -1,131 +0,0 @@
From 3cce544eb5964c14653dddde731cac4cbff97d90 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 14 Dec 2013 22:58:15 +0100
Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 16 ++++++++++++
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 16 ++++++++++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 32 +++++++++++++++++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 34 +++++++++++++++++++++++++
4 files changed, 98 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -34,7 +34,23 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_cubieboard2>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -34,7 +34,39 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
+ mmc3: mmc@01c12000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc3_pins_a>;
+ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 7 11 0>; /* PH11 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
+ allwinner,pins = "PH11";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -334,6 +334,26 @@
#size-cells = <0>;
};
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 32 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc3: mmc@01c12000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c12000 0x1000>;
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 35 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
pio: pinctrl@01c20800 {
compatible = "allwinner,sun7i-a20-pinctrl";
reg = <0x01c20800 0x400>;
@@ -397,6 +417,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
+
+ mmc3_pins_a: mmc3@0 {
+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
+ allwinner,function = "mmc3";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -0,0 +1,124 @@
From 938dfdaa3c0f92e9a490d324f3bce43bbaef7632 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:42 +0800
Subject: [PATCH] net: stmmac: Allocate and pass soc/board specific data to
callbacks
The current .init and .exit callbacks requires access to driver
private data structures. This is not a good seperation and abstraction.
Instead, we add a new .setup callback for allocating private data, and
pass the returned pointer to the other callbacks.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/stmmac.txt | 12 ++++++++----
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 18 ++++++++++++++----
include/linux/stmmac.h | 6 ++++--
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index cdd916d..2090895 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -127,8 +127,9 @@ struct plat_stmmacenet_data {
int riwt_off;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
@@ -169,10 +170,13 @@ Where:
o bus_setup: perform HW setup of the bus. For example, on some ST platforms
this field is used to configure the AMBA bridge to generate more
efficient STBus traffic.
- o init/exit: callbacks used for calling a custom initialization;
+ o setup/init/exit: callbacks used for calling a custom initialization;
this is sometime necessary on some platforms (e.g. ST boxes)
where the HW needs to have set some PIO lines or system cfg
- registers.
+ registers. setup should return a pointer to private data,
+ which will be stored in bsp_priv, and then passed to init and
+ exit callbacks. init/exit callbacks should not use or modify
+ platform data.
o custom_cfg/custom_data: this is a custom configuration that can be passed
while initializing the resources.
o bsp_priv: another private pointer.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index cc6b89a7..704a5e0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -144,9 +144,16 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
}
+ /* Custom setup (if needed) */
+ if (plat_dat->setup) {
+ plat_dat->bsp_priv = plat_dat->setup(pdev);
+ if (IS_ERR(plat_dat->bsp_priv))
+ return PTR_ERR(plat_dat->bsp_priv);
+ }
+
/* Custom initialisation (if needed)*/
if (plat_dat->init) {
- ret = plat_dat->init(pdev);
+ ret = plat_dat->init(pdev, plat_dat->bsp_priv);
if (unlikely(ret))
return ret;
}
@@ -203,7 +210,10 @@ static int stmmac_pltfr_remove(struct platform_device *pdev)
int ret = stmmac_dvr_remove(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
+
+ if (priv->plat->free)
+ priv->plat->free(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -218,7 +228,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
ret = stmmac_suspend(ndev);
if (priv->plat->exit)
- priv->plat->exit(pdev);
+ priv->plat->exit(pdev, priv->plat->bsp_priv);
return ret;
}
@@ -230,7 +240,7 @@ static int stmmac_pltfr_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
if (priv->plat->init)
- priv->plat->init(pdev);
+ priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(ndev);
}
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 33ace71..0a5a7ac 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -113,8 +113,10 @@ struct plat_stmmacenet_data {
int max_speed;
void (*fix_mac_speed)(void *priv, unsigned int speed);
void (*bus_setup)(void __iomem *ioaddr);
- int (*init)(struct platform_device *pdev);
- void (*exit)(struct platform_device *pdev);
+ void *(*setup)(struct platform_device *pdev);
+ void (*free)(struct platform_device *pdev, void *priv);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
void *custom_cfg;
void *custom_data;
void *bsp_priv;
--
1.8.5.5

View file

@ -0,0 +1,31 @@
From 6aedb8c06df732625cf998c1428396914f3139b4 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:44 +0800
Subject: [PATCH] net: stmmac: Honor DT parameter to force DMA store and
forward mode
"snps,force_sf_dma_mode" is documented in stmmac device tree bindings,
but is never handled by the driver.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 704a5e0..634260e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -56,6 +56,8 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
sizeof(struct stmmac_mdio_bus_data),
GFP_KERNEL);
+ plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode");
+
/*
* Currently only the properties needed on SPEAr600
* are provided. All other properties should be added
--
1.8.5.5

View file

@ -0,0 +1,55 @@
From 436f7ecdcc08f71ddc106b7bbe3bcbf1785f3bff Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:45 +0800
Subject: [PATCH] net: stmmac: Deprecate snps, phy-addr and auto-detect PHY
address
The snps,phy-addr device tree property is non-standard, and should be
removed in favor of proper phy node support. Remove it from the binding
documents and warn if the property is still used.
Most PHYs respond to address 0, but a few don't, so auto-detect PHY
address by default, to make up for the lack of explicit address selection.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/devicetree/bindings/net/stmmac.txt | 1 -
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 9 ++++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index d132513..aefb639 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -12,7 +12,6 @@ Required properties:
property
- phy-mode: String, operation mode of the PHY interface.
Supported values are: "mii", "rmii", "gmii", "rgmii".
-- snps,phy-addr phy address to connect to.
- snps,reset-gpio gpio number for phy reset.
- snps,reset-active-low boolean flag to indicate if phy reset is active low.
- snps,reset-delays-us is triplet of delays
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 634260e..82110f1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -50,7 +50,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
if (plat->bus_id < 0)
plat->bus_id = 0;
- of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr);
+ /* Default to phy auto-detection */
+ plat->phy_addr = -1;
+
+ /* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ * and warn of its use. Remove this when phy node support is added.
+ */
+ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
sizeof(struct stmmac_mdio_bus_data),
--
1.8.5.5

View file

@ -0,0 +1,123 @@
From 022066f50f53000679d31eb407693085f37b3f14 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:46 +0800
Subject: [PATCH] net: stmmac: Use driver data and callbacks tied with
compatible strings
The stmmac driver core allows passing feature flags and callbacks via
platform data. Add a similar stmmac_of_data to pass flags and callbacks
tied to compatible strings. This allows us to extend stmmac with glue
layers for different SoCs.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++++++++++++++++-----
include/linux/stmmac.h | 18 +++++++++
2 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 82110f1..bf119db 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -26,8 +26,20 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_net.h>
+#include <linux/of_device.h>
#include "stmmac.h"
+static const struct of_device_id stmmac_dt_ids[] = {
+ /* SoC specific glue layers should come before generic bindings */
+ { .compatible = "st,spear600-gmac"},
+ { .compatible = "snps,dwmac-3.610"},
+ { .compatible = "snps,dwmac-3.70a"},
+ { .compatible = "snps,dwmac-3.710"},
+ { .compatible = "snps,dwmac"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
+
#ifdef CONFIG_OF
static int stmmac_probe_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat,
@@ -35,10 +47,32 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
{
struct device_node *np = pdev->dev.of_node;
struct stmmac_dma_cfg *dma_cfg;
+ const struct of_device_id *device;
if (!np)
return -ENODEV;
+ device = of_match_device(stmmac_dt_ids, &pdev->dev);
+ if (!device)
+ return -ENODEV;
+
+ if (device->data) {
+ const struct stmmac_of_data *data = device->data;
+ plat->has_gmac = data->has_gmac;
+ plat->enh_desc = data->enh_desc;
+ plat->tx_coe = data->tx_coe;
+ plat->rx_coe = data->rx_coe;
+ plat->bugged_jumbo = data->bugged_jumbo;
+ plat->pmt = data->pmt;
+ plat->riwt_off = data->riwt_off;
+ plat->fix_mac_speed = data->fix_mac_speed;
+ plat->bus_setup = data->bus_setup;
+ plat->setup = data->setup;
+ plat->free = data->free;
+ plat->init = data->init;
+ plat->exit = data->exit;
+ }
+
*mac = of_get_mac_address(np);
plat->interface = of_get_phy_mode(np);
@@ -259,16 +293,6 @@ static int stmmac_pltfr_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
stmmac_pltfr_suspend, stmmac_pltfr_resume);
-static const struct of_device_id stmmac_dt_ids[] = {
- { .compatible = "st,spear600-gmac"},
- { .compatible = "snps,dwmac-3.610"},
- { .compatible = "snps,dwmac-3.70a"},
- { .compatible = "snps,dwmac-3.710"},
- { .compatible = "snps,dwmac"},
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-
struct platform_driver stmmac_pltfr_driver = {
.probe = stmmac_pltfr_probe,
.remove = stmmac_pltfr_remove,
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 0a5a7ac..1367974 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -121,4 +121,22 @@ struct plat_stmmacenet_data {
void *custom_data;
void *bsp_priv;
};
+
+/* of_data for SoC glue layer device tree bindings */
+
+struct stmmac_of_data {
+ int has_gmac;
+ int enh_desc;
+ int tx_coe;
+ int rx_coe;
+ int bugged_jumbo;
+ int pmt;
+ int riwt_off;
+ void (*fix_mac_speed)(void *priv, unsigned int speed);
+ void (*bus_setup)(void __iomem *ioaddr);
+ void *(*setup)(struct platform_device *pdev);
+ void (*free)(struct platform_device *pdev, void *priv);
+ int (*init)(struct platform_device *pdev, void *priv);
+ void (*exit)(struct platform_device *pdev, void *priv);
+};
#endif
--
1.8.5.5

View file

@ -0,0 +1,273 @@
From af0bd4e9ba809391f275d0c094ac0bfbfbb3f430 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 21:24:47 +0800
Subject: [PATCH] net: stmmac: sunxi platform extensions for GMAC in Allwinner
A20 SoC's
The Allwinner A20 has an ethernet controller that seems to be
an early version of Synopsys DesignWare MAC 10/100/1000 Universal,
which is supported by the stmmac driver.
Allwinner's GMAC requires setting additional registers in the SoC's
clock control unit.
The exact version of the DWMAC IP that Allwinner uses is unknown,
thus the exact feature set is unknown.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
.../bindings/net/allwinner,sun7i-a20-gmac.txt | 27 ++++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 ++
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c | 140 +++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 +
6 files changed, 185 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
new file mode 100644
index 0000000..ea4d752
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.txt
@@ -0,0 +1,27 @@
+* Allwinner GMAC ethernet controller
+
+This device is a platform glue layer for stmmac.
+Please see stmmac.txt for the other unchanged properties.
+
+Required properties:
+ - compatible: Should be "allwinner,sun7i-a20-gmac"
+ - clocks: Should contain the GMAC main clock, and tx clock
+ The tx clock type should be "allwinner,sun7i-a20-gmac-clk"
+ - clock-names: Should contain the clock names "stmmaceth",
+ and "allwinner_gmac_tx"
+
+Optional properties:
+- phy-supply: phandle to a regulator if the PHY needs one
+
+Examples:
+
+ gmac: ethernet@01c50000 {
+ compatible = "allwinner,sun7i-a20-gmac";
+ reg = <0x01c50000 0x10000>,
+ <0x01c20164 0x4>;
+ interrupts = <0 85 1>;
+ interrupt-names = "macirq";
+ clocks = <&ahb_gates 49>, <&gmac_tx>;
+ clock-names = "stmmaceth", "allwinner_gmac_tx";
+ phy-mode = "mii";
+ };
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index b59d1ef..e2f202e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -26,6 +26,17 @@ config STMMAC_PLATFORM
If unsure, say N.
+config DWMAC_SUNXI
+ bool "Allwinner GMAC support"
+ depends on STMMAC_PLATFORM && ARCH_SUNXI
+ default y
+ ---help---
+ Support for Allwinner A20/A31 GMAC ethernet controllers.
+
+ This selects Allwinner SoC glue layer support for the
+ stmmac device driver. This driver is used for A20/A31
+ GMAC ethernet controller.
+
config STMMAC_PCI
bool "STMMAC PCI bus support"
depends on STMMAC_ETH && PCI
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 356a9dd..ecadece 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
+stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
new file mode 100644
index 0000000..771cd15f
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -0,0 +1,140 @@
+/**
+ * dwmac-sunxi.c - Allwinner sunxi DWMAC specific glue layer
+ *
+ * Copyright (C) 2013 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/stmmac.h>
+#include <linux/clk.h>
+#include <linux/phy.h>
+#include <linux/of_net.h>
+#include <linux/regulator/consumer.h>
+
+struct sunxi_priv_data {
+ int interface;
+ int clk_enabled;
+ struct clk *tx_clk;
+ struct regulator *regulator;
+};
+
+static void *sun7i_gmac_setup(struct platform_device *pdev)
+{
+ struct sunxi_priv_data *gmac;
+ struct device *dev = &pdev->dev;
+
+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
+ if (!gmac)
+ return ERR_PTR(-ENOMEM);
+
+ gmac->interface = of_get_phy_mode(dev->of_node);
+
+ gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
+ if (IS_ERR(gmac->tx_clk)) {
+ dev_err(dev, "could not get tx clock\n");
+ return gmac->tx_clk;
+ }
+
+ /* Optional regulator for PHY */
+ gmac->regulator = devm_regulator_get_optional(dev, "phy");
+ if (IS_ERR(gmac->regulator)) {
+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
+ return ERR_PTR(-EPROBE_DEFER);
+ dev_info(dev, "no regulator found\n");
+ gmac->regulator = NULL;
+ }
+
+ return gmac;
+}
+
+#define SUN7I_GMAC_GMII_RGMII_RATE 125000000
+#define SUN7I_GMAC_MII_RATE 25000000
+
+static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
+{
+ struct sunxi_priv_data *gmac = priv;
+ int ret;
+
+ if (gmac->regulator) {
+ ret = regulator_enable(gmac->regulator);
+ if (ret)
+ return ret;
+ }
+
+ /* Set GMAC interface port mode
+ *
+ * The GMAC TX clock lines are configured by setting the clock
+ * rate, which then uses the auto-reparenting feature of the
+ * clock driver, and enabling/disabling the clock.
+ */
+ if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
+ clk_prepare_enable(gmac->tx_clk);
+ gmac->clk_enabled = 1;
+ } else {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
+ clk_prepare(gmac->tx_clk);
+ }
+
+ return 0;
+}
+
+static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct sunxi_priv_data *gmac = priv;
+
+ if (gmac->clk_enabled) {
+ clk_disable(gmac->tx_clk);
+ gmac->clk_enabled = 0;
+ }
+ clk_unprepare(gmac->tx_clk);
+
+ if (gmac->regulator)
+ regulator_disable(gmac->regulator);
+}
+
+static void sun7i_fix_speed(void *priv, unsigned int speed)
+{
+ struct sunxi_priv_data *gmac = priv;
+
+ /* only GMII mode requires us to reconfigure the clock lines */
+ if (gmac->interface != PHY_INTERFACE_MODE_GMII)
+ return;
+
+ if (gmac->clk_enabled) {
+ clk_disable(gmac->tx_clk);
+ gmac->clk_enabled = 0;
+ }
+ clk_unprepare(gmac->tx_clk);
+
+ if (speed == 1000) {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
+ clk_prepare_enable(gmac->tx_clk);
+ gmac->clk_enabled = 1;
+ } else {
+ clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
+ clk_prepare(gmac->tx_clk);
+ }
+}
+
+/* of_data specifying hardware features and callbacks.
+ * hardware features were copied from Allwinner drivers. */
+const struct stmmac_of_data sun7i_gmac_data = {
+ .has_gmac = 1,
+ .tx_coe = 1,
+ .fix_mac_speed = sun7i_fix_speed,
+ .setup = sun7i_gmac_setup,
+ .init = sun7i_gmac_init,
+ .exit = sun7i_gmac_exit,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c1c141f..d9af26e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -130,6 +130,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
bool stmmac_eee_init(struct stmmac_priv *priv);
#ifdef CONFIG_STMMAC_PLATFORM
+#ifdef CONFIG_DWMAC_SUNXI
+extern const struct stmmac_of_data sun7i_gmac_data;
+#endif
extern struct platform_driver stmmac_pltfr_driver;
static inline int stmmac_register_platform(void)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index bf119db..9d4baa8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -30,6 +30,9 @@
#include "stmmac.h"
static const struct of_device_id stmmac_dt_ids[] = {
+#ifdef CONFIG_DWMAC_SUNXI
+ { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
+#endif
/* SoC specific glue layers should come before generic bindings */
{ .compatible = "st,spear600-gmac"},
{ .compatible = "snps,dwmac-3.610"},
--
1.8.5.5

View file

@ -1,22 +0,0 @@
--- a/drivers/mmc/host/sunxi-mci.c
+++ b/drivers/mmc/host/sunxi-mci.c
@@ -715,8 +715,8 @@ static void sunxi_mmc_request(struct mmc
}
static const struct of_device_id sunxi_mmc_of_match[] = {
- { .compatible = "allwinner,sun4i-mmc", },
- { .compatible = "allwinner,sun5i-mmc", },
+ { .compatible = "allwinner,sun4i-a10-mmc", },
+ { .compatible = "allwinner,sun5i-a13-mmc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
@@ -736,7 +736,7 @@ static int sunxi_mmc_resource_request(st
struct device_node *np = pdev->dev.of_node;
int ret;
- if (of_device_is_compatible(np, "allwinner,sun4i-mmc"))
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc"))
host->idma_des_size_bits = 13;
else
host->idma_des_size_bits = 16;

View file

@ -0,0 +1,45 @@
From cc8e5932c671ba2d3ce511a15c19c47b015bc4ab Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 5 Jan 2014 00:00:30 +0100
Subject: [PATCH] phy-core: phy_get: Leave error logging to the caller
In various cases errors may be expected, ie probe-deferral or a call to
phy_get from a driver where the use of a phy is optional.
Rather then adding all sort of complicated checks for this, and/or adding
special functions like devm_phy_get_optional, simply don't log an error,
and let deciding if get_phy returning an error really should result in a
dev_err up to the caller.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/phy/phy-core.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 5f5b0f4..b355553 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -404,17 +404,11 @@ struct phy *phy_get(struct device *dev, const char *string)
index = of_property_match_string(dev->of_node, "phy-names",
string);
phy = of_phy_get(dev, index);
- if (IS_ERR(phy)) {
- dev_err(dev, "unable to find phy\n");
- return phy;
- }
} else {
phy = phy_lookup(dev, string);
- if (IS_ERR(phy)) {
- dev_err(dev, "unable to find phy\n");
- return phy;
- }
}
+ if (IS_ERR(phy))
+ return phy;
if (!try_module_get(phy->ops->owner))
return ERR_PTR(-EPROBE_DEFER);
--
1.8.5.5

View file

@ -0,0 +1,40 @@
From 37e3cce7288f7d5c34ae630f16faf48bd3d01c18 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 5 Jan 2014 22:40:39 +0100
Subject: [PATCH] phy-core: Don't propagate -ENOSUPP from
phy_pm_runtime_get_sync to caller
The phy-core allows phy_init and phy_power_on to be called multiple times,
but before this patch -ENOSUPP from phy_pm_runtime_get_sync would be
propagated to the caller for the 2nd and later calls.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/phy/phy-core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b355553..6c73837 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -176,6 +176,8 @@ int phy_init(struct phy *phy)
dev_err(&phy->dev, "phy init failed --> %d\n", ret);
goto out;
}
+ } else {
+ ret = 0; /* Override possible ret == -ENOTSUPP */
}
++phy->init_count;
@@ -232,6 +234,8 @@ int phy_power_on(struct phy *phy)
dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
goto out;
}
+ } else {
+ ret = 0; /* Override possible ret == -ENOTSUPP */
}
++phy->power_count;
mutex_unlock(&phy->mutex);
--
1.8.5.5

View file

@ -0,0 +1,48 @@
From 87c01c9ef0602abaa909771c6c6eab1f4c2c384d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 11 Feb 2014 16:55:57 +0100
Subject: [PATCH] phy-core: Don't allow building phy-core as a module
include/phy/phy.h has stub code in there for when building without the
phy-core enabled. This is useful for generic drivers such as ahci-platform,
ehci-platoform and ohci-platform which have support for driving an optional
phy passed to them through the devicetree.
Since on some boards this phy functionality is not needed, being able to
disable the phy subsystem without needing a lot of #ifdef magic in the
driver using it is quite useful.
However this breaks when the module using the phy subsystem is build-in and
the phy-core is not, which leads to the build failing with missing symbol
errors in the linking stage of the zImage.
Which leads to gems such as this being added to the Kconfig for achi_platform:
depends on GENERIC_PHY || !GENERIC_PHY
Rather then duplicating this code in a lot of places using the phy-core,
I believe it is better to simply not allow the phy-core to be built as a
module. The phy core is quite small and has no external dependencies, so
always building it in when enabling it should not be an issue.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/phy/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index afa2354..4ef8755 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -5,7 +5,7 @@
menu "PHY Subsystem"
config GENERIC_PHY
- tristate "PHY Core"
+ bool "PHY Core"
help
Generic PHY support.
--
1.8.5.5

View file

@ -0,0 +1,222 @@
From 9b10bc9f84fc221fcef9ddca92972af9b442f49d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 2 Dec 2013 16:13:32 +0100
Subject: [PATCH] libahci: Allow drivers to override start_engine
Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a
special register to be poked before starting the DMA engine.
This register gets reset on an ahci_stop_engine call, so there is no other
place then ahci_start_engine where this poking can be done.
This commit allows drivers to override ahci_start_engine behavior for use by
the Allwinner AHCI driver (and potentially other drivers in the future).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci.c | 6 ++++--
drivers/ata/ahci.h | 6 ++++++
drivers/ata/libahci.c | 26 +++++++++++++++++++-------
drivers/ata/sata_highbank.c | 3 ++-
4 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index dc2756f..eda68b4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -564,6 +564,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
struct ata_port *ap = link->ap;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
bool online;
int rc;
@@ -574,7 +575,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
deadline, &online, NULL);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
@@ -589,6 +590,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
{
struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
bool online;
@@ -604,7 +606,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
deadline, &online, NULL);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
/* The pseudo configuration device on SIMG4726 attached to
* ASUS P5W-DH Deluxe doesn't send signature FIS after
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 2289efd..64d1a99d 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -323,6 +323,12 @@ struct ahci_host_priv {
u32 em_msg_type; /* EM message type */
struct clk *clk; /* Only for platforms supporting clk */
void *plat_data; /* Other platform data */
+ /*
+ * Optional ahci_start_engine override, if not set this gets set to the
+ * default ahci_start_engine during ahci_save_initial_config, this can
+ * be overridden anytime before the host is activated.
+ */
+ void (*start_engine)(struct ata_port *ap);
};
extern int ahci_ignore_sss;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 36605ab..f839bb3 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -394,6 +394,9 @@ static ssize_t ahci_show_em_supported(struct device *dev,
*
* If inconsistent, config values are fixed up by this function.
*
+ * If it is not set already this function sets hpriv->start_engine to
+ * ahci_start_engine.
+ *
* LOCKING:
* None.
*/
@@ -500,6 +503,9 @@ void ahci_save_initial_config(struct device *dev,
hpriv->cap = cap;
hpriv->cap2 = cap2;
hpriv->port_map = port_map;
+
+ if (!hpriv->start_engine)
+ hpriv->start_engine = ahci_start_engine;
}
EXPORT_SYMBOL_GPL(ahci_save_initial_config);
@@ -766,7 +772,7 @@ static void ahci_start_port(struct ata_port *ap)
/* enable DMA */
if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
/* turn on LEDs */
if (ap->flags & ATA_FLAG_EM) {
@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap)
/* restart engine */
out_restart:
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
return rc;
}
EXPORT_SYMBOL_GPL(ahci_kick_engine);
@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
bool online;
@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
rc = sata_link_hardreset(link, timing, deadline, &online,
ahci_check_ready);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
if (online)
*class = ahci_dev_classify(ap);
@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap)
void ahci_error_handler(struct ata_port *ap)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
ahci_stop_engine(ap);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
}
sata_pmp_error_handler(ap);
@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
struct ata_device *dev = ap->link.device;
u32 devslp, dm, dito, mdat, deto;
@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
PORT_DEVSLP_ADSE);
writel(devslp, port_mmio + PORT_DEVSLP);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
/* enable device sleep feature for the drive */
err_mask = ata_dev_set_feature(dev,
@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
static void ahci_enable_fbs(struct ata_port *ap)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
struct ahci_port_priv *pp = ap->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
u32 fbs;
@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap)
} else
dev_err(ap->host->dev, "Failed to enable FBS\n");
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
}
static void ahci_disable_fbs(struct ata_port *ap)
{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
struct ahci_port_priv *pp = ap->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
u32 fbs;
@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
pp->fbs_enabled = false;
}
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
}
static void ahci_pmp_attach(struct ata_port *ap)
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 870b11e..b3b18d1 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -403,6 +403,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
static const unsigned long timing[] = { 5, 100, 500};
struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf;
bool online;
@@ -431,7 +432,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
break;
} while (!online && retry--);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
if (online)
*class = ahci_dev_classify(ap);
--
1.8.5.5

View file

@ -0,0 +1,255 @@
From bdad8090b5efdb24fa9db00d8e2891927b68dcec Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 16 Jan 2014 14:32:35 +0100
Subject: [PATCH] ahci-platform: Add support for devices with more then 1 clock
The allwinner-sun4i AHCI controller needs 2 clocks to be enabled and the
imx AHCI controller needs 3 clocks to be enabled.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/ata/ahci-platform.txt | 1 +
drivers/ata/ahci.h | 3 +-
drivers/ata/ahci_platform.c | 119 ++++++++++++++++-----
include/linux/ahci_platform.h | 4 +
4 files changed, 99 insertions(+), 28 deletions(-)
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 89de156..3ced07d 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -10,6 +10,7 @@ Required properties:
Optional properties:
- dma-coherent : Present if dma operations are coherent
+- clocks : a list of phandle + clock specifier pairs
Example:
sata@ffe08000 {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 64d1a99d..c12862b 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -51,6 +51,7 @@
enum {
AHCI_MAX_PORTS = 32,
+ AHCI_MAX_CLKS = 3,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
AHCI_MAX_CMDS = 32,
@@ -321,7 +322,7 @@ struct ahci_host_priv {
u32 em_loc; /* enclosure management location */
u32 em_buf_sz; /* EM buffer size in byte */
u32 em_msg_type; /* EM message type */
- struct clk *clk; /* Only for platforms supporting clk */
+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
void *plat_data; /* Other platform data */
/*
* Optional ahci_start_engine override, if not set this gets set to the
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4b231ba..609975d 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -87,6 +87,66 @@ struct ata_port_operations ahci_platform_ops = {
AHCI_SHT("ahci_platform"),
};
+/**
+ * ahci_platform_enable_clks - Enable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the clks found in hpriv->clks, starting
+ * at index 0. If any clk fails to enable it disables all the clks
+ * already enabled in reverse order, and then returns an error.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
+{
+ int c, rc;
+
+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
+ rc = clk_prepare_enable(hpriv->clks[c]);
+ if (rc)
+ goto disable_unprepare_clk;
+ }
+ return 0;
+
+disable_unprepare_clk:
+ while (--c >= 0)
+ clk_disable_unprepare(hpriv->clks[c]);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
+
+/**
+ * ahci_platform_disable_clks - Disable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all the clks found in hpriv->clks, in reverse
+ * order of ahci_platform_enable_clks (starting at the end of the array).
+ *
+ * LOCKING:
+ * None.
+ */
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
+{
+ int c;
+
+ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
+ if (hpriv->clks[c])
+ clk_disable_unprepare(hpriv->clks[c]);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
+
+static void ahci_put_clks(struct ahci_host_priv *hpriv)
+{
+ int c;
+
+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+ clk_put(hpriv->clks[c]);
+}
+
static int ahci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -97,6 +157,7 @@ static int ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
struct ata_host *host;
struct resource *mem;
+ struct clk *clk;
int irq;
int n_ports;
int i;
@@ -131,17 +192,31 @@ static int ahci_probe(struct platform_device *pdev)
return -ENOMEM;
}
- hpriv->clk = clk_get(dev, NULL);
- if (IS_ERR(hpriv->clk)) {
- dev_err(dev, "can't get clock\n");
- } else {
- rc = clk_prepare_enable(hpriv->clk);
- if (rc) {
- dev_err(dev, "clock prepare enable failed");
- goto free_clk;
+ for (i = 0; i < AHCI_MAX_CLKS; i++) {
+ /*
+ * For now we must use clk_get(dev, NULL) for the first clock,
+ * because some platforms (da850, spear13xx) are not yet
+ * converted to use devicetree for clocks. For new platforms
+ * this is equivalent to of_clk_get(dev->of_node, 0).
+ */
+ if (i == 0)
+ clk = clk_get(dev, NULL);
+ else
+ clk = of_clk_get(dev->of_node, i);
+
+ if (IS_ERR(clk)) {
+ rc = PTR_ERR(clk);
+ if (rc == -EPROBE_DEFER)
+ goto free_clk;
+ break;
}
+ hpriv->clks[i] = clk;
}
+ rc = ahci_enable_clks(dev, hpriv);
+ if (rc)
+ goto free_clk;
+
/*
* Some platforms might need to prepare for mmio region access,
* which could be done in the following init call. So, the mmio
@@ -222,11 +297,9 @@ static int ahci_probe(struct platform_device *pdev)
if (pdata && pdata->exit)
pdata->exit(dev);
disable_unprepare_clk:
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
+ ahci_disable_clks(hpriv);
free_clk:
- if (!IS_ERR(hpriv->clk))
- clk_put(hpriv->clk);
+ ahci_put_clks(hpriv);
return rc;
}
@@ -239,10 +312,8 @@ static void ahci_host_stop(struct ata_host *host)
if (pdata && pdata->exit)
pdata->exit(dev);
- if (!IS_ERR(hpriv->clk)) {
- clk_disable_unprepare(hpriv->clk);
- clk_put(hpriv->clk);
- }
+ ahci_disable_clks(hpriv);
+ ahci_put_clks(hpriv);
}
#ifdef CONFIG_PM_SLEEP
@@ -277,8 +348,7 @@ static int ahci_suspend(struct device *dev)
if (pdata && pdata->suspend)
return pdata->suspend(dev);
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
+ ahci_disable_clks(hpriv);
return 0;
}
@@ -290,13 +360,9 @@ static int ahci_resume(struct device *dev)
struct ahci_host_priv *hpriv = host->private_data;
int rc;
- if (!IS_ERR(hpriv->clk)) {
- rc = clk_prepare_enable(hpriv->clk);
- if (rc) {
- dev_err(dev, "clock prepare enable failed");
- return rc;
- }
- }
+ rc = ahci_enable_clks(dev, hpriv);
+ if (rc)
+ return rc;
if (pdata && pdata->resume) {
rc = pdata->resume(dev);
@@ -317,8 +383,7 @@ static int ahci_resume(struct device *dev)
return 0;
disable_unprepare_clk:
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
+ ahci_disable_clks(hpriv);
return rc;
}
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 73a2500..769d065 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -19,6 +19,7 @@
struct device;
struct ata_port_info;
+struct ahci_host_priv;
struct ahci_platform_data {
int (*init)(struct device *dev, void __iomem *addr);
@@ -30,4 +31,7 @@ struct ahci_platform_data {
unsigned int mask_port_map;
};
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+
#endif /* _AHCI_PLATFORM_H */
--
1.8.5.5

View file

@ -0,0 +1,141 @@
From ba6850946d9e1959be1b00f6ae06454546350c75 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 17 Jan 2014 13:23:21 +0100
Subject: [PATCH] ahci-platform: Add support for an optional regulator for
sata-target power
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/ata/ahci-platform.txt | 1 +
drivers/ata/ahci.h | 2 ++
drivers/ata/ahci_platform.c | 36 ++++++++++++++++++++--
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 3ced07d..1ac807f 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -11,6 +11,7 @@ Required properties:
Optional properties:
- dma-coherent : Present if dma operations are coherent
- clocks : a list of phandle + clock specifier pairs
+- target-supply : regulator for SATA target power
Example:
sata@ffe08000 {
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index c12862b..bf8100c 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -37,6 +37,7 @@
#include <linux/clk.h>
#include <linux/libata.h>
+#include <linux/regulator/consumer.h>
/* Enclosure Management Control */
#define EM_CTRL_MSG_TYPE 0x000f0000
@@ -323,6 +324,7 @@ struct ahci_host_priv {
u32 em_buf_sz; /* EM buffer size in byte */
u32 em_msg_type; /* EM message type */
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
+ struct regulator *target_pwr; /* Optional */
void *plat_data; /* Other platform data */
/*
* Optional ahci_start_engine override, if not set this gets set to the
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 609975d..907c076 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -192,6 +192,14 @@ static int ahci_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
+ if (IS_ERR(hpriv->target_pwr)) {
+ rc = PTR_ERR(hpriv->target_pwr);
+ if (rc == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ hpriv->target_pwr = NULL;
+ }
+
for (i = 0; i < AHCI_MAX_CLKS; i++) {
/*
* For now we must use clk_get(dev, NULL) for the first clock,
@@ -213,9 +221,15 @@ static int ahci_probe(struct platform_device *pdev)
hpriv->clks[i] = clk;
}
+ if (hpriv->target_pwr) {
+ rc = regulator_enable(hpriv->target_pwr);
+ if (rc)
+ goto free_clk;
+ }
+
rc = ahci_enable_clks(dev, hpriv);
if (rc)
- goto free_clk;
+ goto disable_regulator;
/*
* Some platforms might need to prepare for mmio region access,
@@ -298,6 +312,9 @@ static int ahci_probe(struct platform_device *pdev)
pdata->exit(dev);
disable_unprepare_clk:
ahci_disable_clks(hpriv);
+disable_regulator:
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
free_clk:
ahci_put_clks(hpriv);
return rc;
@@ -314,6 +331,9 @@ static void ahci_host_stop(struct ata_host *host)
ahci_disable_clks(hpriv);
ahci_put_clks(hpriv);
+
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
}
#ifdef CONFIG_PM_SLEEP
@@ -350,6 +370,9 @@ static int ahci_suspend(struct device *dev)
ahci_disable_clks(hpriv);
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
+
return 0;
}
@@ -360,9 +383,15 @@ static int ahci_resume(struct device *dev)
struct ahci_host_priv *hpriv = host->private_data;
int rc;
+ if (hpriv->target_pwr) {
+ rc = regulator_enable(hpriv->target_pwr);
+ if (rc)
+ return rc;
+ }
+
rc = ahci_enable_clks(dev, hpriv);
if (rc)
- return rc;
+ goto disable_regulator;
if (pdata && pdata->resume) {
rc = pdata->resume(dev);
@@ -384,6 +413,9 @@ static int ahci_resume(struct device *dev)
disable_unprepare_clk:
ahci_disable_clks(hpriv);
+disable_regulator:
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
return rc;
}
--
1.8.5.5

View file

@ -0,0 +1,211 @@
From 05d5a60ae336c122e478cc002afccc880d462b3b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Jan 2014 14:54:40 +0100
Subject: [PATCH] ahci-platform: Add enable_ / disable_resources helper
functions
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci_platform.c | 112 ++++++++++++++++++++++++++++--------------
include/linux/ahci_platform.h | 2 +
2 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 907c076..6ebbc17 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -139,6 +139,68 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
}
EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
+/**
+ * ahci_platform_enable_resources - Enable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all ahci_platform managed resources in
+ * the following order:
+ * 1) Regulator
+ * 2) Clocks (through ahci_platform_enable_clks)
+ *
+ * If resource enabling fails at any point the previous enabled
+ * resources are disabled in reverse order.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
+{
+ int rc;
+
+ if (hpriv->target_pwr) {
+ rc = regulator_enable(hpriv->target_pwr);
+ if (rc)
+ return rc;
+ }
+
+ rc = ahci_platform_enable_clks(hpriv);
+ if (rc)
+ goto disable_regulator;
+
+ return 0;
+
+disable_regulator:
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
+
+/**
+ * ahci_platform_disable_resources - Disable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all ahci_platform managed resources in
+ * the following order:
+ * 1) Clocks (through ahci_platform_disable_clks)
+ * 2) Regulator
+ *
+ * LOCKING:
+ * None.
+ */
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
+{
+ ahci_platform_disable_clks(hpriv);
+
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
+
static void ahci_put_clks(struct ahci_host_priv *hpriv)
{
int c;
@@ -221,15 +283,9 @@ static int ahci_probe(struct platform_device *pdev)
hpriv->clks[i] = clk;
}
- if (hpriv->target_pwr) {
- rc = regulator_enable(hpriv->target_pwr);
- if (rc)
- goto free_clk;
- }
-
- rc = ahci_enable_clks(dev, hpriv);
+ rc = ahci_platform_enable_resources(hpriv);
if (rc)
- goto disable_regulator;
+ goto free_clk;
/*
* Some platforms might need to prepare for mmio region access,
@@ -240,7 +296,7 @@ static int ahci_probe(struct platform_device *pdev)
if (pdata && pdata->init) {
rc = pdata->init(dev, hpriv->mmio);
if (rc)
- goto disable_unprepare_clk;
+ goto disable_resources;
}
ahci_save_initial_config(dev, hpriv,
@@ -310,11 +366,8 @@ static int ahci_probe(struct platform_device *pdev)
pdata_exit:
if (pdata && pdata->exit)
pdata->exit(dev);
-disable_unprepare_clk:
- ahci_disable_clks(hpriv);
-disable_regulator:
- if (hpriv->target_pwr)
- regulator_disable(hpriv->target_pwr);
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
free_clk:
ahci_put_clks(hpriv);
return rc;
@@ -329,11 +382,8 @@ static void ahci_host_stop(struct ata_host *host)
if (pdata && pdata->exit)
pdata->exit(dev);
- ahci_disable_clks(hpriv);
+ ahci_platform_disable_resources(hpriv);
ahci_put_clks(hpriv);
-
- if (hpriv->target_pwr)
- regulator_disable(hpriv->target_pwr);
}
#ifdef CONFIG_PM_SLEEP
@@ -368,10 +418,7 @@ static int ahci_suspend(struct device *dev)
if (pdata && pdata->suspend)
return pdata->suspend(dev);
- ahci_disable_clks(hpriv);
-
- if (hpriv->target_pwr)
- regulator_disable(hpriv->target_pwr);
+ ahci_platform_disable_resources(hpriv);
return 0;
}
@@ -383,26 +430,20 @@ static int ahci_resume(struct device *dev)
struct ahci_host_priv *hpriv = host->private_data;
int rc;
- if (hpriv->target_pwr) {
- rc = regulator_enable(hpriv->target_pwr);
- if (rc)
- return rc;
- }
-
- rc = ahci_enable_clks(dev, hpriv);
+ rc = ahci_platform_enable_resources(hpriv);
if (rc)
- goto disable_regulator;
+ return rc;
if (pdata && pdata->resume) {
rc = pdata->resume(dev);
if (rc)
- goto disable_unprepare_clk;
+ goto disable_resources;
}
if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
rc = ahci_reset_controller(host);
if (rc)
- goto disable_unprepare_clk;
+ goto disable_resources;
ahci_init_controller(host);
}
@@ -411,11 +452,8 @@ static int ahci_resume(struct device *dev)
return 0;
-disable_unprepare_clk:
- ahci_disable_clks(hpriv);
-disable_regulator:
- if (hpriv->target_pwr)
- regulator_disable(hpriv->target_pwr);
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
return rc;
}
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 769d065..b674b01 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -33,5 +33,7 @@ struct ahci_platform_data {
int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
#endif /* _AHCI_PLATFORM_H */
--
1.8.5.5

View file

@ -0,0 +1,344 @@
From 98601575da5276173233dd575bdd61cccdeb861a Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Jan 2014 14:58:04 +0100
Subject: [PATCH] ahci-platform: "Library-ise" ahci_probe functionality
ahci_probe consists of 3 steps:
1) Get resources (get mmio, clks, regulator)
2) Enable resources, handled by ahci_platform_enable_resouces
3) The more or less standard ahci-host controller init sequence
This commit refactors step 1 and 3 into separate functions, so the platform
drivers for AHCI implementations which need a specific order in step 2,
and / or need to do some custom register poking at some time, can re-use
ahci-platform.c code without needing to copy and paste it.
Note that ahci_platform_init_host's prototype takes the 3 non function
members of ahci_platform_data as arguments, the idea is that drivers using
the new exported utility functions will not use ahci_platform_data at all,
and hopefully in the future ahci_platform_data can go away entirely.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci_platform.c | 195 ++++++++++++++++++++++++++++--------------
include/linux/ahci_platform.h | 14 +++
2 files changed, 144 insertions(+), 65 deletions(-)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 6ebbc17..7f3f2ac 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -201,64 +201,64 @@ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
}
EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
-static void ahci_put_clks(struct ahci_host_priv *hpriv)
+static void ahci_platform_put_resources(struct device *dev, void *res)
{
+ struct ahci_host_priv *hpriv = res;
int c;
for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
clk_put(hpriv->clks[c]);
}
-static int ahci_probe(struct platform_device *pdev)
+/**
+ * ahci_platform_get_resources - Get platform resources
+ * @pdev: platform device to get resources for
+ *
+ * This function allocates an ahci_host_priv struct, and gets the
+ * following resources, storing a reference to them inside the returned
+ * struct:
+ *
+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
+ * 2) regulator for controlling the targets power (optional)
+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
+ * or for non devicetree enabled platforms a single clock
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
+ */
+struct ahci_host_priv *ahci_platform_get_resources(
+ struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct ahci_platform_data *pdata = dev_get_platdata(dev);
- const struct platform_device_id *id = platform_get_device_id(pdev);
- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
- const struct ata_port_info *ppi[] = { &pi, NULL };
struct ahci_host_priv *hpriv;
- struct ata_host *host;
- struct resource *mem;
struct clk *clk;
- int irq;
- int n_ports;
- int i;
- int rc;
+ int i, rc = -ENOMEM;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(dev, "no mmio space\n");
- return -EINVAL;
- }
+ if (!devres_open_group(dev, NULL, GFP_KERNEL))
+ return ERR_PTR(-ENOMEM);
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(dev, "no irq\n");
- return -EINVAL;
- }
+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
+ GFP_KERNEL);
+ if (!hpriv)
+ goto err_out;
- if (pdata && pdata->ata_port_info)
- pi = *pdata->ata_port_info;
+ devres_add(dev, hpriv);
- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv) {
- dev_err(dev, "can't alloc ahci_host_priv\n");
- return -ENOMEM;
- }
-
- hpriv->flags |= (unsigned long)pi.private_data;
-
- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
+ hpriv->mmio = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
if (!hpriv->mmio) {
- dev_err(dev, "can't map %pR\n", mem);
- return -ENOMEM;
+ dev_err(dev, "no mmio space\n");
+ goto err_out;
}
hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
if (IS_ERR(hpriv->target_pwr)) {
rc = PTR_ERR(hpriv->target_pwr);
if (rc == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ goto err_out;
hpriv->target_pwr = NULL;
}
@@ -277,33 +277,62 @@ static int ahci_probe(struct platform_device *pdev)
if (IS_ERR(clk)) {
rc = PTR_ERR(clk);
if (rc == -EPROBE_DEFER)
- goto free_clk;
+ goto err_out;
break;
}
hpriv->clks[i] = clk;
}
- rc = ahci_platform_enable_resources(hpriv);
- if (rc)
- goto free_clk;
+ devres_remove_group(dev, NULL);
+ return hpriv;
- /*
- * Some platforms might need to prepare for mmio region access,
- * which could be done in the following init call. So, the mmio
- * region shouldn't be accessed before init (if provided) has
- * returned successfully.
- */
- if (pdata && pdata->init) {
- rc = pdata->init(dev, hpriv->mmio);
- if (rc)
- goto disable_resources;
- }
+err_out:
+ devres_release_group(dev, NULL);
+ return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
+
+/**
+ * ahci_platform_init_host - Bring up an ahci-platform host
+ * @pdev: platform device pointer for the host
+ * @hpriv: ahci-host private data for the host
+ * @pi_template: template for the ata_port_info to use
+ * @force_port_map: param passed to ahci_save_initial_config
+ * @mask_port_map: param passed to ahci_save_initial_config
+ *
+ * This function does all the usual steps needed to bring up an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be initialized / enabled before calling this.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_init_host(struct platform_device *pdev,
+ struct ahci_host_priv *hpriv,
+ const struct ata_port_info *pi_template,
+ unsigned int force_port_map,
+ unsigned int mask_port_map)
+{
+ struct device *dev = &pdev->dev;
+ struct ata_port_info pi = *pi_template;
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ struct ata_host *host;
+ int i, irq, n_ports, rc;
- ahci_save_initial_config(dev, hpriv,
- pdata ? pdata->force_port_map : 0,
- pdata ? pdata->mask_port_map : 0);
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
+ dev_err(dev, "no irq\n");
+ return -EINVAL;
+ }
/* prepare host */
+ hpriv->flags |= (unsigned long)pi.private_data;
+
+ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+
if (hpriv->cap & HOST_CAP_NCQ)
pi.flags |= ATA_FLAG_NCQ;
@@ -320,10 +349,8 @@ static int ahci_probe(struct platform_device *pdev)
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
host = ata_host_alloc_pinfo(dev, ppi, n_ports);
- if (!host) {
- rc = -ENOMEM;
- goto pdata_exit;
- }
+ if (!host)
+ return -ENOMEM;
host->private_data = hpriv;
@@ -338,7 +365,8 @@ static int ahci_probe(struct platform_device *pdev)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- ata_port_desc(ap, "mmio %pR", mem);
+ ata_port_desc(ap, "mmio %pR",
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
/* set enclosure management message type */
@@ -352,13 +380,53 @@ static int ahci_probe(struct platform_device *pdev)
rc = ahci_reset_controller(host);
if (rc)
- goto pdata_exit;
+ return rc;
ahci_init_controller(host);
ahci_print_info(host, "platform");
- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
- &ahci_platform_sht);
+ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
+ &ahci_platform_sht);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_init_host);
+
+static int ahci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct ata_port_info *pi_template;
+ struct ahci_host_priv *hpriv;
+ int rc;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ /*
+ * Some platforms might need to prepare for mmio region access,
+ * which could be done in the following init call. So, the mmio
+ * region shouldn't be accessed before init (if provided) has
+ * returned successfully.
+ */
+ if (pdata && pdata->init) {
+ rc = pdata->init(dev, hpriv->mmio);
+ if (rc)
+ goto disable_resources;
+ }
+
+ if (pdata && pdata->ata_port_info)
+ pi_template = pdata->ata_port_info;
+ else
+ pi_template = &ahci_port_info[id ? id->driver_data : 0];
+
+ rc = ahci_platform_init_host(pdev, hpriv, pi_template,
+ pdata ? pdata->force_port_map : 0,
+ pdata ? pdata->mask_port_map : 0);
if (rc)
goto pdata_exit;
@@ -368,8 +436,6 @@ static int ahci_probe(struct platform_device *pdev)
pdata->exit(dev);
disable_resources:
ahci_platform_disable_resources(hpriv);
-free_clk:
- ahci_put_clks(hpriv);
return rc;
}
@@ -383,7 +449,6 @@ static void ahci_host_stop(struct ata_host *host)
pdata->exit(dev);
ahci_platform_disable_resources(hpriv);
- ahci_put_clks(hpriv);
}
#ifdef CONFIG_PM_SLEEP
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index b674b01..b80c51c 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -20,7 +20,14 @@
struct device;
struct ata_port_info;
struct ahci_host_priv;
+struct platform_device;
+/*
+ * Note ahci_platform_data is deprecated, it is only kept around for use
+ * by the old da850 and spear13xx ahci code.
+ * New drivers should instead declare their own platform_driver struct, and
+ * use ahci_platform* functions in their own probe, suspend and resume methods.
+ */
struct ahci_platform_data {
int (*init)(struct device *dev, void __iomem *addr);
void (*exit)(struct device *dev);
@@ -35,5 +42,12 @@ struct ahci_platform_data {
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
+struct ahci_host_priv *ahci_platform_get_resources(
+ struct platform_device *pdev);
+int ahci_platform_init_host(struct platform_device *pdev,
+ struct ahci_host_priv *hpriv,
+ const struct ata_port_info *pi_template,
+ unsigned int force_port_map,
+ unsigned int mask_port_map);
#endif /* _AHCI_PLATFORM_H */
--
1.8.5.5

View file

@ -0,0 +1,188 @@
From 041cf8356a4eb91ee8118004b2bc9c78cdd7866c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 20 Jan 2014 15:52:07 +0100
Subject: [PATCH] ahci-platform: "Library-ise" suspend / resume functionality
Split suspend / resume code into host suspend / resume functionality and
resource enable / disabling phases, and export the new suspend_ / resume_host
functions.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci_platform.c | 109 ++++++++++++++++++++++++++++++++++++------
include/linux/ahci_platform.h | 5 ++
2 files changed, 99 insertions(+), 15 deletions(-)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 7f3f2ac..bdadec1 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -452,14 +452,26 @@ static void ahci_host_stop(struct ata_host *host)
}
#ifdef CONFIG_PM_SLEEP
-static int ahci_suspend(struct device *dev)
+/**
+ * ahci_platform_suspend_host - Suspend an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to suspend an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be disabled after calling this.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend_host(struct device *dev)
{
- struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev);
struct ahci_host_priv *hpriv = host->private_data;
void __iomem *mmio = hpriv->mmio;
u32 ctl;
- int rc;
if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
dev_err(dev, "firmware update required for suspend/resume\n");
@@ -476,7 +488,64 @@ static int ahci_suspend(struct device *dev)
writel(ctl, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */
- rc = ata_host_suspend(host, PMSG_SUSPEND);
+ return ata_host_suspend(host, PMSG_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
+
+/**
+ * ahci_platform_resume_host - Resume an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to resume an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be initialized / enabled before calling this.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume_host(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ int rc;
+
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+ rc = ahci_reset_controller(host);
+ if (rc)
+ return rc;
+
+ ahci_init_controller(host);
+ }
+
+ ata_host_resume(host);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
+
+/**
+ * ahci_platform_suspend - Suspend an ahci-platform device
+ * @dev: the platform device to suspend
+ *
+ * This function suspends the host associated with the device, followed
+ * by disabling all the resources of the device.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend(struct device *dev)
+{
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+ rc = ahci_platform_suspend_host(dev);
if (rc)
return rc;
@@ -487,8 +556,22 @@ static int ahci_suspend(struct device *dev)
return 0;
}
+EXPORT_SYMBOL_GPL(ahci_platform_suspend);
-static int ahci_resume(struct device *dev)
+/**
+ * ahci_platform_resume - Resume an ahci-platform device
+ * @dev: the platform device to resume
+ *
+ * This function enables all the resources of the device followed by
+ * resuming the host associated with the device.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume(struct device *dev)
{
struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ata_host *host = dev_get_drvdata(dev);
@@ -505,15 +588,9 @@ static int ahci_resume(struct device *dev)
goto disable_resources;
}
- if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
- rc = ahci_reset_controller(host);
- if (rc)
- goto disable_resources;
-
- ahci_init_controller(host);
- }
-
- ata_host_resume(host);
+ rc = ahci_platform_resume_host(dev);
+ if (rc)
+ goto disable_resources;
return 0;
@@ -522,9 +599,11 @@ static int ahci_resume(struct device *dev)
return rc;
}
+EXPORT_SYMBOL_GPL(ahci_platform_resume);
#endif
-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+ ahci_platform_resume);
static const struct of_device_id ahci_of_match[] = {
{ .compatible = "snps,spear-ahci", },
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index b80c51c..542f268 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
unsigned int force_port_map,
unsigned int mask_port_map);
+int ahci_platform_suspend_host(struct device *dev);
+int ahci_platform_resume_host(struct device *dev);
+int ahci_platform_suspend(struct device *dev);
+int ahci_platform_resume(struct device *dev);
+
#endif /* _AHCI_PLATFORM_H */
--
1.8.5.5

View file

@ -1,46 +0,0 @@
From 3eec76bc21d78e56ac8404b59f29dd9dbbd1528a Mon Sep 17 00:00:00 2001
From: Oliver Schinagl <oliver@schinagl.nl>
Date: Mon, 2 Dec 2013 16:13:32 +0100
Subject: [PATCH] libahci: Add a pre ahci_start_engine hook
Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which need a
special register to be poked before starting the DMA engine.
This register gets reset on an ahci_stop_engine call, so there is no other
place then ahci_start_engine where this poking can be done.
This commit adds a pre ahci_start_engine hook for use by the Allwinner AHCI
driver (and potentially other drivers in the future).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci.h | 2 ++
drivers/ata/libahci.c | 4 ++++
2 files changed, 6 insertions(+)
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -323,6 +323,8 @@ struct ahci_host_priv {
u32 em_msg_type; /* EM message type */
struct clk *clk; /* Only for platforms supporting clk */
void *plat_data; /* Other platform data */
+ /* Optional pre ahci_start_engine hook */
+ void (*pre_start_engine)(struct ata_port *ap);
};
extern int ahci_ignore_sss;
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -568,8 +568,12 @@ static int ahci_scr_write(struct ata_lin
void ahci_start_engine(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
+ struct ahci_host_priv *hpriv = ap->host->private_data;
u32 tmp;
+ if (hpriv->pre_start_engine)
+ hpriv->pre_start_engine(ap);
+
/* start DMA */
tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_START;

View file

@ -0,0 +1,352 @@
From 93dd2c512a24c552f1146d746aac112da7677430 Mon Sep 17 00:00:00 2001
From: Olliver Schinagl <oliver@schinagl.nl>
Date: Sat, 18 Jan 2014 15:00:45 +0100
Subject: [PATCH] ARM: sunxi: Add support for Allwinner SUNXi SoCs sata to
ahci_platform
This patch adds support for the ahci sata controler found on Allwinner A10
and A20 SoCs to the ahci_platform driver.
Orignally written by Olliver Schinagl using the approach of having a platform
device which probe method creates a new child platform device which gets
driven by ahci_platform.c, as done by ahci_imx.c .
Refactored by Hans de Goede to add most of the non sunxi specific functionality
to ahci_platform.c and use a platform_data pointer from of_device_id for the
sunxi specific bits.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/ata/ahci-platform.txt | 15 +-
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/ahci_sunxi.c | 249 +++++++++++++++++++++
4 files changed, 271 insertions(+), 3 deletions(-)
create mode 100644 drivers/ata/ahci_sunxi.c
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 1ac807f..499bfed 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -4,7 +4,9 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
Each SATA controller should have its own node.
Required properties:
-- compatible : compatible list, contains "snps,spear-ahci"
+- compatible : compatible list, one of "snps,spear-ahci",
+ "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
+ "allwinner,sun4i-a10-ahci"
- interrupts : <interrupt mapping for SATA IRQ>
- reg : <registers mapping>
@@ -13,10 +15,17 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- target-supply : regulator for SATA target power
-Example:
+Examples:
sata@ffe08000 {
compatible = "snps,spear-ahci";
reg = <0xffe08000 0x1000>;
interrupts = <115>;
-
};
+
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ clocks = <&pll6 0>, <&ahb_gates 25>;
+ target-supply = <&reg_ahci_5v>;
+ };
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4e73772..cc67cc0 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -106,6 +106,15 @@ config AHCI_IMX
If unsure, say N.
+config AHCI_SUNXI
+ tristate "Allwinner sunxi AHCI SATA support"
+ depends on ARCH_SUNXI && SATA_AHCI_PLATFORM
+ help
+ This option enables support for the Allwinner sunxi SoC's
+ onboard AHCI SATA.
+
+ If unsure, say N.
+
config SATA_FSL
tristate "Freescale 3.0Gbps SATA support"
depends on FSL_SOC
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 46518c6..246050b 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o
# SFF w/ custom DMA
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
new file mode 100644
index 0000000..001f7dfc
--- /dev/null
+++ b/drivers/ata/ahci_sunxi.c
@@ -0,0 +1,249 @@
+/*
+ * Allwinner sunxi AHCI SATA platform driver
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
+ * Daniel Wang <danielwang@allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define AHCI_BISTAFR 0x00a0
+#define AHCI_BISTCR 0x00a4
+#define AHCI_BISTFCTR 0x00a8
+#define AHCI_BISTSR 0x00ac
+#define AHCI_BISTDECR 0x00b0
+#define AHCI_DIAGNR0 0x00b4
+#define AHCI_DIAGNR1 0x00b8
+#define AHCI_OOBR 0x00bc
+#define AHCI_PHYCS0R 0x00c0
+#define AHCI_PHYCS1R 0x00c4
+#define AHCI_PHYCS2R 0x00c8
+#define AHCI_TIMER1MS 0x00e0
+#define AHCI_GPARAM1R 0x00e8
+#define AHCI_GPARAM2R 0x00ec
+#define AHCI_PPARAMR 0x00f0
+#define AHCI_TESTR 0x00f4
+#define AHCI_VERSIONR 0x00f8
+#define AHCI_IDR 0x00fc
+#define AHCI_RWCR 0x00fc
+#define AHCI_P0DMACR 0x0170
+#define AHCI_P0PHYCR 0x0178
+#define AHCI_P0PHYSR 0x017c
+
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val &= ~(clr_val);
+ writel(reg_val, reg);
+}
+
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val |= set_val;
+ writel(reg_val, reg);
+}
+
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val &= ~(clr_val);
+ reg_val |= set_val;
+ writel(reg_val, reg);
+}
+
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
+{
+ return (readl(reg) >> shift) & mask;
+}
+
+static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+{
+ u32 reg_val;
+ int timeout;
+
+ /* This magic is from the original code */
+ writel(0, reg_base + AHCI_RWCR);
+ mdelay(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+ (0x7 << 24),
+ (0x5 << 24) | BIT(23) | BIT(18));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+ (0x7 << 20), (0x3 << 20));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+ (0x1f << 5), (0x19 << 5));
+ mdelay(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+ timeout = 250; /* Power up takes aprox 50 us */
+ do {
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+ if (reg_val == 0x02)
+ break;
+
+ if (--timeout == 0) {
+ dev_err(dev, "PHY power up failed.\n");
+ return -EIO;
+ }
+ udelay(1);
+ } while (1);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+ timeout = 100; /* Calibration takes aprox 10 us */
+ do {
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+ if (reg_val == 0x00)
+ break;
+
+ if (--timeout == 0) {
+ dev_err(dev, "PHY calibration failed.\n");
+ return -EIO;
+ }
+ udelay(1);
+ } while (1);
+
+ mdelay(15);
+
+ writel(0x7, reg_base + AHCI_RWCR);
+
+ return 0;
+}
+
+static void ahci_sunxi_start_engine(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+
+ /* Setup DMA before DMA start */
+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
+
+ /* Start DMA */
+ sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
+}
+
+static const struct ata_port_info ahci_sunxi_port_info = {
+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_platform_ops,
+};
+
+static int ahci_sunxi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ahci_host_priv *hpriv;
+ int rc;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ hpriv->start_engine = ahci_sunxi_start_engine;
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+ if (rc)
+ goto disable_resources;
+
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0);
+ if (rc)
+ goto disable_resources;
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+ return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+int ahci_sunxi_resume(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+ rc = ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+ if (rc)
+ goto disable_resources;
+
+ rc = ahci_platform_resume_host(dev);
+ if (rc)
+ goto disable_resources;
+
+ return 0;
+
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
+ return rc;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
+ ahci_sunxi_resume);
+
+static const struct of_device_id ahci_sunxi_of_match[] = {
+ { .compatible = "allwinner,sun4i-a10-ahci", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
+
+static struct platform_driver ahci_sunxi_driver = {
+ .probe = ahci_sunxi_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = "ahci-sunxi",
+ .owner = THIS_MODULE,
+ .of_match_table = ahci_sunxi_of_match,
+ .pm = &ahci_sunxi_pm_ops,
+ },
+};
+module_platform_driver(ahci_sunxi_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
+MODULE_LICENSE("GPL");
--
1.8.5.5

View file

@ -1,436 +0,0 @@
From 22345cc059de4a6ea1dc7657dd6ad86ca16a8814 Mon Sep 17 00:00:00 2001
From: Oliver Schinagl <oliver@schinagl.nl>
Date: Tue, 3 Dec 2013 12:07:01 +0100
Subject: [PATCH] ARM: sunxi: Add ahci-sunxi driver for the Allwinner SUNXi
SoCs sata
This patch adds support for the ahci sata controler found on Allwinner A10
and A20 SoCs.
Orignally written by Olliver Schinagl using the approach of having a platform
device which probe method creates a new child platform device which gets
driven by ahci_platform.c, as done by ahci_imx.c .
Given that almost all functionality already is shared through libahci /
ata-core, and that ahci_platform.c cannot cleanly handle somewhat more complex
platform specific ahci cases, such as the sunxi case, it was refactored into
a stand-alone platform driver by Hans de Goede.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/ata/ahci-sunxi.txt | 24 ++
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/ahci_sunxi.c | 349 +++++++++++++++++++++
4 files changed, 383 insertions(+)
create mode 100644 Documentation/devicetree/bindings/ata/ahci-sunxi.txt
create mode 100644 drivers/ata/ahci_sunxi.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt
@@ -0,0 +1,24 @@
+Allwinner SUNXI AHCI SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible : compatible list, contains "allwinner,sun4i-a10-ahci"
+- reg : <registers mapping>
+- interrupts : <interrupt mapping for AHCI IRQ>
+- clocks : clocks for ACHI
+- clock-names : clock names for AHCI
+
+Optional properties:
+- pwr-supply : regulator to control the power supply GPIO
+
+Example:
+ ahci@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <0 56 1>;
+ clocks = <&ahb_gates 25>, <&pll6 0>;
+ clock-names = "ahb_sata", "pll6_sata";
+ pwr-supply = <&reg_ahci_5v>;
+ };
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -106,6 +106,15 @@ config AHCI_IMX
If unsure, say N.
+config AHCI_SUNXI
+ tristate "Allwinner sunxi AHCI SATA support"
+ depends on ARCH_SUNXI
+ help
+ This option enables support for the Allwinner sunxi SoC's
+ onboard AHCI SATA.
+
+ If unsure, say N.
+
config SATA_FSL
tristate "Freescale 3.0Gbps SATA support"
depends on FSL_SOC
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o
# SFF w/ custom DMA
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
--- /dev/null
+++ b/drivers/ata/ahci_sunxi.c
@@ -0,0 +1,349 @@
+/*
+ * Allwinner sunxi AHCI SATA platform driver
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
+ * Daniel Wang <danielwang@allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define AHCI_BISTAFR 0x00a0
+#define AHCI_BISTCR 0x00a4
+#define AHCI_BISTFCTR 0x00a8
+#define AHCI_BISTSR 0x00ac
+#define AHCI_BISTDECR 0x00b0
+#define AHCI_DIAGNR0 0x00b4
+#define AHCI_DIAGNR1 0x00b8
+#define AHCI_OOBR 0x00bc
+#define AHCI_PHYCS0R 0x00c0
+#define AHCI_PHYCS1R 0x00c4
+#define AHCI_PHYCS2R 0x00c8
+#define AHCI_TIMER1MS 0x00e0
+#define AHCI_GPARAM1R 0x00e8
+#define AHCI_GPARAM2R 0x00ec
+#define AHCI_PPARAMR 0x00f0
+#define AHCI_TESTR 0x00f4
+#define AHCI_VERSIONR 0x00f8
+#define AHCI_IDR 0x00fc
+#define AHCI_RWCR 0x00fc
+#define AHCI_P0DMACR 0x0170
+#define AHCI_P0PHYCR 0x0178
+#define AHCI_P0PHYSR 0x017c
+
+struct sunxi_ahci {
+ struct ahci_host_priv hpriv;
+ struct regulator *pwr;
+ struct clk *sata_clk;
+ struct clk *ahb_clk;
+};
+
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val &= ~(clr_val);
+ writel(reg_val, reg);
+}
+
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val |= set_val;
+ writel(reg_val, reg);
+}
+
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
+{
+ u32 reg_val;
+
+ reg_val = readl(reg);
+ reg_val &= ~(clr_val);
+ reg_val |= set_val;
+ writel(reg_val, reg);
+}
+
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
+{
+ return (readl(reg) >> shift) & mask;
+}
+
+static int sunxi_ahci_phy_init(struct device *dev, void __iomem *reg_base)
+{
+ u32 reg_val;
+ int timeout;
+
+ /* This magic is from the original code */
+ writel(0, reg_base + AHCI_RWCR);
+ mdelay(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+ (0x7 << 24),
+ (0x5 << 24) | BIT(23) | BIT(18));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+ (0x7 << 20), (0x3 << 20));
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+ (0x1f << 5), (0x19 << 5));
+ mdelay(5);
+
+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+ timeout = 0x100000;
+ do {
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+ } while (--timeout && (reg_val != 0x2));
+ if (!timeout) {
+ dev_err(dev, "PHY power up failed.\n");
+ return -EIO;
+ }
+
+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+ timeout = 0x100000;
+ do {
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+ } while (--timeout && reg_val);
+ if (!timeout) {
+ dev_err(dev, "PHY calibration failed.\n");
+ return -EIO;
+ }
+ mdelay(15);
+
+ writel(0x7, reg_base + AHCI_RWCR);
+
+ return 0;
+}
+
+void sunxi_ahci_pre_start_engine(struct ata_port *ap)
+{
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+
+ /* Setup DMA before DMA start */
+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
+}
+
+static int sunxi_ahci_enable_clks(struct sunxi_ahci *ahci)
+{
+ int ret;
+
+ ret = clk_prepare_enable(ahci->sata_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(ahci->ahb_clk);
+ if (ret)
+ clk_disable_unprepare(ahci->sata_clk);
+
+ return ret;
+}
+
+static void sunxi_ahci_disable_clks(struct sunxi_ahci *ahci)
+{
+ clk_disable_unprepare(ahci->ahb_clk);
+ clk_disable_unprepare(ahci->sata_clk);
+}
+
+static void sunxi_ahci_host_stop(struct ata_host *host)
+{
+ struct ahci_host_priv *hpriv = host->private_data;
+ struct sunxi_ahci *ahci = hpriv->plat_data;
+
+ if (!IS_ERR(ahci->pwr))
+ regulator_disable(ahci->pwr);
+
+ sunxi_ahci_disable_clks(ahci);
+}
+
+static struct ata_port_operations sunxi_ahci_platform_ops = {
+ .inherits = &ahci_ops,
+ .host_stop = sunxi_ahci_host_stop,
+};
+
+static const struct ata_port_info sunxiahci_port_info = {
+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &sunxi_ahci_platform_ops,
+};
+
+static struct scsi_host_template sunxi_ahci_platform_sht = {
+ AHCI_SHT("sunxi_ahci"),
+};
+
+static int sunxi_ahci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct ata_port_info *ppi[] = { &sunxiahci_port_info, NULL };
+ struct sunxi_ahci *ahci;
+ struct ata_host *host;
+ int ret;
+
+ ahci = devm_kzalloc(&pdev->dev, sizeof(*ahci), GFP_KERNEL);
+ if (!ahci)
+ return -ENOMEM;
+
+ ahci->pwr = devm_regulator_get_optional(dev, "pwr");
+ if (IS_ERR(ahci->pwr) && PTR_ERR(ahci->pwr) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ host = ata_host_alloc_pinfo(dev, ppi, 1);
+ if (!host)
+ return -ENOMEM;
+
+ host->private_data = &ahci->hpriv;
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
+
+ ahci->hpriv.flags = (unsigned long)ppi[0]->private_data;
+ ahci->hpriv.plat_data = ahci;
+ ahci->hpriv.pre_start_engine = sunxi_ahci_pre_start_engine;
+ ahci->hpriv.mmio = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (IS_ERR(ahci->hpriv.mmio))
+ return PTR_ERR(ahci->hpriv.mmio);
+
+ ahci->ahb_clk = devm_clk_get(&pdev->dev, "ahb_sata");
+ if (IS_ERR(ahci->ahb_clk))
+ return PTR_ERR(ahci->ahb_clk);
+
+ ahci->sata_clk = devm_clk_get(&pdev->dev, "pll6_sata");
+ if (IS_ERR(ahci->sata_clk))
+ return PTR_ERR(ahci->sata_clk);
+
+ ret = sunxi_ahci_enable_clks(ahci);
+ if (ret)
+ return ret;
+
+ if (!IS_ERR(ahci->pwr)) {
+ ret = regulator_enable(ahci->pwr);
+ if (ret) {
+ sunxi_ahci_disable_clks(ahci);
+ return ret;
+ }
+ }
+
+ ret = sunxi_ahci_phy_init(dev, ahci->hpriv.mmio);
+ if (ret) {
+ sunxi_ahci_host_stop(host);
+ return ret;
+ }
+
+ ahci_save_initial_config(dev, &ahci->hpriv, 0, 0);
+
+ ret = ahci_reset_controller(host);
+ if (ret) {
+ sunxi_ahci_host_stop(host);
+ return ret;
+ }
+
+ ahci_init_controller(host);
+ ahci_print_info(host, "sunxi");
+
+ ret = ata_host_activate(host, platform_get_irq(pdev, 0),
+ ahci_interrupt, 0, &sunxi_ahci_platform_sht);
+ if (ret)
+ sunxi_ahci_host_stop(host);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sunxi_ahci_susp(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ struct sunxi_ahci *ahci = hpriv->plat_data;
+ int ret;
+
+ /*
+ * AHCI spec rev1.1 section 8.3.3:
+ * Software must disable interrupts prior to requesting a
+ * transition of the HBA to D3 state.
+ */
+ sunxi_clrbits(hpriv->mmio + HOST_CTL, HOST_IRQ_EN);
+
+ ret = ata_host_suspend(host, PMSG_SUSPEND);
+ if (ret)
+ return ret;
+
+ sunxi_ahci_disable_clks(ahci);
+
+ return 0;
+}
+
+static int sunxi_ahci_resume(struct device *dev)
+{
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ struct sunxi_ahci *ahci = hpriv->plat_data;
+ int ret;
+
+ ret = sunxi_ahci_enable_clks(ahci);
+ if (ret)
+ return ret;
+
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+ ret = ahci_reset_controller(host);
+ if (ret)
+ return ret;
+
+ ahci_init_controller(host);
+ }
+
+ ata_host_resume(host);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sunxi_ahci_pmo, sunxi_ahci_susp, sunxi_ahci_resume);
+
+static const struct of_device_id sunxi_ahci_of_match[] = {
+ { .compatible = "allwinner,sun4i-a10-ahci" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sunxi_ahci_of_match);
+
+static struct platform_driver sunxi_ahci_driver = {
+ .probe = sunxi_ahci_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = "sunxi-ahci",
+ .owner = THIS_MODULE,
+ .of_match_table = sunxi_ahci_of_match,
+ .pm = &sunxi_ahci_pmo,
+ },
+};
+module_platform_driver(sunxi_ahci_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA platform driver");
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
+MODULE_LICENSE("GPL");

View file

@ -0,0 +1,31 @@
From 90189e2c18e983da0ce22e44cd610f9ce2db69b1 Mon Sep 17 00:00:00 2001
From: Roger Quadros <rogerq@ti.com>
Date: Mon, 20 Jan 2014 16:32:33 +0200
Subject: [PATCH] ata: ahci_platform: Add DT compatible for Synopsis DWC AHCI
controller
Add compatible string "snps,dwc-ahci", which should be used
for Synopsis Designware SATA cores. e.g. on TI OMAP5 and DRA7 platforms.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci_platform.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index bdadec1..d7e55ba 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -609,6 +609,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
{ .compatible = "snps,spear-ahci", },
{ .compatible = "snps,exynos5440-ahci", },
{ .compatible = "ibm,476gtr-ahci", },
+ { .compatible = "snps,dwc-ahci", },
{},
};
MODULE_DEVICE_TABLE(of, ahci_of_match);
--
1.8.5.5

View file

@ -1,90 +0,0 @@
From 23af610e09f78822ade4067a400ff9ceb5b020ea Mon Sep 17 00:00:00 2001
From: Oliver Schinagl <oliver@schinagl.nl>
Date: Tue, 3 Dec 2013 12:10:11 +0100
Subject: [PATCH] ARM: sun4i: dts: Add ahci / sata support
This patch adds sunxi sata support to A10 boards that have such a connector.
Some boards also feature a regulator via a GPIO and support for this is also
added.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 27 +++++++++++++++++++++++++++
arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++
3 files changed, 40 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -48,6 +48,10 @@
status = "okay";
};
+ sata: ahci@01c18000 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
mmc0_cd_pin_a1000: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -51,7 +51,19 @@
status = "okay";
};
+ sata: ahci@01c18000 {
+ pwr-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ ahci_pwr_pin_cubieboard: ahci_pwr_pin@0 {
+ allwinner,pins = "PB8";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
@@ -102,4 +114,19 @@
linux,default-trigger = "heartbeat";
};
};
+
+ regulators {
+ compatible = "simple-bus";
+ pinctrl-names = "default";
+
+ reg_ahci_5v: ahci-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "ahci-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-0 = <&ahci_pwr_pin_cubieboard>;
+ gpio = <&pio 1 8 0>;
+ enable-active-high;
+ };
+ };
};
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -338,6 +338,15 @@
status = "disabled";
};
+ sata: ahci@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ clocks = <&ahb_gates 25>, <&pll6 0>;
+ clock-names = "ahb_sata", "pll6_sata";
+ status = "disabled";
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;

View file

@ -0,0 +1,142 @@
From 154a670a945c54300749d5ba008f30bbd6089017 Mon Sep 17 00:00:00 2001
From: Roger Quadros <rogerq@ti.com>
Date: Mon, 27 Jan 2014 16:41:18 +0200
Subject: [PATCH] ata: ahci_platform: Manage SATA PHY
Some platforms have a PHY hooked up to the
SATA controller. The PHY needs to be initialized
and powered up for SATA to work. We do that
using the PHY framework.
CC: Balaji T K <balajitk@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci.h | 2 ++
drivers/ata/ahci_platform.c | 47 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index bf8100c..3ab7ac9 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -37,6 +37,7 @@
#include <linux/clk.h>
#include <linux/libata.h>
+#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
/* Enclosure Management Control */
@@ -325,6 +326,7 @@ struct ahci_host_priv {
u32 em_msg_type; /* EM message type */
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
struct regulator *target_pwr; /* Optional */
+ struct phy *phy; /* If platform uses phy */
void *plat_data; /* Other platform data */
/*
* Optional ahci_start_engine override, if not set this gets set to the
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index d7e55ba..99d38c1 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/libata.h>
#include <linux/ahci_platform.h>
+#include <linux/phy/phy.h>
#include "ahci.h"
static void ahci_host_stop(struct ata_host *host);
@@ -147,6 +148,7 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
* the following order:
* 1) Regulator
* 2) Clocks (through ahci_platform_enable_clks)
+ * 3) Phy
*
* If resource enabling fails at any point the previous enabled
* resources are disabled in reverse order.
@@ -171,8 +173,23 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
if (rc)
goto disable_regulator;
+ if (hpriv->phy) {
+ rc = phy_init(hpriv->phy);
+ if (rc)
+ goto disable_clks;
+
+ rc = phy_power_on(hpriv->phy);
+ if (rc) {
+ phy_exit(hpriv->phy);
+ goto disable_clks;
+ }
+ }
+
return 0;
+disable_clks:
+ ahci_platform_disable_clks(hpriv);
+
disable_regulator:
if (hpriv->target_pwr)
regulator_disable(hpriv->target_pwr);
@@ -186,14 +203,20 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
*
* This function disables all ahci_platform managed resources in
* the following order:
- * 1) Clocks (through ahci_platform_disable_clks)
- * 2) Regulator
+ * 1) Phy
+ * 2) Clocks (through ahci_platform_disable_clks)
+ * 3) Regulator
*
* LOCKING:
* None.
*/
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
{
+ if (hpriv->phy) {
+ phy_power_off(hpriv->phy);
+ phy_exit(hpriv->phy);
+ }
+
ahci_platform_disable_clks(hpriv);
if (hpriv->target_pwr)
@@ -222,6 +245,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
* 2) regulator for controlling the targets power (optional)
* 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
* or for non devicetree enabled platforms a single clock
+ * 4) phy (optional)
*
* LOCKING:
* None.
@@ -283,6 +307,25 @@ struct ahci_host_priv *ahci_platform_get_resources(
hpriv->clks[i] = clk;
}
+ hpriv->phy = devm_phy_get(dev, "sata-phy");
+ if (IS_ERR(hpriv->phy)) {
+ rc = PTR_ERR(hpriv->phy);
+ switch (rc) {
+ case -ENODEV:
+ case -ENOSYS:
+ /* continue normally */
+ hpriv->phy = NULL;
+ break;
+
+ case -EPROBE_DEFER:
+ goto err_out;
+
+ default:
+ dev_err(dev, "couldn't get sata-phy\n");
+ goto err_out;
+ }
+ }
+
devres_remove_group(dev, NULL);
return hpriv;
--
1.8.5.5

View file

@ -1,167 +0,0 @@
From 4ce1f4c3ab04a697e9861b77582077b905b3f8a0 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 3 Jan 2014 10:27:51 +0100
Subject: [PATCH] ARM: sun7i: dts: Add ahci / sata support
This patch adds sunxi sata support to A20 boards that have such a connector.
Some boards also feature a regulator via a GPIO and support for this is also
added.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 +++++++++++++++++++++++++
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 27 +++++++++++++++++++++++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 26 ++++++++++++++++++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++
4 files changed, 89 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -43,7 +43,19 @@
status = "okay";
};
+ sata: ahci@01c18000 {
+ pwr-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ ahci_pwr_pin_cubieboard2: ahci_pwr_pin@0 {
+ allwinner,pins = "PB8";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
@@ -93,4 +105,19 @@
gpios = <&pio 7 20 0>;
};
};
+
+ regulators {
+ compatible = "simple-bus";
+ pinctrl-names = "default";
+
+ reg_ahci_5v: ahci-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "ahci-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-0 = <&ahci_pwr_pin_cubieboard2>;
+ gpio = <&pio 1 8 0>;
+ enable-active-high;
+ };
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -43,6 +43,11 @@
status = "okay";
};
+ sata: ahci@01c18000 {
+ pwr-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
@@ -58,6 +63,13 @@
allwinner,pull = <0>;
};
+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
+ allwinner,pins = "PH12";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_cubietruck: led_pins@0 {
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
allwinner,function = "gpio_out";
@@ -149,4 +161,19 @@
gpio = <&pio 7 3 0>;
};
};
+
+ regulators {
+ compatible = "simple-bus";
+ pinctrl-names = "default";
+
+ reg_ahci_5v: ahci-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "ahci-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
+ gpio = <&pio 7 12 0>;
+ enable-active-high;
+ };
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -52,7 +52,19 @@
status = "okay";
};
+ sata: ahci@01c18000 {
+ pwr-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ ahci_pwr_pin_olinuxinom: ahci_pwr_pin@0 {
+ allwinner,pins = "PB8";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
allwinner,function = "gpio_in";
@@ -123,4 +135,18 @@
default-state = "on";
};
};
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_ahci_5v: ahci-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "ahci-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-0 = <&ahci_pwr_pin_olinuxinom>;
+ gpio = <&pio 1 8 0>;
+ enable-active-high;
+ };
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -433,6 +433,15 @@
};
};
+ sata: ahci@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <0 56 1>;
+ clocks = <&ahb_gates 25>, <&pll6 0>;
+ clock-names = "ahb_sata", "pll6_sata";
+ status = "disabled";
+ };
+
timer@01c20c00 {
compatible = "allwinner,sun4i-timer";
reg = <0x01c20c00 0x90>;

View file

@ -0,0 +1,85 @@
From 48379fed3987d587a25a48e155872e9d3125490d Mon Sep 17 00:00:00 2001
From: Roger Quadros <rogerq@ti.com>
Date: Wed, 9 Oct 2013 15:08:59 +0300
Subject: [PATCH] ata: ahci_platform: runtime resume the device before use
On OMAP platforms the device needs to be runtime resumed before
it can be accessed. The OMAP HWMOD framework takes care of
enabling the module and its resources based on the
device's runtime PM state.
In this patch we runtime resume during .probe() and runtime suspend
after .remove().
We also update the runtime PM state during .resume().
CC: Balaji T K <balajitk@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci.h | 1 +
drivers/ata/ahci_platform.c | 15 +++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 3ab7ac9..51af275b 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -324,6 +324,7 @@ struct ahci_host_priv {
u32 em_loc; /* enclosure management location */
u32 em_buf_sz; /* EM buffer size in byte */
u32 em_msg_type; /* EM message type */
+ bool got_runtime_pm; /* Did we do pm_runtime_get? */
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
struct regulator *target_pwr; /* Optional */
struct phy *phy; /* If platform uses phy */
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 99d38c1..75698a4 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -24,6 +24,7 @@
#include <linux/libata.h>
#include <linux/ahci_platform.h>
#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
#include "ahci.h"
static void ahci_host_stop(struct ata_host *host);
@@ -229,6 +230,11 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
struct ahci_host_priv *hpriv = res;
int c;
+ if (hpriv->got_runtime_pm) {
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ }
+
for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
clk_put(hpriv->clks[c]);
}
@@ -326,6 +332,10 @@ struct ahci_host_priv *ahci_platform_get_resources(
}
}
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ hpriv->got_runtime_pm = true;
+
devres_remove_group(dev, NULL);
return hpriv;
@@ -635,6 +645,11 @@ int ahci_platform_resume(struct device *dev)
if (rc)
goto disable_resources;
+ /* We resumed so update PM runtime state */
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
return 0;
disable_resources:
--
1.8.5.5

View file

@ -0,0 +1,47 @@
From 09de09bc2c236dccb0ed5ed38015e829550a5c28 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 23 Feb 2014 11:37:17 +0100
Subject: [PATCH] ahci_sunxi: Use msleep instead of mdelay
ahci_sunxi_phy_init is called from the probe and resume code paths, and
sleeping is safe in both, so use msleep instead of mdelay.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/ata/ahci_sunxi.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 001f7dfc..d1bf3f7 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -90,7 +90,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
/* This magic is from the original code */
writel(0, reg_base + AHCI_RWCR);
- mdelay(5);
+ msleep(5);
sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
@@ -105,7 +105,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
(0x7 << 20), (0x3 << 20));
sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
(0x1f << 5), (0x19 << 5));
- mdelay(5);
+ msleep(5);
sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
@@ -137,7 +137,7 @@ static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
udelay(1);
} while (1);
- mdelay(15);
+ msleep(15);
writel(0x7, reg_base + AHCI_RWCR);
--
1.8.5.5

View file

@ -0,0 +1,122 @@
From 3cae1df0e62432a80db86c80e261eb9bbed326ee Mon Sep 17 00:00:00 2001
From: Oliver Schinagl <oliver@schinagl.nl>
Date: Tue, 3 Dec 2013 12:10:11 +0100
Subject: [PATCH] ARM: sun4i: dt: Add ahci / sata support
This patch adds sunxi sata support to A10 boards that have such a connector.
Some boards also feature a regulator via a GPIO and support for this is also
added.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 6 +++++
arch/arm/boot/dts/sun4i-a10.dtsi | 8 +++++++
arch/arm/boot/dts/sunxi-ahci-reg.dtsi | 36 ++++++++++++++++++++++++++++++
4 files changed, 54 insertions(+)
create mode 100644 arch/arm/boot/dts/sunxi-ahci-reg.dtsi
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index cbd2e13..d6ec839 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -35,6 +35,10 @@
};
};
+ ahci: sata@01c18000 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
emac_power_pin_a1000: emac_power_pin@0 {
allwinner,pins = "PH15";
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index b139ee6..6df237d8 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -12,6 +12,7 @@
/dts-v1/;
/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-ahci-reg.dtsi"
/ {
model = "Cubietech Cubieboard";
@@ -33,6 +34,11 @@
};
};
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard: led_pins@0 {
allwinner,pins = "PH20", "PH21";
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 336dbec..454077a 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -338,6 +338,14 @@
#size-cells = <0>;
};
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ clocks = <&pll6 0>, <&ahb_gates 25>;
+ status = "disabled";
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
diff --git a/arch/arm/boot/dts/sunxi-ahci-reg.dtsi b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
new file mode 100644
index 0000000..7072af1
--- /dev/null
+++ b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
@@ -0,0 +1,36 @@
+/*
+ * sunxi boards sata target power supply common code
+ *
+ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+ soc@01c00000 {
+ pio: pinctrl@01c20800 {
+ ahci_pwr_pin_a: ahci_pwr_pin@0 {
+ allwinner,pins = "PB8";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+ };
+ };
+
+ reg_ahci_5v: ahci-5v {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ahci_pwr_pin_a>;
+ regulator-name = "ahci-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 1 8 0>;
+ };
+};
--
1.8.5.5

View file

@ -0,0 +1,127 @@
From c7b99b7afc3882c1b38a15da8d1625dd448c6fee Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 3 Jan 2014 10:27:51 +0100
Subject: [PATCH] ARM: sun7i: dt: Add ahci / sata support
This patch adds sunxi sata support to A20 boards that have such a connector.
Some boards also feature a regulator via a GPIO and support for this is also
added.
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 6 ++++++
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 18 ++++++++++++++++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 6 ++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
4 files changed, 38 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 7bf4935..07823c2 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -13,12 +13,18 @@
/dts-v1/;
/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-ahci-reg.dtsi"
/ {
model = "Cubietech Cubieboard2";
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
soc@01c00000 {
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index 025ce52..403bd2e 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -13,13 +13,26 @@
/dts-v1/;
/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-ahci-reg.dtsi"
/ {
model = "Cubietech Cubietruck";
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
soc@01c00000 {
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
+ allwinner,pins = "PH12";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_cubietruck: led_pins@0 {
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
allwinner,function = "gpio_out";
@@ -90,4 +103,9 @@
gpios = <&pio 7 7 0>;
};
};
+
+ reg_ahci_5v: ahci-5v {
+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
+ gpio = <&pio 7 12 0>;
+ };
};
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index b02a796..d5c6799 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -13,12 +13,18 @@
/dts-v1/;
/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-ahci-reg.dtsi"
/ {
model = "Olimex A20-Olinuxino Micro";
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
soc@01c00000 {
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index daaafd0..3385994 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -392,6 +392,14 @@
#size-cells = <0>;
};
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <0 56 4>;
+ clocks = <&pll6 0>, <&ahb_gates 25>;
+ status = "disabled";
+ };
+
pio: pinctrl@01c20800 {
compatible = "allwinner,sun7i-a20-pinctrl";
reg = <0x01c20800 0x400>;
--
1.8.5.5

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,56 @@
From 40889884d53094fe9987a45f9df99fdf1f311910 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Feb 2014 10:47:51 +0100
Subject: [PATCH] sunxi-mmc: Simplify clk delay setting
clk_sunxi_mmc_phase_control() does its own locking, so there is no need to
lock at the host. Without the locking having a separate sunxi_mmc_set_clk_dly()
makes no sense, so simply call clk_sunxi_mmc_phase_control() directly.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index f33bc30..f4bfaf0 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -420,17 +420,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
}
}
-static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
- u32 oclk_dly, u32 sclk_dly)
-{
- unsigned long iflags;
- struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
-
- spin_lock_irqsave(&smc_host->lock, iflags);
- clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
- spin_unlock_irqrestore(&smc_host->lock, iflags);
-}
-
struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
{ MMC_CLK_400K, 0, 7 },
{ MMC_CLK_25M, 0, 5 },
@@ -450,6 +439,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
u32 sclk_dly;
u32 temp;
struct sunxi_mmc_clk_dly *dly = NULL;
+ struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
newrate = clk_round_rate(smc_host->clk_mod, rate);
if (smc_host->clk_mod_rate == newrate) {
@@ -508,7 +498,7 @@ static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
sclk_dly--;
}
- sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
+ clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
sunxi_mmc_oclk_onoff(smc_host, 1);
/* oclk_onoff sets various irq status bits, clear these */
--
1.8.5.5

View file

@ -0,0 +1,49 @@
From 0a6ec6db90c73b037428bf3a94a6281754007c25 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 16:55:54 +0100
Subject: [PATCH] sunxi-mmc: Don't set mmc clk in low power mode
The android driver uses an io-flag to descern whether a controller is
hooked up to a sdcard slot, or to an onboard sdio dev. And for sdcard slots
it sets the clock in a low-power mode.
This is causing transmission errors when talking to the sdio-wifi on the
cubietruck, and this may be the cause of problems with some type sdcards
too. This patch fixes things by simply never setting the clk in low power
mode.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 3 ---
drivers/mmc/host/sunxi-mmc.h | 1 -
2 files changed, 4 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index f4bfaf0..c1a9d8a 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -400,9 +400,6 @@ static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
if (oclk_en)
rval |= SDXC_CARD_CLOCK_ON;
- if (!host->io_flag)
- rval |= SDXC_LOW_POWER_ON;
-
mci_writel(host, REG_CLKCR, rval);
rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER;
diff --git a/drivers/mmc/host/sunxi-mmc.h b/drivers/mmc/host/sunxi-mmc.h
index cbd6d49..a738850 100644
--- a/drivers/mmc/host/sunxi-mmc.h
+++ b/drivers/mmc/host/sunxi-mmc.h
@@ -211,7 +211,6 @@ struct sunxi_mmc_host {
/* flags */
u32 power_on:1;
- u32 io_flag:1;
u32 wait_dma:1;
dma_addr_t sg_dma;
--
1.8.5.5

View file

@ -0,0 +1,32 @@
From 3ec947a9717509e204c7f09609717951beb7ef04 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 17:11:58 +0100
Subject: [PATCH] sunxi-mmc: Stop claiming UHS modes
UHS requires a regulator to set the signaling voltage, as well as special
code to handle the signal voltage switching. We've never added the code
for this from the android driver to the upstream driver, so stop claiming
support for this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index c1a9d8a..2eaed10 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -803,8 +803,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
- MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
- MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_DRIVER_TYPE_A;
+ MMC_CAP_SDIO_IRQ;
mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
ret = mmc_add_host(mmc);
--
1.8.5.5

View file

@ -0,0 +1,34 @@
From dffb4d4d1fe3a6ba93102756152ec4518dbeac00 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 17:13:19 +0100
Subject: [PATCH] sunxi-mmc: Or in caps, rather then overriding them
Now that we use mmc_of_parse() there are already some caps set by mmc_of_parse,
so or in our driver caps, rather then using an assignment. This fixes the
card running only in 1 bit mode instead of 4 bit mode problem we've had
since we switched to using mmc_of_parse().
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 2eaed10..d5e8ff9 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -802,9 +802,9 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
else
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_SDIO_IRQ;
- mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
+ mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
ret = mmc_add_host(mmc);
--
1.8.5.5

View file

@ -0,0 +1,45 @@
From 73797537f3904fec60a647b3b209bf7add092ad5 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 21:59:08 +0100
Subject: [PATCH] sunxi-mmc: Don't call mmc_of_parse until we're ready to
mmc_of_parse registers an irq handler for the gpio pins for cd, this irq
handler will reference host->ops, so don't call mmc_of_parse until we're
done setting everything up.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index d5e8ff9..cceae68 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -766,10 +766,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
return -ENOMEM;
}
- ret = mmc_of_parse(mmc);
- if (ret)
- goto error_free_host;
-
host = mmc_priv(mmc);
host->mmc = mmc;
spin_lock_init(&host->lock);
@@ -806,8 +802,11 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
MMC_CAP_SDIO_IRQ;
mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
- ret = mmc_add_host(mmc);
+ ret = mmc_of_parse(mmc);
+ if (ret)
+ goto error_free_dma;
+ ret = mmc_add_host(mmc);
if (ret)
goto error_free_dma;
--
1.8.5.5

View file

@ -1,4 +1,4 @@
From a8cfe8ebdb18e6724b6520e08602b8e72e762ab9 Mon Sep 17 00:00:00 2001
From 7bd0d82ef525e8949425fe271fb86eacf3822821 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 15 Dec 2013 19:44:01 +0100
Subject: [PATCH] ARM: sunxi: clk: export clk_sunxi_mmc_phase_control
@ -9,6 +9,9 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 file changed, 22 insertions(+)
create mode 100644 include/linux/clk/sunxi.h
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
new file mode 100644
index 0000000..1ef5c89
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
@ -34,3 +37,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
+
+#endif
--
1.8.5.5

View file

@ -1,4 +1,4 @@
From 4f43ab43125a12dbc23e352ac0eb4fd80a876fb5 Mon Sep 17 00:00:00 2001
From fcba369ee1af8657353bb1e37807aa492c462263 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Fri, 20 Sep 2013 20:29:17 -0300
Subject: [PATCH] clk: sunxi: Implement MMC phase control
@ -11,9 +11,11 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar>
drivers/clk/sunxi/clk-sunxi.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 3283179..46a38b4 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -361,6 +361,41 @@ static void sun4i_get_mod0_factors(u32 *
@@ -500,6 +500,41 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
/**
@ -55,3 +57,6 @@ Signed-off-by: Emilio López <emilio@elopez.com.ar>
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
--
1.8.5.5

View file

@ -0,0 +1,44 @@
From 0483aa124d32bdcafc84623a31141a49e71cc72d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Feb 2014 08:54:20 +0100
Subject: [PATCH] sunxi-mmc: fixup: revert "add host initialization for when
the sdio irq is enabled"
This is not necessary since when the host is not initialized at this point
yet the irq line from the mmc controller is not enabled, so writing the
host controller interrupt mask cannot cause interrupts at this point.
More over doing this is wrong, as it leads to unbalanced calling of
clk_prepare_enable and regulator_power_on.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/mmc/host/sunxi-mmc.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 2dc446c..f33bc30 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -593,18 +593,9 @@ static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
unsigned long flags;
- int ret;
u32 imask;
spin_lock_irqsave(&smc_host->lock, flags);
-
- /* Make sure the controller is in a sane state before enabling irqs */
- ret = sunxi_mmc_init_host(host->mmc);
- if (ret) {
- spin_unlock_irqrestore(&smc_host->lock, flags);
- return ret;
- }
-
imask = mci_readl(smc_host, REG_IMASK);
if (enable) {
smc_host->sdio_imask = SDXC_SDIO_INTERRUPT;
--
1.8.5.5

View file

@ -1,31 +0,0 @@
From 109e7dc17a77f84d56e76dea873363a8262bc806 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Thu, 19 Sep 2013 21:59:32 +0200
Subject: [PATCH] clk: sunxi: Add support for USB clocks
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/clk/sunxi/clk-sunxi.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -705,6 +705,10 @@ static const struct gates_data sun4i_ahb
.mask = {0x7F77FFF, 0x14FB3F},
};
+static const struct gates_data sun47i_usb_gates_data __initconst = {
+ .mask = {0x1C0},
+};
+
static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
.mask = {0x147667e7, 0x185915},
};
@@ -1021,6 +1025,7 @@ static const struct of_device_id clk_mux
static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
+ {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
{.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},

View file

@ -1,7 +1,7 @@
From 33b0123664b627005728cfe7b1967b790392ceec Mon Sep 17 00:00:00 2001
From 85f17a0d652853455ac633fc965cea8431038518 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 14 Dec 2013 17:20:13 +0100
Subject: [PATCH] ARM: sunxi: fix sun5i-a13 port F multiplexing
Subject: [PATCH] pinctrl-sunxi: Fix sun5i-a13 port F multiplexing
The correct value for selecting the mmc0 function on port F pins is 2 not 4,
as per the data-sheet:
@ -13,9 +13,11 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
drivers/pinctrl/pinctrl-sunxi-pins.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-sunxi-pins.h b/drivers/pinctrl/pinctrl-sunxi-pins.h
index 6fd8d4d..3d60669 100644
--- a/drivers/pinctrl/pinctrl-sunxi-pins.h
+++ b/drivers/pinctrl/pinctrl-sunxi-pins.h
@@ -1932,27 +1932,27 @@ static const struct sunxi_desc_pin sun5i
@@ -1932,27 +1932,27 @@
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
@ -49,3 +51,6 @@ Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
SUNXI_FUNCTION(0x0, "gpio_in"),
--
1.8.5.5

View file

@ -0,0 +1,49 @@
From 613c8489f6b576166aa31d32cbd573f6b7952e06 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 15 Feb 2014 12:58:17 +0100
Subject: [PATCH] pinctrl-sunxi: Fix hang on gpio irq
Our irq handler was missing chained_irq_enter / exit calls, causing a
hard hang as soon as a gpio irq happened.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/pinctrl/pinctrl-sunxi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 74635cc..cc9bd1b 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -13,6 +13,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/gpio.h>
+#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -665,9 +666,12 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
{
+ struct irq_chip *chip = irq_get_chip(irq);
struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
+ chained_irq_enter(chip, desc);
+
/* Clear all interrupts */
writel(reg, pctl->membase + IRQ_STATUS_REG);
@@ -679,6 +683,7 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
generic_handle_irq(pin_irq);
}
}
+ chained_irq_exit(chip, desc);
}
static struct of_device_id sunxi_pinctrl_match[] = {
--
1.8.5.5

View file

@ -0,0 +1,26 @@
From 9d506cbf0e7b0e017d78f244e2b4c0fc71206c6c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 15 Feb 2014 12:56:42 +0100
Subject: [PATCH] pinctrl-sunxi: Fix masking when setting irq type
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/pinctrl/pinctrl-sunxi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index cc9bd1b..917af0a 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -583,7 +583,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
spin_lock_irqsave(&pctl->lock, flags);
regval = readl(pctl->membase + reg);
- regval &= ~IRQ_CFG_IRQ_MASK;
+ regval &= ~(IRQ_CFG_IRQ_MASK << index);
writel(regval | (mode << index), pctl->membase + reg);
spin_unlock_irqrestore(&pctl->lock, flags);
--
1.8.5.5

View file

@ -0,0 +1,46 @@
From a5f3d2672d5b9efe93be0bf66d69156bf806220b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 22:04:20 +0100
Subject: [PATCH] pinctrl-sunxi: Fix interrupt register offset calculation
This fixing setting the interrupt type for eints >= 8.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/pinctrl/pinctrl-sunxi.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-sunxi.h b/drivers/pinctrl/pinctrl-sunxi.h
index 01c494f..552b0e9 100644
--- a/drivers/pinctrl/pinctrl-sunxi.h
+++ b/drivers/pinctrl/pinctrl-sunxi.h
@@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin)
static inline u32 sunxi_irq_cfg_reg(u16 irq)
{
- u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
+ u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
return reg + IRQ_CFG_REG;
}
@@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
static inline u32 sunxi_irq_ctrl_reg(u16 irq)
{
- u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
+ u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
return reg + IRQ_CTRL_REG;
}
@@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
static inline u32 sunxi_irq_status_reg(u16 irq)
{
- u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
+ u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
return reg + IRQ_STATUS_REG;
}
--
1.8.5.5

View file

@ -1,31 +0,0 @@
From 6b5cb5cada555c90562aed82e8891439a35009ab Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Sun, 6 Oct 2013 14:04:50 +0200
Subject: [PATCH] clk: sun5i: Add support for USB clocks
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/clk/sunxi/clk-sunxi.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -709,6 +709,10 @@ static const struct gates_data sun47i_us
.mask = {0x1C0},
};
+static const struct gates_data sun5i_usb_gates_data __initconst = {
+ .mask = {0x140},
+};
+
static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
.mask = {0x147667e7, 0x185915},
};
@@ -1028,6 +1032,7 @@ static const struct of_device_id clk_gat
{.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
{.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
+ {.compatible = "allwinner,sun5i-usb-gates-clk", .data = &sun5i_usb_gates_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},

View file

@ -1,493 +0,0 @@
From 825ce97e1faa39bfd30c3dca95fba5eb021cb534 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Wed, 18 Sep 2013 21:45:03 +0200
Subject: [PATCH] ARM: sunxi: usb: Add Allwinner sunXi EHCI driver
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Conflicts:
drivers/usb/host/Makefile
---
drivers/usb/host/Kconfig | 9 +
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-sunxi.c | 446 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 456 insertions(+)
create mode 100644 drivers/usb/host/ehci-sunxi.c
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -273,6 +273,15 @@ config USB_OCTEON_EHCI
USB 2.0 device support. All CN6XXX based chips with USB are
supported.
+config USB_SUNXI_EHCI
+ tristate "Allwinner sunXi EHCI support"
+ depends on ARCH_SUNXI
+ default n
+ help
+ Enable support for the Allwinner sunXi on-chip EHCI
+ controller. It is needed for high-speed (480Mbit/sec)
+ USB 2.0 device support.
+
endif # USB_EHCI_HCD
config USB_OXU210HP_HCD
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-
obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o
+obj-$(CONFIG_USB_SUNXI_EHCI) += ehci-sunxi.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
--- /dev/null
+++ b/drivers/usb/host/ehci-sunxi.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2013 Roman Byshko
+ *
+ * Roman Byshko <rbyshko@gmail.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define DRV_DESC "Allwinner sunXi EHCI driver"
+#define DRV_NAME "sunxi-ehci"
+
+#define SUNXI_USB_PASSBY_EN 1
+
+#define SUNXI_EHCI_AHB_ICHR8_EN BIT(10)
+#define SUNXI_EHCI_AHB_INCR4_BURST_EN BIT(9)
+#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN BIT(8)
+#define SUNXI_EHCI_ULPI_BYPASS_EN BIT(0)
+
+struct sunxi_ehci_hcd {
+ struct clk *phy_clk;
+ struct clk *ahb_ehci_clk;
+ struct reset_control *reset;
+ struct regulator *vbus_reg;
+ void __iomem *csr;
+ void __iomem *pmuirq;
+ int irq;
+ int id;
+};
+
+
+static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci,u32 addr, u32 data, u32 len)
+{
+ u32 j = 0;
+ u32 temp = 0;
+ u32 usbc_bit = 0;
+ void __iomem *dest = sunxi_ehci->csr;
+
+ usbc_bit = BIT(sunxi_ehci->id << 1);
+
+ for (j = 0; j < len; j++) {
+ temp = readl(dest);
+
+ /* clear the address portion */
+ temp &= ~(0xff << 8);
+
+ /* set the address */
+ temp |= ((addr + j) << 8);
+ writel(temp, dest);
+
+ /* set the data bit and clear usbc bit*/
+ temp = readb(dest);
+ if (data & 0x1)
+ temp |= BIT(7);
+ else
+ temp &= ~BIT(7);
+ temp &= ~usbc_bit;
+ writeb(temp, dest);
+
+ /* flip usbc_bit */
+ __set_bit(usbc_bit, dest);
+ __clear_bit(usbc_bit, dest);
+
+ data >>= 1;
+ }
+}
+
+/* FIXME: should this function be protected by a lock?
+ * ehci1 and ehci0 could call it concurrently with same csr.
+ */
+static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci)
+{
+ /* The following comments are machine
+ * translated from Chinese, you have been warned!
+ */
+
+ /* adjust PHY's magnitude and rate */
+ usb_phy_write(sunxi_ehci, 0x20, 0x14, 5);
+
+ /* threshold adjustment disconnect */
+ usb_phy_write(sunxi_ehci, 0x2a, 3, 2);
+
+ return;
+}
+
+static void sunxi_usb_passby(struct sunxi_ehci_hcd *sunxi_ehci, int enable)
+{
+ unsigned long reg_value = 0;
+ unsigned long bits = 0;
+ static DEFINE_SPINLOCK(lock);
+ unsigned long flags = 0;
+ void __iomem *addr = sunxi_ehci->pmuirq;
+
+ bits = SUNXI_EHCI_AHB_ICHR8_EN |
+ SUNXI_EHCI_AHB_INCR4_BURST_EN |
+ SUNXI_EHCI_AHB_INCRX_ALIGN_EN |
+ SUNXI_EHCI_ULPI_BYPASS_EN;
+
+ spin_lock_irqsave(&lock, flags);
+
+ reg_value = readl(addr);
+
+ if (enable)
+ reg_value |= bits;
+ else
+ reg_value &= ~bits;
+
+ writel(reg_value, addr);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return;
+}
+
+static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci)
+{
+ regulator_disable(sunxi_ehci->vbus_reg);
+
+ sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN);
+
+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
+ clk_disable_unprepare(sunxi_ehci->phy_clk);
+
+ reset_control_assert(sunxi_ehci->reset);
+}
+
+static int sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci)
+{
+ int ret;
+
+ ret = clk_prepare_enable(sunxi_ehci->phy_clk);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(sunxi_ehci->reset);
+ if (ret)
+ goto fail1;
+
+ ret = clk_prepare_enable(sunxi_ehci->ahb_ehci_clk);
+ if (ret)
+ goto fail2;
+
+ sunxi_usb_phy_init(sunxi_ehci);
+
+ sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN);
+
+ ret = regulator_enable(sunxi_ehci->vbus_reg);
+ if (ret)
+ goto fail3;
+
+ return 0;
+
+fail3:
+ clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
+fail2:
+ reset_control_assert(sunxi_ehci->reset);
+fail1:
+ clk_disable_unprepare(sunxi_ehci->phy_clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int sunxi_ehci_suspend(struct device *dev)
+{
+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ int ret;
+
+ bool do_wakeup = device_may_wakeup(dev);
+
+ ret = ehci_suspend(hcd, do_wakeup);
+
+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+ sunxi_ehci_disable(sunxi_ehci);
+
+ return ret;
+}
+
+static int sunxi_ehci_resume(struct device *dev)
+{
+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ int ret;
+
+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+ ret = sunxi_ehci_enable(sunxi_ehci);
+ if (ret)
+ return ret;
+
+ return ehci_resume(hcd, false);
+}
+
+
+static const struct dev_pm_ops sunxi_ehci_pmops = {
+ .suspend = sunxi_ehci_suspend,
+ .resume = sunxi_ehci_resume,
+};
+
+#define SUNXI_EHCI_PMOPS (&sunxi_ehci_pmops)
+#else /* !CONFIG_PM */
+#define SUNXI_EHCI_PMOPS NULL
+#endif /* CONFIG_PM */
+
+static const struct ehci_driver_overrides sunxi_overrides __initconst = {
+ .reset = NULL,
+ .extra_priv_size = sizeof(struct sunxi_ehci_hcd),
+};
+
+/* FIXME: Should there be two instances of hc_driver,
+ * or one is enough to handle two EHCI controllers? */
+static struct hc_driver __read_mostly sunxi_ehci_hc_driver;
+
+static int sunxi_ehci_init(struct platform_device *pdev, struct usb_hcd *hcd,
+ struct sunxi_ehci_hcd *sunxi_ehci)
+{
+ void __iomem *ehci_regs = NULL;
+ struct resource *res = NULL;
+
+ sunxi_ehci->vbus_reg = devm_regulator_get(&pdev->dev, "vbus");
+ if (IS_ERR(sunxi_ehci->vbus_reg)) {
+ if (PTR_ERR(sunxi_ehci->vbus_reg) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ dev_info(&pdev->dev, "no USB VBUS power supply found\n");
+ }
+
+ sunxi_ehci->id = of_alias_get_id(pdev->dev.of_node, "ehci");
+ if (sunxi_ehci->id < 0)
+ return sunxi_ehci->id;
+
+ /* FIXME: should res be freed on some failure? */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ return -ENXIO;
+ }
+ ehci_regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ehci_regs))
+ return PTR_ERR(ehci_regs);
+
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = resource_size(res);
+ hcd->regs = ehci_regs;
+ hcd_to_ehci(hcd)->caps = ehci_regs;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ return -ENXIO;
+ }
+ sunxi_ehci->pmuirq = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(sunxi_ehci->pmuirq))
+ return PTR_ERR(sunxi_ehci->pmuirq);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ return -ENXIO;
+ }
+
+ /* FIXME: this one byte needs to be shared between both EHCIs,
+ * that is why ioremap instead of devm_ioremap_resource,
+ * memory is not unmaped back for now.
+ */
+ sunxi_ehci->csr = ioremap(res->start, resource_size(res));
+ if (IS_ERR(sunxi_ehci->csr)) {
+ dev_err(&pdev->dev, "failed to remap memory\n");
+ return PTR_ERR(sunxi_ehci->csr);
+ }
+
+ sunxi_ehci->irq = platform_get_irq(pdev, 0);
+ if (!sunxi_ehci->irq) {
+ dev_err(&pdev->dev, "failed to get IRQ\n");
+ return -ENODEV;
+ }
+
+ sunxi_ehci->phy_clk = devm_clk_get(&pdev->dev, "usb_phy");
+ if (IS_ERR(sunxi_ehci->phy_clk)) {
+ dev_err(&pdev->dev, "failed to get usb_phy clock\n");
+ return PTR_ERR(sunxi_ehci->phy_clk);
+ }
+ sunxi_ehci->ahb_ehci_clk = devm_clk_get(&pdev->dev, "ahb_ehci");
+ if (IS_ERR(sunxi_ehci->ahb_ehci_clk)) {
+ dev_err(&pdev->dev, "failed to get ahb_ehci clock\n");
+ return PTR_ERR(sunxi_ehci->ahb_ehci_clk);
+ }
+
+ sunxi_ehci->reset = reset_control_get(&pdev->dev, "ehci_reset");
+ if (IS_ERR(sunxi_ehci->reset))
+ {
+ dev_err(&pdev->dev, "failed to get ehci_reset reset line\n");
+ return PTR_ERR(sunxi_ehci->reset);
+ }
+
+ return 0;
+}
+
+static int sunxi_ehci_probe(struct platform_device *pdev)
+{
+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
+ struct usb_hcd *hcd = NULL;
+ int ret;
+
+ if (pdev->num_resources != 4) {
+ dev_err(&pdev->dev, "invalid number of resources: %i\n",
+ pdev->num_resources);
+ return -ENODEV;
+ }
+
+ if (pdev->resource[0].flags != IORESOURCE_MEM
+ || pdev->resource[1].flags != IORESOURCE_MEM
+ || pdev->resource[2].flags != IORESOURCE_MEM
+ || pdev->resource[3].flags != IORESOURCE_IRQ) {
+ dev_err(&pdev->dev, "invalid resource type\n");
+ return -ENODEV;
+ }
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+ hcd = usb_create_hcd(&sunxi_ehci_hc_driver, &pdev->dev,
+ dev_name(&pdev->dev));
+ if (!hcd) {
+ dev_err(&pdev->dev, "unable to create HCD\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, hcd);
+
+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+ ret = sunxi_ehci_init(pdev, hcd, sunxi_ehci);
+ if (ret)
+ goto fail1;
+
+ ret = sunxi_ehci_enable(sunxi_ehci);
+ if (ret)
+ goto fail1;
+
+ ret = usb_add_hcd(hcd, sunxi_ehci->irq, IRQF_SHARED | IRQF_DISABLED);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add USB HCD\n");
+ goto fail2;
+ }
+
+ return 0;
+
+fail2:
+ sunxi_ehci_disable(sunxi_ehci);
+
+fail1:
+ usb_put_hcd(hcd);
+ return ret;
+}
+
+static int sunxi_ehci_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
+
+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+ usb_remove_hcd(hcd);
+
+ sunxi_ehci_disable(sunxi_ehci);
+
+ usb_put_hcd(hcd);
+
+ return 0;
+}
+
+static void sunxi_ehci_shutdown(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct sunxi_ehci_hcd *sunxi_ehci = NULL;
+
+ sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+
+ usb_hcd_platform_shutdown(pdev);
+
+ sunxi_ehci_disable(sunxi_ehci);
+}
+
+static const struct of_device_id ehci_of_match[] = {
+ {.compatible = "allwinner,sunxi-ehci"},
+ {},
+};
+
+static struct platform_driver ehci_sunxi_driver = {
+ .driver = {
+ .of_match_table = ehci_of_match,
+ .name = DRV_NAME,
+ .pm = SUNXI_EHCI_PMOPS,
+ },
+ .probe = sunxi_ehci_probe,
+ .remove = sunxi_ehci_remove,
+ .shutdown = sunxi_ehci_shutdown,
+};
+
+static int __init sunxi_ehci_init_module(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info(DRV_NAME ": " DRV_DESC "\n");
+
+ ehci_init_driver(&sunxi_ehci_hc_driver, &sunxi_overrides);
+
+ return platform_driver_register(&ehci_sunxi_driver);
+}
+module_init(sunxi_ehci_init_module);
+
+static void __exit sunxi_ehci_exit_module(void)
+{
+ platform_driver_unregister(&ehci_sunxi_driver);
+}
+module_exit(sunxi_ehci_exit_module);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, ehci_of_match);
+MODULE_AUTHOR("Roman Byshko <rbyshko@gmail.com>");

View file

@ -0,0 +1,129 @@
From 6c6bc98f6a2b1f91071564efdb77c90307610018 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
Date: Sat, 15 Feb 2014 14:02:51 +0100
Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 +++++
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 +++++
arch/arm/boot/dts/sun4i-a10.dtsi | 54 ++++++++++++++++++++++++++++++
3 files changed, 70 insertions(+)
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index d6ec839..4b2a694 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -35,6 +35,14 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index 6df237d8..ef85b8e 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -34,6 +34,14 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 454077a..a8e0df3 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -338,6 +338,46 @@
#size-cells = <0>;
};
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <32>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <33>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc3: mmc@01c12000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c12000 0x1000>;
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <35>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
ahci: sata@01c18000 {
compatible = "allwinner,sun4i-a10-ahci";
reg = <0x01c18000 0x1000>;
@@ -416,6 +456,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
+
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
};
timer@01c20c00 {
--
1.8.5.5

View file

@ -1,27 +0,0 @@
From 04f41bafdff26bd895f2a1f894fd427779d7ed51 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Thu, 19 Sep 2013 21:58:47 +0200
Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -93,6 +93,14 @@
clock-output-names = "pll6_sata", "pll6_other", "pll6";
};
+ usb:usb@0x01c200cc {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun47i-usb-gates-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
+ };
+
/* dummy is 200M */
cpu: cpu@01c20054 {
#clock-cells = <0>;

View file

@ -1,58 +0,0 @@
From ec53e86224acaa3891148fa298bb1504f3579d6b Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Wed, 18 Sep 2013 00:30:04 +0200
Subject: [PATCH] ARM: sun4i: dt: Add USB EHCI bindings
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Conflicts:
arch/arm/boot/dts/sun4i-a10.dtsi
---
arch/arm/boot/dts/sun4i-a10.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -17,6 +17,8 @@
aliases {
ethernet0 = &emac;
+ ehci1 = &ehci0;
+ ehci2 = &ehci1;
};
cpus {
@@ -563,5 +565,33 @@
clock-frequency = <100000>;
status = "disabled";
};
+
+ usb_rst: reset@0x01c200cc {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun4i-clock-reset";
+ reg = <0x01c200cc 0x4>;
+ };
+
+ ehci0: ehci0@0x01c14000 {
+ compatible = "allwinner,sunxi-ehci";
+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
+ interrupts = <39>;
+ resets = <&usb_rst 1>;
+ reset-names = "ehci_reset";
+ clocks = <&usb 8>, <&ahb_gates 1>;
+ clock-names = "usb_phy", "ahb_ehci";
+ status = "disabled";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ compatible = "allwinner,sunxi-ehci";
+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
+ interrupts = <40>;
+ resets = <&usb_rst 2>;
+ reset-names = "ehci_reset";
+ clocks = <&usb 8>, <&ahb_gates 3>;
+ clock-names = "usb_phy", "ahb_ehci";
+ status = "disabled";
+ };
};
};

View file

@ -1,38 +1,42 @@
From 48332fd7217cf5b06b438503513e54e6138e0637 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 14 Dec 2013 22:58:14 +0100
From 5bfbb46a8685de4c67f084aea983fc9a50c882ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
Date: Sat, 15 Feb 2014 14:02:29 +0100
Subject: [PATCH] ARM: dts: sun5i: Add support for mmc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 32 ++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a10s.dtsi | 34 ++++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 16 +++++++++++
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 16 +++++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 17 ++++++++++++
5 files changed, 115 insertions(+)
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 30 ++++++++++++++++
arch/arm/boot/dts/sun5i-a10s.dtsi | 44 ++++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts | 15 ++++++++
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 15 ++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 37 ++++++++++++++++++++
5 files changed, 141 insertions(+)
diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
index 3c9f8b3..5c7b454 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
@@ -34,7 +34,39 @@
@@ -34,7 +34,37 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxino_micro>;
+ cd-gpios = <&pio 6 1 0>; /* PG1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
+ mmc1: mmc@01c10000 {
+ pinctrl-names = "default";
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc1_pins_a>;
+ pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>;
+ cd-gpios = <&pio 6 13 0>; /* PG13 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
@ -41,22 +45,24 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ allwinner,pull = <1>;
+ };
+
+ mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin@0 {
+ allwinner,pins = "PG13";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PE3";
allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 3a9b33d..3a7039e 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -293,6 +293,26 @@
@@ -299,6 +299,36 @@
#size-cells = <0>;
};
@ -79,11 +85,21 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
@@ -363,6 +383,20 @@
@@ -369,6 +399,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
@ -104,18 +120,19 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
};
timer@01c20c00 {
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
index fe2ce0a..2f08bb2 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
@@ -20,7 +20,23 @@
@@ -20,7 +20,22 @@
compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
@ -124,24 +141,25 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxinom: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index a4ba5ff..a7280f5 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -23,7 +23,23 @@
};
@@ -19,7 +19,22 @@
compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
@ -150,15 +168,17 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 9612c52..63a35b8 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -274,6 +274,16 @@
@@ -281,6 +281,36 @@
#size-cells = <1>;
ranges;
@ -171,11 +191,31 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <33>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;
@@ -326,6 +336,13 @@
@@ -333,6 +363,13 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
@ -189,3 +229,6 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
};
timer@01c20c00 {
--
1.8.5.5

View file

@ -1,81 +0,0 @@
From 875bbd46c296e4b9ed130848bc64be5cf39669c8 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Wed, 18 Sep 2013 22:45:06 +0200
Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to Cubieboard-A10
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Conflicts:
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
---
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 46 ++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -77,6 +77,20 @@
allwinner,drive = <1>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
+
+ usb2_vbus_pin: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
};
uart0: serial@01c28000 {
@@ -96,6 +110,16 @@
pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
+
+ ehci0: ehci0@0x01c14000 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
};
leds {
@@ -128,5 +152,27 @@
gpio = <&pio 1 8 0>;
enable-active-high;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ };
};
};

View file

@ -0,0 +1,160 @@
From a3bddfdd19c49f0bde7aa2ff496773c575763d07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
Date: Sat, 15 Feb 2014 14:02:01 +0100
Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 61 +++++++++++++++++++++++++
4 files changed, 100 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 07823c2..a8186f5 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -20,6 +20,14 @@
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index 403bd2e..6cd7cca 100644
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index d5c6799..d4e2355 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -20,12 +20,35 @@
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ status = "okay";
+ };
+
+ mmc3: mmc@01c12000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc3_pins_a>;
+ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 7 11 0>; /* PH11 */
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
};
pinctrl@01c20800 {
+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
+ allwinner,pins = "PH11";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 3385994..3bc6ac5 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -392,6 +392,46 @@
#size-cells = <0>;
};
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 32 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 33 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 34 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ mmc3: mmc@01c12000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c12000 0x1000>;
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <0 35 4>;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
ahci: sata@01c18000 {
compatible = "allwinner,sun4i-a10-ahci";
reg = <0x01c18000 0x1000>;
@@ -510,6 +550,27 @@
allwinner,drive = <3>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
+
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
+ mmc3_pins_a: mmc3@0 {
+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
+ allwinner,function = "mmc3";
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {
--
1.8.5.5

View file

@ -1,78 +0,0 @@
From 9a86b6c16abc11b1090fbf4e102b4eed1d474d96 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Wed, 18 Sep 2013 00:30:40 +0200
Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to the Mele A1000
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 46 +++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -73,6 +73,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
+
+ usb2_vbus_pin: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
};
uart0: serial@01c28000 {
@@ -86,6 +100,16 @@
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
};
+
+ ehci0: ehci0@0x01c14000 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
};
leds {
@@ -117,5 +141,27 @@
enable-active-high;
gpio = <&pio 7 15 0>;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ };
};
};

View file

@ -0,0 +1,64 @@
From 11347c2a116f36b95d6cc3b315a1f269da6d42a0 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 17:20:21 +0100
Subject: [PATCH] ARM: sun4i: dt: Fixup mmc bindings
1) Now that we're no longer overriding the caps set by mmc_of_parse we need
to set cd-inverted for our card detection to work.
2) Now that we no longer claim UHS modes support we will never use any DDR
modes, so drive-strength 2 is enough for the mmc data pins.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index a8e0df3..ba05e6e 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -345,6 +345,7 @@
clock-names = "ahb", "mod";
interrupts = <32>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -355,6 +356,7 @@
clock-names = "ahb", "mod";
interrupts = <33>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -365,6 +367,7 @@
clock-names = "ahb", "mod";
interrupts = <34>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -375,6 +378,7 @@
clock-names = "ahb", "mod";
interrupts = <35>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -460,7 +464,7 @@
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
allwinner,function = "mmc0";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
--
1.8.5.5

View file

@ -0,0 +1,107 @@
From 1fa41bc5a6659e453ca19086f195b02a23dc3bbe Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 17:25:54 +0100
Subject: [PATCH] ARM: sun5i: dt: Fixup mmc bindings
1) Now that we're no longer overriding the caps set by mmc_of_parse we need
to set cd-inverted for our card detection to work.
2) Now that we no longer claim UHS modes support we will never use any DDR
modes, so drive-strength 2 is enough for the mmc data pins.
3) mmc1 on the A13 is not routed to any pins, and thus unusable, remove it
from the dtsi
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++--
arch/arm/boot/dts/sun5i-a13.dtsi | 14 +++-----------
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 3a7039e..15dfa9a 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -306,6 +306,7 @@
clock-names = "ahb", "mod";
interrupts = <32>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -316,6 +317,7 @@
clock-names = "ahb", "mod";
interrupts = <33>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -326,6 +328,7 @@
clock-names = "ahb", "mod";
interrupts = <34>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -403,14 +406,14 @@
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
allwinner,function = "mmc0";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
mmc1_pins_a: mmc1@0 {
allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8";
allwinner,function = "mmc1";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 63a35b8..14a99d0 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -288,16 +288,7 @@
clock-names = "ahb", "mod";
interrupts = <32>;
bus-width = <4>;
- status = "disabled";
- };
-
- mmc1: mmc@01c10000 {
- compatible = "allwinner,sun5i-a13-mmc";
- reg = <0x01c10000 0x1000>;
- clocks = <&ahb_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mod";
- interrupts = <33>;
- bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -308,6 +299,7 @@
clock-names = "ahb", "mod";
interrupts = <34>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -367,7 +359,7 @@
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
allwinner,function = "mmc0";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
};
--
1.8.5.5

View file

@ -0,0 +1,73 @@
From e48e7ba7f97e883a24036df04cb474cf7cd22574 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 17 Feb 2014 17:16:08 +0100
Subject: [PATCH] ARM: sun7i: dt: Fixup mmc bindings
1) Now that we're no longer overriding the caps set by mmc_of_parse we need
to set cd-inverted for our card detection to work.
2) Now that we no longer claim UHS modes support we will never use any DDR
modes, so drive-strength 2 is enough for the mmc data pins.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 3bc6ac5..f4ecd79 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -399,6 +399,7 @@
clock-names = "ahb", "mod";
interrupts = <0 32 4>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -409,6 +410,7 @@
clock-names = "ahb", "mod";
interrupts = <0 33 4>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -419,6 +421,7 @@
clock-names = "ahb", "mod";
interrupts = <0 34 4>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -429,6 +432,7 @@
clock-names = "ahb", "mod";
interrupts = <0 35 4>;
bus-width = <4>;
+ cd-inverted;
status = "disabled";
};
@@ -554,7 +558,7 @@
mmc0_pins_a: mmc0@0 {
allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
allwinner,function = "mmc0";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
@@ -568,7 +572,7 @@
mmc3_pins_a: mmc3@0 {
allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
allwinner,function = "mmc3";
- allwinner,drive = <3>;
+ allwinner,drive = <2>;
allwinner,pull = <0>;
};
};
--
1.8.5.5

View file

@ -1,27 +0,0 @@
From b7739d837e1176b2206ee541075c9eba0a263695 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Thu, 19 Sep 2013 21:24:20 +0200
Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -89,6 +89,14 @@
clock-output-names = "pll6_sata", "pll6_other", "pll6";
};
+ usb:usb@0x01c200cc {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun47i-usb-gates-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
+ };
+
cpu: cpu@01c20054 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-cpu-clk";

View file

@ -1,58 +0,0 @@
From a82eb088ea3fa4c25b256400690a30f4b0392e91 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Thu, 19 Sep 2013 21:36:10 +0200
Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Conflicts:
arch/arm/boot/dts/sun7i-a20.dtsi
---
arch/arm/boot/dts/sun7i-a20.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -18,6 +18,8 @@
aliases {
ethernet0 = &gmac;
+ ehci1 = &ehci0;
+ ehci2 = &ehci1;
};
cpus {
@@ -623,5 +625,33 @@
#interrupt-cells = <3>;
interrupts = <1 9 0xf04>;
};
+
+ usb_rst: reset@0x01c200cc {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun4i-clock-reset";
+ reg = <0x01c200cc 0x4>;
+ };
+
+ ehci0: ehci0@0x01c14000 {
+ compatible = "allwinner,sunxi-ehci";
+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
+ interrupts = <0 39 1>;
+ resets = <&usb_rst 1>;
+ reset-names = "ehci_reset";
+ clocks = <&usb 8>, <&ahb_gates 1>;
+ clock-names = "usb_phy", "ahb_ehci";
+ status = "disabled";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ compatible = "allwinner,sunxi-ehci";
+ reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
+ interrupts = <0 40 1>;
+ resets = <&usb_rst 2>;
+ reset-names = "ehci_reset";
+ clocks = <&usb 8>, <&ahb_gates 3>;
+ clock-names = "usb_phy", "ahb_ehci";
+ status = "disabled";
+ };
};
};

View file

@ -1,80 +0,0 @@
From 8ba068f40cce9612d2ac0879b6978274ab497d31 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Thu, 19 Sep 2013 21:29:45 +0200
Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings for Cubieboard2
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Conflicts:
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 45 +++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -69,6 +69,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
+
+ usb2_vbus_pin: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
};
uart0: serial@01c28000 {
@@ -86,6 +100,15 @@
i2c1: i2c@01c2b000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins_a>;
+ };
+
+ ehci0: ehci0@0x01c14000 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ vbus-supply = <&reg_usb2_vbus>;
status = "okay";
};
};
@@ -119,5 +142,27 @@
gpio = <&pio 1 8 0>;
enable-active-high;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ };
};
};

View file

@ -1,86 +0,0 @@
From 5031cb9d88fe9ea4a37fe342ec5f8e2f0f930e00 Mon Sep 17 00:00:00 2001
From: Zalan Blenessy <zalan.blenessy@gmail.com>
Date: Sun, 22 Dec 2013 17:08:10 +0100
Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to Olinuxino A20 Micro dts
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 47 +++++++++++++++++++++++++
1 file changed, 47 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -85,6 +85,20 @@
allwinner,drive = <1>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
+
+ usb2_vbus_pin: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
};
uart0: serial@01c28000 {
@@ -122,6 +136,16 @@
pinctrl-0 = <&i2c2_pins_a>;
status = "okay";
};
+
+ ehci0: ehci0@0x01c14000 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci1: ehci1@0x01c1c000 {
+ vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
};
leds {
@@ -138,6 +162,7 @@
regulators {
compatible = "simple-bus";
+ pinctrl-names = "default";
reg_ahci_5v: ahci-5v {
compatible = "regulator-fixed";
@@ -148,5 +173,27 @@
gpio = <&pio 1 8 0>;
enable-active-high;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ };
};
};

View file

@ -1,83 +0,0 @@
From 90cab9a5e7c43bfbda25dd114a838f4e4b50b6ff Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 17 Dec 2013 23:04:57 +0100
Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to cubietruck dts
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 46 ++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -43,11 +43,21 @@
status = "okay";
};
+ ehci0: ehci0@0x01c14000 {
+ vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
sata: ahci@01c18000 {
pwr-supply = <&reg_ahci_5v>;
status = "okay";
};
+ ehci1: ehci1@0x01c1c000 {
+ vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
allwinner,pins = "PH1";
@@ -90,6 +100,20 @@
allwinner,drive = <0>;
allwinner,pull = <2>;
};
+
+ usb1_vbus_pin: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
+
+ usb2_vbus_pin: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <2>;
+ };
};
uart0: serial@01c28000 {
@@ -175,5 +199,27 @@
gpio = <&pio 7 12 0>;
enable-active-high;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ };
};
};

View file

@ -1,27 +0,0 @@
From f017ea35bd87e7935fbf5a03bc016d8b1efa03c0 Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Tue, 24 Sep 2013 20:02:39 +0200
Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB Host clocks
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -90,6 +90,14 @@
clock-output-names = "pll6_sata", "pll6_other", "pll6";
};
+ usb:usb@0x01c200cc {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun5i-usb-gates-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_phy";
+ };
+
/* dummy is 200M */
cpu: cpu@01c20054 {
#clock-cells = <0>;

View file

@ -1,46 +0,0 @@
From 3d3aa5f5c67d3f860b68def6a0ffce5e7175f85e Mon Sep 17 00:00:00 2001
From: arokux <arokux@gmail.com>
Date: Tue, 24 Sep 2013 20:03:40 +0200
Subject: [PATCH] ARM: sun5i: dt: Add USB EHCI bindings
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -16,6 +16,10 @@
/ {
interrupt-parent = <&intc>;
+ aliases {
+ ehci1 = &ehci0;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -423,5 +427,22 @@
interrupts = <82>, <83>;
clocks = <&ahb_gates 28>;
};
+
+ usb_rst: reset@0x01c200cc {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun4i-clock-reset";
+ reg = <0x01c200cc 0x4>;
+ };
+
+ ehci0: ehci0@0x01c14000 {
+ compatible = "allwinner,sunxi-ehci";
+ reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
+ interrupts = <39>;
+ resets = <&usb_rst 1>;
+ reset-names = "ehci_reset";
+ clocks = <&usb 8>, <&ahb_gates 1>;
+ clock-names = "usb_phy", "ahb_ehci";
+ status = "disabled";
+ };
};
};

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