mirror of https://github.com/hak5/openwrt-owl.git
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: 39782owl
parent
2c771cc71f
commit
ac4b9dbb3c
|
@ -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
|
||||
|
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Stefan Roese
|
||||
* Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun4i-a10.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Olimex A10-Olinuxino LIME";
|
||||
compatible = "olimex,a10-olinuxino-lime", "allwinner,sun4i-a10";
|
||||
|
||||
soc@01c00000 {
|
||||
emac: ethernet@01c0b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&emac_pins_a>;
|
||||
phy = <&phy1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
mdio@01c0b080 {
|
||||
status = "okay";
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
sdc0: sdc@01c0f000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdc0_pins_a>;
|
||||
pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
|
||||
cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
cd-mode = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sata: ahci@01c18000 {
|
||||
pwr-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinctrl@01c20800 {
|
||||
ahci_pwr_pin: ahci_pwr_pin@0 {
|
||||
allwinner,pins = "PC3";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
led_pins_olinuxino: led_pins@0 {
|
||||
allwinner,pins = "PH2";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <1>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
allwinner,pins = "PH6";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <2>;
|
||||
};
|
||||
|
||||
usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
allwinner,pins = "PH3";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@01c2ac00 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c1: i2c@01c2b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci0: ehci0@0x01c14000 {
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci1: ehci1@0x01c1c000 {
|
||||
vbus-supply = <®_usb2_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&led_pins_olinuxino>;
|
||||
|
||||
green {
|
||||
label = "a10-olinuxino-lime:green:usr";
|
||||
gpios = <&pio 7 2 0>;
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
|
||||
reg_usb1_vbus: usb1-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb1_vbus_pin>;
|
||||
regulator-name = "usb1-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 6 0>;
|
||||
};
|
||||
|
||||
reg_usb2_vbus: usb2-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb2_vbus_pin>;
|
||||
regulator-name = "usb2-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 3 0>;
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
pinctrl-names = "default";
|
||||
|
||||
reg_ahci_5v: ahci-5v {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "ahci-5v";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
pinctrl-0 = <&ahci_pwr_pin>;
|
||||
gpio = <&pio 2 3 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 Stefan Roese
|
||||
* Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun4i-a10.dtsi"
|
||||
|
||||
/ {
|
||||
model = "pcDuino";
|
||||
compatible = "pcduino,a10-pcduino", "allwinner,sun4i-a10";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "earlyprintk console=ttyS0,115200";
|
||||
};
|
||||
|
||||
soc@01c00000 {
|
||||
emac: ethernet@01c0b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&emac_pins_a>;
|
||||
phy = <&phy1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
mdio@01c0b080 {
|
||||
status = "okay";
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
sdc0: sdc@01c0f000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdc0_pins_a>;
|
||||
pinctrl-1 = <&mmc0_cd_pin_pcduino>;
|
||||
cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
cd-mode = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinctrl@01c20800 {
|
||||
mmc0_cd_pin_pcduino: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
led_pins_pcduino: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <1>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
allwinner,pins = "PH6";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <2>;
|
||||
};
|
||||
|
||||
usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
allwinner,pins = "PH3";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@01c2ac00 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c1: i2c@01c2b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci0: ehci0@0x01c14000 {
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci1: ehci1@0x01c1c000 {
|
||||
vbus-supply = <®_usb2_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&led_pins_pcduino>;
|
||||
|
||||
blue {
|
||||
label = "pcduino:blue:usr";
|
||||
gpios = <&pio 7 21 0>; /* LED1 */
|
||||
};
|
||||
|
||||
green {
|
||||
label = "pcduino:green:usr";
|
||||
gpios = <&pio 7 20 0>; /* LED2 */
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
|
||||
reg_usb1_vbus: usb1-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb1_vbus_pin>;
|
||||
regulator-name = "usb1-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 6 0>;
|
||||
};
|
||||
|
||||
reg_usb2_vbus: usb2-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb2_vbus_pin>;
|
||||
regulator-name = "usb2-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 3 0>;
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
pinctrl-names = "default";
|
||||
|
||||
vcc_3v3_reg: regulator@0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_3v3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -19,45 +19,7 @@
|
|||
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
sdc0: sdc@01c0f000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdc0_pins_a>;
|
||||
pinctrl-1 = <&mmc0_cd_pin_cubietruck>;
|
||||
cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
cd-mode = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci0: ehci0@0x01c14000 {
|
||||
vbus-supply = <®_usb1_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sata: ahci@01c18000 {
|
||||
pwr-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci1: ehci1@0x01c1c000 {
|
||||
vbus-supply = <®_usb2_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinctrl@01c20800 {
|
||||
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
|
||||
allwinner,pins = "PH12";
|
||||
allwinner,function = "gpio_out";
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
led_pins_cubietruck: led_pins@0 {
|
||||
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
|
||||
allwinner,function = "gpio_out";
|
||||
|
@ -112,41 +74,4 @@
|
|||
gpios = <&pio 7 7 0>;
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
pinctrl-names = "default";
|
||||
|
||||
reg_ahci_5v: ahci-5v {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "ahci-5v";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
|
||||
gpio = <&pio 7 12 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
reg_usb1_vbus: usb1-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb1_vbus_pin>;
|
||||
regulator-name = "usb1-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 6 0>;
|
||||
};
|
||||
|
||||
reg_usb2_vbus: usb2-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb2_vbus_pin>;
|
||||
regulator-name = "usb2-vbus";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 3 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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");
|
|
@ -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
|
|
@ -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,},
|
||||
{}
|
|
@ -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 {
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
From e28b63650ff934751b9fe56415dc2491a6c6b704 Mon Sep 17 00:00:00 2001
|
||||
From 7405ae68d251191677e51aadb4308d6ce5212bbe Mon Sep 17 00:00:00 2001
|
||||
From: Chen-Yu Tsai <wens@csie.org>
|
||||
Date: Sat, 7 Dec 2013 01:29:41 +0800
|
||||
Date: Mon, 10 Feb 2014 18:35:52 +0800
|
||||
Subject: [PATCH] ARM: dts: sun7i: cubieboard2: Enable GMAC instead of EMAC
|
||||
|
||||
GMAC has better performance and fewer hardware issues.
|
||||
|
@ -8,9 +8,11 @@ Use the GMAC in MII mode for ethernet instead of the EMAC.
|
|||
|
||||
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 23 ++++++++---------------
|
||||
1 file changed, 8 insertions(+), 15 deletions(-)
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 ++++++++++++---------------
|
||||
1 file changed, 12 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
index 5c51cb8..7bf4935 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
@@ -19,21 +19,6 @@
|
||||
|
@ -32,21 +34,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
|||
- };
|
||||
- };
|
||||
-
|
||||
mmc0: mmc@01c0f000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc0_pins_a>;
|
||||
@@ -111,6 +96,14 @@
|
||||
vbus-supply = <®_usb2_vbus>;
|
||||
pinctrl@01c20800 {
|
||||
led_pins_cubieboard2: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
@@ -60,6 +45,18 @@
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ gmac: ethernet@01c50000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&gmac_pins_mii>;
|
||||
+ snps,phy-addr = <1>;
|
||||
+ pinctrl-0 = <&gmac_pins_mii_a>;
|
||||
+ phy = <&phy1>;
|
||||
+ phy-mode = "mii";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ phy1: ethernet-phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
leds {
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
From e39d51b2236ab17628fe5d110296cd33a9c4427e Mon Sep 17 00:00:00 2001
|
||||
From e401b86036245d2d62d825f0e3e12286c111b281 Mon Sep 17 00:00:00 2001
|
||||
From: Chen-Yu Tsai <wens@csie.org>
|
||||
Date: Sat, 7 Dec 2013 01:29:42 +0800
|
||||
Subject: [PATCH] ARM: dts: sun7i: olinuxino-micro: Enable GMAC instead of EMAC
|
||||
Date: Mon, 10 Feb 2014 18:35:53 +0800
|
||||
Subject: [PATCH] ARM: dts: sun7i: a20-olinuxino-micro: Enable GMAC instead of
|
||||
EMAC
|
||||
|
||||
GMAC has better performance and fewer hardware issues.
|
||||
Use the GMAC in MII mode for ethernet instead of the EMAC.
|
||||
|
||||
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++---------------
|
||||
1 file changed, 8 insertions(+), 15 deletions(-)
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 27 +++++++++++--------------
|
||||
1 file changed, 12 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
index ead3013..b02a796 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
@@ -19,21 +19,6 @@
|
||||
|
@ -32,21 +35,28 @@ Signed-off-by: Chen-Yu Tsai <wens@csie.org>
|
|||
- };
|
||||
- };
|
||||
-
|
||||
mmc0: mmc@01c0f000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc0_pins_a>;
|
||||
@@ -146,6 +131,14 @@
|
||||
vbus-supply = <®_usb2_vbus>;
|
||||
pinctrl@01c20800 {
|
||||
led_pins_olinuxino: led_pins@0 {
|
||||
allwinner,pins = "PH2";
|
||||
@@ -78,6 +63,18 @@
|
||||
pinctrl-0 = <&i2c2_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ gmac: ethernet@01c50000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&gmac_pins_mii>;
|
||||
+ snps,phy-addr = <1>;
|
||||
+ pinctrl-0 = <&gmac_pins_mii_a>;
|
||||
+ phy = <&phy1>;
|
||||
+ phy-mode = "mii";
|
||||
+ status = "okay";
|
||||
+
|
||||
+ phy1: ethernet-phy@1 {
|
||||
+ reg = <1>;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
leds {
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -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
|
|
@ -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 {
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 {
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
|
@ -0,0 +1,352 @@
|
|||
From 93dd2c512a24c552f1146d746aac112da7677430 Mon Sep 17 00:00:00 2001
|
||||
From: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Date: Sat, 18 Jan 2014 15:00:45 +0100
|
||||
Subject: [PATCH] ARM: sunxi: Add support for Allwinner SUNXi SoCs sata to
|
||||
ahci_platform
|
||||
|
||||
This patch adds support for the ahci sata controler found on Allwinner A10
|
||||
and A20 SoCs to the ahci_platform driver.
|
||||
|
||||
Orignally written by Olliver Schinagl using the approach of having a platform
|
||||
device which probe method creates a new child platform device which gets
|
||||
driven by ahci_platform.c, as done by ahci_imx.c .
|
||||
|
||||
Refactored by Hans de Goede to add most of the non sunxi specific functionality
|
||||
to ahci_platform.c and use a platform_data pointer from of_device_id for the
|
||||
sunxi specific bits.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
.../devicetree/bindings/ata/ahci-platform.txt | 15 +-
|
||||
drivers/ata/Kconfig | 9 +
|
||||
drivers/ata/Makefile | 1 +
|
||||
drivers/ata/ahci_sunxi.c | 249 +++++++++++++++++++++
|
||||
4 files changed, 271 insertions(+), 3 deletions(-)
|
||||
create mode 100644 drivers/ata/ahci_sunxi.c
|
||||
|
||||
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
|
||||
index 1ac807f..499bfed 100644
|
||||
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
|
||||
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
|
||||
@@ -4,7 +4,9 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
|
||||
Each SATA controller should have its own node.
|
||||
|
||||
Required properties:
|
||||
-- compatible : compatible list, contains "snps,spear-ahci"
|
||||
+- compatible : compatible list, one of "snps,spear-ahci",
|
||||
+ "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
|
||||
+ "allwinner,sun4i-a10-ahci"
|
||||
- interrupts : <interrupt mapping for SATA IRQ>
|
||||
- reg : <registers mapping>
|
||||
|
||||
@@ -13,10 +15,17 @@ Optional properties:
|
||||
- clocks : a list of phandle + clock specifier pairs
|
||||
- target-supply : regulator for SATA target power
|
||||
|
||||
-Example:
|
||||
+Examples:
|
||||
sata@ffe08000 {
|
||||
compatible = "snps,spear-ahci";
|
||||
reg = <0xffe08000 0x1000>;
|
||||
interrupts = <115>;
|
||||
-
|
||||
};
|
||||
+
|
||||
+ ahci: sata@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <56>;
|
||||
+ clocks = <&pll6 0>, <&ahb_gates 25>;
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ };
|
||||
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
|
||||
index 4e73772..cc67cc0 100644
|
||||
--- a/drivers/ata/Kconfig
|
||||
+++ b/drivers/ata/Kconfig
|
||||
@@ -106,6 +106,15 @@ config AHCI_IMX
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config AHCI_SUNXI
|
||||
+ tristate "Allwinner sunxi AHCI SATA support"
|
||||
+ depends on ARCH_SUNXI && SATA_AHCI_PLATFORM
|
||||
+ help
|
||||
+ This option enables support for the Allwinner sunxi SoC's
|
||||
+ onboard AHCI SATA.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config SATA_FSL
|
||||
tristate "Freescale 3.0Gbps SATA support"
|
||||
depends on FSL_SOC
|
||||
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
|
||||
index 46518c6..246050b 100644
|
||||
--- a/drivers/ata/Makefile
|
||||
+++ b/drivers/ata/Makefile
|
||||
@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
|
||||
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
|
||||
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
|
||||
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
|
||||
+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o
|
||||
|
||||
# SFF w/ custom DMA
|
||||
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
|
||||
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
|
||||
new file mode 100644
|
||||
index 0000000..001f7dfc
|
||||
--- /dev/null
|
||||
+++ b/drivers/ata/ahci_sunxi.c
|
||||
@@ -0,0 +1,249 @@
|
||||
+/*
|
||||
+ * Allwinner sunxi AHCI SATA platform driver
|
||||
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
|
||||
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
|
||||
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
|
||||
+ * Daniel Wang <danielwang@allwinnertech.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms and conditions of the GNU General Public License,
|
||||
+ * version 2, as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
+ * more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ahci_platform.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regulator/consumer.h>
|
||||
+#include "ahci.h"
|
||||
+
|
||||
+#define AHCI_BISTAFR 0x00a0
|
||||
+#define AHCI_BISTCR 0x00a4
|
||||
+#define AHCI_BISTFCTR 0x00a8
|
||||
+#define AHCI_BISTSR 0x00ac
|
||||
+#define AHCI_BISTDECR 0x00b0
|
||||
+#define AHCI_DIAGNR0 0x00b4
|
||||
+#define AHCI_DIAGNR1 0x00b8
|
||||
+#define AHCI_OOBR 0x00bc
|
||||
+#define AHCI_PHYCS0R 0x00c0
|
||||
+#define AHCI_PHYCS1R 0x00c4
|
||||
+#define AHCI_PHYCS2R 0x00c8
|
||||
+#define AHCI_TIMER1MS 0x00e0
|
||||
+#define AHCI_GPARAM1R 0x00e8
|
||||
+#define AHCI_GPARAM2R 0x00ec
|
||||
+#define AHCI_PPARAMR 0x00f0
|
||||
+#define AHCI_TESTR 0x00f4
|
||||
+#define AHCI_VERSIONR 0x00f8
|
||||
+#define AHCI_IDR 0x00fc
|
||||
+#define AHCI_RWCR 0x00fc
|
||||
+#define AHCI_P0DMACR 0x0170
|
||||
+#define AHCI_P0PHYCR 0x0178
|
||||
+#define AHCI_P0PHYSR 0x017c
|
||||
+
|
||||
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val &= ~(clr_val);
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val |= set_val;
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val &= ~(clr_val);
|
||||
+ reg_val |= set_val;
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
|
||||
+{
|
||||
+ return (readl(reg) >> shift) & mask;
|
||||
+}
|
||||
+
|
||||
+static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+ int timeout;
|
||||
+
|
||||
+ /* This magic is from the original code */
|
||||
+ writel(0, reg_base + AHCI_RWCR);
|
||||
+ mdelay(5);
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
|
||||
+ (0x7 << 24),
|
||||
+ (0x5 << 24) | BIT(23) | BIT(18));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
|
||||
+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
|
||||
+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
|
||||
+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
|
||||
+ (0x7 << 20), (0x3 << 20));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
|
||||
+ (0x1f << 5), (0x19 << 5));
|
||||
+ mdelay(5);
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
|
||||
+
|
||||
+ timeout = 250; /* Power up takes aprox 50 us */
|
||||
+ do {
|
||||
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
|
||||
+ if (reg_val == 0x02)
|
||||
+ break;
|
||||
+
|
||||
+ if (--timeout == 0) {
|
||||
+ dev_err(dev, "PHY power up failed.\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ udelay(1);
|
||||
+ } while (1);
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
|
||||
+
|
||||
+ timeout = 100; /* Calibration takes aprox 10 us */
|
||||
+ do {
|
||||
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
|
||||
+ if (reg_val == 0x00)
|
||||
+ break;
|
||||
+
|
||||
+ if (--timeout == 0) {
|
||||
+ dev_err(dev, "PHY calibration failed.\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ udelay(1);
|
||||
+ } while (1);
|
||||
+
|
||||
+ mdelay(15);
|
||||
+
|
||||
+ writel(0x7, reg_base + AHCI_RWCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ahci_sunxi_start_engine(struct ata_port *ap)
|
||||
+{
|
||||
+ void __iomem *port_mmio = ahci_port_base(ap);
|
||||
+ struct ahci_host_priv *hpriv = ap->host->private_data;
|
||||
+
|
||||
+ /* Setup DMA before DMA start */
|
||||
+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
|
||||
+
|
||||
+ /* Start DMA */
|
||||
+ sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
|
||||
+}
|
||||
+
|
||||
+static const struct ata_port_info ahci_sunxi_port_info = {
|
||||
+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
|
||||
+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
|
||||
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
|
||||
+ .pio_mask = ATA_PIO4,
|
||||
+ .udma_mask = ATA_UDMA6,
|
||||
+ .port_ops = &ahci_platform_ops,
|
||||
+};
|
||||
+
|
||||
+static int ahci_sunxi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct ahci_host_priv *hpriv;
|
||||
+ int rc;
|
||||
+
|
||||
+ hpriv = ahci_platform_get_resources(pdev);
|
||||
+ if (IS_ERR(hpriv))
|
||||
+ return PTR_ERR(hpriv);
|
||||
+
|
||||
+ hpriv->start_engine = ahci_sunxi_start_engine;
|
||||
+
|
||||
+ rc = ahci_platform_enable_resources(hpriv);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
|
||||
+ if (rc)
|
||||
+ goto disable_resources;
|
||||
+
|
||||
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0);
|
||||
+ if (rc)
|
||||
+ goto disable_resources;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+disable_resources:
|
||||
+ ahci_platform_disable_resources(hpriv);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+int ahci_sunxi_resume(struct device *dev)
|
||||
+{
|
||||
+ struct ata_host *host = dev_get_drvdata(dev);
|
||||
+ struct ahci_host_priv *hpriv = host->private_data;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = ahci_platform_enable_resources(hpriv);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
|
||||
+ if (rc)
|
||||
+ goto disable_resources;
|
||||
+
|
||||
+ rc = ahci_platform_resume_host(dev);
|
||||
+ if (rc)
|
||||
+ goto disable_resources;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+disable_resources:
|
||||
+ ahci_platform_disable_resources(hpriv);
|
||||
+ return rc;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
|
||||
+ ahci_sunxi_resume);
|
||||
+
|
||||
+static const struct of_device_id ahci_sunxi_of_match[] = {
|
||||
+ { .compatible = "allwinner,sun4i-a10-ahci", },
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
|
||||
+
|
||||
+static struct platform_driver ahci_sunxi_driver = {
|
||||
+ .probe = ahci_sunxi_probe,
|
||||
+ .remove = ata_platform_remove_one,
|
||||
+ .driver = {
|
||||
+ .name = "ahci-sunxi",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = ahci_sunxi_of_match,
|
||||
+ .pm = &ahci_sunxi_pm_ops,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(ahci_sunxi_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
|
||||
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -1,436 +0,0 @@
|
|||
From 22345cc059de4a6ea1dc7657dd6ad86ca16a8814 Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Schinagl <oliver@schinagl.nl>
|
||||
Date: Tue, 3 Dec 2013 12:07:01 +0100
|
||||
Subject: [PATCH] ARM: sunxi: Add ahci-sunxi driver for the Allwinner SUNXi
|
||||
SoCs sata
|
||||
|
||||
This patch adds support for the ahci sata controler found on Allwinner A10
|
||||
and A20 SoCs.
|
||||
|
||||
Orignally written by Olliver Schinagl using the approach of having a platform
|
||||
device which probe method creates a new child platform device which gets
|
||||
driven by ahci_platform.c, as done by ahci_imx.c .
|
||||
|
||||
Given that almost all functionality already is shared through libahci /
|
||||
ata-core, and that ahci_platform.c cannot cleanly handle somewhat more complex
|
||||
platform specific ahci cases, such as the sunxi case, it was refactored into
|
||||
a stand-alone platform driver by Hans de Goede.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
.../devicetree/bindings/ata/ahci-sunxi.txt | 24 ++
|
||||
drivers/ata/Kconfig | 9 +
|
||||
drivers/ata/Makefile | 1 +
|
||||
drivers/ata/ahci_sunxi.c | 349 +++++++++++++++++++++
|
||||
4 files changed, 383 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/ata/ahci-sunxi.txt
|
||||
create mode 100644 drivers/ata/ahci_sunxi.c
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt
|
||||
@@ -0,0 +1,24 @@
|
||||
+Allwinner SUNXI AHCI SATA Controller
|
||||
+
|
||||
+SATA nodes are defined to describe on-chip Serial ATA controllers.
|
||||
+Each SATA controller should have its own node.
|
||||
+
|
||||
+Required properties:
|
||||
+- compatible : compatible list, contains "allwinner,sun4i-a10-ahci"
|
||||
+- reg : <registers mapping>
|
||||
+- interrupts : <interrupt mapping for AHCI IRQ>
|
||||
+- clocks : clocks for ACHI
|
||||
+- clock-names : clock names for AHCI
|
||||
+
|
||||
+Optional properties:
|
||||
+- pwr-supply : regulator to control the power supply GPIO
|
||||
+
|
||||
+Example:
|
||||
+ ahci@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <0 56 1>;
|
||||
+ clocks = <&ahb_gates 25>, <&pll6 0>;
|
||||
+ clock-names = "ahb_sata", "pll6_sata";
|
||||
+ pwr-supply = <®_ahci_5v>;
|
||||
+ };
|
||||
--- a/drivers/ata/Kconfig
|
||||
+++ b/drivers/ata/Kconfig
|
||||
@@ -106,6 +106,15 @@ config AHCI_IMX
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config AHCI_SUNXI
|
||||
+ tristate "Allwinner sunxi AHCI SATA support"
|
||||
+ depends on ARCH_SUNXI
|
||||
+ help
|
||||
+ This option enables support for the Allwinner sunxi SoC's
|
||||
+ onboard AHCI SATA.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config SATA_FSL
|
||||
tristate "Freescale 3.0Gbps SATA support"
|
||||
depends on FSL_SOC
|
||||
--- a/drivers/ata/Makefile
|
||||
+++ b/drivers/ata/Makefile
|
||||
@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
|
||||
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
|
||||
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
|
||||
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
|
||||
+obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o
|
||||
|
||||
# SFF w/ custom DMA
|
||||
obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/ata/ahci_sunxi.c
|
||||
@@ -0,0 +1,349 @@
|
||||
+/*
|
||||
+ * Allwinner sunxi AHCI SATA platform driver
|
||||
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
|
||||
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
|
||||
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
|
||||
+ * Daniel Wang <danielwang@allwinnertech.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms and conditions of the GNU General Public License,
|
||||
+ * version 2, as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
+ * more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regulator/consumer.h>
|
||||
+#include "ahci.h"
|
||||
+
|
||||
+#define AHCI_BISTAFR 0x00a0
|
||||
+#define AHCI_BISTCR 0x00a4
|
||||
+#define AHCI_BISTFCTR 0x00a8
|
||||
+#define AHCI_BISTSR 0x00ac
|
||||
+#define AHCI_BISTDECR 0x00b0
|
||||
+#define AHCI_DIAGNR0 0x00b4
|
||||
+#define AHCI_DIAGNR1 0x00b8
|
||||
+#define AHCI_OOBR 0x00bc
|
||||
+#define AHCI_PHYCS0R 0x00c0
|
||||
+#define AHCI_PHYCS1R 0x00c4
|
||||
+#define AHCI_PHYCS2R 0x00c8
|
||||
+#define AHCI_TIMER1MS 0x00e0
|
||||
+#define AHCI_GPARAM1R 0x00e8
|
||||
+#define AHCI_GPARAM2R 0x00ec
|
||||
+#define AHCI_PPARAMR 0x00f0
|
||||
+#define AHCI_TESTR 0x00f4
|
||||
+#define AHCI_VERSIONR 0x00f8
|
||||
+#define AHCI_IDR 0x00fc
|
||||
+#define AHCI_RWCR 0x00fc
|
||||
+#define AHCI_P0DMACR 0x0170
|
||||
+#define AHCI_P0PHYCR 0x0178
|
||||
+#define AHCI_P0PHYSR 0x017c
|
||||
+
|
||||
+struct sunxi_ahci {
|
||||
+ struct ahci_host_priv hpriv;
|
||||
+ struct regulator *pwr;
|
||||
+ struct clk *sata_clk;
|
||||
+ struct clk *ahb_clk;
|
||||
+};
|
||||
+
|
||||
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val &= ~(clr_val);
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val |= set_val;
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+
|
||||
+ reg_val = readl(reg);
|
||||
+ reg_val &= ~(clr_val);
|
||||
+ reg_val |= set_val;
|
||||
+ writel(reg_val, reg);
|
||||
+}
|
||||
+
|
||||
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
|
||||
+{
|
||||
+ return (readl(reg) >> shift) & mask;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_ahci_phy_init(struct device *dev, void __iomem *reg_base)
|
||||
+{
|
||||
+ u32 reg_val;
|
||||
+ int timeout;
|
||||
+
|
||||
+ /* This magic is from the original code */
|
||||
+ writel(0, reg_base + AHCI_RWCR);
|
||||
+ mdelay(5);
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
|
||||
+ (0x7 << 24),
|
||||
+ (0x5 << 24) | BIT(23) | BIT(18));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
|
||||
+ (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
|
||||
+ (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
|
||||
+ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
|
||||
+ (0x7 << 20), (0x3 << 20));
|
||||
+ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
|
||||
+ (0x1f << 5), (0x19 << 5));
|
||||
+ mdelay(5);
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
|
||||
+
|
||||
+ timeout = 0x100000;
|
||||
+ do {
|
||||
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
|
||||
+ } while (--timeout && (reg_val != 0x2));
|
||||
+ if (!timeout) {
|
||||
+ dev_err(dev, "PHY power up failed.\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
|
||||
+
|
||||
+ timeout = 0x100000;
|
||||
+ do {
|
||||
+ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
|
||||
+ } while (--timeout && reg_val);
|
||||
+ if (!timeout) {
|
||||
+ dev_err(dev, "PHY calibration failed.\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ mdelay(15);
|
||||
+
|
||||
+ writel(0x7, reg_base + AHCI_RWCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void sunxi_ahci_pre_start_engine(struct ata_port *ap)
|
||||
+{
|
||||
+ struct ahci_host_priv *hpriv = ap->host->private_data;
|
||||
+
|
||||
+ /* Setup DMA before DMA start */
|
||||
+ sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
|
||||
+}
|
||||
+
|
||||
+static int sunxi_ahci_enable_clks(struct sunxi_ahci *ahci)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = clk_prepare_enable(ahci->sata_clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_prepare_enable(ahci->ahb_clk);
|
||||
+ if (ret)
|
||||
+ clk_disable_unprepare(ahci->sata_clk);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void sunxi_ahci_disable_clks(struct sunxi_ahci *ahci)
|
||||
+{
|
||||
+ clk_disable_unprepare(ahci->ahb_clk);
|
||||
+ clk_disable_unprepare(ahci->sata_clk);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_ahci_host_stop(struct ata_host *host)
|
||||
+{
|
||||
+ struct ahci_host_priv *hpriv = host->private_data;
|
||||
+ struct sunxi_ahci *ahci = hpriv->plat_data;
|
||||
+
|
||||
+ if (!IS_ERR(ahci->pwr))
|
||||
+ regulator_disable(ahci->pwr);
|
||||
+
|
||||
+ sunxi_ahci_disable_clks(ahci);
|
||||
+}
|
||||
+
|
||||
+static struct ata_port_operations sunxi_ahci_platform_ops = {
|
||||
+ .inherits = &ahci_ops,
|
||||
+ .host_stop = sunxi_ahci_host_stop,
|
||||
+};
|
||||
+
|
||||
+static const struct ata_port_info sunxiahci_port_info = {
|
||||
+ AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
|
||||
+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
|
||||
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
|
||||
+ .pio_mask = ATA_PIO4,
|
||||
+ .udma_mask = ATA_UDMA6,
|
||||
+ .port_ops = &sunxi_ahci_platform_ops,
|
||||
+};
|
||||
+
|
||||
+static struct scsi_host_template sunxi_ahci_platform_sht = {
|
||||
+ AHCI_SHT("sunxi_ahci"),
|
||||
+};
|
||||
+
|
||||
+static int sunxi_ahci_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ const struct ata_port_info *ppi[] = { &sunxiahci_port_info, NULL };
|
||||
+ struct sunxi_ahci *ahci;
|
||||
+ struct ata_host *host;
|
||||
+ int ret;
|
||||
+
|
||||
+ ahci = devm_kzalloc(&pdev->dev, sizeof(*ahci), GFP_KERNEL);
|
||||
+ if (!ahci)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ahci->pwr = devm_regulator_get_optional(dev, "pwr");
|
||||
+ if (IS_ERR(ahci->pwr) && PTR_ERR(ahci->pwr) == -EPROBE_DEFER)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ host = ata_host_alloc_pinfo(dev, ppi, 1);
|
||||
+ if (!host)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ host->private_data = &ahci->hpriv;
|
||||
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
|
||||
+
|
||||
+ ahci->hpriv.flags = (unsigned long)ppi[0]->private_data;
|
||||
+ ahci->hpriv.plat_data = ahci;
|
||||
+ ahci->hpriv.pre_start_engine = sunxi_ahci_pre_start_engine;
|
||||
+ ahci->hpriv.mmio = devm_ioremap_resource(dev,
|
||||
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
|
||||
+ if (IS_ERR(ahci->hpriv.mmio))
|
||||
+ return PTR_ERR(ahci->hpriv.mmio);
|
||||
+
|
||||
+ ahci->ahb_clk = devm_clk_get(&pdev->dev, "ahb_sata");
|
||||
+ if (IS_ERR(ahci->ahb_clk))
|
||||
+ return PTR_ERR(ahci->ahb_clk);
|
||||
+
|
||||
+ ahci->sata_clk = devm_clk_get(&pdev->dev, "pll6_sata");
|
||||
+ if (IS_ERR(ahci->sata_clk))
|
||||
+ return PTR_ERR(ahci->sata_clk);
|
||||
+
|
||||
+ ret = sunxi_ahci_enable_clks(ahci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!IS_ERR(ahci->pwr)) {
|
||||
+ ret = regulator_enable(ahci->pwr);
|
||||
+ if (ret) {
|
||||
+ sunxi_ahci_disable_clks(ahci);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = sunxi_ahci_phy_init(dev, ahci->hpriv.mmio);
|
||||
+ if (ret) {
|
||||
+ sunxi_ahci_host_stop(host);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ahci_save_initial_config(dev, &ahci->hpriv, 0, 0);
|
||||
+
|
||||
+ ret = ahci_reset_controller(host);
|
||||
+ if (ret) {
|
||||
+ sunxi_ahci_host_stop(host);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ahci_init_controller(host);
|
||||
+ ahci_print_info(host, "sunxi");
|
||||
+
|
||||
+ ret = ata_host_activate(host, platform_get_irq(pdev, 0),
|
||||
+ ahci_interrupt, 0, &sunxi_ahci_platform_sht);
|
||||
+ if (ret)
|
||||
+ sunxi_ahci_host_stop(host);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+static int sunxi_ahci_susp(struct device *dev)
|
||||
+{
|
||||
+ struct ata_host *host = dev_get_drvdata(dev);
|
||||
+ struct ahci_host_priv *hpriv = host->private_data;
|
||||
+ struct sunxi_ahci *ahci = hpriv->plat_data;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * AHCI spec rev1.1 section 8.3.3:
|
||||
+ * Software must disable interrupts prior to requesting a
|
||||
+ * transition of the HBA to D3 state.
|
||||
+ */
|
||||
+ sunxi_clrbits(hpriv->mmio + HOST_CTL, HOST_IRQ_EN);
|
||||
+
|
||||
+ ret = ata_host_suspend(host, PMSG_SUSPEND);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ sunxi_ahci_disable_clks(ahci);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sunxi_ahci_resume(struct device *dev)
|
||||
+{
|
||||
+ struct ata_host *host = dev_get_drvdata(dev);
|
||||
+ struct ahci_host_priv *hpriv = host->private_data;
|
||||
+ struct sunxi_ahci *ahci = hpriv->plat_data;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = sunxi_ahci_enable_clks(ahci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
|
||||
+ ret = ahci_reset_controller(host);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ahci_init_controller(host);
|
||||
+ }
|
||||
+
|
||||
+ ata_host_resume(host);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static SIMPLE_DEV_PM_OPS(sunxi_ahci_pmo, sunxi_ahci_susp, sunxi_ahci_resume);
|
||||
+
|
||||
+static const struct of_device_id sunxi_ahci_of_match[] = {
|
||||
+ { .compatible = "allwinner,sun4i-a10-ahci" },
|
||||
+ { /* sentinel */ },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, sunxi_ahci_of_match);
|
||||
+
|
||||
+static struct platform_driver sunxi_ahci_driver = {
|
||||
+ .probe = sunxi_ahci_probe,
|
||||
+ .remove = ata_platform_remove_one,
|
||||
+ .driver = {
|
||||
+ .name = "sunxi-ahci",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = sunxi_ahci_of_match,
|
||||
+ .pm = &sunxi_ahci_pmo,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(sunxi_ahci_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA platform driver");
|
||||
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
|
||||
+MODULE_LICENSE("GPL");
|
|
@ -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
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
From 23af610e09f78822ade4067a400ff9ceb5b020ea Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Schinagl <oliver@schinagl.nl>
|
||||
Date: Tue, 3 Dec 2013 12:10:11 +0100
|
||||
Subject: [PATCH] ARM: sun4i: dts: Add ahci / sata support
|
||||
|
||||
This patch adds sunxi sata support to A10 boards that have such a connector.
|
||||
Some boards also feature a regulator via a GPIO and support for this is also
|
||||
added.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
|
||||
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 27 +++++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++
|
||||
3 files changed, 40 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
@@ -48,6 +48,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
mmc0_cd_pin_a1000: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
@@ -51,7 +51,19 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ pwr-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_cubieboard: ahci_pwr_pin@0 {
|
||||
+ allwinner,pins = "PB8";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
@@ -102,4 +114,19 @@
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ regulators {
|
||||
+ compatible = "simple-bus";
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ regulator-name = "ahci-5v";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_cubieboard>;
|
||||
+ gpio = <&pio 1 8 0>;
|
||||
+ enable-active-high;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
@@ -338,6 +338,15 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <56>;
|
||||
+ clocks = <&ahb_gates 25>, <&pll6 0>;
|
||||
+ clock-names = "ahb_sata", "pll6_sata";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
intc: interrupt-controller@01c20400 {
|
||||
compatible = "allwinner,sun4i-ic";
|
||||
reg = <0x01c20400 0x400>;
|
|
@ -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
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
From 4ce1f4c3ab04a697e9861b77582077b905b3f8a0 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 3 Jan 2014 10:27:51 +0100
|
||||
Subject: [PATCH] ARM: sun7i: dts: Add ahci / sata support
|
||||
|
||||
This patch adds sunxi sata support to A20 boards that have such a connector.
|
||||
Some boards also feature a regulator via a GPIO and support for this is also
|
||||
added.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 +++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 27 +++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 26 ++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++
|
||||
4 files changed, 89 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
@@ -43,7 +43,19 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ pwr-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_cubieboard2: ahci_pwr_pin@0 {
|
||||
+ allwinner,pins = "PB8";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
@@ -93,4 +105,19 @@
|
||||
gpios = <&pio 7 20 0>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ regulators {
|
||||
+ compatible = "simple-bus";
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ regulator-name = "ahci-5v";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_cubieboard2>;
|
||||
+ gpio = <&pio 1 8 0>;
|
||||
+ enable-active-high;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
@@ -43,6 +43,11 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ pwr-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
@@ -58,6 +63,13 @@
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
|
||||
+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@0 {
|
||||
+ allwinner,pins = "PH12";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
led_pins_cubietruck: led_pins@0 {
|
||||
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
|
||||
allwinner,function = "gpio_out";
|
||||
@@ -149,4 +161,19 @@
|
||||
gpio = <&pio 7 3 0>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ regulators {
|
||||
+ compatible = "simple-bus";
|
||||
+ pinctrl-names = "default";
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ regulator-name = "ahci-5v";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
|
||||
+ gpio = <&pio 7 12 0>;
|
||||
+ enable-active-high;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
@@ -52,7 +52,19 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ pwr-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_olinuxinom: ahci_pwr_pin@0 {
|
||||
+ allwinner,pins = "PB8";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
allwinner,function = "gpio_in";
|
||||
@@ -123,4 +135,18 @@
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ regulators {
|
||||
+ compatible = "simple-bus";
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ regulator-name = "ahci-5v";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_olinuxinom>;
|
||||
+ gpio = <&pio 1 8 0>;
|
||||
+ enable-active-high;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
@@ -433,6 +433,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ sata: ahci@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <0 56 1>;
|
||||
+ clocks = <&ahb_gates 25>, <&pll6 0>;
|
||||
+ clock-names = "ahb_sata", "pll6_sata";
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
timer@01c20c00 {
|
||||
compatible = "allwinner,sun4i-timer";
|
||||
reg = <0x01c20c00 0x90>;
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
From 3cae1df0e62432a80db86c80e261eb9bbed326ee Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Schinagl <oliver@schinagl.nl>
|
||||
Date: Tue, 3 Dec 2013 12:10:11 +0100
|
||||
Subject: [PATCH] ARM: sun4i: dt: Add ahci / sata support
|
||||
|
||||
This patch adds sunxi sata support to A10 boards that have such a connector.
|
||||
Some boards also feature a regulator via a GPIO and support for this is also
|
||||
added.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun4i-a10-a1000.dts | 4 ++++
|
||||
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 6 +++++
|
||||
arch/arm/boot/dts/sun4i-a10.dtsi | 8 +++++++
|
||||
arch/arm/boot/dts/sunxi-ahci-reg.dtsi | 36 ++++++++++++++++++++++++++++++
|
||||
4 files changed, 54 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/sunxi-ahci-reg.dtsi
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
index cbd2e13..d6ec839 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
@@ -35,6 +35,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ ahci: sata@01c18000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
emac_power_pin_a1000: emac_power_pin@0 {
|
||||
allwinner,pins = "PH15";
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
index b139ee6..6df237d8 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun4i-a10.dtsi"
|
||||
+/include/ "sunxi-ahci-reg.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Cubietech Cubieboard";
|
||||
@@ -33,6 +34,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
led_pins_cubieboard: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
index 336dbec..454077a 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
@@ -338,6 +338,14 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
+ ahci: sata@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <56>;
|
||||
+ clocks = <&pll6 0>, <&ahb_gates 25>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
intc: interrupt-controller@01c20400 {
|
||||
compatible = "allwinner,sun4i-ic";
|
||||
reg = <0x01c20400 0x400>;
|
||||
diff --git a/arch/arm/boot/dts/sunxi-ahci-reg.dtsi b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
|
||||
new file mode 100644
|
||||
index 0000000..7072af1
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/sunxi-ahci-reg.dtsi
|
||||
@@ -0,0 +1,36 @@
|
||||
+/*
|
||||
+ * sunxi boards sata target power supply common code
|
||||
+ *
|
||||
+ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * The code contained herein is licensed under the GNU General Public
|
||||
+ * License. You may obtain a copy of the GNU General Public License
|
||||
+ * Version 2 or later at the following locations:
|
||||
+ *
|
||||
+ * http://www.opensource.org/licenses/gpl-license.html
|
||||
+ * http://www.gnu.org/copyleft/gpl.html
|
||||
+ */
|
||||
+
|
||||
+/ {
|
||||
+ soc@01c00000 {
|
||||
+ pio: pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_a: ahci_pwr_pin@0 {
|
||||
+ allwinner,pins = "PB8";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_a>;
|
||||
+ regulator-name = "ahci-5v";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 1 8 0>;
|
||||
+ };
|
||||
+};
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
From c7b99b7afc3882c1b38a15da8d1625dd448c6fee Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 3 Jan 2014 10:27:51 +0100
|
||||
Subject: [PATCH] ARM: sun7i: dt: Add ahci / sata support
|
||||
|
||||
This patch adds sunxi sata support to A20 boards that have such a connector.
|
||||
Some boards also feature a regulator via a GPIO and support for this is also
|
||||
added.
|
||||
|
||||
Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 6 ++++++
|
||||
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 18 ++++++++++++++++++
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 6 ++++++
|
||||
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
|
||||
4 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
index 7bf4935..07823c2 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
@@ -13,12 +13,18 @@
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun7i-a20.dtsi"
|
||||
+/include/ "sunxi-ahci-reg.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Cubietech Cubieboard2";
|
||||
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
led_pins_cubieboard2: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
index 025ce52..403bd2e 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
@@ -13,13 +13,26 @@
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun7i-a20.dtsi"
|
||||
+/include/ "sunxi-ahci-reg.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Cubietech Cubietruck";
|
||||
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
|
||||
+ allwinner,pins = "PH12";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
led_pins_cubietruck: led_pins@0 {
|
||||
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
|
||||
allwinner,function = "gpio_out";
|
||||
@@ -90,4 +103,9 @@
|
||||
gpios = <&pio 7 7 0>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
|
||||
+ gpio = <&pio 7 12 0>;
|
||||
+ };
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
index b02a796..d5c6799 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
@@ -13,12 +13,18 @@
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "sun7i-a20.dtsi"
|
||||
+/include/ "sunxi-ahci-reg.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Olimex A20-Olinuxino Micro";
|
||||
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
led_pins_olinuxino: led_pins@0 {
|
||||
allwinner,pins = "PH2";
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
index daaafd0..3385994 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
@@ -392,6 +392,14 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
+ ahci: sata@01c18000 {
|
||||
+ compatible = "allwinner,sun4i-a10-ahci";
|
||||
+ reg = <0x01c18000 0x1000>;
|
||||
+ interrupts = <0 56 4>;
|
||||
+ clocks = <&pll6 0>, <&ahb_gates 25>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
pio: pinctrl@01c20800 {
|
||||
compatible = "allwinner,sun7i-a20-pinctrl";
|
||||
reg = <0x01c20800 0x400>;
|
||||
--
|
||||
1.8.5.5
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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,},
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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,},
|
|
@ -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>");
|
|
@ -0,0 +1,129 @@
|
|||
From 6c6bc98f6a2b1f91071564efdb77c90307610018 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
|
||||
Date: Sat, 15 Feb 2014 14:02:51 +0100
|
||||
Subject: [PATCH] ARM: dts: sun4i: Add support for mmc
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun4i-a10-a1000.dts | 8 +++++
|
||||
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 8 +++++
|
||||
arch/arm/boot/dts/sun4i-a10.dtsi | 54 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 70 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
index d6ec839..4b2a694 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
@@ -35,6 +35,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ pinctrl-names = "default", "default";
|
||||
+ pinctrl-0 = <&mmc0_pins_a>;
|
||||
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
|
||||
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
status = "okay";
|
||||
};
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
index 6df237d8..ef85b8e 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
@@ -34,6 +34,14 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ pinctrl-names = "default", "default";
|
||||
+ pinctrl-0 = <&mmc0_pins_a>;
|
||||
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
|
||||
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
index 454077a..a8e0df3 100644
|
||||
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
|
||||
@@ -338,6 +338,46 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c0f000 0x1000>;
|
||||
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <32>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc1: mmc@01c10000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c10000 0x1000>;
|
||||
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <33>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc2: mmc@01c11000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c11000 0x1000>;
|
||||
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <34>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc3: mmc@01c12000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c12000 0x1000>;
|
||||
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <35>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
compatible = "allwinner,sun4i-a10-ahci";
|
||||
reg = <0x01c18000 0x1000>;
|
||||
@@ -416,6 +456,20 @@
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ mmc0_pins_a: mmc0@0 {
|
||||
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
|
||||
+ allwinner,function = "mmc0";
|
||||
+ allwinner,drive = <3>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
|
||||
+ allwinner,pins = "PH1";
|
||||
+ allwinner,function = "gpio_in";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <1>;
|
||||
+ };
|
||||
};
|
||||
|
||||
timer@01c20c00 {
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -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>;
|
|
@ -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";
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
From 875bbd46c296e4b9ed130848bc64be5cf39669c8 Mon Sep 17 00:00:00 2001
|
||||
From: arokux <arokux@gmail.com>
|
||||
Date: Wed, 18 Sep 2013 22:45:06 +0200
|
||||
Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to Cubieboard-A10
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
---
|
||||
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 46 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 46 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
|
||||
@@ -77,6 +77,20 @@
|
||||
allwinner,drive = <1>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH6";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
@@ -96,6 +110,16 @@
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ ehci0: ehci0@0x01c14000 {
|
||||
+ vbus-supply = <®_usb1_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: ehci1@0x01c1c000 {
|
||||
+ vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
leds {
|
||||
@@ -128,5 +152,27 @@
|
||||
gpio = <&pio 1 8 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb1_vbus_pin>;
|
||||
+ regulator-name = "usb1-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 6 0>;
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb2_vbus_pin>;
|
||||
+ regulator-name = "usb2-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 3 0>;
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -0,0 +1,160 @@
|
|||
From a3bddfdd19c49f0bde7aa2ff496773c575763d07 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <david.lanzendoerfer@o2s.ch>
|
||||
Date: Sat, 15 Feb 2014 14:02:01 +0100
|
||||
Subject: [PATCH] ARM: dts: sun7i: Add support for mmc
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 8 ++++
|
||||
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 8 ++++
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 23 ++++++++++
|
||||
arch/arm/boot/dts/sun7i-a20.dtsi | 61 +++++++++++++++++++++++++
|
||||
4 files changed, 100 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
index 07823c2..a8186f5 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
@@ -20,6 +20,14 @@
|
||||
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ pinctrl-names = "default", "default";
|
||||
+ pinctrl-0 = <&mmc0_pins_a>;
|
||||
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
|
||||
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
index 403bd2e..6cd7cca 100644
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
index d5c6799..d4e2355 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
@@ -20,12 +20,35 @@
|
||||
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
|
||||
|
||||
soc@01c00000 {
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ pinctrl-names = "default", "default";
|
||||
+ pinctrl-0 = <&mmc0_pins_a>;
|
||||
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
|
||||
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ mmc3: mmc@01c12000 {
|
||||
+ pinctrl-names = "default", "default";
|
||||
+ pinctrl-0 = <&mmc3_pins_a>;
|
||||
+ pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
|
||||
+ cd-gpios = <&pio 7 11 0>; /* PH11 */
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinctrl@01c20800 {
|
||||
+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
|
||||
+ allwinner,pins = "PH11";
|
||||
+ allwinner,function = "gpio_in";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <1>;
|
||||
+ };
|
||||
+
|
||||
led_pins_olinuxino: led_pins@0 {
|
||||
allwinner,pins = "PH2";
|
||||
allwinner,function = "gpio_out";
|
||||
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
index 3385994..3bc6ac5 100644
|
||||
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
|
||||
@@ -392,6 +392,46 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
+ mmc0: mmc@01c0f000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c0f000 0x1000>;
|
||||
+ clocks = <&ahb_gates 8>, <&mmc0_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <0 32 4>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc1: mmc@01c10000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c10000 0x1000>;
|
||||
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <0 33 4>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc2: mmc@01c11000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c11000 0x1000>;
|
||||
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <0 34 4>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
+ mmc3: mmc@01c12000 {
|
||||
+ compatible = "allwinner,sun5i-a13-mmc";
|
||||
+ reg = <0x01c12000 0x1000>;
|
||||
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
|
||||
+ clock-names = "ahb", "mod";
|
||||
+ interrupts = <0 35 4>;
|
||||
+ bus-width = <4>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
compatible = "allwinner,sun4i-a10-ahci";
|
||||
reg = <0x01c18000 0x1000>;
|
||||
@@ -510,6 +550,27 @@
|
||||
allwinner,drive = <3>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ mmc0_pins_a: mmc0@0 {
|
||||
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
|
||||
+ allwinner,function = "mmc0";
|
||||
+ allwinner,drive = <3>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
|
||||
+ allwinner,pins = "PH1";
|
||||
+ allwinner,function = "gpio_in";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <1>;
|
||||
+ };
|
||||
+
|
||||
+ mmc3_pins_a: mmc3@0 {
|
||||
+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
|
||||
+ allwinner,function = "mmc3";
|
||||
+ allwinner,drive = <3>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
};
|
||||
|
||||
timer@01c20c00 {
|
||||
--
|
||||
1.8.5.5
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
From 9a86b6c16abc11b1090fbf4e102b4eed1d474d96 Mon Sep 17 00:00:00 2001
|
||||
From: arokux <arokux@gmail.com>
|
||||
Date: Wed, 18 Sep 2013 00:30:40 +0200
|
||||
Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to the Mele A1000
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun4i-a10-a1000.dts | 46 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 46 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
||||
@@ -73,6 +73,20 @@
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH6";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
@@ -86,6 +100,16 @@
|
||||
pinctrl-0 = <&i2c0_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ ehci0: ehci0@0x01c14000 {
|
||||
+ vbus-supply = <®_usb1_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: ehci1@0x01c1c000 {
|
||||
+ vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
leds {
|
||||
@@ -117,5 +141,27 @@
|
||||
enable-active-high;
|
||||
gpio = <&pio 7 15 0>;
|
||||
};
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb1_vbus_pin>;
|
||||
+ regulator-name = "usb1-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 6 0>;
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb2_vbus_pin>;
|
||||
+ regulator-name = "usb2-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 3 0>;
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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";
|
|
@ -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";
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -1,80 +0,0 @@
|
|||
From 8ba068f40cce9612d2ac0879b6978274ab497d31 Mon Sep 17 00:00:00 2001
|
||||
From: arokux <arokux@gmail.com>
|
||||
Date: Thu, 19 Sep 2013 21:29:45 +0200
|
||||
Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings for Cubieboard2
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 45 +++++++++++++++++++++++++++++
|
||||
1 file changed, 45 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
|
||||
@@ -69,6 +69,20 @@
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH6";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
@@ -86,6 +100,15 @@
|
||||
i2c1: i2c@01c2b000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
+ };
|
||||
+
|
||||
+ ehci0: ehci0@0x01c14000 {
|
||||
+ vbus-supply = <®_usb1_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: ehci1@0x01c1c000 {
|
||||
+ vbus-supply = <®_usb2_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
@@ -119,5 +142,27 @@
|
||||
gpio = <&pio 1 8 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb1_vbus_pin>;
|
||||
+ regulator-name = "usb1-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 6 0>;
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb2_vbus_pin>;
|
||||
+ regulator-name = "usb2-vbus";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 3 0>;
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -1,86 +0,0 @@
|
|||
From 5031cb9d88fe9ea4a37fe342ec5f8e2f0f930e00 Mon Sep 17 00:00:00 2001
|
||||
From: Zalan Blenessy <zalan.blenessy@gmail.com>
|
||||
Date: Sun, 22 Dec 2013 17:08:10 +0100
|
||||
Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to Olinuxino A20 Micro dts
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 47 +++++++++++++++++++++++++
|
||||
1 file changed, 47 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
|
||||
@@ -85,6 +85,20 @@
|
||||
allwinner,drive = <1>;
|
||||
allwinner,pull = <0>;
|
||||
};
|
||||
+
|
||||
+ usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH6";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
@@ -122,6 +136,16 @@
|
||||
pinctrl-0 = <&i2c2_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+ ehci0: ehci0@0x01c14000 {
|
||||
+ vbus-supply = <®_usb1_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: ehci1@0x01c1c000 {
|
||||
+ vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
leds {
|
||||
@@ -138,6 +162,7 @@
|
||||
|
||||
regulators {
|
||||
compatible = "simple-bus";
|
||||
+ pinctrl-names = "default";
|
||||
|
||||
reg_ahci_5v: ahci-5v {
|
||||
compatible = "regulator-fixed";
|
||||
@@ -148,5 +173,27 @@
|
||||
gpio = <&pio 1 8 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb1_vbus_pin>;
|
||||
+ regulator-name = "usb1-vbus";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 6 0>;
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb2_vbus_pin>;
|
||||
+ regulator-name = "usb2-vbus";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 3 0>;
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -1,83 +0,0 @@
|
|||
From 90cab9a5e7c43bfbda25dd114a838f4e4b50b6ff Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 17 Dec 2013 23:04:57 +0100
|
||||
Subject: [PATCH] ARM: dts: sun7i: Add ehci nodes to cubietruck dts
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 46 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 46 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
|
||||
@@ -43,11 +43,21 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ ehci0: ehci0@0x01c14000 {
|
||||
+ vbus-supply = <®_usb1_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
sata: ahci@01c18000 {
|
||||
pwr-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ ehci1: ehci1@0x01c1c000 {
|
||||
+ vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
mmc0_cd_pin_cubietruck: mmc0_cd_pin@0 {
|
||||
allwinner,pins = "PH1";
|
||||
@@ -90,6 +100,20 @@
|
||||
allwinner,drive = <0>;
|
||||
allwinner,pull = <2>;
|
||||
};
|
||||
+
|
||||
+ usb1_vbus_pin: usb1_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH6";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
+
|
||||
+ usb2_vbus_pin: usb2_vbus_pin@0 {
|
||||
+ allwinner,pins = "PH3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <2>;
|
||||
+ };
|
||||
};
|
||||
|
||||
uart0: serial@01c28000 {
|
||||
@@ -175,5 +199,27 @@
|
||||
gpio = <&pio 7 12 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb1_vbus_pin>;
|
||||
+ regulator-name = "usb1-vbus";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 6 0>;
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&usb2_vbus_pin>;
|
||||
+ regulator-name = "usb2-vbus";
|
||||
+ regulator-min-microvolt = <5000000>;
|
||||
+ regulator-max-microvolt = <5000000>;
|
||||
+ enable-active-high;
|
||||
+ gpio = <&pio 7 3 0>;
|
||||
+ };
|
||||
};
|
||||
};
|
|
@ -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>;
|
|
@ -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
Loading…
Reference in New Issue