sunxi: drop 3.14 support

Signed-off-by: John Crispin <blogic@openwrt.org>

SVN-Revision: 44824
This commit is contained in:
John Crispin 2015-03-16 07:41:24 +00:00
parent eb396d6569
commit c0a15a57bd
128 changed files with 0 additions and 19237 deletions

View file

@ -1,465 +0,0 @@
CONFIG_AHCI_SUNXI=y
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAS_RESET_CONTROLLER=y
CONFIG_ARCH_HAS_TICK_BROADCAST=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MULTIPLATFORM=y
# CONFIG_ARCH_MULTI_CPU_AUTO is not set
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_NR_GPIO=288
CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_ARM=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
# CONFIG_ARM_CPU_SUSPEND is not set
CONFIG_ARM_ERRATA_430973=y
CONFIG_ARM_ERRATA_720789=y
CONFIG_ARM_ERRATA_754322=y
CONFIG_ARM_ERRATA_775420=y
CONFIG_ARM_GIC=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
# CONFIG_ARM_LPAE is not set
CONFIG_ARM_NR_BANKS=8
CONFIG_ARM_PATCH_PHYS_VIRT=y
CONFIG_ARM_PSCI=y
CONFIG_ARM_THUMB=y
# CONFIG_ARM_THUMBEE is not set
CONFIG_ARM_VIRT_EXT=y
CONFIG_ATA=y
CONFIG_ATAGS=y
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_AUDIT_GENERIC=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_AVERAGE=y
CONFIG_BINFMT_MISC=y
CONFIG_BLK_CGROUP=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_BOUNCE=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CFQ_GROUP_IOSCHED=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_FREEZER=y
# CONFIG_CGROUP_NET_CLASSID is not set
# CONFIG_CGROUP_PERF is not set
# CONFIG_CGROUP_SCHED is not set
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLKSRC_OF=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE="console=ttyS0,115200 earlyprintk rootwait root=/dev/mmcblk0p2"
CONFIG_CMDLINE_FORCE=y
CONFIG_COMMON_CLK=y
CONFIG_COMPACTION=y
CONFIG_CONFIGFS_FS=y
CONFIG_CONNECTOR=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_COREDUMP=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_CPUSETS=y
CONFIG_CPU_32v6K=y
CONFIG_CPU_32v7=y
CONFIG_CPU_ABRT_EV7=y
# CONFIG_CPU_BPREDICT_DISABLE is not set
CONFIG_CPU_CACHE_V7=y
CONFIG_CPU_CACHE_VIPT=y
CONFIG_CPU_COPY_V6=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
CONFIG_CPU_HAS_ASID=y
# CONFIG_CPU_ICACHE_DISABLE is not set
CONFIG_CPU_PABRT_V7=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_TLB_V7=y
CONFIG_CPU_V7=y
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_DEV_SUNXI_SS=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_DCACHE_WORD_ACCESS=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_UART_8250 is not set
# CONFIG_DEBUG_UART_PL01X is not set
# CONFIG_DEBUG_USER is not set
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_DIRECT_IO=y
CONFIG_DMADEVICES=y
CONFIG_DMA_OF=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DWMAC_SUNXI=y
# CONFIG_DW_DMAC_CORE is not set
CONFIG_DYNAMIC_DEBUG=y
# CONFIG_EEPROM_SUNXI_SID is not set
CONFIG_ELF_CORE=y
# CONFIG_EMBEDDED is not set
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_EXPERT is not set
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_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_ARM_ARCH_TIMER=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_BPF_JIT=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_PROC_CPU=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_SMP=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_UID16=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HIGHMEM=y
# CONFIG_HIGHPTE is not set
CONFIG_HWMON=y
CONFIG_HW_CONSOLE=y
CONFIG_HZ_FIXED=0
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_MUX=y
# CONFIG_I2C_MUX_GPIO is not set
# CONFIG_I2C_MUX_PCA9541 is not set
# CONFIG_I2C_MUX_PCA954x is not set
CONFIG_I2C_MUX_PINCTRL=y
CONFIG_I2C_MV64XXX=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
CONFIG_INPUT_AXP20X_PEK=y
CONFIG_INPUT_KEYBOARD=y
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_IOMMU_HELPER=y
CONFIG_IOSCHED_CFQ=y
CONFIG_IPC_NS=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_BOOTP is not set
CONFIG_IP_PNP_DHCP=y
# CONFIG_IP_PNP_RARP is not set
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_KALLSYMS=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
CONFIG_KEYBOARD_SUN4I_LRADC=y
CONFIG_KSM=y
CONFIG_KTIME_SCALAR=y
CONFIG_LEDS_GPIO=y
# CONFIG_LEDS_REGULATOR is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_LOG_BUF_SHIFT=19
CONFIG_LZ4_DECOMPRESS=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_MDIO_BOARDINFO=y
CONFIG_MDIO_SUN4I=y
# CONFIG_MEMCG is not set
CONFIG_MFD_AXP20X=y
CONFIG_MFD_CORE=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_SUNXI=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MULTI_IRQ_HANDLER=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
CONFIG_NEED_DMA_MAP_STATE=y
# CONFIG_NEON is not set
# CONFIG_NET_CLS_CGROUP is not set
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_NS=y
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_NET_VENDOR_ALLWINNER=y
CONFIG_NLS=y
CONFIG_NO_BOOTMEM=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
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
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PAGE_OFFSET=0xC0000000
# CONFIG_PARTITION_ADVANCED is not set
# CONFIG_PCI_SYSCALL is not set
CONFIG_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PID_NS=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PINCTRL_SUNXI=y
CONFIG_PM=y
CONFIG_PM_CLK=y
# CONFIG_PM_DEBUG is not set
CONFIG_PM_RUNTIME=y
CONFIG_POWER_SUPPLY=y
CONFIG_PPS=y
CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_RCU=y
CONFIG_PRINTK_TIME=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_PROC_EVENTS=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PWM=y
CONFIG_PWM_SUNXI=y
CONFIG_PWM_SYSFS=y
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTA=y
CONFIG_QUOTACTL=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_RCU_BOOST is not set
CONFIG_RCU_CPU_STALL_VERBOSE=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RD_BZIP2=y
CONFIG_RD_GZIP=y
CONFIG_RD_LZ4=y
CONFIG_RD_LZMA=y
CONFIG_RD_LZO=y
CONFIG_RD_XZ=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_AXP20X=y
# CONFIG_REGULATOR_DEBUG is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
CONFIG_RELAY=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESOURCE_COUNTERS=y
# CONFIG_RFKILL_REGULATOR is not set
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SCHED_HRTICK=y
CONFIG_SCSI=y
CONFIG_SECURITYFS=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=8
CONFIG_SERIAL_8250_SYSRQ=y
CONFIG_SERIO=y
# CONFIG_SERIO_APBPS2 is not set
# CONFIG_SERIO_OLPC_APSP is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLUB_DEBUG_ON is not set
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=y
# CONFIG_STAGING is not set
# CONFIG_STMMAC_DA is not set
# CONFIG_STMMAC_DEBUG_FS is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
CONFIG_STOP_MACHINE=y
CONFIG_STRICT_DEVMEM=y
# CONFIG_SUN4I_EMAC is not set
CONFIG_SUN4I_TIMER=y
CONFIG_SUN5I_HSTIMER=y
CONFIG_SUNXI_WATCHDOG=y
CONFIG_SWIOTLB=y
CONFIG_SWP_EMULATE=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_TASK_XACCT=y
# CONFIG_TCP_CONG_ADVANCED is not set
# CONFIG_THUMB2_KERNEL is not set
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_TOUCHSCREEN_BU21013 is not set
# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set
# CONFIG_TOUCHSCREEN_DYNAPRO is not set
# CONFIG_TOUCHSCREEN_EGALAX is not set
# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
# CONFIG_TOUCHSCREEN_MAX11801 is not set
# CONFIG_TOUCHSCREEN_PIXCIR is not set
# CONFIG_TOUCHSCREEN_ST1232 is not set
CONFIG_TOUCHSCREEN_SUN4I=y
# CONFIG_TOUCHSCREEN_TSC2005 is not set
# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
CONFIG_TREE_PREEMPT_RCU=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UID16=y
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_COMMON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_SUPPORT=y
# CONFIG_USER_NS is not set
CONFIG_USE_OF=y
CONFIG_UTS_NS=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_VFP=y
CONFIG_VFPv3=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_XEN is not set
CONFIG_XFRM_ALGO=y
CONFIG_XFRM_USER=y
CONFIG_XPS=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZBOOT_ROM_BSS=0
CONFIG_ZBOOT_ROM_TEXT=0
# CONFIG_ZBUD is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA_FLAG=0

View file

@ -1,28 +0,0 @@
From b25983b215e889447ae670a158b1af5e7f253091 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Thu, 2 Jan 2014 22:05:04 +0100
Subject: [PATCH] ARM: sun4i: a10: Add missing serial aliases
Some UART aliases have been defined, but not all of them. Add the remaining
ones to be consistent and to ease the parsing of the DT by the bootloaders.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -19,6 +19,12 @@
ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ serial6 = &uart6;
+ serial7 = &uart7;
};
cpus {

View file

@ -1,32 +0,0 @@
From b6e3460ee25b8af673d00df0435a304f5dbf7c40 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Thu, 2 Jan 2014 22:05:04 +0100
Subject: [PATCH] ARM: sun6i: Add missing serial aliases
Some UART aliases have been defined, but not all of them. Add the remaining
ones to be consistent and to ease the parsing of the DT by the bootloaders.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -16,6 +16,16 @@
/ {
interrupt-parent = <&gic>;
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ };
+
+
cpus {
#address-cells = <1>;
#size-cells = <0>;

View file

@ -1,30 +0,0 @@
From 1070f51b55d11e8831317d718acf2af46a181311 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Thu, 2 Jan 2014 22:05:04 +0100
Subject: [PATCH] ARM: sun7i: Add missing serial aliases
Some UART aliases have been defined, but not all of them. Add the remaining
ones to be consistent and to ease the parsing of the DT by the bootloaders.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/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
@@ -18,6 +18,14 @@
aliases {
ethernet0 = &emac;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ serial6 = &uart6;
+ serial7 = &uart7;
};
cpus {

View file

@ -1,27 +0,0 @@
From 0ffac463caf4b0022cf0d917552d51b3ec82849a Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Mon, 13 Jan 2014 11:08:47 +0100
Subject: [PATCH] ARM: sun5i: a13: Add missing serial aliases
Some UART aliases have been defined, but not all of them. Add the remaining
ones to be consistent and to ease the parsing of the DT by the bootloaders.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -16,6 +16,11 @@
/ {
interrupt-parent = <&intc>;
+ aliases {
+ serial0 = &uart1;
+ serial1 = &uart3;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;

View file

@ -1,30 +0,0 @@
From 875f2d579db0c3ea113f6367af9ccb32b3dbebcc Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 14 Jan 2014 22:49:50 +0800
Subject: [PATCH] ARM: dts: sun7i: add pin muxing options for UART2
UART2 is used on CubieTruck to connect to the Bluetooth module.
Add the pin set used in this case.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -381,6 +381,13 @@
allwinner,pull = <0>;
};
+ uart2_pins_a: uart2@0 {
+ allwinner,pins = "PI16", "PI17", "PI18", "PI19";
+ allwinner,function = "uart2";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
uart6_pins_a: uart6@0 {
allwinner,pins = "PI12", "PI13";
allwinner,function = "uart6";

View file

@ -1,78 +0,0 @@
From 2fc6dcd5e7c76c203d2e174e70ef21393a231163 Mon Sep 17 00:00:00 2001
From: Zoltan HERPAI <wigyori@uid0.hu>
Date: Mon, 13 Jan 2014 14:15:01 +0100
Subject: [PATCH] ARM: sun4i: dt: Add basic board support for LinkSprite
pcDuino
This patch will add a basic board support DT for the
LinkSprite pcDuino board.
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/sun4i-a10-pcduino.dts | 48 +++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
create mode 100644 arch/arm/boot/dts/sun4i-a10-pcduino.dts
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -284,6 +284,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
sun4i-a10-cubieboard.dtb \
sun4i-a10-mini-xplus.dtb \
sun4i-a10-hackberry.dtb \
+ sun4i-a10-pcduino.dtb \
sun5i-a10s-olinuxino-micro.dtb \
sun5i-a13-olinuxino.dtb \
sun5i-a13-olinuxino-micro.dtb \
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 Zoltan HERPAI
+ * Zoltan HERPAI <wigyori@uid0.hu>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+
+/ {
+ model = "LinkSprite pcDuino";
+ compatible = "linksprite,a10-pcduino", "allwinner,sun4i-a10";
+
+ soc@01c00000 {
+ emac: ethernet@01c0b000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_pins_a>;
+ phy = <&phy1>;
+ status = "okay";
+ };
+
+ mdio@01c0b080 {
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+ };
+ };
+};

View file

@ -1,31 +0,0 @@
From 0f9bb2cf6171f47d932df46e34cc5cfce384ff3d Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Tue, 18 Feb 2014 14:04:44 +0000
Subject: [PATCH] ARM: sun7i: add arch timer node
The Allwinner A20 SoC is built around a pair of Cortex-A7 cores,
which have the usual generic timers. Report this in the DT.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.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
@@ -49,6 +49,14 @@
reg = <0x40000000 0x80000000>;
};
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>,
+ <1 11 0xf08>,
+ <1 10 0xf08>;
+ };
+
clocks {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -1,141 +0,0 @@
From a1c70ed831e4d5356618834202b0da3aa34e218e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 10 Jan 2014 23:23:06 +0100
Subject: [PATCH] ARM: sun4i: dt: Add support for the A10-OLinuXino-LIME board
This add support for the A10-OLinuXino-LIME:
https://www.olimex.com/Products/OLinuXino/A10/A10-OLinuXino-LIME
A low cost Allwinner A10 based dev-board, with sata, ethernet, hdmi and 2x USB.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 111 +++++++++++++++++++++++++
2 files changed, 112 insertions(+)
create mode 100644 arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -284,6 +284,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
sun4i-a10-cubieboard.dtb \
sun4i-a10-mini-xplus.dtb \
sun4i-a10-hackberry.dtb \
+ sun4i-a10-olinuxino-lime.dtb \
sun4i-a10-pcduino.dtb \
sun5i-a10s-olinuxino-micro.dtb \
sun5i-a13-olinuxino.dtb \
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.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>;
+ };
+ };
+
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
+ pinctrl@01c20800 {
+ ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 {
+ allwinner,pins = "PC3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ led_pins_olinuxinolime: led_pins@0 {
+ allwinner,pins = "PH2";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <1>;
+ allwinner,pull = <0>;
+ };
+ };
+
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins_olinuxinolime>;
+
+ green {
+ label = "a10-olinuxino-lime:green:usr";
+ gpios = <&pio 7 2 0>;
+ default-state = "on";
+ };
+ };
+
+ reg_ahci_5v: ahci-5v {
+ pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>;
+ gpio = <&pio 2 3 0>;
+ status = "okay";
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
+};

View file

@ -1,77 +0,0 @@
From 7f94ebf35b017f1664e957857a7f36752e2577cd Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Wed, 5 Feb 2014 14:05:04 +0100
Subject: [PATCH] ARM: sun6i: dt: Add PLL6 and SPI module clocks
The module clocks in the A31 are still compatible with the A10 one. Add the SPI
module clocks and the PLL6 in the device tree to allow their use by the SPI
controllers.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 46 ++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 9 deletions(-)
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -83,16 +83,12 @@
clocks = <&osc24M>;
};
- /*
- * This is a dummy clock, to be used as placeholder on
- * other mux clocks when a specific parent clock is not
- * yet implemented. It should be dropped when the driver
- * is complete.
- */
- pll6: pll6 {
+ pll6: clk@01c20028 {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ compatible = "allwinner,sun6i-a31-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6";
};
cpu: cpu@01c20050 {
@@ -192,6 +188,38 @@
"apb2_uart1", "apb2_uart2", "apb2_uart3",
"apb2_uart4", "apb2_uart5";
};
+
+ spi0_clk: clk@01c200a0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a0 0x4>;
+ clocks = <&osc24M>, <&pll6>;
+ clock-output-names = "spi0";
+ };
+
+ spi1_clk: clk@01c200a4 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a4 0x4>;
+ clocks = <&osc24M>, <&pll6>;
+ clock-output-names = "spi1";
+ };
+
+ spi2_clk: clk@01c200a8 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200a8 0x4>;
+ clocks = <&osc24M>, <&pll6>;
+ clock-output-names = "spi2";
+ };
+
+ spi3_clk: clk@01c200ac {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-mod0-clk";
+ reg = <0x01c200ac 0x4>;
+ clocks = <&osc24M>, <&pll6>;
+ clock-output-names = "spi3";
+ };
};
soc@01c00000 {

View file

@ -1,134 +0,0 @@
From 35b7dfc295f4d6079572a22a225c7444134e1f72 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(-)
--- 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>;

View file

@ -1,254 +0,0 @@
From 266f79cef78cdf3545065a4786506eee0ae012b3 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(-)
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -47,34 +47,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>;
@@ -82,7 +86,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>;
@@ -96,6 +100,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -103,9 +108,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>;
@@ -118,9 +124,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>;
@@ -139,9 +146,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>;
@@ -155,6 +163,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -162,9 +171,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>;
--- 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>;

View file

@ -1,107 +0,0 @@
From 8bd1bb3a670aae791c4b2e9ab13c92768233368a 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(-)
--- 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>;

View file

@ -1,127 +0,0 @@
From c57b781689bba48dad635caf005962cc9c8e5e3d 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(-)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -62,11 +62,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 {
@@ -76,21 +77,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>;
@@ -98,7 +101,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>;
@@ -111,6 +114,7 @@
compatible = "allwinner,sun4i-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>;
+ clock-output-names = "cpu";
};
axi: axi@01c20054 {
@@ -118,6 +122,7 @@
compatible = "allwinner,sun4i-axi-clk";
reg = <0x01c20054 0x4>;
clocks = <&cpu>;
+ clock-output-names = "axi";
};
ahb: ahb@01c20054 {
@@ -125,9 +130,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>;
@@ -152,9 +158,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>;
@@ -170,6 +177,7 @@
compatible = "allwinner,sun4i-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+ clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
@@ -177,9 +185,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>;

View file

@ -1,51 +0,0 @@
From 95c1fe603fbea0fd01d98262bd5ff7d5442a86db Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Mon, 24 Feb 2014 17:29:06 +0100
Subject: [PATCH] ARM: sun6i: dt: Fix mod0 compatible
The module 0 clock compatibles were changed between the time the patch was sent
and it was merged. Update the compatibles.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -200,7 +200,7 @@
spi0_clk: clk@01c200a0 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-mod0-clk";
+ compatible = "allwinner,sun4i-a10-mod0-clk";
reg = <0x01c200a0 0x4>;
clocks = <&osc24M>, <&pll6>;
clock-output-names = "spi0";
@@ -208,7 +208,7 @@
spi1_clk: clk@01c200a4 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-mod0-clk";
+ compatible = "allwinner,sun4i-a10-mod0-clk";
reg = <0x01c200a4 0x4>;
clocks = <&osc24M>, <&pll6>;
clock-output-names = "spi1";
@@ -216,7 +216,7 @@
spi2_clk: clk@01c200a8 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-mod0-clk";
+ compatible = "allwinner,sun4i-a10-mod0-clk";
reg = <0x01c200a8 0x4>;
clocks = <&osc24M>, <&pll6>;
clock-output-names = "spi2";
@@ -224,7 +224,7 @@
spi3_clk: clk@01c200ac {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-mod0-clk";
+ compatible = "allwinner,sun4i-a10-mod0-clk";
reg = <0x01c200ac 0x4>;
clocks = <&osc24M>, <&pll6>;
clock-output-names = "spi3";

View file

@ -1,23 +0,0 @@
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -26,6 +26,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 {

View file

@ -1,51 +0,0 @@
From 3e1660161aacc5aeeebb09a0c8d91ad01399e5cd 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(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -330,6 +330,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 {

View file

@ -1,34 +0,0 @@
From 22b9ac16c600694b12479a75461bce031295e4b9 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(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -653,6 +653,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>;

View file

@ -1,48 +0,0 @@
From 9f6deb688f4cb733cd3f36e0cc88f14d2f81982d Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:50 +0800
Subject: [PATCH] ARM: dts: sun7i: Add pin muxing options for the GMAC
The A20 has EMAC and GMAC muxed on the same pins.
Add pin sets with gmac function for MII and RGMII mode to the DTSI.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -492,6 +492,32 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ gmac_pins_mii_a: gmac_mii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA9", "PA10",
+ "PA11", "PA12", "PA13", "PA14",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ gmac_pins_rgmii_a: gmac_rgmii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2",
+ "PA3", "PA4", "PA5", "PA6",
+ "PA7", "PA8", "PA10",
+ "PA11", "PA12", "PA13",
+ "PA15", "PA16";
+ allwinner,function = "gmac";
+ /*
+ * data lines in RGMII mode use DDR mode
+ * and need a higher signal drive strength
+ */
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -1,33 +0,0 @@
From d09483e1cfcc00be70450c469c3c23496a063d98 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(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -65,6 +65,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 {

View file

@ -1,56 +0,0 @@
From 856cae07bff4d7e7a111affd4f15803142d29880 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:52 +0800
Subject: [PATCH] ARM: dts: sun7i: cubieboard2: Enable GMAC instead of EMAC
GMAC has better performance and fewer hardware issues.
Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -19,21 +19,6 @@
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
soc@01c00000 {
- emac: ethernet@01c0b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&emac_pins_a>;
- phy = <&phy1>;
- status = "okay";
- };
-
- mdio@01c0b080 {
- status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
- };
-
pinctrl@01c20800 {
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -60,6 +45,18 @@
pinctrl-0 = <&i2c1_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_mii_a>;
+ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
leds {

View file

@ -1,57 +0,0 @@
From f5b426a2eb246e91eb2de0cd215565d38d1d5ce7 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:53 +0800
Subject: [PATCH] ARM: dts: sun7i: a20-olinuxino-micro: Enable GMAC instead of
EMAC
GMAC has better performance and fewer hardware issues.
Use the GMAC in MII mode for ethernet instead of the EMAC.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 27 +++++++++++--------------
1 file changed, 12 insertions(+), 15 deletions(-)
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -19,21 +19,6 @@
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
soc@01c00000 {
- emac: ethernet@01c0b000 {
- pinctrl-names = "default";
- pinctrl-0 = <&emac_pins_a>;
- phy = <&phy1>;
- status = "okay";
- };
-
- mdio@01c0b080 {
- status = "okay";
-
- phy1: ethernet-phy@1 {
- reg = <1>;
- };
- };
-
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
@@ -78,6 +63,18 @@
pinctrl-0 = <&i2c2_pins_a>;
status = "okay";
};
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_mii_a>;
+ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
leds {

View file

@ -1,26 +0,0 @@
From 614b4b996be81daca9d8333e1ac163d23e1701c4 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:54 +0800
Subject: [PATCH] ARM: dts: sun7i: Add ethernet alias for GMAC
All Allwinner A20 boards we support can only use either EMAC or GMAC,
as they share the same pins. As we have switched all supported to
GMAC, we should alias GMAC (the active controller) as ethernet0,
so u-boot will insert the MAC address for the correct controller.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -17,7 +17,7 @@
interrupt-parent = <&gic>;
aliases {
- ethernet0 = &emac;
+ ethernet0 = &gmac;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;

View file

@ -1,30 +0,0 @@
From b5325f9813a6a7cf80ede22fbee66376abbe2384 Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Fri, 7 Feb 2014 16:21:51 +0100
Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -315,6 +315,15 @@
clock-output-names = "ir1";
};
+ usb_clk: clk@01c200cc {
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ compatible = "allwinner,sun4i-a10-usb-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
+ };
+
spi3_clk: clk@01c200d4 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-mod0-clk";

View file

@ -1,49 +0,0 @@
From 5b08dd0d672b59fff16d02239ca6a36aaecdb1ca Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Fri, 7 Feb 2014 16:21:52 +0100
Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB clocks
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 9 +++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 9 +++++++++
2 files changed, 18 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -272,6 +272,15 @@
clock-output-names = "ir0";
};
+ usb_clk: clk@01c200cc {
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ compatible = "allwinner,sun5i-a13-usb-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_phy";
+ };
+
mbus_clk: clk@01c2015c {
#clock-cells = <0>;
compatible = "allwinner,sun4i-mod0-clk";
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -274,6 +274,15 @@
clock-output-names = "ir0";
};
+ usb_clk: clk@01c200cc {
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ compatible = "allwinner,sun5i-a13-usb-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_phy";
+ };
+
mbus_clk: clk@01c2015c {
#clock-cells = <0>;
compatible = "allwinner,sun4i-mod0-clk";

View file

@ -1,30 +0,0 @@
From 25a1ac92997df2b1e2c76a374d444605cbc96a9f Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Fri, 7 Feb 2014 16:21:53 +0100
Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -313,6 +313,15 @@
clock-output-names = "ir1";
};
+ usb_clk: clk@01c200cc {
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ compatible = "allwinner,sun4i-a10-usb-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&pll6 1>;
+ clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
+ };
+
spi3_clk: clk@01c200d4 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-mod0-clk";

View file

@ -1,78 +0,0 @@
From 68a7d9940935cb71440a9ff384e5859592b0dbfd 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] 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:
http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/pinctrl/pinctrl-sunxi-pins.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/pinctrl/pinctrl-sunxi-pins.h
+++ b/drivers/pinctrl/pinctrl-sunxi-pins.h
@@ -1932,27 +1932,27 @@ static const struct sunxi_desc_pin sun5i
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* D1 */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* D0 */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* CLK */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* CMD */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* D3 */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x4, "mmc0")), /* D2 */
+ SUNXI_FUNCTION(0x2, "mmc0")), /* D2 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
SUNXI_FUNCTION(0x0, "gpio_in"),
--- 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/irqchip/chained_irq.h>
#include <linux/module.h>
@@ -670,6 +671,8 @@ static void sunxi_pinctrl_irq_handler(un
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);
@@ -683,6 +686,7 @@ static void sunxi_pinctrl_irq_handler(un
}
chained_irq_exit(chip, desc);
}
+ chained_irq_exit(chip, desc);
}
static struct of_device_id sunxi_pinctrl_match[] = {

View file

@ -1,217 +0,0 @@
From 843da234cfc0e7014f9e2da82786a485e0820665 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Thu, 13 Mar 2014 15:32:05 +0100
Subject: [PATCH] irq: Add a new IRQCHIP_EOI_THREADED flag
This flag must be used in combination with handle_fasteoi_irq, when set
handle_fasteoi_irq will delay the calling of chip->irq_eoi until the threaded
handler has run.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
include/linux/irq.h | 3 +++
kernel/irq/chip.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
kernel/irq/internals.h | 1 +
kernel/irq/manage.c | 2 +-
4 files changed, 45 insertions(+), 9 deletions(-)
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -349,6 +349,8 @@ struct irq_chip {
* IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
* when irq enabled
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
+ * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
+ * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
*/
enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
@@ -357,6 +359,7 @@ enum {
IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
IRQCHIP_SKIP_SET_WAKE = (1 << 4),
IRQCHIP_ONESHOT_SAFE = (1 << 5),
+ IRQCHIP_EOI_THREADED = (1 << 6),
};
/* This include will go away once we isolated irq_desc usage to core code */
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
}
}
+void unmask_threaded_irq(struct irq_desc *desc)
+{
+ struct irq_chip *chip = desc->irq_data.chip;
+
+ if (chip->flags & IRQCHIP_EOI_THREADED)
+ chip->irq_eoi(&desc->irq_data);
+
+ if (chip->irq_unmask) {
+ chip->irq_unmask(&desc->irq_data);
+ irq_state_clr_masked(desc);
+ }
+}
+
/*
* handle_nested_irq - Handle a nested irq from a irq thread
* @irq: the interrupt number
@@ -435,6 +448,27 @@ static inline void preflow_handler(struc
static inline void preflow_handler(struct irq_desc *desc) { }
#endif
+static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
+{
+ if (!(desc->istate & IRQS_ONESHOT)) {
+ chip->irq_eoi(&desc->irq_data);
+ return;
+ }
+ /*
+ * We need to unmask in the following cases:
+ * - Oneshot irq which did not wake the thread (caused by a
+ * spurious interrupt or a primary handler handling it
+ * completely).
+ */
+ if (!irqd_irq_disabled(&desc->irq_data) &&
+ irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
+ chip->irq_eoi(&desc->irq_data);
+ unmask_irq(desc);
+ } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
+ chip->irq_eoi(&desc->irq_data);
+ }
+}
+
/**
* handle_fasteoi_irq - irq handler for transparent controllers
* @irq: the interrupt number
@@ -448,6 +482,8 @@ static inline void preflow_handler(struc
void
handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
{
+ struct irq_chip *chip = desc->irq_data.chip;
+
raw_spin_lock(&desc->lock);
if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, str
preflow_handler(desc);
handle_irq_event(desc);
- if (desc->istate & IRQS_ONESHOT)
- cond_unmask_irq(desc);
+ cond_unmask_eoi_irq(desc, chip);
-out_eoi:
- desc->irq_data.chip->irq_eoi(&desc->irq_data);
-out_unlock:
raw_spin_unlock(&desc->lock);
return;
out:
- if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
- goto out_eoi;
- goto out_unlock;
+ if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
+ chip->irq_eoi(&desc->irq_data);
+ raw_spin_unlock(&desc->lock);
}
/**
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -73,6 +73,7 @@ extern void irq_percpu_enable(struct irq
extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
extern void mask_irq(struct irq_desc *desc);
extern void unmask_irq(struct irq_desc *desc);
+extern void unmask_threaded_irq(struct irq_desc *desc);
extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -713,7 +713,7 @@ again:
if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
irqd_irq_masked(&desc->irq_data))
- unmask_irq(desc);
+ unmask_threaded_irq(desc);
out_unlock:
raw_spin_unlock_irq(&desc->lock);
--- a/drivers/irqchip/irq-sun4i.c
+++ b/drivers/irqchip/irq-sun4i.c
@@ -41,13 +41,11 @@ static asmlinkage void __exception_irq_e
static void sun4i_irq_ack(struct irq_data *irqd)
{
unsigned int irq = irqd_to_hwirq(irqd);
- unsigned int irq_off = irq % 32;
- int reg = irq / 32;
- u32 val;
- val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
- writel(val | (1 << irq_off),
- sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
+ if (irq != 0)
+ return; /* Only IRQ 0 / the ENMI needs to be acked */
+
+ writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
}
static void sun4i_irq_mask(struct irq_data *irqd)
@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_
static struct irq_chip sun4i_irq_chip = {
.name = "sun4i_irq",
- .irq_ack = sun4i_irq_ack,
+ .irq_eoi = sun4i_irq_ack,
.irq_mask = sun4i_irq_mask,
.irq_unmask = sun4i_irq_unmask,
+ .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
};
static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
- irq_set_chip_and_handler(virq, &sun4i_irq_chip,
- handle_level_irq);
+ irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
return 0;
@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct d
writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
- /* Mask all the interrupts */
+ /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
@@ -140,10 +138,24 @@ static asmlinkage void __exception_irq_e
{
u32 irq, hwirq;
+ /*
+ * hwirq == 0 can mean one of 3 things:
+ * 1) no more irqs pending
+ * 2) irq 0 pending
+ * 3) spurious irq
+ * So if we immediately get a reading of 0, check the irq-pending reg
+ * to differentiate between 2 and 3. We only do this once to avoid
+ * the extra check in the common case of 1 hapening after having
+ * read the vector-reg once.
+ */
hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
- while (hwirq != 0) {
+ if (hwirq == 0 &&
+ !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
+ return;
+
+ do {
irq = irq_find_mapping(sun4i_irq_domain, hwirq);
handle_IRQ(irq, regs);
hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
- }
+ } while (hwirq != 0);
}

View file

@ -1,36 +0,0 @@
From 4c228d02d1339a286e259893062ea445be82b573 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 7 Jan 2014 18:56:29 +0800
Subject: [PATCH] pinctrl: sunxi: create irq/pin mapping during init
The irq/pin mapping is used to lookup the pin to mux to the irq
function when the irq is enabled. It is created when gpio_to_irq
is called. Creating the mapping during init allows us to map the
interrupts directly from the device tree.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/pinctrl/pinctrl-sunxi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -531,8 +531,6 @@ static int sunxi_pinctrl_gpio_to_irq(str
if (!desc)
return -EINVAL;
- pctl->irq_array[desc->irqnum] = offset;
-
dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
chip->label, offset + chip->base, desc->irqnum);
@@ -759,6 +757,9 @@ static int sunxi_pinctrl_build_state(str
struct sunxi_desc_function *func = pin->functions;
while (func->name) {
+ /* Create interrupt mapping while we're at it */
+ if (!strcmp(func->name, "irq"))
+ pctl->irq_array[func->irqnum] = pin->pin.number;
sunxi_pinctrl_add_function(pctl, func->name);
func++;
}

View file

@ -1,26 +0,0 @@
From 77f1265dd02dfd5dcaa0ebd6d3ea1d131bc095e2 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 7 Jan 2014 19:01:29 +0800
Subject: [PATCH] pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl
irq chip
The sunxi pinctrl irq chip driver does not support wakeup at the
moment. Adding IRQCHIP_SKIP_SET_WAKE lets the irqs work with drivers
using wakeup.
Also add a name to the irq chip.
---
drivers/pinctrl/pinctrl-sunxi.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -661,6 +661,8 @@ static struct irq_chip sunxi_pinctrl_irq
.irq_mask_ack = sunxi_pinctrl_irq_mask_ack,
.irq_unmask = sunxi_pinctrl_irq_unmask,
.irq_set_type = sunxi_pinctrl_irq_set_type,
+ .name = "sunxi-pio",
+ .flags = IRQCHIP_SKIP_SET_WAKE,
};
static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)

View file

@ -1,26 +0,0 @@
From eda34c0692e479dd9cd2b7cb70986ae57f15187f Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Tue, 7 Jan 2014 18:50:01 +0800
Subject: [PATCH] ARM: dts: sun7i: Add #interrupt-cells to pinctrl node
The pinctrl device is also an interrupt controller for external
interrupts. Add the missing #interrupt-cells property.
Also remove the unused #address-cells property.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -424,7 +424,7 @@
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;

View file

@ -1,97 +0,0 @@
From 6e763a8ebe7a16ae5635ade146fd2930749ed775 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 1 Mar 2014 14:57:56 +0100
Subject: [PATCH] ARM: sunxi: dt: Add sunxi-common-regulators include file
Most sunxi boards with a sata connector also have a gpio controlled connector
for sata target power and almost all sunxi boards have a gpio controlled vbus
for usb1 and usb2.
This commit adds an include file for the regulators representing these
supplies, avoiding the need to copy and paste the regulator code to allmost
all sunxi board dts files.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sunxi-common-regulators.dtsi | 75 ++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 arch/arm/boot/dts/sunxi-common-regulators.dtsi
--- /dev/null
+++ b/arch/arm/boot/dts/sunxi-common-regulators.dtsi
@@ -0,0 +1,75 @@
+/*
+ * sunxi boards common regulator (ahci target power supply, usb-vbus) 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>;
+ };
+
+ usb1_vbus_pin_a: usb1_vbus_pin@0 {
+ allwinner,pins = "PH6";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ usb2_vbus_pin_a: usb2_vbus_pin@0 {
+ allwinner,pins = "PH3";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+ };
+ };
+
+ reg_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>;
+ status = "disabled";
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb1_vbus_pin_a>;
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 6 0>;
+ status = "disabled";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_pin_a>;
+ regulator-name = "usb2-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&pio 7 3 0>;
+ status = "disabled";
+ };
+};

View file

@ -1,73 +0,0 @@
From c9bfaadf8973cb4d9074e80c4bf8708deca62712 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:54 +0100
Subject: [PATCH] ARM: dt: sun7i: Add A20 SPI controller nodes
The A20 has 4 SPI controllers compatible with the one found in the A10. Add
them in the DT.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -401,6 +401,28 @@
#size-cells = <1>;
ranges;
+ spi0: spi@01c05000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c05000 0x1000>;
+ interrupts = <0 10 4>;
+ clocks = <&ahb_gates 20>, <&spi0_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@01c06000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c06000 0x1000>;
+ interrupts = <0 11 4>;
+ clocks = <&ahb_gates 21>, <&spi1_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
emac: ethernet@01c0b000 {
compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>;
@@ -417,6 +439,28 @@
#size-cells = <0>;
};
+ spi2: spi@01c17000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c17000 0x1000>;
+ interrupts = <0 12 4>;
+ clocks = <&ahb_gates 22>, <&spi2_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi3: spi@01c1f000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c1f000 0x1000>;
+ interrupts = <0 50 4>;
+ clocks = <&ahb_gates 23>, <&spi3_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
pio: pinctrl@01c20800 {
compatible = "allwinner,sun7i-a20-pinctrl";
reg = <0x01c20800 0x400>;

View file

@ -1,72 +0,0 @@
From cac3c4d67c80c4895d0d44e609beb535d66af6a3 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:55 +0100
Subject: [PATCH] ARM: dt: sun4i: Add A10 SPI controller nodes
The A10 has 4 SPI controllers that are now supported. Add them in the DT.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -339,6 +339,28 @@
#size-cells = <1>;
ranges;
+ spi0: spi@01c05000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c05000 0x1000>;
+ interrupts = <10>;
+ clocks = <&ahb_gates 20>, <&spi0_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@01c06000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c06000 0x1000>;
+ interrupts = <11>;
+ clocks = <&ahb_gates 21>, <&spi1_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
emac: ethernet@01c0b000 {
compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>;
@@ -355,6 +377,28 @@
#size-cells = <0>;
};
+ spi2: spi@01c17000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c17000 0x1000>;
+ interrupts = <12>;
+ clocks = <&ahb_gates 22>, <&spi2_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi3: spi@01c1f000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c1f000 0x1000>;
+ interrupts = <50>;
+ clocks = <&ahb_gates 23>, <&spi3_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;

View file

@ -1,55 +0,0 @@
From aeb3b73fc416e14afd25f25e69f8713488edcc1b Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:57 +0100
Subject: [PATCH] ARM: dt: sun5i: Add A13 SPI controller nodes
The A13 has 3 SPI controllers compatible with the one found in the A10. Add
them in the DT.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -298,6 +298,39 @@
#size-cells = <1>;
ranges;
+ spi0: spi@01c05000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c05000 0x1000>;
+ interrupts = <10>;
+ clocks = <&ahb_gates 20>, <&spi0_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@01c06000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c06000 0x1000>;
+ interrupts = <11>;
+ clocks = <&ahb_gates 21>, <&spi1_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi2: spi@01c17000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c17000 0x1000>;
+ interrupts = <12>;
+ clocks = <&ahb_gates 22>, <&spi2_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic";
reg = <0x01c20400 0x400>;

View file

@ -1,559 +0,0 @@
From 86cb7c7ab176112f8b0031dc7c8d19103ba52277 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Wed, 5 Feb 2014 14:05:05 +0100
Subject: [PATCH] spi: sunxi: Add Allwinner A31 SPI controller driver
The Allwinner A31 has a new SPI controller IP compared to the older Allwinner
SoCs.
It supports DMA, but the driver only does PIO for now, and DMA will be
supported eventually.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../devicetree/bindings/spi/spi-sun6i.txt | 24 +
drivers/spi/Kconfig | 6 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-sun6i.c | 483 +++++++++++++++++++++
4 files changed, 514 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/spi-sun6i.txt
create mode 100644 drivers/spi/spi-sun6i.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -0,0 +1,24 @@
+Allwinner A31 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun6i-a31-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+ needed:
+ - "ahb": the gated AHB parent clock
+ - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset controller asserting this device in
+ reset
+
+Example:
+
+spi1: spi@01c69000 {
+ compatible = "allwinner,sun6i-a31-spi";
+ reg = <0x01c69000 0x1000>;
+ interrupts = <0 66 4>;
+ clocks = <&ahb1_gates 21>, <&spi1_clk>;
+ clock-names = "ahb", "mod";
+ resets = <&ahb1_rst 21>;
+};
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -455,6 +455,12 @@ config SPI_SIRF
help
SPI driver for CSR SiRFprimaII SoCs
+config SPI_SUN6I
+ tristate "Allwinner A31 SPI controller"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ help
+ This enables using the SPI controller on the Allwinner A31 SoCs.
+
config SPI_MXS
tristate "Freescale MXS SPI controller"
depends on ARCH_MXS
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hsp
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
+obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
obj-$(CONFIG_SPI_TEGRA20_SLINK) += spi-tegra20-slink.o
--- /dev/null
+++ b/drivers/spi/spi-sun6i.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN6I_FIFO_DEPTH 128
+
+#define SUN6I_GBL_CTL_REG 0x04
+#define SUN6I_GBL_CTL_BUS_ENABLE BIT(0)
+#define SUN6I_GBL_CTL_MASTER BIT(1)
+#define SUN6I_GBL_CTL_TP BIT(7)
+#define SUN6I_GBL_CTL_RST BIT(31)
+
+#define SUN6I_TFR_CTL_REG 0x08
+#define SUN6I_TFR_CTL_CPHA BIT(0)
+#define SUN6I_TFR_CTL_CPOL BIT(1)
+#define SUN6I_TFR_CTL_SPOL BIT(2)
+#define SUN6I_TFR_CTL_CS_MASK 0x3
+#define SUN6I_TFR_CTL_CS(cs) (((cs) & SUN6I_TFR_CTL_CS_MASK) << 4)
+#define SUN6I_TFR_CTL_CS_MANUAL BIT(6)
+#define SUN6I_TFR_CTL_CS_LEVEL BIT(7)
+#define SUN6I_TFR_CTL_DHB BIT(8)
+#define SUN6I_TFR_CTL_FBS BIT(12)
+#define SUN6I_TFR_CTL_XCH BIT(31)
+
+#define SUN6I_INT_CTL_REG 0x10
+#define SUN6I_INT_CTL_RF_OVF BIT(8)
+#define SUN6I_INT_CTL_TC BIT(12)
+
+#define SUN6I_INT_STA_REG 0x14
+
+#define SUN6I_FIFO_CTL_REG 0x18
+#define SUN6I_FIFO_CTL_RF_RST BIT(15)
+#define SUN6I_FIFO_CTL_TF_RST BIT(31)
+
+#define SUN6I_FIFO_STA_REG 0x1c
+#define SUN6I_FIFO_STA_RF_CNT_MASK 0x7f
+#define SUN6I_FIFO_STA_RF_CNT_BITS 0
+#define SUN6I_FIFO_STA_TF_CNT_MASK 0x7f
+#define SUN6I_FIFO_STA_TF_CNT_BITS 16
+
+#define SUN6I_CLK_CTL_REG 0x24
+#define SUN6I_CLK_CTL_CDR2_MASK 0xff
+#define SUN6I_CLK_CTL_CDR2(div) (((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
+#define SUN6I_CLK_CTL_CDR1_MASK 0xf
+#define SUN6I_CLK_CTL_CDR1(div) (((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN6I_CLK_CTL_DRS BIT(12)
+
+#define SUN6I_BURST_CNT_REG 0x30
+#define SUN6I_BURST_CNT(cnt) ((cnt) & 0xffffff)
+
+#define SUN6I_XMIT_CNT_REG 0x34
+#define SUN6I_XMIT_CNT(cnt) ((cnt) & 0xffffff)
+
+#define SUN6I_BURST_CTL_CNT_REG 0x38
+#define SUN6I_BURST_CTL_CNT_STC(cnt) ((cnt) & 0xffffff)
+
+#define SUN6I_TXDATA_REG 0x200
+#define SUN6I_RXDATA_REG 0x300
+
+struct sun6i_spi {
+ struct spi_master *master;
+ void __iomem *base_addr;
+ struct clk *hclk;
+ struct clk *mclk;
+ struct reset_control *rstc;
+
+ struct completion done;
+
+ const u8 *tx_buf;
+ u8 *rx_buf;
+ int len;
+};
+
+static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
+{
+ return readl(sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value)
+{
+ writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi, int len)
+{
+ u32 reg, cnt;
+ u8 byte;
+
+ /* See how much data is available */
+ reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG);
+ reg &= SUN6I_FIFO_STA_RF_CNT_MASK;
+ cnt = reg >> SUN6I_FIFO_STA_RF_CNT_BITS;
+
+ if (len > cnt)
+ len = cnt;
+
+ while (len--) {
+ byte = readb(sspi->base_addr + SUN6I_RXDATA_REG);
+ if (sspi->rx_buf)
+ *sspi->rx_buf++ = byte;
+ }
+}
+
+static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi, int len)
+{
+ u8 byte;
+
+ if (len > sspi->len)
+ len = sspi->len;
+
+ while (len--) {
+ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+ writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG);
+ sspi->len--;
+ }
+}
+
+static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+ struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
+ u32 reg;
+
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+ reg &= ~SUN6I_TFR_CTL_CS_MASK;
+ reg |= SUN6I_TFR_CTL_CS(spi->chip_select);
+
+ if (enable)
+ reg |= SUN6I_TFR_CTL_CS_LEVEL;
+ else
+ reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
+
+ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+}
+
+
+static int sun6i_spi_transfer_one(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct sun6i_spi *sspi = spi_master_get_devdata(master);
+ unsigned int mclk_rate, div, timeout;
+ unsigned int tx_len = 0;
+ int ret = 0;
+ u32 reg;
+
+ /* We don't support transfer larger than the FIFO */
+ if (tfr->len > SUN6I_FIFO_DEPTH)
+ return -EINVAL;
+
+ reinit_completion(&sspi->done);
+ sspi->tx_buf = tfr->tx_buf;
+ sspi->rx_buf = tfr->rx_buf;
+ sspi->len = tfr->len;
+
+ /* Clear pending interrupts */
+ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
+
+ /* Reset FIFO */
+ sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG,
+ SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST);
+
+ /*
+ * Setup the transfer control register: Chip Select,
+ * polarities, etc.
+ */
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+
+ if (spi->mode & SPI_CPOL)
+ reg |= SUN6I_TFR_CTL_CPOL;
+ else
+ reg &= ~SUN6I_TFR_CTL_CPOL;
+
+ if (spi->mode & SPI_CPHA)
+ reg |= SUN6I_TFR_CTL_CPHA;
+ else
+ reg &= ~SUN6I_TFR_CTL_CPHA;
+
+ if (spi->mode & SPI_LSB_FIRST)
+ reg |= SUN6I_TFR_CTL_FBS;
+ else
+ reg &= ~SUN6I_TFR_CTL_FBS;
+
+ /*
+ * If it's a TX only transfer, we don't want to fill the RX
+ * FIFO with bogus data
+ */
+ if (sspi->rx_buf)
+ reg &= ~SUN6I_TFR_CTL_DHB;
+ else
+ reg |= SUN6I_TFR_CTL_DHB;
+
+ /* We want to control the chip select manually */
+ reg |= SUN6I_TFR_CTL_CS_MANUAL;
+
+ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
+
+ /* Ensure that we have a parent clock fast enough */
+ mclk_rate = clk_get_rate(sspi->mclk);
+ if (mclk_rate < (2 * spi->max_speed_hz)) {
+ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+ mclk_rate = clk_get_rate(sspi->mclk);
+ }
+
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ cdr)
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Wether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+ div = mclk_rate / (2 * spi->max_speed_hz);
+ if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+ if (div > 0)
+ div--;
+
+ reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+ } else {
+ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+ reg = SUN6I_CLK_CTL_CDR1(div);
+ }
+
+ sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
+
+ /* Setup the transfer now... */
+ if (sspi->tx_buf)
+ tx_len = tfr->len;
+
+ /* Setup the counters */
+ sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, SUN6I_BURST_CNT(tfr->len));
+ sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, SUN6I_XMIT_CNT(tx_len));
+ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG,
+ SUN6I_BURST_CTL_CNT_STC(tx_len));
+
+ /* Fill the TX FIFO */
+ sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+ /* Enable the interrupts */
+ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
+
+ /* Start the transfer */
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+
+ timeout = wait_for_completion_timeout(&sspi->done,
+ msecs_to_jiffies(1000));
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+
+out:
+ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+
+ return ret;
+}
+
+static irqreturn_t sun6i_spi_handler(int irq, void *dev_id)
+{
+ struct sun6i_spi *sspi = dev_id;
+ u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG);
+
+ /* Transfer complete */
+ if (status & SUN6I_INT_CTL_TC) {
+ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC);
+ complete(&sspi->done);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int sun6i_spi_runtime_resume(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct sun6i_spi *sspi = spi_master_get_devdata(master);
+ int ret;
+
+ ret = clk_prepare_enable(sspi->hclk);
+ if (ret) {
+ dev_err(dev, "Couldn't enable AHB clock\n");
+ goto out;
+ }
+
+ ret = clk_prepare_enable(sspi->mclk);
+ if (ret) {
+ dev_err(dev, "Couldn't enable module clock\n");
+ goto err;
+ }
+
+ ret = reset_control_deassert(sspi->rstc);
+ if (ret) {
+ dev_err(dev, "Couldn't deassert the device from reset\n");
+ goto err2;
+ }
+
+ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
+ SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
+
+ return 0;
+
+err2:
+ clk_disable_unprepare(sspi->mclk);
+err:
+ clk_disable_unprepare(sspi->hclk);
+out:
+ return ret;
+}
+
+static int sun6i_spi_runtime_suspend(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct sun6i_spi *sspi = spi_master_get_devdata(master);
+
+ reset_control_assert(sspi->rstc);
+ clk_disable_unprepare(sspi->mclk);
+ clk_disable_unprepare(sspi->hclk);
+
+ return 0;
+}
+
+static int sun6i_spi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct sun6i_spi *sspi;
+ struct resource *res;
+ int ret = 0, irq;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
+ if (!master) {
+ dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, master);
+ sspi = spi_master_get_devdata(master);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(sspi->base_addr)) {
+ ret = PTR_ERR(sspi->base_addr);
+ goto err_free_master;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "No spi IRQ specified\n");
+ ret = -ENXIO;
+ goto err_free_master;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
+ 0, "sun6i-spi", sspi);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request IRQ\n");
+ goto err_free_master;
+ }
+
+ sspi->master = master;
+ master->set_cs = sun6i_spi_set_cs;
+ master->transfer_one = sun6i_spi_transfer_one;
+ master->num_chipselect = 4;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+ master->dev.of_node = pdev->dev.of_node;
+ master->auto_runtime_pm = true;
+
+ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(sspi->hclk)) {
+ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+ ret = PTR_ERR(sspi->hclk);
+ goto err_free_master;
+ }
+
+ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(sspi->mclk)) {
+ dev_err(&pdev->dev, "Unable to acquire module clock\n");
+ ret = PTR_ERR(sspi->mclk);
+ goto err_free_master;
+ }
+
+ init_completion(&sspi->done);
+
+ sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(sspi->rstc)) {
+ dev_err(&pdev->dev, "Couldn't get reset controller\n");
+ ret = PTR_ERR(sspi->rstc);
+ goto err_free_master;
+ }
+
+ /*
+ * This wake-up/shutdown pattern is to be able to have the
+ * device woken up, even if runtime_pm is disabled
+ */
+ ret = sun6i_spi_runtime_resume(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't resume the device\n");
+ goto err_free_master;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot register SPI master\n");
+ goto err_pm_disable;
+ }
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ sun6i_spi_runtime_suspend(&pdev->dev);
+err_free_master:
+ spi_master_put(master);
+ return ret;
+}
+
+static int sun6i_spi_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id sun6i_spi_match[] = {
+ { .compatible = "allwinner,sun6i-a31-spi", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun6i_spi_match);
+
+static const struct dev_pm_ops sun6i_spi_pm_ops = {
+ .runtime_resume = sun6i_spi_runtime_resume,
+ .runtime_suspend = sun6i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun6i_spi_driver = {
+ .probe = sun6i_spi_probe,
+ .remove = sun6i_spi_remove,
+ .driver = {
+ .name = "sun6i-spi",
+ .owner = THIS_MODULE,
+ .of_match_table = sun6i_spi_match,
+ .pm = &sun6i_spi_pm_ops,
+ },
+};
+module_platform_driver(sun6i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
+MODULE_LICENSE("GPL");

View file

@ -1,558 +0,0 @@
From 1ae7667375308c27023d793372d6be1f3b89f5b5 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:53 +0100
Subject: [PATCH] spi: sunxi: Add Allwinner A10 SPI controller driver
The older Allwinner SoCs (A10, A13, A10s and A20) all have the same SPI
controller.
Unfortunately, this SPI controller, even though quite similar, is significantly
different from the recently supported A31 SPI controller (different registers
offset, split/merged registers, etc.). Supporting both controllers in a single
driver would be unreasonable, hence the addition of a new driver.
Like its more recent counterpart, it supports DMA, but the driver only does PIO
until we have a dmaengine driver for this platform.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../devicetree/bindings/spi/spi-sun4i.txt | 24 ++
drivers/spi/Kconfig | 6 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-sun4i.c | 477 +++++++++++++++++++++
4 files changed, 508 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/spi-sun4i.txt
create mode 100644 drivers/spi/spi-sun4i.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sun4i.txt
@@ -0,0 +1,24 @@
+Allwinner A10 SPI controller
+
+Required properties:
+- compatible: Should be "allwinner,sun4-a10-spi".
+- reg: Should contain register location and length.
+- interrupts: Should contain interrupt.
+- clocks: phandle to the clocks feeding the SPI controller. Two are
+ needed:
+ - "ahb": the gated AHB parent clock
+ - "mod": the parent module clock
+- clock-names: Must contain the clock names described just above
+
+Example:
+
+spi1: spi@01c06000 {
+ compatible = "allwinner,sun4i-a10-spi";
+ reg = <0x01c06000 0x1000>;
+ interrupts = <11>;
+ clocks = <&ahb_gates 21>, <&spi1_clk>;
+ clock-names = "ahb", "mod";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -455,6 +455,12 @@ config SPI_SIRF
help
SPI driver for CSR SiRFprimaII SoCs
+config SPI_SUN4I
+ tristate "Allwinner A10 SoCs SPI controller"
+ depends on ARCH_SUNXI || COMPILE_TEST
+ help
+ SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+
config SPI_SUN6I
tristate "Allwinner A31 SPI controller"
depends on ARCH_SUNXI || COMPILE_TEST
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hsp
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
+obj-$(CONFIG_SPI_SUN4I) += spi-sun4i.o
obj-$(CONFIG_SPI_SUN6I) += spi-sun6i.o
obj-$(CONFIG_SPI_TEGRA114) += spi-tegra114.o
obj-$(CONFIG_SPI_TEGRA20_SFLASH) += spi-tegra20-sflash.o
--- /dev/null
+++ b/drivers/spi/spi-sun4i.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+
+#define SUN4I_FIFO_DEPTH 64
+
+#define SUN4I_RXDATA_REG 0x00
+
+#define SUN4I_TXDATA_REG 0x04
+
+#define SUN4I_CTL_REG 0x08
+#define SUN4I_CTL_ENABLE BIT(0)
+#define SUN4I_CTL_MASTER BIT(1)
+#define SUN4I_CTL_CPHA BIT(2)
+#define SUN4I_CTL_CPOL BIT(3)
+#define SUN4I_CTL_CS_ACTIVE_LOW BIT(4)
+#define SUN4I_CTL_LMTF BIT(6)
+#define SUN4I_CTL_TF_RST BIT(8)
+#define SUN4I_CTL_RF_RST BIT(9)
+#define SUN4I_CTL_XCH BIT(10)
+#define SUN4I_CTL_CS_MASK 0x3000
+#define SUN4I_CTL_CS(cs) (((cs) << 12) & SUN4I_CTL_CS_MASK)
+#define SUN4I_CTL_DHB BIT(15)
+#define SUN4I_CTL_CS_MANUAL BIT(16)
+#define SUN4I_CTL_CS_LEVEL BIT(17)
+#define SUN4I_CTL_TP BIT(18)
+
+#define SUN4I_INT_CTL_REG 0x0c
+#define SUN4I_INT_CTL_TC BIT(16)
+
+#define SUN4I_INT_STA_REG 0x10
+
+#define SUN4I_DMA_CTL_REG 0x14
+
+#define SUN4I_WAIT_REG 0x18
+
+#define SUN4I_CLK_CTL_REG 0x1c
+#define SUN4I_CLK_CTL_CDR2_MASK 0xff
+#define SUN4I_CLK_CTL_CDR2(div) ((div) & SUN4I_CLK_CTL_CDR2_MASK)
+#define SUN4I_CLK_CTL_CDR1_MASK 0xf
+#define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN4I_CLK_CTL_DRS BIT(12)
+
+#define SUN4I_BURST_CNT_REG 0x20
+#define SUN4I_BURST_CNT(cnt) ((cnt) & 0xffffff)
+
+#define SUN4I_XMIT_CNT_REG 0x24
+#define SUN4I_XMIT_CNT(cnt) ((cnt) & 0xffffff)
+
+#define SUN4I_FIFO_STA_REG 0x28
+#define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f
+#define SUN4I_FIFO_STA_RF_CNT_BITS 0
+#define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f
+#define SUN4I_FIFO_STA_TF_CNT_BITS 16
+
+struct sun4i_spi {
+ struct spi_master *master;
+ void __iomem *base_addr;
+ struct clk *hclk;
+ struct clk *mclk;
+
+ struct completion done;
+
+ const u8 *tx_buf;
+ u8 *rx_buf;
+ int len;
+};
+
+static inline u32 sun4i_spi_read(struct sun4i_spi *sspi, u32 reg)
+{
+ return readl(sspi->base_addr + reg);
+}
+
+static inline void sun4i_spi_write(struct sun4i_spi *sspi, u32 reg, u32 value)
+{
+ writel(value, sspi->base_addr + reg);
+}
+
+static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
+{
+ u32 reg, cnt;
+ u8 byte;
+
+ /* See how much data is available */
+ reg = sun4i_spi_read(sspi, SUN4I_FIFO_STA_REG);
+ reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
+ cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
+
+ if (len > cnt)
+ len = cnt;
+
+ while (len--) {
+ byte = readb(sspi->base_addr + SUN4I_RXDATA_REG);
+ if (sspi->rx_buf)
+ *sspi->rx_buf++ = byte;
+ }
+}
+
+static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len)
+{
+ u8 byte;
+
+ if (len > sspi->len)
+ len = sspi->len;
+
+ while (len--) {
+ byte = sspi->tx_buf ? *sspi->tx_buf++ : 0;
+ writeb(byte, sspi->base_addr + SUN4I_TXDATA_REG);
+ sspi->len--;
+ }
+}
+
+static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
+{
+ struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
+ u32 reg;
+
+ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+
+ reg &= ~SUN4I_CTL_CS_MASK;
+ reg |= SUN4I_CTL_CS(spi->chip_select);
+
+ if (enable)
+ reg |= SUN4I_CTL_CS_LEVEL;
+ else
+ reg &= ~SUN4I_CTL_CS_LEVEL;
+
+ /*
+ * Even though this looks irrelevant since we are supposed to
+ * be controlling the chip select manually, this bit also
+ * controls the levels of the chip select for inactive
+ * devices.
+ *
+ * If we don't set it, the chip select level will go low by
+ * default when the device is idle, which is not really
+ * expected in the common case where the chip select is active
+ * low.
+ */
+ if (spi->mode & SPI_CS_HIGH)
+ reg &= ~SUN4I_CTL_CS_ACTIVE_LOW;
+ else
+ reg |= SUN4I_CTL_CS_ACTIVE_LOW;
+
+ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
+}
+
+static int sun4i_spi_transfer_one(struct spi_master *master,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+{
+ struct sun4i_spi *sspi = spi_master_get_devdata(master);
+ unsigned int mclk_rate, div, timeout;
+ unsigned int tx_len = 0;
+ int ret = 0;
+ u32 reg;
+
+ /* We don't support transfer larger than the FIFO */
+ if (tfr->len > SUN4I_FIFO_DEPTH)
+ return -EINVAL;
+
+ reinit_completion(&sspi->done);
+ sspi->tx_buf = tfr->tx_buf;
+ sspi->rx_buf = tfr->rx_buf;
+ sspi->len = tfr->len;
+
+ /* Clear pending interrupts */
+ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, ~0);
+
+
+ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+
+ /* Reset FIFOs */
+ sun4i_spi_write(sspi, SUN4I_CTL_REG,
+ reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST);
+
+ /*
+ * Setup the transfer control register: Chip Select,
+ * polarities, etc.
+ */
+ if (spi->mode & SPI_CPOL)
+ reg |= SUN4I_CTL_CPOL;
+ else
+ reg &= ~SUN4I_CTL_CPOL;
+
+ if (spi->mode & SPI_CPHA)
+ reg |= SUN4I_CTL_CPHA;
+ else
+ reg &= ~SUN4I_CTL_CPHA;
+
+ if (spi->mode & SPI_LSB_FIRST)
+ reg |= SUN4I_CTL_LMTF;
+ else
+ reg &= ~SUN4I_CTL_LMTF;
+
+
+ /*
+ * If it's a TX only transfer, we don't want to fill the RX
+ * FIFO with bogus data
+ */
+ if (sspi->rx_buf)
+ reg &= ~SUN4I_CTL_DHB;
+ else
+ reg |= SUN4I_CTL_DHB;
+
+ /* We want to control the chip select manually */
+ reg |= SUN4I_CTL_CS_MANUAL;
+
+ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
+
+ /* Ensure that we have a parent clock fast enough */
+ mclk_rate = clk_get_rate(sspi->mclk);
+ if (mclk_rate < (2 * spi->max_speed_hz)) {
+ clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz);
+ mclk_rate = clk_get_rate(sspi->mclk);
+ }
+
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Wether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+ div = mclk_rate / (2 * spi->max_speed_hz);
+ if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
+ if (div > 0)
+ div--;
+
+ reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
+ } else {
+ div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz);
+ reg = SUN4I_CLK_CTL_CDR1(div);
+ }
+
+ sun4i_spi_write(sspi, SUN4I_CLK_CTL_REG, reg);
+
+ /* Setup the transfer now... */
+ if (sspi->tx_buf)
+ tx_len = tfr->len;
+
+ /* Setup the counters */
+ sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
+ sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
+
+ /* Fill the TX FIFO */
+ sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
+
+ /* Enable the interrupts */
+ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
+
+ /* Start the transfer */
+ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+ sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
+
+ timeout = wait_for_completion_timeout(&sspi->done,
+ msecs_to_jiffies(1000));
+ if (!timeout) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
+
+out:
+ sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
+
+ return ret;
+}
+
+static irqreturn_t sun4i_spi_handler(int irq, void *dev_id)
+{
+ struct sun4i_spi *sspi = dev_id;
+ u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
+
+ /* Transfer complete */
+ if (status & SUN4I_INT_CTL_TC) {
+ sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC);
+ complete(&sspi->done);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int sun4i_spi_runtime_resume(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct sun4i_spi *sspi = spi_master_get_devdata(master);
+ int ret;
+
+ ret = clk_prepare_enable(sspi->hclk);
+ if (ret) {
+ dev_err(dev, "Couldn't enable AHB clock\n");
+ goto out;
+ }
+
+ ret = clk_prepare_enable(sspi->mclk);
+ if (ret) {
+ dev_err(dev, "Couldn't enable module clock\n");
+ goto err;
+ }
+
+ sun4i_spi_write(sspi, SUN4I_CTL_REG,
+ SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP);
+
+ return 0;
+
+err:
+ clk_disable_unprepare(sspi->hclk);
+out:
+ return ret;
+}
+
+static int sun4i_spi_runtime_suspend(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct sun4i_spi *sspi = spi_master_get_devdata(master);
+
+ clk_disable_unprepare(sspi->mclk);
+ clk_disable_unprepare(sspi->hclk);
+
+ return 0;
+}
+
+static int sun4i_spi_probe(struct platform_device *pdev)
+{
+ struct spi_master *master;
+ struct sun4i_spi *sspi;
+ struct resource *res;
+ int ret = 0, irq;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
+ if (!master) {
+ dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, master);
+ sspi = spi_master_get_devdata(master);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sspi->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(sspi->base_addr)) {
+ ret = PTR_ERR(sspi->base_addr);
+ goto err_free_master;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "No spi IRQ specified\n");
+ ret = -ENXIO;
+ goto err_free_master;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler,
+ 0, "sun4i-spi", sspi);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request IRQ\n");
+ goto err_free_master;
+ }
+
+ sspi->master = master;
+ master->set_cs = sun4i_spi_set_cs;
+ master->transfer_one = sun4i_spi_transfer_one;
+ master->num_chipselect = 4;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+ master->dev.of_node = pdev->dev.of_node;
+ master->auto_runtime_pm = true;
+
+ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(sspi->hclk)) {
+ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+ ret = PTR_ERR(sspi->hclk);
+ goto err_free_master;
+ }
+
+ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(sspi->mclk)) {
+ dev_err(&pdev->dev, "Unable to acquire module clock\n");
+ ret = PTR_ERR(sspi->mclk);
+ goto err_free_master;
+ }
+
+ init_completion(&sspi->done);
+
+ /*
+ * This wake-up/shutdown pattern is to be able to have the
+ * device woken up, even if runtime_pm is disabled
+ */
+ ret = sun4i_spi_runtime_resume(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't resume the device\n");
+ goto err_free_master;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot register SPI master\n");
+ goto err_pm_disable;
+ }
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ sun4i_spi_runtime_suspend(&pdev->dev);
+err_free_master:
+ spi_master_put(master);
+ return ret;
+}
+
+static int sun4i_spi_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id sun4i_spi_match[] = {
+ { .compatible = "allwinner,sun4i-a10-spi", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun4i_spi_match);
+
+static const struct dev_pm_ops sun4i_spi_pm_ops = {
+ .runtime_resume = sun4i_spi_runtime_resume,
+ .runtime_suspend = sun4i_spi_runtime_suspend,
+};
+
+static struct platform_driver sun4i_spi_driver = {
+ .probe = sun4i_spi_probe,
+ .remove = sun4i_spi_remove,
+ .driver = {
+ .name = "sun4i-spi",
+ .owner = THIS_MODULE,
+ .of_match_table = sun4i_spi_match,
+ .pm = &sun4i_spi_pm_ops,
+ },
+};
+module_platform_driver(sun4i_spi_driver);
+
+MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A1X/A20 SPI controller driver");
+MODULE_LICENSE("GPL");

View file

@ -1,29 +0,0 @@
From 3aa7ff0de5bddc825406ffff49dc4a38b13ebac3 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Wed, 5 Feb 2014 14:05:07 +0100
Subject: [PATCH] ARM: sunxi: Enable A31 SPI and SID in the defconfig
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/configs/sunxi_defconfig | 3 +++
1 file changed, 3 insertions(+)
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -24,6 +24,7 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EEPROM_SUNXI_SID=y
CONFIG_NETDEVICES=y
CONFIG_SUN4I_EMAC=y
# CONFIG_NET_CADENCE is not set
@@ -48,6 +49,8 @@ CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MV64XXX=y
+CONFIG_SPI=y
+CONFIG_SPI_SUN6I=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y

View file

@ -1,33 +0,0 @@
From c38fe0f410a59e194ef5e58429658506d853f1b4 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:58 +0100
Subject: [PATCH] ARM: dt: sun7i: Add SPI muxing options
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -571,6 +571,20 @@
allwinner,drive = <3>;
allwinner,pull = <0>;
};
+
+ spi1_pins_a: spi1@0 {
+ allwinner,pins = "PI16", "PI17", "PI18", "PI19";
+ allwinner,function = "spi1";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ spi2_pins_a: spi2@0 {
+ allwinner,pins = "PC19", "PC20", "PC21", "PC22";
+ allwinner,function = "spi2";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -1,41 +0,0 @@
From 3f134732aaf4d785532c716f4ef7703d631a510b Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 22 Feb 2014 22:35:59 +0100
Subject: [PATCH] ARM: dts: sun7i: Enable the SPI controllers of the
A20-olinuxino-micro
The A20-Olinuxino-micro has two SPI bus exposed on its UEXT connectors, enable
them.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -18,7 +18,24 @@
model = "Olimex A20-Olinuxino Micro";
compatible = "olimex,a20-olinuxino-micro", "allwinner,sun7i-a20";
+ aliases {
+ spi0 = &spi1;
+ spi1 = &spi2;
+ };
+
soc@01c00000 {
+ spi1: spi@01c06000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins_a>;
+ status = "okay";
+ };
+
+ spi2: spi@01c17000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";

View file

@ -1,78 +0,0 @@
From a9868f7ef1d3828e55de36cfeac2f84a77653a1e 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 | 10 ++++++++++
arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++
3 files changed, 22 insertions(+)
--- 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";
--- 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-common-regulators.dtsi"
/ {
model = "Cubietech Cubieboard";
@@ -33,6 +34,11 @@
};
};
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -77,4 +83,8 @@
linux,default-trigger = "heartbeat";
};
};
+
+ reg_ahci_5v: ahci-5v {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -388,6 +388,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";
+ };
+
spi3: spi@01c1f000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c1f000 0x1000>;

View file

@ -1,136 +0,0 @@
From cf454a47b64ef78ff85b097c8cb404120c14e6a5 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 | 10 ++++++++++
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 19 +++++++++++++++++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 10 ++++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
4 files changed, 47 insertions(+)
--- 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-common-regulators.dtsi"
/ {
model = "Cubietech Cubieboard2";
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
soc@01c00000 {
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -74,4 +80,8 @@
gpios = <&pio 7 20 0>;
};
};
+
+ reg_ahci_5v: ahci-5v {
+ status = "okay";
+ };
};
--- 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-common-regulators.dtsi"
/ {
model = "Cubietech Cubietruck";
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
soc@01c00000 {
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
+ ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
+ allwinner,pins = "PH12";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
led_pins_cubietruck: led_pins@0 {
allwinner,pins = "PH7", "PH11", "PH20", "PH21";
allwinner,function = "gpio_out";
@@ -104,4 +117,10 @@
gpios = <&pio 7 7 0>;
};
};
+
+ reg_ahci_5v: ahci-5v {
+ pinctrl-0 = <&ahci_pwr_pin_cubietruck>;
+ gpio = <&pio 7 12 0>;
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "Olimex A20-Olinuxino Micro";
@@ -36,6 +37,11 @@
status = "okay";
};
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
@@ -105,4 +111,8 @@
default-state = "on";
};
};
+
+ reg_ahci_5v: ahci-5v {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -450,6 +450,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";
+ };
+
spi3: spi@01c1f000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c1f000 0x1000>;

View file

@ -1,46 +0,0 @@
From ac45fe6b0056d1f92b7c7e5f13514b591a6a9caf Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sun, 2 Feb 2014 14:55:23 +0100
Subject: [PATCH] wdt: sunxi: Introduce a new compatible for the A10 and A31
For historical reasons, the Allwinner A10 compatibles are not following the
patterns used for this other Allwinner SoCs.
Introduce a new compatible following the usual pattern, and deprecate the olders.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt | 7 ++++---
drivers/watchdog/sunxi_wdt.c | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)
--- a/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt
@@ -2,13 +2,14 @@ Allwinner SoCs Watchdog timer
Required properties:
-- compatible : should be "allwinner,<soc-family>-wdt", the currently supported
- SoC families being sun4i and sun6i
+- compatible : should be either "allwinner,sun4i-a10-wdt" or
+ "allwinner,sun6i-a31-wdt" (deprecated:
+ "allwinner,sun4i-wdt", "allwinner,sun6i-wdt")
- reg : Specifies base physical address and size of the registers.
Example:
wdt: watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
--- a/drivers/watchdog/sunxi_wdt.c
+++ b/drivers/watchdog/sunxi_wdt.c
@@ -206,6 +206,7 @@ static void sunxi_wdt_shutdown(struct pl
static const struct of_device_id sunxi_wdt_dt_ids[] = {
{ .compatible = "allwinner,sun4i-wdt" },
+ { .compatible = "allwinner,sun4i-a10-wdt" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);

View file

@ -1,73 +0,0 @@
From f722ea226581a75107ef16b46db1b7b5b999c93a Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sun, 2 Feb 2014 14:55:25 +0100
Subject: [PATCH] ARM: sunxi: dt: Update the watchdog compatibles
The watchdog compatibles were following a different pattern than the one found
in the other devices. Now that the driver supports the right pattern, switch to
it in the DT.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 2 +-
arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +-
arch/arm/boot/dts/sun5i-a13.dtsi | 2 +-
arch/arm/boot/dts/sun6i-a31.dtsi | 2 +-
arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -487,7 +487,7 @@
};
wdt: watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -392,7 +392,7 @@
};
wdt: watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -393,7 +393,7 @@
};
wdt: watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -289,7 +289,7 @@
};
wdt1: watchdog@01c20ca0 {
- compatible = "allwinner,sun6i-wdt";
+ compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
};
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -608,7 +608,7 @@
};
wdt: watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};

View file

@ -1,26 +0,0 @@
From 30e5365b3ad3858bbdf40e8364c1e3260861b4e4 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sun, 2 Feb 2014 14:55:24 +0100
Subject: [PATCH] ARM: sunxi: Add the new watchog compatibles to the reboot
code
Now that the watchdog driver has new compatibles, we need to support them in
the machine reboot code too.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/mach-sunxi/sunxi.c | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -95,7 +95,9 @@ static void sun6i_restart(enum reboot_mo
static struct of_device_id sunxi_restart_ids[] = {
{ .compatible = "allwinner,sun4i-wdt" },
+ { .compatible = "allwinner,sun4i-a10-wdt" },
{ .compatible = "allwinner,sun6i-wdt" },
+ { .compatible = "allwinner,sun6i-a31-wdt" },
{ /*sentinel*/ }
};

View file

@ -1,81 +0,0 @@
From 991b5f6d2af837b56adfcb3b3a1fe167647b9fdb Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Wed, 18 Sep 2013 00:30:04 +0200
Subject: [PATCH] ARM: sun4i: dt: Add USB host bindings
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -377,6 +377,38 @@
#size-cells = <0>;
};
+ usbphy: phy@01c13400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun4i-a10-usb-phy";
+ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+ reg-names = "phy_ctrl", "pmu1", "pmu2";
+ clocks = <&usb_clk 8>;
+ clock-names = "usb_phy";
+ resets = <&usb_clk 1>, <&usb_clk 2>;
+ reset-names = "usb1_reset", "usb2_reset";
+ status = "disabled";
+ };
+
+ ehci0: usb@01c14000 {
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <39>;
+ clocks = <&ahb_gates 1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@01c14400 {
+ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <64>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
spi2: spi@01c17000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c17000 0x1000>;
@@ -396,6 +428,26 @@
status = "disabled";
};
+ ehci1: usb@01c1c000 {
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
+ reg = <0x01c1c000 0x100>;
+ interrupts = <40>;
+ clocks = <&ahb_gates 3>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@01c1c400 {
+ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
+ reg = <0x01c1c400 0x100>;
+ interrupts = <65>;
+ clocks = <&usb_clk 7>, <&ahb_gates 4>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
spi3: spi@01c1f000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c1f000 0x1000>;

View file

@ -1,55 +0,0 @@
From 1b5a1b92147936c5aa2acec1683663b4d22e9ae6 Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Tue, 24 Sep 2013 20:03:40 +0200
Subject: [PATCH] ARM: sun5i: dt: Add USB host bindings
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a10s.dtsi | 32 ++++++++++++++++++++++++++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 32 ++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -320,6 +320,38 @@
#size-cells = <0>;
};
+ usbphy: phy@01c13400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun5i-a13-usb-phy";
+ reg = <0x01c13400 0x10 0x01c14800 0x4>;
+ reg-names = "phy_ctrl", "pmu1";
+ clocks = <&usb_clk 8>;
+ clock-names = "usb_phy";
+ resets = <&usb_clk 1>;
+ reset-names = "usb1_reset";
+ status = "disabled";
+ };
+
+ ehci0: usb@01c14000 {
+ compatible = "allwinner,sun5i-a13-ehci", "generic-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <39>;
+ clocks = <&ahb_gates 1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@01c14400 {
+ compatible = "allwinner,sun5i-a13-ohci", "generic-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <40>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
spi2: spi@01c17000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c17000 0x1000>;

View file

@ -1,81 +0,0 @@
From 008dffff2fa751c988671c4fc0c9a404ea808280 Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Thu, 19 Sep 2013 21:36:10 +0200
Subject: [PATCH] ARM: sun7i: dt: Add USB host bindings
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -439,6 +439,38 @@
#size-cells = <0>;
};
+ usbphy: phy@01c13400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun7i-a20-usb-phy";
+ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+ reg-names = "phy_ctrl", "pmu1", "pmu2";
+ clocks = <&usb_clk 8>;
+ clock-names = "usb_phy";
+ resets = <&usb_clk 1>, <&usb_clk 2>;
+ reset-names = "usb1_reset", "usb2_reset";
+ status = "disabled";
+ };
+
+ ehci0: usb@01c14000 {
+ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <0 39 4>;
+ clocks = <&ahb_gates 1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@01c14400 {
+ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <0 64 4>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
spi2: spi@01c17000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c17000 0x1000>;
@@ -458,6 +490,26 @@
status = "disabled";
};
+ ehci1: usb@01c1c000 {
+ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
+ reg = <0x01c1c000 0x100>;
+ interrupts = <0 40 4>;
+ clocks = <&ahb_gates 3>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@01c1c400 {
+ compatible = "allwinner,sun7i-a20-ohci", "generic-ohci";
+ reg = <0x01c1c400 0x100>;
+ interrupts = <0 65 4>;
+ clocks = <&usb_clk 7>, <&ahb_gates 4>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
spi3: spi@01c1f000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c1f000 0x1000>;

View file

@ -1,240 +0,0 @@
From f2509ec45a09013e300460a967f694561d169b98 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 11 Jan 2014 04:47:38 +0100
Subject: [PATCH] ARM: sun4i: dt: Add USB host nodes to hackberry dts
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Based on fex file settings, the fex file also contains a mysterious line:
usb_hub_vcc_en_gpio = port:PB09<1><0><default><0>
Which also clashes with usbc0, which has:
usb_drv_vbus_gpio = port:PB09<1><0><default><0>
So if usb does not work properly we need someone with a hackberry to look
closer into this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-hackberry.dts | 40 +++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "Miniand Hackberry";
@@ -35,6 +36,28 @@
};
};
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
pio: pinctrl@01c20800 {
pinctrl-names = "default";
pinctrl-0 = <&hackberry_hogs>;
@@ -45,6 +68,13 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ usb2_vbus_pin_hackberry: usb2_vbus_pin@0 {
+ allwinner,pins = "PH12";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
uart0: serial@01c28000 {
@@ -66,4 +96,14 @@
gpio = <&pio 7 19 0>;
};
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ pinctrl-0 = <&usb2_vbus_pin_hackberry>;
+ gpio = <&pio 7 12 0>;
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
@@ -13,16 +13,47 @@
/dts-v1/;
/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "PineRiver Mini X-Plus";
compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10";
soc@01c00000 {
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
@@ -12,6 +12,7 @@
/dts-v1/;
/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "LinkSprite pcDuino";
@@ -33,6 +34,28 @@
};
};
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -45,4 +68,12 @@
status = "okay";
};
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -34,11 +34,33 @@
};
};
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
};
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -87,4 +109,12 @@
reg_ahci_5v: ahci-5v {
status = "okay";
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};

View file

@ -1,121 +0,0 @@
From 9f193366e6094f6e2087c4767e7e413a395bf0d2 Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Tue, 24 Sep 2013 20:07:53 +0200
Subject: [PATCH] ARM: sun5i: dt: Add USB host nodes to A13-Olinuxino
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -13,12 +13,26 @@
/dts-v1/;
/include/ "sun5i-a13.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "Olimex A13-Olinuxino";
compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
soc@01c00000 {
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PG9";
@@ -26,6 +40,13 @@
allwinner,drive = <1>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin_olinuxino: usb1_vbus_pin@0 {
+ allwinner,pins = "PG11";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
uart1: serial@01c28400 {
@@ -63,4 +84,10 @@
default-state = "on";
};
};
+
+ reg_usb1_vbus: usb1-vbus {
+ pinctrl-0 = <&usb1_vbus_pin_olinuxino>;
+ gpio = <&pio 6 11 0>;
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
@@ -14,12 +14,26 @@
/dts-v1/;
/include/ "sun5i-a13.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
/ {
model = "Olimex A13-Olinuxino Micro";
compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
soc@01c00000 {
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxinom: led_pins@0 {
allwinner,pins = "PG9";
@@ -27,6 +41,13 @@
allwinner,drive = <1>;
allwinner,pull = <0>;
};
+
+ usb1_vbus_pin_olinuxinom: usb1_vbus_pin@0 {
+ allwinner,pins = "PG11";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
uart1: serial@01c28400 {
@@ -65,4 +86,10 @@
default-state = "on";
};
};
+
+ reg_usb1_vbus: usb1-vbus {
+ pinctrl-0 = <&usb1_vbus_pin_olinuxinom>;
+ gpio = <&pio 6 11 0>;
+ status = "okay";
+ };
};

View file

@ -1,161 +0,0 @@
From 56de1b69bf6782338193e373cee06fff252b31da 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: sun7i: dt: Add USB host nodes to cubietruck dts
Add nodes for the usb-phy and ehci- and ohci-usb-host controllers.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -20,11 +20,33 @@
compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
soc@01c00000 {
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
};
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
allwinner,pins = "PH12";
@@ -123,4 +145,12 @@
gpio = <&pio 7 12 0>;
status = "okay";
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -20,11 +20,33 @@
compatible = "cubietech,cubieboard2", "allwinner,sun7i-a20";
soc@01c00000 {
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
ahci: sata@01c18000 {
target-supply = <&reg_ahci_5v>;
status = "okay";
};
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_cubieboard2: led_pins@0 {
allwinner,pins = "PH20", "PH21";
@@ -84,4 +106,12 @@
reg_ahci_5v: ahci-5v {
status = "okay";
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -31,6 +31,20 @@
status = "okay";
};
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
spi2: spi@01c17000 {
pinctrl-names = "default";
pinctrl-0 = <&spi2_pins_a>;
@@ -42,6 +56,14 @@
status = "okay";
};
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
pinctrl@01c20800 {
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
@@ -115,4 +137,12 @@
reg_ahci_5v: ahci-5v {
status = "okay";
};
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
};

View file

@ -1,341 +0,0 @@
From afbd58e1b1219cbcbe2cc07273fc51f658891e9b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 23 Dec 2013 16:21:02 +0100
Subject: [PATCH] input: Add new sun4i-ts driver for Allwinner sunxi SoC's rtp
controller
Note the sun4i-ts controller is capable of detecting a second touch, but when
a second touch is present then the accuracy becomes so bad the reported touch
location is not useable.
The original android driver contains some complicated heuristics using the
aprox. distance between the 2 touches to see if the user is making a pinch
open / close movement, and then reports emulated multi-touch events around
the last touch coordinate (as the dual-touch coordinates are worthless).
These kinds of heuristics are just asking for trouble (and don't belong
in the kernel). So this driver offers straight forward, reliable single
touch functionality only.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../bindings/input/touchscreen/sun4i.txt | 15 ++
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/sun4i-ts.c | 262 +++++++++++++++++++++
4 files changed, 288 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
create mode 100644 drivers/input/touchscreen/sun4i-ts.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
@@ -0,0 +1,15 @@
+sun4i resistive touchscreen controller
+--------------------------------------
+
+Required properties:
+ - compatible: "allwinner,sun4i-ts"
+ - reg: mmio address range of the chip
+ - interrupts: interrupt to which the chip is connected
+
+Example:
+
+ rtp: rtp@01c25000 {
+ compatible = "allwinner,sun4i-ts";
+ reg = <0x01c25000 0x100>;
+ interrupts = <29>;
+ };
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -906,6 +906,16 @@ config TOUCHSCREEN_STMPE
To compile this driver as a module, choose M here: the
module will be called stmpe-ts.
+config TOUCHSCREEN_SUN4I
+ tristate "Allwinner sun4i resistive touchscreen controller support"
+ depends on ARCH_SUNXI
+ help
+ This selects support for the resistive touchscreen controller
+ found on Allwinner sunxi SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun4i-ts.
+
config TOUCHSCREEN_SUR40
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
depends on USB
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixc
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
--- /dev/null
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -0,0 +1,262 @@
+/*
+ * Allwinner sunxi resistive touchscreen controller driver
+ *
+ * Copyright (C) 2013 - 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * The sun4i-ts controller is capable of detecting a second touch, but when a
+ * second touch is present then the accuracy becomes so bad the reported touch
+ * location is not useable.
+ *
+ * The original android driver contains some complicated heuristics using the
+ * aprox. distance between the 2 touches to see if the user is making a pinch
+ * open / close movement, and then reports emulated multi-touch events around
+ * the last touch coordinate (as the dual-touch coordinates are worthless).
+ *
+ * These kinds of heuristics are just asking for trouble (and don't belong
+ * in the kernel). So this driver offers straight forward, reliable single
+ * touch functionality only.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define TP_CTRL0 0x00
+#define TP_CTRL1 0x04
+#define TP_CTRL2 0x08
+#define TP_CTRL3 0x0c
+#define TP_INT_FIFOC 0x10
+#define TP_INT_FIFOS 0x14
+#define TP_TPR 0x18
+#define TP_CDAT 0x1c
+#define TEMP_DATA 0x20
+#define TP_DATA 0x24
+
+/* TP_CTRL0 bits */
+#define ADC_FIRST_DLY(x) ((x) << 24) /* 8 bits */
+#define ADC_FIRST_DLY_MODE(x) ((x) << 23)
+#define ADC_CLK_SEL(x) ((x) << 22)
+#define ADC_CLK_DIV(x) ((x) << 20) /* 3 bits */
+#define FS_DIV(x) ((x) << 16) /* 4 bits */
+#define T_ACQ(x) ((x) << 0) /* 16 bits */
+
+/* TP_CTRL1 bits */
+#define STYLUS_UP_DEBOUN(x) ((x) << 12) /* 8 bits */
+#define STYLUS_UP_DEBOUN_EN(x) ((x) << 9)
+#define TOUCH_PAN_CALI_EN(x) ((x) << 6)
+#define TP_DUAL_EN(x) ((x) << 5)
+#define TP_MODE_EN(x) ((x) << 4)
+#define TP_ADC_SELECT(x) ((x) << 3)
+#define ADC_CHAN_SELECT(x) ((x) << 0) /* 3 bits */
+
+/* TP_CTRL2 bits */
+#define TP_SENSITIVE_ADJUST(x) ((x) << 28) /* 4 bits */
+#define TP_MODE_SELECT(x) ((x) << 26) /* 2 bits */
+#define PRE_MEA_EN(x) ((x) << 24)
+#define PRE_MEA_THRE_CNT(x) ((x) << 0) /* 24 bits */
+
+/* TP_CTRL3 bits */
+#define FILTER_EN(x) ((x) << 2)
+#define FILTER_TYPE(x) ((x) << 0) /* 2 bits */
+
+/* TP_INT_FIFOC irq and fifo mask / control bits */
+#define TEMP_IRQ_EN(x) ((x) << 18)
+#define OVERRUN_IRQ_EN(x) ((x) << 17)
+#define DATA_IRQ_EN(x) ((x) << 16)
+#define TP_DATA_XY_CHANGE(x) ((x) << 13)
+#define FIFO_TRIG(x) ((x) << 8) /* 5 bits */
+#define DATA_DRQ_EN(x) ((x) << 7)
+#define FIFO_FLUSH(x) ((x) << 4)
+#define TP_UP_IRQ_EN(x) ((x) << 1)
+#define TP_DOWN_IRQ_EN(x) ((x) << 0)
+
+/* TP_INT_FIFOS irq and fifo status bits */
+#define TEMP_DATA_PENDING BIT(18)
+#define FIFO_OVERRUN_PENDING BIT(17)
+#define FIFO_DATA_PENDING BIT(16)
+#define TP_IDLE_FLG BIT(2)
+#define TP_UP_PENDING BIT(1)
+#define TP_DOWN_PENDING BIT(0)
+
+/* TP_TPR bits */
+#define TEMP_ENABLE(x) ((x) << 16)
+#define TEMP_PERIOD(x) ((x) << 0) /* t = x * 256 * 16 / clkin */
+
+struct sun4i_ts_data {
+ struct device *dev;
+ struct input_dev *input;
+ void __iomem *base;
+ unsigned int irq;
+ bool ignore_fifo_data;
+};
+
+static irqreturn_t sun4i_ts_irq(int irq, void *dev_id)
+{
+ struct sun4i_ts_data *ts = dev_id;
+ u32 reg_val, x, y;
+
+ reg_val = readl(ts->base + TP_INT_FIFOS);
+
+ if (reg_val & FIFO_DATA_PENDING) {
+ x = readl(ts->base + TP_DATA);
+ y = readl(ts->base + TP_DATA);
+ /* The 1st location reported after an up event is unreliable */
+ if (!ts->ignore_fifo_data) {
+ input_report_abs(ts->input, ABS_X, x);
+ input_report_abs(ts->input, ABS_Y, y);
+ /*
+ * The hardware has a separate down status bit, but
+ * that gets set before we get the first location,
+ * resulting in reporting a click on the old location.
+ */
+ input_report_key(ts->input, BTN_TOUCH, 1);
+ input_sync(ts->input);
+ } else {
+ ts->ignore_fifo_data = false;
+ }
+ }
+
+ if (reg_val & TP_UP_PENDING) {
+ ts->ignore_fifo_data = true;
+ input_report_key(ts->input, BTN_TOUCH, 0);
+ input_sync(ts->input);
+ }
+
+ writel(reg_val, ts->base + TP_INT_FIFOS);
+
+ return IRQ_HANDLED;
+}
+
+static int sun4i_ts_open(struct input_dev *dev)
+{
+ struct sun4i_ts_data *ts = input_get_drvdata(dev);
+
+ /* Flush, set trig level to 1, enable data and up irqs */
+ writel(DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) | TP_UP_IRQ_EN(1),
+ ts->base + TP_INT_FIFOC);
+
+ return 0;
+}
+
+static void sun4i_ts_close(struct input_dev *dev)
+{
+ struct sun4i_ts_data *ts = input_get_drvdata(dev);
+
+ /* Deactivate all IRQs */
+ writel(0, ts->base + TP_INT_FIFOC);
+}
+
+static int sun4i_ts_probe(struct platform_device *pdev)
+{
+ struct sun4i_ts_data *ts;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->dev = dev;
+ ts->ignore_fifo_data = true;
+
+ ts->input = devm_input_allocate_device(dev);
+ if (!ts->input)
+ return -ENOMEM;
+
+ ts->input->name = pdev->name;
+ ts->input->phys = "sun4i_ts/input0";
+ ts->input->open = sun4i_ts_open;
+ ts->input->close = sun4i_ts_close;
+ ts->input->id.bustype = BUS_HOST;
+ ts->input->id.vendor = 0x0001;
+ ts->input->id.product = 0x0001;
+ ts->input->id.version = 0x0100;
+ ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
+ set_bit(BTN_TOUCH, ts->input->keybit);
+ input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0);
+ input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0);
+ input_set_drvdata(ts->input, ts);
+
+ ts->base = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (IS_ERR(ts->base))
+ return PTR_ERR(ts->base);
+
+ ts->irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(dev, ts->irq, sun4i_ts_irq, 0, "sun4i-ts", ts);
+ if (ret)
+ return ret;
+
+ /*
+ * Select HOSC clk, clkin = clk / 6, adc samplefreq = clkin / 8192,
+ * t_acq = clkin / (16 * 64)
+ */
+ writel(ADC_CLK_SEL(0) | ADC_CLK_DIV(2) | FS_DIV(7) | T_ACQ(63),
+ ts->base + TP_CTRL0);
+
+ /*
+ * sensitive_adjust = 15 : max, which is not all that sensitive,
+ * tp_mode = 0 : only x and y coordinates, as we don't use dual touch
+ */
+ writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0),
+ ts->base + TP_CTRL2);
+
+ /* Enable median filter, type 1 : 5/3 */
+ writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3);
+
+ /* Enable temperature measurement, period 1953 (2 seconds) */
+ writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR);
+
+ /*
+ * Set stylus up debounce to aprox 10 ms, enable debounce, and
+ * finally enable tp mode.
+ */
+ writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1),
+ ts->base + TP_CTRL1);
+
+ ret = input_register_device(ts->input);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, ts);
+ return 0;
+}
+
+static const struct of_device_id sun4i_ts_of_match[] = {
+ { .compatible = "allwinner,sun4i-ts", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_ts_of_match);
+
+static struct platform_driver sun4i_ts_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sun4i-ts",
+ .of_match_table = of_match_ptr(sun4i_ts_of_match),
+ },
+ .probe = sun4i_ts_probe,
+};
+
+module_platform_driver(sun4i_ts_driver);
+
+MODULE_DESCRIPTION("Allwinner sun4i resistive touchscreen controller driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");

View file

@ -1,256 +0,0 @@
From d8b5553dbf60e519d565dbd83327b08865e960e2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 27 Dec 2013 15:25:28 +0100
Subject: [PATCH] input: sun4i-ts: Add support for temperature sensor
The sun4i resisitive touchscreen controller also comes with a built-in
temperature sensor. This commit adds support for it.
This commit also introduces a new "ts-attached" device-tree property,
when this is not set, the input part of the driver won't register. This way
the internal temperature sensor can be used to measure the SoC temperature
independent of there actually being a touchscreen attached to the controller.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../bindings/input/touchscreen/sun4i.txt | 5 +
drivers/input/touchscreen/sun4i-ts.c | 140 ++++++++++++++++-----
2 files changed, 114 insertions(+), 31 deletions(-)
--- a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
@@ -6,10 +6,15 @@ Required properties:
- reg: mmio address range of the chip
- interrupts: interrupt to which the chip is connected
+Optional properties:
+ - allwinner,ts-attached: boolean indicating that an actual touchscreen is
+ attached to the controller
+
Example:
rtp: rtp@01c25000 {
compatible = "allwinner,sun4i-ts";
reg = <0x01c25000 0x100>;
interrupts = <29>;
+ allwinner,ts-attached;
};
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -3,6 +3,9 @@
*
* Copyright (C) 2013 - 2014 Hans de Goede <hdegoede@redhat.com>
*
+ * The hwmon parts are based on work by Corentin LABBE which is:
+ * Copyright (C) 2013 Corentin LABBE <clabbe.montjoie@gmail.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
@@ -30,6 +33,7 @@
*/
#include <linux/err.h>
+#include <linux/hwmon.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
@@ -106,14 +110,12 @@ struct sun4i_ts_data {
void __iomem *base;
unsigned int irq;
bool ignore_fifo_data;
+ int temp_data;
};
-static irqreturn_t sun4i_ts_irq(int irq, void *dev_id)
+static void sun4i_ts_irq_handle_input(struct sun4i_ts_data *ts, u32 reg_val)
{
- struct sun4i_ts_data *ts = dev_id;
- u32 reg_val, x, y;
-
- reg_val = readl(ts->base + TP_INT_FIFOS);
+ u32 x, y;
if (reg_val & FIFO_DATA_PENDING) {
x = readl(ts->base + TP_DATA);
@@ -139,6 +141,20 @@ static irqreturn_t sun4i_ts_irq(int irq,
input_report_key(ts->input, BTN_TOUCH, 0);
input_sync(ts->input);
}
+}
+
+static irqreturn_t sun4i_ts_irq(int irq, void *dev_id)
+{
+ struct sun4i_ts_data *ts = dev_id;
+ u32 reg_val;
+
+ reg_val = readl(ts->base + TP_INT_FIFOS);
+
+ if (reg_val & TEMP_DATA_PENDING)
+ ts->temp_data = readl(ts->base + TEMP_DATA);
+
+ if (ts->input)
+ sun4i_ts_irq_handle_input(ts, reg_val);
writel(reg_val, ts->base + TP_INT_FIFOS);
@@ -149,9 +165,9 @@ static int sun4i_ts_open(struct input_de
{
struct sun4i_ts_data *ts = input_get_drvdata(dev);
- /* Flush, set trig level to 1, enable data and up irqs */
- writel(DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) | TP_UP_IRQ_EN(1),
- ts->base + TP_INT_FIFOC);
+ /* Flush, set trig level to 1, enable temp, data and up irqs */
+ writel(TEMP_IRQ_EN(1) | DATA_IRQ_EN(1) | FIFO_TRIG(1) | FIFO_FLUSH(1) |
+ TP_UP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
return 0;
}
@@ -160,15 +176,48 @@ static void sun4i_ts_close(struct input_
{
struct sun4i_ts_data *ts = input_get_drvdata(dev);
- /* Deactivate all IRQs */
- writel(0, ts->base + TP_INT_FIFOC);
+ /* Deactivate all input IRQs */
+ writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sun4i_ts_data *ts = dev_get_drvdata(dev);
+
+ /* No temp_data until the first irq */
+ if (ts->temp_data == -1)
+ return -EAGAIN;
+
+ return sprintf(buf, "%d\n", (ts->temp_data - 1447) * 100);
+}
+
+static ssize_t show_temp_label(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "SoC temperature\n");
}
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL);
+
+static struct attribute *sun4i_ts_attrs[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_temp1_label.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(sun4i_ts);
+
static int sun4i_ts_probe(struct platform_device *pdev)
{
struct sun4i_ts_data *ts;
struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device *hwmon;
int ret;
+ bool ts_attached;
+
+ ts_attached = of_property_read_bool(np, "allwinner,ts-attached");
ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL);
if (!ts)
@@ -176,24 +225,27 @@ static int sun4i_ts_probe(struct platfor
ts->dev = dev;
ts->ignore_fifo_data = true;
+ ts->temp_data = -1;
- ts->input = devm_input_allocate_device(dev);
- if (!ts->input)
- return -ENOMEM;
-
- ts->input->name = pdev->name;
- ts->input->phys = "sun4i_ts/input0";
- ts->input->open = sun4i_ts_open;
- ts->input->close = sun4i_ts_close;
- ts->input->id.bustype = BUS_HOST;
- ts->input->id.vendor = 0x0001;
- ts->input->id.product = 0x0001;
- ts->input->id.version = 0x0100;
- ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
- set_bit(BTN_TOUCH, ts->input->keybit);
- input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0);
- input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0);
- input_set_drvdata(ts->input, ts);
+ if (ts_attached) {
+ ts->input = devm_input_allocate_device(dev);
+ if (!ts->input)
+ return -ENOMEM;
+
+ ts->input->name = pdev->name;
+ ts->input->phys = "sun4i_ts/input0";
+ ts->input->open = sun4i_ts_open;
+ ts->input->close = sun4i_ts_close;
+ ts->input->id.bustype = BUS_HOST;
+ ts->input->id.vendor = 0x0001;
+ ts->input->id.product = 0x0001;
+ ts->input->id.version = 0x0100;
+ ts->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
+ set_bit(BTN_TOUCH, ts->input->keybit);
+ input_set_abs_params(ts->input, ABS_X, 0, 4095, 0, 0);
+ input_set_abs_params(ts->input, ABS_Y, 0, 4095, 0, 0);
+ input_set_drvdata(ts->input, ts);
+ }
ts->base = devm_ioremap_resource(dev,
platform_get_resource(pdev, IORESOURCE_MEM, 0));
@@ -232,14 +284,39 @@ static int sun4i_ts_probe(struct platfor
writel(STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1) | TP_MODE_EN(1),
ts->base + TP_CTRL1);
- ret = input_register_device(ts->input);
- if (ret)
- return ret;
+ hwmon = devm_hwmon_device_register_with_groups(ts->dev, "sun4i_ts",
+ ts, sun4i_ts_groups);
+ if (IS_ERR(hwmon))
+ return PTR_ERR(hwmon);
+
+ writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
+
+ if (ts_attached) {
+ ret = input_register_device(ts->input);
+ if (ret) {
+ writel(0, ts->base + TP_INT_FIFOC);
+ return ret;
+ }
+ }
platform_set_drvdata(pdev, ts);
return 0;
}
+static int sun4i_ts_remove(struct platform_device *pdev)
+{
+ struct sun4i_ts_data *ts = platform_get_drvdata(pdev);
+
+ /* Explicit unregister to avoid open/close changing the imask later */
+ if (ts->input)
+ input_unregister_device(ts->input);
+
+ /* Deactivate all IRQs */
+ writel(0, ts->base + TP_INT_FIFOC);
+
+ return 0;
+}
+
static const struct of_device_id sun4i_ts_of_match[] = {
{ .compatible = "allwinner,sun4i-ts", },
{ /* sentinel */ }
@@ -253,6 +330,7 @@ static struct platform_driver sun4i_ts_d
.of_match_table = of_match_ptr(sun4i_ts_of_match),
},
.probe = sun4i_ts_probe,
+ .remove = sun4i_ts_remove,
};
module_platform_driver(sun4i_ts_driver);

View file

@ -1,326 +0,0 @@
From 3f8fd9b9e2daefb7be4c46369f86af1c7bb2f1ca Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 1 Jan 2014 19:44:49 +0100
Subject: [PATCH] input: Add new sun4i-lradc-keys driver
Allwinnner sunxi SoCs have a low resolution adc (called lradc) which is
specifically designed to have various (tablet) keys (ie home, back, search,
etc). attached to it using a resistor network. This adds a driver for this.
There are 2 channels, currently this driver only supports chan0 since there
are no boards known to use chan1. The devicetree properties are already
prefixed with chan0 as preparation for chan1 support in the future.
This has been tested on an olimex a10s-olinuxino-micro, a13-olinuxino, and
a20-olinuxino-micro.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/input/sun4i-lradc-keys.txt | 22 ++
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/sun4i-lradc-keys.c | 243 +++++++++++++++++++++
4 files changed, 276 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
create mode 100644 drivers/input/keyboard/sun4i-lradc-keys.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
@@ -0,0 +1,22 @@
+Allwinner sun4i low res adc attached tablet keys
+------------------------------------------------
+
+Required properties:
+ - compatible: "allwinner,sun4i-lradc-keys"
+ - reg: mmio address range of the chip
+ - interrupts: interrupt to which the chip is connected
+ - allwinner,chan0-step: step in mV between keys must be 150 or 200
+ - linux,chan0-keycodes: array of dt-bindings/input/input.h KEY_ codes
+
+Example:
+
+#include <dt-bindings/input/input.h>
+
+ lradc: lradc@01c22800 {
+ compatible = "allwinner,sun4i-lradc-keys";
+ reg = <0x01c22800 0x100>;
+ interrupts = <31>;
+ allwinner,chan0-step = <200>;
+ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
+ KEY_MENU KEY_ENTER KEY_HOME>;
+ };
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -544,6 +544,16 @@ config KEYBOARD_STMPE
To compile this driver as a module, choose M here: the module will be
called stmpe-keypad.
+config KEYBOARD_SUN4I_LRADC
+ tristate "Allwinner sun4i low res adc attached tablet keys support"
+ depends on ARCH_SUNXI
+ help
+ This selects support for the Allwinner low res adc attached tablet
+ keys found on Allwinner sunxi SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sun4i-lradc-keys.
+
config KEYBOARD_DAVINCI
tristate "TI DaVinci Key Scan"
depends on ARCH_DAVINCI_DM365
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_k
obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
+obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
--- /dev/null
+++ b/drivers/input/keyboard/sun4i-lradc-keys.c
@@ -0,0 +1,243 @@
+/*
+ * Allwinner sun4i low res adc attached tablet keys driver
+ *
+ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Allwinnner sunxi SoCs have a lradc which is specifically designed to have
+ * various (tablet) keys (ie home, back, search, etc). attached to it using
+ * a resistor network. This driver is for the keys on such boards.
+ *
+ * There are 2 channels, currently this driver only supports chan0 since there
+ * are no boards known to use chan1. The devicetree properties are already
+ * prefixed with chan0 as preparation for chan1 support in the future.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define LRADC_CTRL 0x00
+#define LRADC_INTC 0x04
+#define LRADC_INTS 0x08
+#define LRADC_DATA0 0x0c
+#define LRADC_DATA1 0x10
+
+/* LRADC_CTRL bits */
+#define FIRST_CONVERT_DLY(x) ((x) << 24) /* 8 bits */
+#define CHAN_SELECT(x) ((x) << 22) /* 2 bits */
+#define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */
+#define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */
+#define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */
+#define HOLD_EN(x) ((x) << 6)
+#define LEVELB_VOL(x) ((x) << 4) /* 2 bits */
+#define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */
+#define ENABLE(x) ((x) << 0)
+
+/* LRADC_INTC and LRADC_INTS bits */
+#define CHAN1_KEYUP_IRQ BIT(12)
+#define CHAN1_ALRDY_HOLD_IRQ BIT(11)
+#define CHAN1_HOLD_IRQ BIT(10)
+#define CHAN1_KEYDOWN_IRQ BIT(9)
+#define CHAN1_DATA_IRQ BIT(8)
+#define CHAN0_KEYUP_IRQ BIT(4)
+#define CHAN0_ALRDY_HOLD_IRQ BIT(3)
+#define CHAN0_HOLD_IRQ BIT(2)
+#define CHAN0_KEYDOWN_IRQ BIT(1)
+#define CHAN0_DATA_IRQ BIT(0)
+
+#define MAX_KEYS 13
+
+/* Lookup table to map the adc val to a keycode index for 150 mv step size */
+static const u8 adc_val_to_key_index_step150[64] = {
+ 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2,
+ 3, 3, 3, 3,
+ 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6,
+ 7, 7, 7, 7,
+ 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9,
+ 10, 10, 10, 10,
+ 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
+};
+
+/* Lookup table to map the adc val to a keycode index for 200 mv step size */
+static const u8 adc_val_to_key_index_step200[64] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+struct sun4i_lradc_data {
+ struct device *dev;
+ struct input_dev *input;
+ void __iomem *base;
+ u32 chan0_step;
+ u32 chan0_keycode;
+ u32 chan0_keycodes[MAX_KEYS];
+};
+
+static irqreturn_t sun4i_lradc_irq(int irq, void *dev_id)
+{
+ struct sun4i_lradc_data *lradc = dev_id;
+ u32 ints, val;
+
+ ints = readl(lradc->base + LRADC_INTS);
+
+ /*
+ * lradc supports only one keypress at a time, release does not give
+ * any info as to which key was released, so we cache the keycode.
+ */
+ if ((ints & CHAN0_KEYDOWN_IRQ) && lradc->chan0_keycode == 0) {
+ val = readl(lradc->base + LRADC_DATA0);
+ if (lradc->chan0_step == 150)
+ val = adc_val_to_key_index_step150[val];
+ else
+ val = adc_val_to_key_index_step200[val];
+
+ lradc->chan0_keycode = lradc->chan0_keycodes[val];
+ input_report_key(lradc->input, lradc->chan0_keycode, 1);
+ }
+
+ if (ints & CHAN0_KEYUP_IRQ) {
+ input_report_key(lradc->input, lradc->chan0_keycode, 0);
+ lradc->chan0_keycode = 0;
+ }
+
+ input_sync(lradc->input);
+
+ writel(ints, lradc->base + LRADC_INTS);
+
+ return IRQ_HANDLED;
+}
+
+static int sun4i_lradc_open(struct input_dev *dev)
+{
+ struct sun4i_lradc_data *lradc = input_get_drvdata(dev);
+
+ /*
+ * Set sample time to 16 ms / 62.5 Hz. Wait 2 * 16 ms for key to
+ * stabilize on press, wait (1 + 1) * 16 ms for key release
+ */
+ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) |
+ SAMPLE_RATE(2) | ENABLE(1), lradc->base + LRADC_CTRL);
+
+ writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC);
+
+ return 0;
+}
+
+static void sun4i_lradc_close(struct input_dev *dev)
+{
+ struct sun4i_lradc_data *lradc = input_get_drvdata(dev);
+
+ /* Disable lradc, leave other settings unchanged */
+ writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) |
+ SAMPLE_RATE(2), lradc->base + LRADC_CTRL);
+ writel(0, lradc->base + LRADC_INTC);
+}
+
+static int sun4i_lradc_probe(struct platform_device *pdev)
+{
+ struct sun4i_lradc_data *lradc;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ int i, ret;
+
+ lradc = devm_kzalloc(dev, sizeof(struct sun4i_lradc_data), GFP_KERNEL);
+ if (!lradc)
+ return -ENOMEM;
+
+ ret = of_property_read_u32(np, "allwinner,chan0-step",
+ &lradc->chan0_step);
+ if (ret || (lradc->chan0_step != 150 && lradc->chan0_step != 200)) {
+ dev_err(dev, "Invalid allwinner,chan0-step dt-property\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MAX_KEYS; i++)
+ of_property_read_u32_index(np, "linux,chan0-keycodes",
+ i, &lradc->chan0_keycodes[i]);
+
+ lradc->dev = dev;
+ lradc->input = devm_input_allocate_device(dev);
+ if (!lradc->input)
+ return -ENOMEM;
+
+ lradc->input->name = pdev->name;
+ lradc->input->phys = "sun4i_lradc/input0";
+ lradc->input->open = sun4i_lradc_open;
+ lradc->input->close = sun4i_lradc_close;
+ lradc->input->id.bustype = BUS_HOST;
+ lradc->input->id.vendor = 0x0001;
+ lradc->input->id.product = 0x0001;
+ lradc->input->id.version = 0x0100;
+ lradc->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY);
+ for (i = 0; i < MAX_KEYS; i++)
+ set_bit(lradc->chan0_keycodes[i], lradc->input->keybit);
+ input_set_drvdata(lradc->input, lradc);
+
+ lradc->base = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (IS_ERR(lradc->base))
+ return PTR_ERR(lradc->base);
+
+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), sun4i_lradc_irq,
+ 0, "sun4i-lradc-keys", lradc);
+ if (ret)
+ return ret;
+
+ ret = input_register_device(lradc->input);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, lradc);
+ return 0;
+}
+
+static const struct of_device_id sun4i_lradc_of_match[] = {
+ { .compatible = "allwinner,sun4i-lradc-keys", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match);
+
+static struct platform_driver sun4i_lradc_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sun4i-lradc-keys",
+ .of_match_table = of_match_ptr(sun4i_lradc_of_match),
+ },
+ .probe = sun4i_lradc_probe,
+};
+
+module_platform_driver(sun4i_lradc_driver);
+
+MODULE_DESCRIPTION("Allwinner sun4i low res adc attached tablet keys driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");

View file

@ -1,26 +0,0 @@
From 87d0c26803eec56971c8a7e6299aefc4d72dfb3c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 1 Jan 2014 19:51:36 +0100
Subject: [PATCH] ARM: dts: sun4i: Add lradc node
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -549,6 +549,13 @@
interrupts = <24>;
};
+ lradc: lradc@01c22800 {
+ compatible = "allwinner,sun4i-lradc-keys";
+ reg = <0x01c22800 0x100>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
sid: eeprom@01c23800 {
compatible = "allwinner,sun4i-sid";
reg = <0x01c23800 0x10>;

View file

@ -1,53 +0,0 @@
From 9041b1f6118b32929e6357affb53db28439a11e7 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 1 Jan 2014 19:50:33 +0100
Subject: [PATCH] ARM: dts: sun5i: Add lradc node
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 8 ++++++++
arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 8 ++++++++
arch/arm/boot/dts/sun5i-a13.dtsi | 7 +++++++
4 files changed, 30 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -14,6 +14,7 @@
/dts-v1/;
/include/ "sun5i-a13.dtsi"
/include/ "sunxi-common-regulators.dtsi"
+#include <dt-bindings/input/input.h>
/ {
model = "Olimex A13-Olinuxino";
@@ -49,6 +50,13 @@
};
};
+ lradc: lradc@01c22800 {
+ allwinner,chan0-step = <200>;
+ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
+ KEY_MENU KEY_ENTER KEY_HOME>;
+ status = "okay";
+ };
+
uart1: serial@01c28400 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_b>;
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -429,6 +429,13 @@
reg = <0x01c20c90 0x10>;
};
+ lradc: lradc@01c22800 {
+ compatible = "allwinner,sun4i-lradc-keys";
+ reg = <0x01c22800 0x100>;
+ interrupts = <31>;
+ status = "disabled";
+ };
+
sid: eeprom@01c23800 {
compatible = "allwinner,sun4i-sid";
reg = <0x01c23800 0x10>;

View file

@ -1,52 +0,0 @@
From 98e21d18a26032912bf6c979f084c200a94e976b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 1 Jan 2014 20:26:21 +0100
Subject: [PATCH] ARM: dts: sun7i: Add lradc node
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 9 +++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 7 +++++++
2 files changed, 16 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -14,6 +14,7 @@
/dts-v1/;
/include/ "sun7i-a20.dtsi"
/include/ "sunxi-common-regulators.dtsi"
+#include <dt-bindings/input/input.h>
/ {
model = "Olimex A20-Olinuxino Micro";
@@ -73,6 +74,14 @@
};
};
+ lradc: lradc@01c22800 {
+ allwinner,chan0-step = <200>;
+ linux,chan0-keycodes = <KEY_VOLUMEUP KEY_VOLUMEDOWN
+ KEY_MENU KEY_SEARCH KEY_HOME
+ KEY_ESC KEY_ENTER>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -670,6 +670,13 @@
interrupts = <0 24 4>;
};
+ lradc: lradc@01c22800 {
+ compatible = "allwinner,sun4i-lradc-keys";
+ reg = <0x01c22800 0x100>;
+ interrupts = <0 31 4>;
+ status = "disabled";
+ };
+
sid: eeprom@01c23800 {
compatible = "allwinner,sun7i-a20-sid";
reg = <0x01c23800 0x200>;

View file

@ -1,112 +0,0 @@
From bfea2b9be28b20e076d5df8863c25e966f413fa3 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Fri, 20 Dec 2013 22:41:07 +0100
Subject: [PATCH] reset: Add of_reset_control_get
In some cases, you might need to deassert from reset an hardware block that
doesn't associated to a struct device (CPUs, timers, etc.).
Add a small helper to retrieve the reset controller from the device tree
without the need to pass a struct device.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/reset/core.c | 39 ++++++++++++++++++++++++++++++---------
include/linux/reset.h | 4 ++++
2 files changed, 34 insertions(+), 9 deletions(-)
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -127,15 +127,16 @@ int reset_control_deassert(struct reset_
EXPORT_SYMBOL_GPL(reset_control_deassert);
/**
- * reset_control_get - Lookup and obtain a reference to a reset controller.
- * @dev: device to be reset by the controller
+ * of_reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @node: device to be reset by the controller
* @id: reset line name
*
* Returns a struct reset_control or IS_ERR() condition containing errno.
*
* Use of id names is optional.
*/
-struct reset_control *reset_control_get(struct device *dev, const char *id)
+struct reset_control *of_reset_control_get(struct device_node *node,
+ const char *id)
{
struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
struct reset_controller_dev *r, *rcdev;
@@ -144,13 +145,10 @@ struct reset_control *reset_control_get(
int rstc_id;
int ret;
- if (!dev)
- return ERR_PTR(-EINVAL);
-
if (id)
- index = of_property_match_string(dev->of_node,
+ index = of_property_match_string(node,
"reset-names", id);
- ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
+ ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
index, &args);
if (ret)
return ERR_PTR(ret);
@@ -185,12 +183,35 @@ struct reset_control *reset_control_get(
return ERR_PTR(-ENOMEM);
}
- rstc->dev = dev;
rstc->rcdev = rcdev;
rstc->id = rstc_id;
return rstc;
}
+EXPORT_SYMBOL_GPL(of_reset_control_get);
+
+/**
+ * reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Returns a struct reset_control or IS_ERR() condition containing errno.
+ *
+ * Use of id names is optional.
+ */
+struct reset_control *reset_control_get(struct device *dev, const char *id)
+{
+ struct reset_control *rstc;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ rstc = of_reset_control_get(dev->of_node, id);
+ if (!IS_ERR(rstc))
+ rstc->dev = dev;
+
+ return rstc;
+}
EXPORT_SYMBOL_GPL(reset_control_get);
/**
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_RESET_H_
#define _LINUX_RESET_H_
+#include <linux/of.h>
+
struct device;
struct reset_control;
@@ -8,6 +10,8 @@ int reset_control_reset(struct reset_con
int reset_control_assert(struct reset_control *rstc);
int reset_control_deassert(struct reset_control *rstc);
+struct reset_control *of_reset_control_get(struct device_node *node,
+ const char *id);
struct reset_control *reset_control_get(struct device *dev, const char *id);
void reset_control_put(struct reset_control *rstc);
struct reset_control *devm_reset_control_get(struct device *dev, const char *id);

View file

@ -1,62 +0,0 @@
From 3ec31fa2ce161d35f787354037f94d9d22d825d1 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Fri, 20 Dec 2013 22:41:08 +0100
Subject: [PATCH] clocksource: sun5i: Add support for reset controller
The Allwinner A31 that uses this timer has the timer IP asserted in reset.
Add an optional reset property to the DT, and deassert the timer from reset if
it's there.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt | 4 ++++
drivers/clocksource/timer-sun5i.c | 6 ++++++
2 files changed, 10 insertions(+)
--- a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
+++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
@@ -9,6 +9,9 @@ Required properties:
one)
- clocks: phandle to the source clock (usually the AHB clock)
+Optionnal properties:
+- resets: phandle to a reset controller asserting the timer
+
Example:
timer@01c60000 {
@@ -19,4 +22,5 @@ timer@01c60000 {
<0 53 1>,
<0 54 1>;
clocks = <&ahb1_gates 19>;
+ resets = <&ahb1rst 19>;
};
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
+#include <linux/reset.h>
#include <linux/sched_clock.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -143,6 +144,7 @@ static u64 sun5i_timer_sched_read(void)
static void __init sun5i_timer_init(struct device_node *node)
{
+ struct reset_control *rstc;
unsigned long rate;
struct clk *clk;
int ret, irq;
@@ -162,6 +164,10 @@ static void __init sun5i_timer_init(stru
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
+ rstc = of_reset_control_get(node, NULL);
+ if (!IS_ERR(rstc))
+ reset_control_deassert(rstc);
+
writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
timer_base + TIMER_CTL_REG(1));

View file

@ -1,50 +0,0 @@
From 0bf618fda3ad24649add0bf943d16a9b4f5c3463 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:37 +0800
Subject: [PATCH] clk: sunxi: add clock-output-names dt property support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
sunxi clock drivers use dt node name as clock name, but clock
nodes should be named clk@X, so the names would be the same.
Let the drivers read clock names from dt clock-output-names
property.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -51,6 +51,8 @@ static void __init sun4i_osc_clk_setup(s
if (!gate)
goto err_free_fixed;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
/* set up gate and fixed rate properties */
gate->reg = of_iomap(node, 0);
gate->bit_idx = SUNXI_OSC24M_GATE;
@@ -601,6 +603,8 @@ static void __init sunxi_mux_clk_setup(s
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
i++;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
clk = clk_register_mux(NULL, clk_name, parents, i,
CLK_SET_RATE_NO_REPARENT, reg,
data->shift, SUNXI_MUX_GATE_WIDTH,
@@ -660,6 +664,8 @@ static void __init sunxi_divider_clk_set
clk_parent = of_clk_get_parent_name(node, 0);
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
reg, data->shift, data->width,
data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,

View file

@ -1,78 +0,0 @@
From 8f3156f3f2b70128b2761526c208c8e3bfda694e Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:39 +0800
Subject: [PATCH] clk: sunxi: add names for pll5, pll6 parent clocks to
factors_data
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some factor clocks, such as the parent clock of pll5 and pll6, have
multiple output names. Add the corresponding names to factors_data
tied to compatible string.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -389,6 +389,7 @@ struct factors_data {
int mux;
struct clk_factors_config *table;
void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+ const char *name;
};
static struct clk_factors_config sun4i_pll1_config = {
@@ -457,6 +458,14 @@ static const struct factors_data sun4i_p
.enable = 31,
.table = &sun4i_pll5_config,
.getter = sun4i_get_pll5_factors,
+ .name = "pll5",
+};
+
+static const struct factors_data sun4i_pll6_data __initconst = {
+ .enable = 31,
+ .table = &sun4i_pll5_config,
+ .getter = sun4i_get_pll5_factors,
+ .name = "pll6",
};
static const struct factors_data sun4i_apb1_data __initconst = {
@@ -499,14 +508,14 @@ static struct clk * __init sunxi_factors
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
i++;
- /* Nodes should be providing the name via clock-output-names
- * but originally our dts didn't, and so we used node->name.
- * The new, better nodes look like clk@deadbeef, so we pull the
- * name just in this case */
- if (!strcmp("clk", clk_name)) {
- of_property_read_string_index(node, "clock-output-names",
- 0, &clk_name);
- }
+ /*
+ * some factor clocks, such as pll5 and pll6, may have multiple
+ * outputs, and have their name designated in factors_data
+ */
+ if (data->name)
+ clk_name = data->name;
+ else
+ of_property_read_string(node, "clock-output-names", &clk_name);
factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
if (!factors)
@@ -838,7 +847,7 @@ static const struct divs_data pll5_divs_
};
static const struct divs_data pll6_divs_data __initconst = {
- .factors = &sun4i_pll5_data,
+ .factors = &sun4i_pll6_data,
.div = {
{ .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
{ .fixed = 2 }, /* P, other */

View file

@ -1,128 +0,0 @@
From 0643a93746775da2189ab0afd8f748afcaa791c5 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 7 Feb 2014 16:21:49 +0100
Subject: [PATCH] clk: sunxi: Add support for USB clock-register reset bits
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The usb-clk register is special in that it not only contains clk gate bits,
but also has a few reset bits. This commit adds support for this by allowing
gates type sunxi clks to also register a reset controller.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 71 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -18,6 +18,7 @@
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/reset-controller.h>
#include "clk-factors.h"
@@ -688,6 +689,59 @@ static void __init sunxi_divider_clk_set
/**
+ * sunxi_gates_reset... - reset bits in leaf gate clk registers handling
+ */
+
+struct gates_reset_data {
+ void __iomem *reg;
+ spinlock_t *lock;
+ struct reset_controller_dev rcdev;
+};
+
+static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct gates_reset_data *data = container_of(rcdev,
+ struct gates_reset_data,
+ rcdev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(data->lock, flags);
+
+ reg = readl(data->reg);
+ writel(reg & ~BIT(id), data->reg);
+
+ spin_unlock_irqrestore(data->lock, flags);
+
+ return 0;
+}
+
+static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct gates_reset_data *data = container_of(rcdev,
+ struct gates_reset_data,
+ rcdev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(data->lock, flags);
+
+ reg = readl(data->reg);
+ writel(reg | BIT(id), data->reg);
+
+ spin_unlock_irqrestore(data->lock, flags);
+
+ return 0;
+}
+
+static struct reset_control_ops sunxi_gates_reset_ops = {
+ .assert = sunxi_gates_reset_assert,
+ .deassert = sunxi_gates_reset_deassert,
+};
+
+/**
* sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
*/
@@ -695,6 +749,7 @@ static void __init sunxi_divider_clk_set
struct gates_data {
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
+ u32 reset_mask;
};
static const struct gates_data sun4i_axi_gates_data __initconst = {
@@ -765,6 +820,7 @@ static void __init sunxi_gates_clk_setup
struct gates_data *data)
{
struct clk_onecell_data *clk_data;
+ struct gates_reset_data *reset_data;
const char *clk_parent;
const char *clk_name;
void *reg;
@@ -808,6 +864,21 @@ static void __init sunxi_gates_clk_setup
clk_data->clk_num = i;
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ /* Register a reset controler for gates with reset bits */
+ if (data->reset_mask == 0)
+ return;
+
+ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+ if (!reset_data)
+ return;
+
+ reset_data->reg = reg;
+ reset_data->lock = &clk_lock;
+ reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
+ reset_data->rcdev.ops = &sunxi_gates_reset_ops;
+ reset_data->rcdev.of_node = node;
+ reset_controller_register(&reset_data->rcdev);
}

View file

@ -1,40 +0,0 @@
From 0566b74f93eaf6b2281d2605a63e06e6ba809334 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 3 Feb 2014 09:51:40 +0800
Subject: [PATCH] clk: sunxi: get divs parent clock name from parent factor
clock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Divs clocks consist of a parent factor clock with multiple outputs,
and seperate clocks for each output. Get the name of the parent
clock from the parent factor clock, instead of the DT node name.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-sunxi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -940,7 +940,7 @@ static void __init sunxi_divs_clk_setup(
struct divs_data *data)
{
struct clk_onecell_data *clk_data;
- const char *parent = node->name;
+ const char *parent;
const char *clk_name;
struct clk **clks, *pclk;
struct clk_hw *gate_hw, *rate_hw;
@@ -954,6 +954,7 @@ static void __init sunxi_divs_clk_setup(
/* Set up factor clock that we will be dividing */
pclk = sunxi_factors_clk_setup(node, data->factors);
+ parent = __clk_get_name(pclk);
reg = of_iomap(node, 0);

View file

@ -1,69 +0,0 @@
From c61dfeb17581d32360a817ba40636aaed85caade Mon Sep 17 00:00:00 2001
From: Roman Byshko <rbyshko@gmail.com>
Date: Fri, 7 Feb 2014 16:21:50 +0100
Subject: [PATCH] clk: sunxi: Add USB clock register defintions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add register definitions for the usb-clk register found on sun4i, sun5i and
sun7i SoCs.
Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 5 +++++
drivers/clk/sunxi/clk-sunxi.c | 12 ++++++++++++
2 files changed, 17 insertions(+)
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -37,6 +37,8 @@ Required properties:
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
"allwinner,sun7i-a20-out-clk" - for the external output clocks
+ "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
+ "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
Required properties for all clocks:
- reg : shall be the control register address for the clock.
@@ -49,6 +51,9 @@ Required properties for all clocks:
Additionally, "allwinner,*-gates-clk" clocks require:
- clock-output-names : the corresponding gate names that the clock controls
+And "allwinner,*-usb-clk" clocks also require:
+- reset-cells : shall be set to 1
+
Clock consumers should specify the desired clocks they use with a
"clocks" phandle cell. Consumers that are using a gated clock should
provide an additional ID in their clock property. This ID is the
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -816,6 +816,16 @@ static const struct gates_data sun7i_a20
.mask = { 0xff80ff },
};
+static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
+ .mask = {0x1C0},
+ .reset_mask = 0x07,
+};
+
+static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
+ .mask = {0x140},
+ .reset_mask = 0x03,
+};
+
static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_data *data)
{
@@ -1107,6 +1117,8 @@ static const struct of_device_id clk_gat
{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
+ {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
+ {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
{}
};

View file

@ -1,104 +0,0 @@
From c225f78660cd61914f25dd00499c7ae71d1d6919 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Wed, 5 Feb 2014 14:05:03 +0100
Subject: [PATCH] clk: sunxi: Add support for PLL6 on the A31
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The A31 has a slightly different PLL6 clock. Add support for this new clock in
our driver.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
drivers/clk/sunxi/clk-sunxi.c | 45 +++++++++++++++++++++++
2 files changed, 46 insertions(+)
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -11,6 +11,7 @@ Required properties:
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
"allwinner,sun4i-pll5-clk" - for the PLL5 clock
"allwinner,sun4i-pll6-clk" - for the PLL6 clock
+ "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-axi-clk" - for the AXI clock
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -252,7 +252,38 @@ static void sun4i_get_pll5_factors(u32 *
*n = DIV_ROUND_UP(div, (*k+1));
}
+/**
+ * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6
+ * PLL6 rate is calculated as follows
+ * rate = parent_rate * n * (k + 1) / 2
+ * parent_rate is always 24Mhz
+ */
+
+static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /*
+ * We always have 24MHz / 2, so we can just say that our
+ * parent clock is 12MHz.
+ */
+ parent_rate = parent_rate / 2;
+
+ /* Normalize value to a parent_rate multiple (24M / 2) */
+ div = *freq / parent_rate;
+ *freq = parent_rate * div;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+ *k = div / 32;
+ if (*k > 3)
+ *k = 3;
+
+ *n = DIV_ROUND_UP(div, (*k+1));
+}
/**
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
@@ -420,6 +451,13 @@ static struct clk_factors_config sun4i_p
.kwidth = 2,
};
+static struct clk_factors_config sun6i_a31_pll6_config = {
+ .nshift = 8,
+ .nwidth = 5,
+ .kshift = 4,
+ .kwidth = 2,
+};
+
static struct clk_factors_config sun4i_apb1_config = {
.mshift = 0,
.mwidth = 5,
@@ -469,6 +507,12 @@ static const struct factors_data sun4i_p
.name = "pll6",
};
+static const struct factors_data sun6i_a31_pll6_data __initconst = {
+ .enable = 31,
+ .table = &sun6i_a31_pll6_config,
+ .getter = sun6i_a31_get_pll6_factors,
+};
+
static const struct factors_data sun4i_apb1_data __initconst = {
.table = &sun4i_apb1_config,
.getter = sun4i_get_apb1_factors,
@@ -1069,6 +1113,7 @@ 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,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
{.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},

View file

@ -1,175 +0,0 @@
From dd91dc4b9c55c8fa24738249214274442e2fcbd3 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 10 Feb 2014 18:35:47 +0800
Subject: [PATCH] clk: sunxi: Add Allwinner A20/A31 GMAC clock unit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Allwinner A20/A31 clock module controls the transmit clock source
and interface type of the GMAC ethernet controller. Model this as
a single clock for GMAC drivers to use.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 30 +++++++
drivers/clk/sunxi/clk-sunxi.c | 96 +++++++++++++++++++++++
2 files changed, 126 insertions(+)
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -38,6 +38,7 @@ Required properties:
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
"allwinner,sun7i-a20-out-clk" - for the external output clocks
+ "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
@@ -55,6 +56,9 @@ Additionally, "allwinner,*-gates-clk" cl
And "allwinner,*-usb-clk" clocks also require:
- reset-cells : shall be set to 1
+For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
+dummy clocks at 25 MHz and 125 MHz, respectively. See example.
+
Clock consumers should specify the desired clocks they use with a
"clocks" phandle cell. Consumers that are using a gated clock should
provide an additional ID in their clock property. This ID is the
@@ -82,3 +86,29 @@ cpu: cpu@01c20054 {
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>;
};
+
+mii_phy_tx_clk: clk@2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ clock-output-names = "mii_phy_tx";
+};
+
+gmac_int_tx_clk: clk@3 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_int_tx";
+};
+
+gmac_clk: clk@01c20164 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun7i-a20-gmac-clk";
+ reg = <0x01c20164 0x4>;
+ /*
+ * The first clock must be fixed at 25MHz;
+ * the second clock must be fixed at 125MHz
+ */
+ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
+ clock-output-names = "gmac";
+};
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -411,6 +411,102 @@ static void sun7i_a20_get_out_factors(u3
/**
+ * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
+ *
+ * This clock looks something like this
+ * ________________________
+ * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
+ * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
+ * Ext. 125MHz RGMII TX clk >--|__divider__/ |
+ * |________________________|
+ *
+ * The external 125 MHz reference is optional, i.e. GMAC can use its
+ * internal TX clock just fine. The A31 GMAC clock module does not have
+ * the divider controls for the external reference.
+ *
+ * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
+ * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
+ * select the appropriate source and gate/ungate the output to the PHY.
+ *
+ * Only the GMAC should use this clock. Altering the clock so that it doesn't
+ * match the GMAC's operation parameters will result in the GMAC not being
+ * able to send traffic out. The GMAC driver should set the clock rate and
+ * enable/disable this clock to configure the required state. The clock
+ * driver then responds by auto-reparenting the clock.
+ */
+
+#define SUN7I_A20_GMAC_GPIT 2
+#define SUN7I_A20_GMAC_MASK 0x3
+#define SUN7I_A20_GMAC_PARENTS 2
+
+static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ struct clk_mux *mux;
+ struct clk_gate *gate;
+ const char *clk_name = node->name;
+ const char *parents[SUN7I_A20_GMAC_PARENTS];
+ void *reg;
+
+ if (of_property_read_string(node, "clock-output-names", &clk_name))
+ return;
+
+ /* allocate mux and gate clock structs */
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+ if (!mux)
+ return;
+
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate)
+ goto free_mux;
+
+ /* gmac clock requires exactly 2 parents */
+ parents[0] = of_clk_get_parent_name(node, 0);
+ parents[1] = of_clk_get_parent_name(node, 1);
+ if (!parents[0] || !parents[1])
+ goto free_gate;
+
+ reg = of_iomap(node, 0);
+ if (!reg)
+ goto free_gate;
+
+ /* set up gate and fixed rate properties */
+ gate->reg = reg;
+ gate->bit_idx = SUN7I_A20_GMAC_GPIT;
+ gate->lock = &clk_lock;
+ mux->reg = reg;
+ mux->mask = SUN7I_A20_GMAC_MASK;
+ mux->flags = CLK_MUX_INDEX_BIT;
+ mux->lock = &clk_lock;
+
+ clk = clk_register_composite(NULL, clk_name,
+ parents, SUN7I_A20_GMAC_PARENTS,
+ &mux->hw, &clk_mux_ops,
+ NULL, NULL,
+ &gate->hw, &clk_gate_ops,
+ 0);
+
+ if (IS_ERR(clk))
+ goto iounmap_reg;
+
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ clk_register_clkdev(clk, clk_name, NULL);
+
+ return;
+
+iounmap_reg:
+ iounmap(reg);
+free_gate:
+ kfree(gate);
+free_mux:
+ kfree(mux);
+}
+CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
+ sun7i_a20_gmac_clk_setup);
+
+
+
+/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/

View file

@ -1,178 +0,0 @@
From 45ff9697ed1668e82ca3902b32309e157464e745 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Thu, 6 Feb 2014 09:55:57 +0100
Subject: [PATCH] clk: sunxi: Add new clock compatibles
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Allwinner A10 compatibles were following a slightly different compatible
patterns than the rest of the SoCs for historical reasons. Add compatibles
matching the other pattern to the clock driver for consistency, and keep the
older one for backward compatibility.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 36 +++++++++++------------
drivers/clk/sunxi/clk-sunxi.c | 30 +++++++++----------
2 files changed, 33 insertions(+), 33 deletions(-)
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -6,37 +6,37 @@ This binding uses the common clock bindi
Required properties:
- compatible : shall be one of the following:
- "allwinner,sun4i-osc-clk" - for a gatable oscillator
- "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
+ "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
+ "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
- "allwinner,sun4i-pll5-clk" - for the PLL5 clock
- "allwinner,sun4i-pll6-clk" - for the PLL6 clock
+ "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
+ "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
- "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
- "allwinner,sun4i-axi-clk" - for the AXI clock
- "allwinner,sun4i-axi-gates-clk" - for the AXI gates
- "allwinner,sun4i-ahb-clk" - for the AHB clock
- "allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
+ "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
+ "allwinner,sun4i-a10-axi-clk" - for the AXI clock
+ "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
+ "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
+ "allwinner,sun4i-a10-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
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
- "allwinner,sun4i-apb0-clk" - for the APB0 clock
- "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10
+ "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
+ "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
- "allwinner,sun4i-apb1-clk" - for the APB1 clock
- "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
- "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10
+ "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
+ "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
+ "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
- "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
+ "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
"allwinner,sun7i-a20-out-clk" - for the external output clocks
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
@@ -68,21 +68,21 @@ For example:
osc24M: osc24M@01c20050 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-osc-clk";
+ compatible = "allwinner,sun4i-a10-osc-clk";
reg = <0x01c20050 0x4>;
clocks = <&osc24M_fixed>;
};
pll1: pll1@01c20000 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-pll1-clk";
+ compatible = "allwinner,sun4i-a10-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
};
cpu: cpu@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-cpu-clk";
+ compatible = "allwinner,sun4i-a10-cpu-clk";
reg = <0x01c20054 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll1>;
};
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -80,7 +80,7 @@ err_free_gate:
err_free_fixed:
kfree(fixed);
}
-CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
+CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
@@ -1207,52 +1207,52 @@ free_clkdata:
/* Matches for factors clocks */
static const struct of_device_id clk_factors_match[] __initconst = {
- {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
+ {.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
- {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
- {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
+ {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
+ {.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
{}
};
/* Matches for divider clocks */
static const struct of_device_id clk_div_match[] __initconst = {
- {.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,},
- {.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,},
- {.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,},
+ {.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,},
+ {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
+ {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
{.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
{}
};
/* Matches for divided outputs */
static const struct of_device_id clk_divs_match[] __initconst = {
- {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
- {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
+ {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
+ {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
{}
};
/* Matches for mux clocks */
static const struct of_device_id clk_mux_match[] __initconst = {
- {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
- {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
+ {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
+ {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
{}
};
/* Matches for gate clocks */
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,sun4i-a10-axi-gates-clk", .data = &sun4i_axi_gates_data,},
+ {.compatible = "allwinner,sun4i-a10-ahb-gates-clk", .data = &sun4i_ahb_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,},
{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
- {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
+ {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
{.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
- {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
+ {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
{.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},

View file

@ -1,68 +0,0 @@
From b416520f239aeaa4207ebe84c22247cff2da444f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Thu, 5 Sep 2013 19:52:41 -0300
Subject: [PATCH] clk: sunxi: factors: automatic reparenting support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit implements .determine_rate, so that our factor clocks can be
reparented when needed.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
---
drivers/clk/sunxi/clk-factors.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -77,6 +77,41 @@ static long clk_factors_round_rate(struc
return rate;
}
+static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_p)
+{
+ struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ int i, num_parents;
+ unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
+
+ /* find the parent that can help provide the fastest rate <= rate */
+ num_parents = __clk_get_num_parents(clk);
+ for (i = 0; i < num_parents; i++) {
+ parent = clk_get_parent_by_index(clk, i);
+ if (!parent)
+ continue;
+ if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
+ parent_rate = __clk_round_rate(parent, rate);
+ else
+ parent_rate = __clk_get_rate(parent);
+
+ child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
+
+ if (child_rate <= rate && child_rate > best_child_rate) {
+ best_parent = parent;
+ best = parent_rate;
+ best_child_rate = child_rate;
+ }
+ }
+
+ if (best_parent)
+ *best_parent_p = best_parent;
+ *best_parent_rate = best;
+
+ return best_child_rate;
+}
+
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
@@ -113,6 +148,7 @@ static int clk_factors_set_rate(struct c
}
const struct clk_ops clk_factors_ops = {
+ .determine_rate = clk_factors_determine_rate,
.recalc_rate = clk_factors_recalc_rate,
.round_rate = clk_factors_round_rate,
.set_rate = clk_factors_set_rate,

View file

@ -1,87 +0,0 @@
From 36268d704307282109ec246f65cac2a42c825629 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
Date: Fri, 20 Sep 2013 20:29:17 -0300
Subject: [PATCH] clk: sunxi: Implement MMC phase control
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
HdG: add header exporting clk_sunxi_mmc_phase_control
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/clk/sunxi/clk-sunxi.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/clk/sunxi.h | 22 ++++++++++++++++++++++
2 files changed, 57 insertions(+)
create mode 100644 include/linux/clk/sunxi.h
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -507,6 +507,41 @@ CLK_OF_DECLARE(sun7i_a20_gmac, "allwinne
/**
+ * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
+ */
+
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output)
+{
+ #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
+ #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+
+ struct clk_composite *composite = to_clk_composite(hw);
+ struct clk_hw *rate_hw = composite->rate_hw;
+ struct clk_factors *factors = to_clk_factors(rate_hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+
+ reg = readl(factors->reg);
+
+ /* set sample clock phase control */
+ reg &= ~(0x7 << 20);
+ reg |= ((sample & 0x7) << 20);
+
+ /* set output clock phase control */
+ reg &= ~(0x7 << 8);
+ reg |= ((output & 0x7) << 8);
+
+ writel(reg, factors->reg);
+
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+}
+
+
+/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 - Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_CLK_SUNXI_H_
+#define __LINUX_CLK_SUNXI_H_
+
+#include <linux/clk.h>
+
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
+
+#endif

View file

@ -1,872 +0,0 @@
From 3b5db9d024f173c30ef4060c31bb8e9fbd194cc1 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(-)
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -606,6 +606,7 @@ static int ahci_vt8251_hardreset(struct
unsigned long deadline)
{
struct ata_port *ap = link->ap;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
bool online;
int rc;
@@ -616,7 +617,7 @@ static int ahci_vt8251_hardreset(struct
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);
@@ -631,6 +632,7 @@ static int ahci_p5wdh_hardreset(struct a
{
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;
@@ -646,7 +648,7 @@ static int ahci_p5wdh_hardreset(struct a
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
--- 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
@@ -51,6 +52,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,
@@ -322,8 +324,15 @@ 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 */
+ struct regulator *target_pwr; /* Optional */
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;
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -394,6 +394,9 @@ static ssize_t ahci_show_em_supported(st
*
* 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 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_p
/* 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_lin
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_lin
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 *a
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(struc
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(s
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(s
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_p
} 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_
pp->fbs_enabled = false;
}
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
}
static void ahci_pmp_attach(struct ata_port *ap)
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -403,6 +403,7 @@ static int ahci_highbank_hardreset(struc
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(struc
break;
} while (!online && retry--);
- ahci_start_engine(ap);
+ hpriv->start_engine(ap);
if (online)
*class = ahci_dev_classify(ap);
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -10,6 +10,8 @@ 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 {
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -87,78 +87,252 @@ static struct scsi_host_template ahci_pl
AHCI_SHT("ahci_platform"),
};
-static int ahci_probe(struct platform_device *pdev)
+/**
+ * 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)
{
- 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;
- int irq;
- int n_ports;
- int i;
- int rc;
+ int c, rc;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(dev, "no mmio space\n");
- return -EINVAL;
+ 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;
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(dev, "no irq\n");
- return -EINVAL;
- }
+disable_unprepare_clk:
+ while (--c >= 0)
+ clk_disable_unprepare(hpriv->clks[c]);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
- if (pdata && pdata->ata_port_info)
- pi = *pdata->ata_port_info;
+/**
+ * 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;
- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv) {
- dev_err(dev, "can't alloc ahci_host_priv\n");
- return -ENOMEM;
+ 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);
+
+/**
+ * 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;
}
- hpriv->flags |= (unsigned long)pi.private_data;
+ 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);
- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
+ if (hpriv->target_pwr)
+ regulator_disable(hpriv->target_pwr);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
+
+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]);
+}
+
+/**
+ * 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_host_priv *hpriv;
+ struct clk *clk;
+ int i, rc = -ENOMEM;
+
+ if (!devres_open_group(dev, NULL, GFP_KERNEL))
+ return ERR_PTR(-ENOMEM);
+
+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
+ GFP_KERNEL);
+ if (!hpriv)
+ goto err_out;
+
+ devres_add(dev, hpriv);
+
+ 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->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;
+ 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)
+ goto err_out;
+ 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,
+ * 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 err_out;
+ break;
}
+ hpriv->clks[i] = clk;
}
- /*
- * 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_unprepare_clk;
- }
+ devres_remove_group(dev, NULL);
+ return hpriv;
+
+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;
@@ -175,10 +349,8 @@ static int ahci_probe(struct platform_de
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;
@@ -193,7 +365,8 @@ static int ahci_probe(struct platform_de
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 */
@@ -207,13 +380,53 @@ static int ahci_probe(struct platform_de
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;
@@ -221,12 +434,8 @@ static int ahci_probe(struct platform_de
pdata_exit:
if (pdata && pdata->exit)
pdata->exit(dev);
-disable_unprepare_clk:
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
-free_clk:
- if (!IS_ERR(hpriv->clk))
- clk_put(hpriv->clk);
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
return rc;
}
@@ -239,21 +448,30 @@ static void ahci_host_stop(struct ata_ho
if (pdata && pdata->exit)
pdata->exit(dev);
- if (!IS_ERR(hpriv->clk)) {
- clk_disable_unprepare(hpriv->clk);
- clk_put(hpriv->clk);
- }
+ ahci_platform_disable_resources(hpriv);
}
#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");
@@ -270,61 +488,122 @@ static int ahci_suspend(struct device *d
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;
if (pdata && pdata->suspend)
return pdata->suspend(dev);
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
+ ahci_platform_disable_resources(hpriv);
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);
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_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
if (pdata && pdata->resume) {
rc = pdata->resume(dev);
if (rc)
- goto disable_unprepare_clk;
- }
-
- if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
- rc = ahci_reset_controller(host);
- if (rc)
- goto disable_unprepare_clk;
-
- ahci_init_controller(host);
+ goto disable_resources;
}
- ata_host_resume(host);
+ rc = ahci_platform_resume_host(dev);
+ if (rc)
+ goto disable_resources;
return 0;
-disable_unprepare_clk:
- if (!IS_ERR(hpriv->clk))
- clk_disable_unprepare(hpriv->clk);
+disable_resources:
+ ahci_platform_disable_resources(hpriv);
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", },
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -19,7 +19,15 @@
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);
@@ -30,4 +38,21 @@ 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);
+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);
+
+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 */

View file

@ -1,340 +0,0 @@
From 49270be12ed66b6aff84292f63c16ed77a62e8a6 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
--- 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-ch
Each SATA controller should have its own node.
Required properties:
-- compatible : compatible list, contains "snps,spear-ahci"
+- compatible : compatible list, one of "snps,spear-ahci",
+ "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
+ "allwinner,sun4i-a10-ahci"
- interrupts : <interrupt mapping for SATA IRQ>
- reg : <registers mapping>
@@ -13,10 +15,17 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- target-supply : regulator for SATA target power
-Example:
+Examples:
sata@ffe08000 {
compatible = "snps,spear-ahci";
reg = <0xffe08000 0x1000>;
interrupts = <115>;
-
};
+
+ ahci: sata@01c18000 {
+ compatible = "allwinner,sun4i-a10-ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ clocks = <&pll6 0>, <&ahb_gates 25>;
+ target-supply = <&reg_ahci_5v>;
+ };
--- 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
--- 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
--- /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");

View file

@ -1,202 +0,0 @@
From a52ae09871d171d6771b4bef2d4c56dd435e740f 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(+)
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -23,6 +23,8 @@
#include <linux/platform_device.h>
#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);
@@ -147,6 +149,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_
* 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 +174,23 @@ int ahci_platform_enable_resources(struc
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 +204,20 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_r
*
* 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)
@@ -206,6 +230,11 @@ static void ahci_platform_put_resources(
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]);
}
@@ -222,6 +251,7 @@ static void ahci_platform_put_resources(
* 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 +313,29 @@ struct ahci_host_priv *ahci_platform_get
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;
+ }
+ }
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ hpriv->got_runtime_pm = true;
+
devres_remove_group(dev, NULL);
return hpriv;
@@ -592,6 +645,11 @@ int ahci_platform_resume(struct device *
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:
@@ -609,6 +667,7 @@ static const struct of_device_id ahci_of
{ .compatible = "snps,spear-ahci", },
{ .compatible = "snps,exynos5440-ahci", },
{ .compatible = "ibm,476gtr-ahci", },
+ { .compatible = "snps,dwc-ahci", },
{},
};
MODULE_DEVICE_TABLE(of, ahci_of_match);
--- 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 */
@@ -324,8 +325,10 @@ 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 */
void *plat_data; /* Other platform data */
/*
* Optional ahci_start_engine override, if not set this gets set to the
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -90,7 +90,7 @@ static int ahci_sunxi_phy_init(struct de
/* 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 de
(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 de
udelay(1);
} while (1);
- mdelay(15);
+ msleep(15);
writel(0x7, reg_base + AHCI_RWCR);

View file

@ -1,344 +0,0 @@
From 49ff47db168655cac5213cf5dd1844b08fb9823c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 5 Jan 2014 14:42:39 +0100
Subject: [PATCH] ohci-platform: Add support for devicetree instantiation
Add support for ohci-platform instantiation from devicetree, including
optionally getting clks and a phy from devicetree, and enabling / disabling
those on power_on / off.
This should allow using ohci-platform from devicetree in various cases.
Specifically after this commit it can be used for the ohci controller found
on Allwinner sunxi SoCs.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
Documentation/devicetree/bindings/usb/usb-ohci.txt | 22 +++
drivers/usb/host/ohci-platform.c | 162 ++++++++++++++++++---
2 files changed, 162 insertions(+), 22 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/usb-ohci.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -0,0 +1,25 @@
+USB OHCI controllers
+
+Required properties:
+- compatible : "generic-ohci"
+- reg : ohci controller register range (address and length)
+- interrupts : ohci controller interrupt
+
+Optional properties:
+- big-endian-regs : boolean, set this for hcds with big-endian registers
+- big-endian-desc : boolean, set this for hcds with big-endian descriptors
+- big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+- clocks : a list of phandle + clock specifier pairs
+- phys : phandle + phy specifier pair
+- phy-names : "usb"
+
+Example:
+
+ ohci0: usb@01c14400 {
+ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
+ reg = <0x01c14400 0x100>;
+ interrupts = <64>;
+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ };
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -3,6 +3,7 @@
*
* Copyright 2007 Michael Buesch <m@bues.ch>
* Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
*
* Derived from the OCHI-SSB driver
* Derived from the OHCI-PCI driver
@@ -14,11 +15,14 @@
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/hrtimer.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/usb.h>
@@ -27,6 +31,13 @@
#include "ohci.h"
#define DRIVER_DESC "OHCI generic platform driver"
+#define OHCI_MAX_CLKS 3
+#define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
+
+struct ohci_platform_priv {
+ struct clk *clks[OHCI_MAX_CLKS];
+ struct phy *phy;
+};
static const char hcd_name[] = "ohci-platform";
@@ -48,11 +59,67 @@ static int ohci_platform_reset(struct us
return ohci_setup(hcd);
}
+static int ohci_platform_power_on(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk, ret;
+
+ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+ ret = clk_prepare_enable(priv->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ if (priv->phy) {
+ ret = phy_init(priv->phy);
+ if (ret)
+ goto err_disable_clks;
+
+ ret = phy_power_on(priv->phy);
+ if (ret)
+ goto err_exit_phy;
+ }
+
+ return 0;
+
+err_exit_phy:
+ phy_exit(priv->phy);
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(priv->clks[clk]);
+
+ return ret;
+}
+
+static void ohci_platform_power_off(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk;
+
+ if (priv->phy) {
+ phy_power_off(priv->phy);
+ phy_exit(priv->phy);
+ }
+
+ for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--)
+ if (priv->clks[clk])
+ clk_disable_unprepare(priv->clks[clk]);
+}
+
static struct hc_driver __read_mostly ohci_platform_hc_driver;
static const struct ohci_driver_overrides platform_overrides __initconst = {
- .product_desc = "Generic Platform OHCI controller",
- .reset = ohci_platform_reset,
+ .product_desc = "Generic Platform OHCI controller",
+ .reset = ohci_platform_reset,
+ .extra_priv_size = sizeof(struct ohci_platform_priv),
+};
+
+static struct usb_ohci_pdata ohci_platform_defaults = {
+ .power_on = ohci_platform_power_on,
+ .power_suspend = ohci_platform_power_off,
+ .power_off = ohci_platform_power_off,
};
static int ohci_platform_probe(struct platform_device *dev)
@@ -60,17 +127,24 @@ static int ohci_platform_probe(struct pl
struct usb_hcd *hcd;
struct resource *res_mem;
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
- int irq;
- int err = -ENOMEM;
-
- if (!pdata) {
- WARN_ON(1);
- return -ENODEV;
- }
+ struct ohci_platform_priv *priv;
+ struct ohci_hcd *ohci;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
+ /*
+ * Use reasonable defaults so platforms don't have to provide these
+ * with DT probing on ARM.
+ */
+ if (!pdata)
+ pdata = &ohci_platform_defaults;
+
+ err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return err;
+
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -83,17 +157,66 @@ static int ohci_platform_probe(struct pl
return -ENXIO;
}
+ hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+ dev_name(&dev->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ohci_priv(hcd);
+ ohci = hcd_to_ohci(hcd);
+
+ if (pdata == &ohci_platform_defaults && dev->dev.of_node) {
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+ ohci->flags |= OHCI_QUIRK_BE_MMIO;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+ ohci->flags |= OHCI_QUIRK_BE_DESC;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ if (ohci->flags & OHCI_QUIRK_BE_MMIO) {
+ dev_err(&dev->dev,
+ "Error big-endian-regs not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+#ifndef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
+ if (ohci->flags & OHCI_QUIRK_BE_DESC) {
+ dev_err(&dev->dev,
+ "Error big-endian-desc not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+ if (err == -EPROBE_DEFER)
+ goto err_put_hcd;
+ priv->phy = NULL;
+ }
+
+ for (clk = 0; clk < OHCI_MAX_CLKS; clk++) {
+ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+ if (IS_ERR(priv->clks[clk])) {
+ err = PTR_ERR(priv->clks[clk]);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->clks[clk] = NULL;
+ break;
+ }
+ }
+ }
+
if (pdata->power_on) {
err = pdata->power_on(dev);
if (err < 0)
- return err;
- }
-
- hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
- dev_name(&dev->dev));
- if (!hcd) {
- err = -ENOMEM;
- goto err_power;
+ goto err_put_clks;
}
hcd->rsrc_start = res_mem->start;
@@ -102,11 +225,11 @@ static int ohci_platform_probe(struct pl
hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
if (IS_ERR(hcd->regs)) {
err = PTR_ERR(hcd->regs);
- goto err_put_hcd;
+ goto err_power;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_put_hcd;
+ goto err_power;
device_wakeup_enable(hcd->self.controller);
@@ -114,11 +237,17 @@ static int ohci_platform_probe(struct pl
return err;
-err_put_hcd:
- usb_put_hcd(hcd);
err_power:
if (pdata->power_off)
pdata->power_off(dev);
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(priv->clks[clk]);
+err_put_hcd:
+ if (pdata == &ohci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
+ usb_put_hcd(hcd);
return err;
}
@@ -127,13 +256,22 @@ static int ohci_platform_remove(struct p
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
+ int clk;
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
if (pdata->power_off)
pdata->power_off(dev);
+ for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
+ clk_put(priv->clks[clk]);
+
+ usb_put_hcd(hcd);
+
+ if (pdata == &ohci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
return 0;
}
@@ -180,6 +318,12 @@ static int ohci_platform_resume(struct d
#define ohci_platform_resume NULL
#endif /* CONFIG_PM */
+static const struct of_device_id ohci_platform_ids[] = {
+ { .compatible = "generic-ohci", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ohci_platform_ids);
+
static const struct platform_device_id ohci_platform_table[] = {
{ "ohci-platform", 0 },
{ }
@@ -200,6 +344,7 @@ static struct platform_driver ohci_platf
.owner = THIS_MODULE,
.name = "ohci-platform",
.pm = &ohci_platform_pm_ops,
+ .of_match_table = ohci_platform_ids,
}
};

View file

@ -1,414 +0,0 @@
From 738b350437abfca820dae226549ecf4fb100fa30 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 5 Jan 2014 00:04:02 +0100
Subject: [PATCH] ehci-platform: Add support for clks and phy passed through
devicetree
Currently ehci-platform is only used in combination with devicetree when used
with some Via socs. By extending it to (optionally) get clks and a phy from
devicetree, and enabling / disabling those on power_on / off, it can be used
more generically. Specifically after this commit it can be used for the
ehci controller on Allwinner sunxi SoCs.
Since ehci-platform is intended to handle any generic enough non pci ehci
device, add a "usb-ehci" compatibility string.
There already is a usb-ehci device-tree bindings document, update this
with clks and phy bindings info.
Although actually quite generic so far the via,vt8500 compatibilty string
had its own bindings document. Somehow we even ended up with 2 of them. Since
these provide no extra information over the generic usb-ehci documentation,
this patch removes them.
The ehci-ppc-of.c driver also claims the usb-ehci compatibility string,
even though it mostly is ibm,usb-ehci-440epx specific. ehci-platform.c is
not needed on ppc platforms, so add a !PPC_OF dependency to it to avoid
2 drivers claiming the same compatibility string getting build on ppc.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
Documentation/devicetree/bindings/usb/usb-ehci.txt | 25 +++-
.../devicetree/bindings/usb/via,vt8500-ehci.txt | 15 ---
.../devicetree/bindings/usb/vt8500-ehci.txt | 12 --
drivers/usb/host/Kconfig | 1 +
drivers/usb/host/ehci-platform.c | 147 +++++++++++++++++----
5 files changed, 142 insertions(+), 58 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
delete mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -1,19 +1,20 @@
USB EHCI controllers
Required properties:
- - compatible : should be "usb-ehci".
+ - compatible : should be "generic-ehci".
- reg : should contain at least address and length of the standard EHCI
register set for the device. Optional platform-dependent registers
(debug-port or other) can be also specified here, but only after
definition of standard EHCI registers.
- interrupts : one EHCI interrupt should be described here.
-If device registers are implemented in big endian mode, the device
-node should have "big-endian-regs" property.
-If controller implementation operates with big endian descriptors,
-"big-endian-desc" property should be specified.
-If both big endian registers and descriptors are used by the controller
-implementation, "big-endian" property can be specified instead of having
-both "big-endian-regs" and "big-endian-desc".
+
+Optional properties:
+ - big-endian-regs : boolean, set this for hcds with big-endian registers
+ - big-endian-desc : boolean, set this for hcds with big-endian descriptors
+ - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
+ - clocks : a list of phandle + clock specifier pairs
+ - phys : phandle + phy specifier pair
+ - phy-names : "usb"
Example (Sequoia 440EPx):
ehci@e0000300 {
@@ -23,3 +24,13 @@ Example (Sequoia 440EPx):
reg = <0 e0000300 90 0 e0000390 70>;
big-endian;
};
+
+Example (Allwinner sun4i A10 SoC):
+ ehci0: usb@01c14000 {
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
+ reg = <0x01c14000 0x100>;
+ interrupts = <39>;
+ clocks = <&ahb_gates 1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ };
--- a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-VIA/Wondermedia VT8500 EHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "via,vt8500-ehci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : ehci controller interrupt
-
-Example:
-
- ehci@d8007900 {
- compatible = "via,vt8500-ehci";
- reg = <0xd8007900 0x200>;
- interrupts = <43>;
- };
--- a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
-
-Required properties:
- - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
- - reg: Address range of the ehci registers. size should be 0x200
- - interrupts: Should contain the ehci interrupt.
-
-usb: ehci@D8007100 {
- compatible = "wm,prizm-ehci", "usb-ehci";
- reg = <0xD8007100 0x200>;
- interrupts = <1>;
-};
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -3,6 +3,7 @@
*
* Copyright 2007 Steven Brown <sbrown@cortland.com>
* Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
*
* Derived from the ohci-ssb driver
* Copyright 2007 Michael Buesch <m@bues.ch>
@@ -18,6 +19,7 @@
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/kernel.h>
@@ -25,6 +27,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -33,6 +36,13 @@
#include "ehci.h"
#define DRIVER_DESC "EHCI generic platform driver"
+#define EHCI_MAX_CLKS 3
+#define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
+
+struct ehci_platform_priv {
+ struct clk *clks[EHCI_MAX_CLKS];
+ struct phy *phy;
+};
static const char hcd_name[] = "ehci-platform";
@@ -45,8 +55,10 @@ static int ehci_platform_reset(struct us
hcd->has_tt = pdata->has_tt;
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
- ehci->big_endian_desc = pdata->big_endian_desc;
- ehci->big_endian_mmio = pdata->big_endian_mmio;
+ if (pdata->big_endian_desc)
+ ehci->big_endian_desc = 1;
+ if (pdata->big_endian_mmio)
+ ehci->big_endian_mmio = 1;
ehci->ignore_oc = pdata->ignore_oc;
if (pdata->pre_setup) {
@@ -65,38 +77,91 @@ static int ehci_platform_reset(struct us
return 0;
}
+static int ehci_platform_power_on(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk, ret;
+
+ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) {
+ ret = clk_prepare_enable(priv->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ if (priv->phy) {
+ ret = phy_init(priv->phy);
+ if (ret)
+ goto err_disable_clks;
+
+ ret = phy_power_on(priv->phy);
+ if (ret)
+ goto err_exit_phy;
+ }
+
+ return 0;
+
+err_exit_phy:
+ phy_exit(priv->phy);
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(priv->clks[clk]);
+
+ return ret;
+}
+
+static void ehci_platform_power_off(struct platform_device *dev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk;
+
+ if (priv->phy) {
+ phy_power_off(priv->phy);
+ phy_exit(priv->phy);
+ }
+
+ for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--)
+ if (priv->clks[clk])
+ clk_disable_unprepare(priv->clks[clk]);
+}
+
static struct hc_driver __read_mostly ehci_platform_hc_driver;
static const struct ehci_driver_overrides platform_overrides __initconst = {
- .reset = ehci_platform_reset,
+ .reset = ehci_platform_reset,
+ .extra_priv_size = sizeof(struct ehci_platform_priv),
};
-static struct usb_ehci_pdata ehci_platform_defaults;
+static struct usb_ehci_pdata ehci_platform_defaults = {
+ .power_on = ehci_platform_power_on,
+ .power_suspend = ehci_platform_power_off,
+ .power_off = ehci_platform_power_off,
+};
static int ehci_platform_probe(struct platform_device *dev)
{
struct usb_hcd *hcd;
struct resource *res_mem;
- struct usb_ehci_pdata *pdata;
- int irq;
- int err;
+ struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ehci_platform_priv *priv;
+ struct ehci_hcd *ehci;
+ int err, irq, clk = 0;
if (usb_disabled())
return -ENODEV;
/*
- * use reasonable defaults so platforms don't have to provide these.
- * with DT probing on ARM, none of these are set.
+ * Use reasonable defaults so platforms don't have to provide these
+ * with DT probing on ARM.
*/
- if (!dev_get_platdata(&dev->dev))
- dev->dev.platform_data = &ehci_platform_defaults;
+ if (!pdata)
+ pdata = &ehci_platform_defaults;
err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
if (err)
return err;
- pdata = dev_get_platdata(&dev->dev);
-
irq = platform_get_irq(dev, 0);
if (irq < 0) {
dev_err(&dev->dev, "no irq provided");
@@ -108,17 +173,66 @@ static int ehci_platform_probe(struct pl
return -ENXIO;
}
+ hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+ dev_name(&dev->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ platform_set_drvdata(dev, hcd);
+ dev->dev.platform_data = pdata;
+ priv = hcd_to_ehci_priv(hcd);
+ ehci = hcd_to_ehci(hcd);
+
+ if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+ ehci->big_endian_mmio = 1;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian-desc"))
+ ehci->big_endian_desc = 1;
+
+ if (of_property_read_bool(dev->dev.of_node, "big-endian"))
+ ehci->big_endian_mmio = ehci->big_endian_desc = 1;
+
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+ if (ehci->big_endian_mmio) {
+ dev_err(&dev->dev,
+ "Error big-endian-regs not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+ if (ehci->big_endian_desc) {
+ dev_err(&dev->dev,
+ "Error big-endian-desc not compiled in\n");
+ err = -EINVAL;
+ goto err_put_hcd;
+ }
+#endif
+ priv->phy = devm_phy_get(&dev->dev, "usb");
+ if (IS_ERR(priv->phy)) {
+ err = PTR_ERR(priv->phy);
+ if (err == -EPROBE_DEFER)
+ goto err_put_hcd;
+ priv->phy = NULL;
+ }
+
+ for (clk = 0; clk < EHCI_MAX_CLKS; clk++) {
+ priv->clks[clk] = of_clk_get(dev->dev.of_node, clk);
+ if (IS_ERR(priv->clks[clk])) {
+ err = PTR_ERR(priv->clks[clk]);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->clks[clk] = NULL;
+ break;
+ }
+ }
+ }
+
if (pdata->power_on) {
err = pdata->power_on(dev);
if (err < 0)
- return err;
- }
-
- hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
- dev_name(&dev->dev));
- if (!hcd) {
- err = -ENOMEM;
- goto err_power;
+ goto err_put_clks;
}
hcd->rsrc_start = res_mem->start;
@@ -127,22 +241,28 @@ static int ehci_platform_probe(struct pl
hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
if (IS_ERR(hcd->regs)) {
err = PTR_ERR(hcd->regs);
- goto err_put_hcd;
+ goto err_power;
}
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
- goto err_put_hcd;
+ goto err_power;
device_wakeup_enable(hcd->self.controller);
platform_set_drvdata(dev, hcd);
return err;
-err_put_hcd:
- usb_put_hcd(hcd);
err_power:
if (pdata->power_off)
pdata->power_off(dev);
+err_put_clks:
+ while (--clk >= 0)
+ clk_put(priv->clks[clk]);
+err_put_hcd:
+ if (pdata == &ehci_platform_defaults)
+ dev->dev.platform_data = NULL;
+
+ usb_put_hcd(hcd);
return err;
}
@@ -151,13 +271,19 @@ static int ehci_platform_remove(struct p
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
+ int clk;
usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
if (pdata->power_off)
pdata->power_off(dev);
+ for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
+ clk_put(priv->clks[clk]);
+
+ usb_put_hcd(hcd);
+
if (pdata == &ehci_platform_defaults)
dev->dev.platform_data = NULL;
@@ -208,8 +334,10 @@ static int ehci_platform_resume(struct d
static const struct of_device_id vt8500_ehci_ids[] = {
{ .compatible = "via,vt8500-ehci", },
{ .compatible = "wm,prizm-ehci", },
+ { .compatible = "generic-ehci", },
{}
};
+MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
static const struct platform_device_id ehci_platform_table[] = {
{ "ehci-platform", 0 },

View file

@ -1,72 +0,0 @@
From 2adf0917bc9d6db8d957d56c8289a623be4027b6 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 11 Feb 2014 17:41:48 +0100
Subject: [PATCH] uhci-platform: Change compatible string from platform-uhci to
generic-uhci
This brings the uhci-platform bindings in sync with what we've done for
the ohci- and ehci-platform drivers. As discussed there using platform as a
prefix is a bit weird as the platform bus is a Linux specific thing and
the bindings are supposed to be OS agnostic.
Note that the old platform-uhci compatible string is kept around for, well,
compatibility reasons.
While at it rename the bindings txt file to match the name of all the
other ?hci-platform bindings docs.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Documentation/devicetree/bindings/usb/platform-uhci.txt | 15 ---------------
Documentation/devicetree/bindings/usb/usb-uhci.txt | 15 +++++++++++++++
drivers/usb/host/uhci-platform.c | 1 +
3 files changed, 16 insertions(+), 15 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/usb/platform-uhci.txt
create mode 100644 Documentation/devicetree/bindings/usb/usb-uhci.txt
--- a/Documentation/devicetree/bindings/usb/platform-uhci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Generic Platform UHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "platform-uhci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : UHCI controller interrupt
-
-Example:
-
- uhci@d8007b00 {
- compatible = "platform-uhci";
- reg = <0xd8007b00 0x200>;
- interrupts = <43>;
- };
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt
@@ -0,0 +1,15 @@
+Generic Platform UHCI Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "generic-uhci" (deprecated: "platform-uhci")
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : UHCI controller interrupt
+
+Example:
+
+ uhci@d8007b00 {
+ compatible = "generic-uhci";
+ reg = <0xd8007b00 0x200>;
+ interrupts = <43>;
+ };
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -148,6 +148,7 @@ static void uhci_hcd_platform_shutdown(s
}
static const struct of_device_id platform_uhci_ids[] = {
+ { .compatible = "generic-uhci", },
{ .compatible = "platform-uhci", },
{}
};

View file

@ -1,49 +0,0 @@
From 8fd033e1b6cdd30c32762ef1c5e2216226dd61e1 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 11 Feb 2014 17:50:51 +0100
Subject: [PATCH] xhci-platform: Change compatible string from xhci-platform to
generic-xhci
This brings the xhci-platform bindings in sync with what we've done for
the ohci- and ehci-platform drivers. As discussed there using platform as a
postfix is a bit weird as the platform bus is a Linux specific thing and
the bindings are supposed to be OS agnostic.
Note that the old xhci-platform compatible string is kept around for, well,
compatibility reasons.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Documentation/devicetree/bindings/usb/usb-xhci.txt | 4 ++--
drivers/usb/host/xhci-plat.c | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -1,14 +1,14 @@
USB xHCI controllers
Required properties:
- - compatible: should be "xhci-platform".
+ - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
Example:
usb@f0931000 {
- compatible = "xhci-platform";
+ compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -234,6 +234,7 @@ static const struct dev_pm_ops xhci_plat
#ifdef CONFIG_OF
static const struct of_device_id usb_xhci_of_match[] = {
+ { .compatible = "generic-xhci" },
{ .compatible = "xhci-platform" },
{ },
};

View file

@ -1,410 +0,0 @@
From 56feaa546c5ce4152fe14f725e9fc6b85f8a565b Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sat, 4 Jan 2014 23:56:17 +0100
Subject: [PATCH] PHY: sunxi: Add driver for sunxi usb phy
The Allwinner A1x / A2x SoCs have 2 or 3 usb phys which are all accessed
through a single set of registers. Besides this there are also some other
phy related bits which need poking, which are per phy, but shared between the
ohci and ehci controllers, so these are also controlled from this new phy
driver.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
.../devicetree/bindings/phy/sun4i-usb-phy.txt | 26 ++
drivers/phy/Kconfig | 11 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-sun4i-usb.c | 331 +++++++++++++++++++++
4 files changed, 369 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
create mode 100644 drivers/phy/phy-sun4i-usb.c
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -0,0 +1,26 @@
+Allwinner sun4i USB PHY
+-----------------------
+
+Required properties:
+- compatible : should be one of "allwinner,sun4i-a10-usb-phy",
+ "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy"
+- reg : a list of offset + length pairs
+- reg-names : "phy_ctrl", "pmu1" and for sun4i or sun7i "pmu2"
+- #phy-cells : from the generic phy bindings, must be 1
+- clocks : phandle + clock specifier for the phy clock
+- clock-names : "usb_phy"
+- resets : a list of phandle + reset specifier pairs
+- reset-names : "usb0_reset", "usb1_reset" and for sun4i or sun7i "usb2_reset"
+
+Example:
+ usbphy: phy@0x01c13400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun4i-a10-usb-phy";
+ /* phy base regs, phy1 pmu reg, phy2 pmu reg */
+ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+ reg-names = "phy_ctrl", "pmu1", "pmu2";
+ clocks = <&usb_clk 8>;
+ clock-names = "usb_phy";
+ resets = <&usb_clk 1>, <&usb_clk 2>;
+ reset-names = "usb1_reset", "usb2_reset";
+ };
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -65,4 +65,15 @@ config BCM_KONA_USB2_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
+config PHY_SUN4I_USB
+ tristate "Allwinner sunxi SoC USB PHY driver"
+ depends on ARCH_SUNXI && HAS_IOMEM && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the transceiver that is part of Allwinner
+ sunxi SoCs.
+
+ This driver controls the entire USB PHY block, both the USB OTG
+ parts, as well as the 2 regular USB 2 host PHYs.
+
endmenu
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += p
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
+obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
--- /dev/null
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -0,0 +1,331 @@
+/*
+ * Allwinner sun4i USB phy driver
+ *
+ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+
+#define REG_ISCR 0x00
+#define REG_PHYCTL 0x04
+#define REG_PHYBIST 0x08
+#define REG_PHYTUNE 0x0c
+
+#define PHYCTL_DATA BIT(7)
+
+#define SUNXI_AHB_ICHR8_EN BIT(10)
+#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
+#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
+#define SUNXI_ULPI_BYPASS_EN BIT(0)
+
+/* Common Control Bits for Both PHYs */
+#define PHY_PLL_BW 0x03
+#define PHY_RES45_CAL_EN 0x0c
+
+/* Private Control Bits for Each PHY */
+#define PHY_TX_AMPLITUDE_TUNE 0x20
+#define PHY_TX_SLEWRATE_TUNE 0x22
+#define PHY_VBUSVALID_TH_SEL 0x25
+#define PHY_PULLUP_RES_SEL 0x27
+#define PHY_OTG_FUNC_EN 0x28
+#define PHY_VBUS_DET_EN 0x29
+#define PHY_DISCON_TH_SEL 0x2a
+
+#define MAX_PHYS 3
+
+struct sun4i_usb_phy_data {
+ struct clk *clk;
+ void __iomem *base;
+ struct mutex mutex;
+ int num_phys;
+ u32 disc_thresh;
+ struct sun4i_usb_phy {
+ struct phy *phy;
+ void __iomem *pmu;
+ struct regulator *vbus;
+ struct reset_control *reset;
+ int index;
+ } phys[MAX_PHYS];
+};
+
+#define to_sun4i_usb_phy_data(phy) \
+ container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
+
+static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
+ int len)
+{
+ struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
+ u32 temp, usbc_bit = BIT(phy->index * 2);
+ int i;
+
+ mutex_lock(&phy_data->mutex);
+
+ for (i = 0; i < len; i++) {
+ temp = readl(phy_data->base + REG_PHYCTL);
+
+ /* clear the address portion */
+ temp &= ~(0xff << 8);
+
+ /* set the address */
+ temp |= ((addr + i) << 8);
+ writel(temp, phy_data->base + REG_PHYCTL);
+
+ /* set the data bit and clear usbc bit*/
+ temp = readb(phy_data->base + REG_PHYCTL);
+ if (data & 0x1)
+ temp |= PHYCTL_DATA;
+ else
+ temp &= ~PHYCTL_DATA;
+ temp &= ~usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ /* pulse usbc_bit */
+ temp = readb(phy_data->base + REG_PHYCTL);
+ temp |= usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ temp = readb(phy_data->base + REG_PHYCTL);
+ temp &= ~usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ data >>= 1;
+ }
+ mutex_unlock(&phy_data->mutex);
+}
+
+static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
+{
+ u32 bits, reg_value;
+
+ if (!phy->pmu)
+ return;
+
+ bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
+ SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
+
+ reg_value = readl(phy->pmu);
+
+ if (enable)
+ reg_value |= bits;
+ else
+ reg_value &= ~bits;
+
+ writel(reg_value, phy->pmu);
+}
+
+static int sun4i_usb_phy_init(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+ int ret;
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(phy->reset);
+ if (ret) {
+ clk_disable_unprepare(data->clk);
+ return ret;
+ }
+
+ /* Adjust PHY's magnitude and rate */
+ sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
+
+ /* Disconnect threshold adjustment */
+ sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2);
+
+ sun4i_usb_phy_passby(phy, 1);
+
+ return 0;
+}
+
+static int sun4i_usb_phy_exit(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+ sun4i_usb_phy_passby(phy, 0);
+ reset_control_assert(phy->reset);
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+static int sun4i_usb_phy_power_on(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ int ret = 0;
+
+ if (phy->vbus)
+ ret = regulator_enable(phy->vbus);
+
+ return ret;
+}
+
+static int sun4i_usb_phy_power_off(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+
+ if (phy->vbus)
+ regulator_disable(phy->vbus);
+
+ return 0;
+}
+
+static struct phy_ops sun4i_usb_phy_ops = {
+ .init = sun4i_usb_phy_init,
+ .exit = sun4i_usb_phy_exit,
+ .power_on = sun4i_usb_phy_power_on,
+ .power_off = sun4i_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *sun4i_usb_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+ if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys))
+ return ERR_PTR(-ENODEV);
+
+ return data->phys[args->args[0]].phy;
+}
+
+static int sun4i_usb_phy_probe(struct platform_device *pdev)
+{
+ struct sun4i_usb_phy_data *data;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void __iomem *pmu = NULL;
+ struct phy_provider *phy_provider;
+ struct reset_control *reset;
+ struct regulator *vbus;
+ struct resource *res;
+ struct phy *phy;
+ char name[16];
+ int i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ mutex_init(&data->mutex);
+
+ if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
+ data->num_phys = 2;
+ else
+ data->num_phys = 3;
+
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy"))
+ data->disc_thresh = 3;
+ else
+ data->disc_thresh = 2;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
+ data->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ data->clk = devm_clk_get(dev, "usb_phy");
+ if (IS_ERR(data->clk)) {
+ dev_err(dev, "could not get usb_phy clock\n");
+ return PTR_ERR(data->clk);
+ }
+
+ /* Skip 0, 0 is the phy for otg which is not yet supported. */
+ for (i = 1; i < data->num_phys; i++) {
+ snprintf(name, sizeof(name), "usb%d_vbus", i);
+ vbus = devm_regulator_get_optional(dev, name);
+ if (IS_ERR(vbus)) {
+ if (PTR_ERR(vbus) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ vbus = NULL;
+ }
+
+ snprintf(name, sizeof(name), "usb%d_reset", i);
+ reset = devm_reset_control_get(dev, name);
+ if (IS_ERR(reset)) {
+ dev_err(dev, "failed to get reset %s\n", name);
+ return PTR_ERR(reset);
+ }
+
+ if (i) { /* No pmu for usbc0 */
+ snprintf(name, sizeof(name), "pmu%d", i);
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, name);
+ pmu = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pmu))
+ return PTR_ERR(pmu);
+ }
+
+ phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY %d\n", i);
+ return PTR_ERR(phy);
+ }
+
+ data->phys[i].phy = phy;
+ data->phys[i].pmu = pmu;
+ data->phys[i].vbus = vbus;
+ data->phys[i].reset = reset;
+ data->phys[i].index = i;
+ phy_set_drvdata(phy, &data->phys[i]);
+ }
+
+ dev_set_drvdata(dev, data);
+ phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static const struct of_device_id sun4i_usb_phy_of_match[] = {
+ { .compatible = "allwinner,sun4i-a10-usb-phy" },
+ { .compatible = "allwinner,sun5i-a13-usb-phy" },
+ { .compatible = "allwinner,sun7i-a20-usb-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
+
+static struct platform_driver sun4i_usb_phy_driver = {
+ .probe = sun4i_usb_phy_probe,
+ .driver = {
+ .of_match_table = sun4i_usb_phy_of_match,
+ .name = "sun4i-usb-phy",
+ .owner = THIS_MODULE,
+ }
+};
+module_platform_driver(sun4i_usb_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load diff

View file

@ -1,159 +0,0 @@
From b66989fe7a41e1093b1f825967ab29963e06cccd 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 | 58 ++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
--- 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";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -377,6 +377,50 @@
#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>;
+ cd-inverted;
+ status = "disabled";
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun4i-a10-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&ahb_gates 9>, <&mmc1_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <33>;
+ bus-width = <4>;
+ cd-inverted;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun4i-a10-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&ahb_gates 10>, <&mmc2_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <34>;
+ bus-width = <4>;
+ cd-inverted;
+ status = "disabled";
+ };
+
+ mmc3: mmc@01c12000 {
+ compatible = "allwinner,sun4i-a10-mmc";
+ reg = <0x01c12000 0x1000>;
+ clocks = <&ahb_gates 11>, <&mmc3_clk>;
+ clock-names = "ahb", "mod";
+ interrupts = <35>;
+ bus-width = <4>;
+ cd-inverted;
+ status = "disabled";
+ };
+
usbphy: phy@01c13400 {
#phy-cells = <1>;
compatible = "allwinner,sun4i-a10-usb-phy";
@@ -529,6 +573,20 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
};
timer@01c20c00 {
--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
@@ -20,6 +20,14 @@
compatible = "pineriver,mini-xplus", "allwinner,sun4i-a10";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ status = "okay";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
@@ -33,6 +33,15 @@
};
};
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-mode = <1>;
+ status = "okay";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.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";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;

View file

@ -1,125 +0,0 @@
From 7afa5fb704679e84c59e5ad25bbdf7605844c5ca 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 | 30 +++++++++++++++
arch/arm/boot/dts/sun5i-a10s.dtsi | 47 ++++++++++++++++++++++++
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 | 29 +++++++++++++++
5 files changed, 136 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
@@ -21,6 +21,14 @@
compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
+ status = "okay";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
status = "okay";
@@ -35,6 +43,13 @@
};
pinctrl@01c20800 {
+ mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxinom: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -21,6 +21,14 @@
compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc0_pins_a>;
+ pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
+ cd-gpios = <&pio 6 0 0>; /* PG0 */
+ status = "okay";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
status = "okay";
@@ -35,6 +43,13 @@
};
pinctrl@01c20800 {
+ mmc0_cd_pin_olinuxino: mmc0_cd_pin@0 {
+ allwinner,pins = "PG0";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PG9";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -320,6 +320,28 @@
#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>;
+ cd-inverted;
+ 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>;
+ cd-inverted;
+ status = "disabled";
+ };
+
usbphy: phy@01c13400 {
#phy-cells = <1>;
compatible = "allwinner,sun5i-a13-usb-phy";
@@ -415,6 +437,13 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -1,171 +0,0 @@
From 33654facee61ebbd88684c9cf482ec2ea41f575e 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 | 65 +++++++++++++++++++++++++
4 files changed, 104 insertions(+)
--- 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";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -20,6 +20,14 @@
compatible = "cubietech,cubietruck", "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";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -32,6 +32,22 @@
status = "okay";
};
+ 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";
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
@@ -66,6 +82,13 @@
};
pinctrl@01c20800 {
+ mmc3_cd_pin_olinuxinom: mmc3_cd_pin@0 {
+ allwinner,pins = "PH11";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
led_pins_olinuxino: led_pins@0 {
allwinner,pins = "PH2";
allwinner,function = "gpio_out";
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -439,6 +439,50 @@
#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>;
+ cd-inverted;
+ 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>;
+ cd-inverted;
+ 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>;
+ cd-inverted;
+ 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>;
+ cd-inverted;
+ status = "disabled";
+ };
+
usbphy: phy@01c13400 {
#phy-cells = <1>;
compatible = "allwinner,sun7i-a20-usb-phy";
@@ -645,6 +689,27 @@
allwinner,drive = <0>;
allwinner,pull = <0>;
};
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+ mmc0_cd_pin_reference_design: mmc0_cd_pin@0 {
+ allwinner,pins = "PH1";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
+ mmc3_pins_a: mmc3@0 {
+ allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
+ allwinner,function = "mmc3";
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {

View file

@ -1,239 +0,0 @@
From b9ad0253e6c68ac3d37fd2ed8ed9bf8a334e4b65 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Sat, 15 Mar 2014 14:40:59 +0100
Subject: [PATCH] ARM: sun7i/sun6i: irqchip: Add irqchip driver for NMI
controller
Allwinner A20/A31 SoCs have special registers to control / (un)mask /
acknowledge NMI. This NMI controller is separated and independent from GIC.
This patch adds a new irqchip to manage NMI.
Signed-off-by: Carlo Caione <carlo@caione.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-sunxi-nmi.c | 208 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+)
create mode 100644 drivers/irqchip/irq-sunxi-nmi.c
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) +=
obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o
obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
+obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
--- /dev/null
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -0,0 +1,208 @@
+/*
+ * Allwinner A20/A31 SoCs NMI IRQ chip driver.
+ *
+ * Carlo Caione <carlo.caione@gmail.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/device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/irqchip/chained_irq.h>
+#include "irqchip.h"
+
+#define SUNXI_NMI_SRC_TYPE_MASK 0x00000003
+
+enum {
+ SUNXI_SRC_TYPE_LEVEL_LOW = 0,
+ SUNXI_SRC_TYPE_EDGE_FALLING,
+ SUNXI_SRC_TYPE_LEVEL_HIGH,
+ SUNXI_SRC_TYPE_EDGE_RISING,
+};
+
+struct sunxi_sc_nmi_reg_offs {
+ u32 ctrl;
+ u32 pend;
+ u32 enable;
+};
+
+static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = {
+ .ctrl = 0x00,
+ .pend = 0x04,
+ .enable = 0x08,
+};
+
+static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
+ .ctrl = 0x00,
+ .pend = 0x04,
+ .enable = 0x34,
+};
+
+static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
+ u32 val)
+{
+ irq_reg_writel(val, gc->reg_base + off);
+}
+
+static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off)
+{
+ return irq_reg_readl(gc->reg_base + off);
+}
+
+static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_get_chip(irq);
+ unsigned int virq = irq_find_mapping(domain, 0);
+
+ chained_irq_enter(chip, desc);
+ generic_handle_irq(virq);
+ chained_irq_exit(chip, desc);
+}
+
+static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ struct irq_chip_type *ct = gc->chip_types;
+ u32 src_type_reg;
+ u32 ctrl_off = ct->regs.type;
+ unsigned int src_type;
+ unsigned int i;
+
+ irq_gc_lock(gc);
+
+ switch (flow_type & IRQF_TRIGGER_MASK) {
+ case IRQ_TYPE_EDGE_FALLING:
+ src_type = SUNXI_SRC_TYPE_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ src_type = SUNXI_SRC_TYPE_EDGE_RISING;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ src_type = SUNXI_SRC_TYPE_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_NONE:
+ case IRQ_TYPE_LEVEL_LOW:
+ src_type = SUNXI_SRC_TYPE_LEVEL_LOW;
+ break;
+ default:
+ irq_gc_unlock(gc);
+ pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n",
+ __func__, data->irq);
+ return -EBADR;
+ }
+
+ irqd_set_trigger_type(data, flow_type);
+ irq_setup_alt_chip(data, flow_type);
+
+ for (i = 0; i <= gc->num_ct; i++, ct++)
+ if (ct->type & flow_type)
+ ctrl_off = ct->regs.type;
+
+ src_type_reg = sunxi_sc_nmi_read(gc, ctrl_off);
+ src_type_reg &= ~SUNXI_NMI_SRC_TYPE_MASK;
+ src_type_reg |= src_type;
+ sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg);
+
+ irq_gc_unlock(gc);
+
+ return IRQ_SET_MASK_OK;
+}
+
+static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
+ struct sunxi_sc_nmi_reg_offs *reg_offs)
+{
+ struct irq_domain *domain;
+ struct irq_chip_generic *gc;
+ unsigned int irq;
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ int ret;
+
+
+ domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL);
+ if (!domain) {
+ pr_err("%s: Could not register interrupt domain.\n", node->name);
+ return -ENOMEM;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, 1, 2, node->name,
+ handle_fasteoi_irq, clr, 0,
+ IRQ_GC_INIT_MASK_CACHE);
+ if (ret) {
+ pr_err("%s: Could not allocate generic interrupt chip.\n",
+ node->name);
+ goto fail_irqd_remove;
+ }
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (irq <= 0) {
+ pr_err("%s: unable to parse irq\n", node->name);
+ ret = -EINVAL;
+ goto fail_irqd_remove;
+ }
+
+ gc = irq_get_domain_generic_chip(domain, 0);
+ gc->reg_base = of_iomap(node, 0);
+ if (!gc->reg_base) {
+ pr_err("%s: unable to map resource\n", node->name);
+ ret = -ENOMEM;
+ goto fail_irqd_remove;
+ }
+
+ gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
+ gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit;
+ gc->chip_types[0].chip.irq_set_type = sunxi_sc_nmi_set_type;
+ gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED;
+ gc->chip_types[0].regs.ack = reg_offs->pend;
+ gc->chip_types[0].regs.mask = reg_offs->enable;
+ gc->chip_types[0].regs.type = reg_offs->ctrl;
+
+ gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
+ gc->chip_types[1].chip.name = gc->chip_types[0].chip.name;
+ gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
+ gc->chip_types[1].chip.irq_set_type = sunxi_sc_nmi_set_type;
+ gc->chip_types[1].regs.ack = reg_offs->pend;
+ gc->chip_types[1].regs.mask = reg_offs->enable;
+ gc->chip_types[1].regs.type = reg_offs->ctrl;
+ gc->chip_types[1].handler = handle_edge_irq;
+
+ sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
+ sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1);
+
+ irq_set_handler_data(irq, domain);
+ irq_set_chained_handler(irq, sunxi_sc_nmi_handle_irq);
+
+ return 0;
+
+fail_irqd_remove:
+ irq_domain_remove(domain);
+
+ return ret;
+}
+
+static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
+}
+IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init);
+
+static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
+}
+IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);

View file

@ -1,47 +0,0 @@
From eebb592523672ee7288b9327bd222165db638d1a Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Thu, 27 Feb 2014 20:34:21 +0100
Subject: [PATCH] ARM: sun7i/sun6i: dts: Add NMI irqchip support
This patch adds DTS entries for NMI controller as child of GIC.
Signed-off-by: Carlo Caione <carlo@caione.org>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 8 ++++++++
arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
2 files changed, 16 insertions(+)
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -370,6 +370,14 @@
interrupts = <1 9 0xf04>;
};
+ nmi_intc: interrupt-controller@01f00c0c {
+ compatible = "allwinner,sun6i-a31-sc-nmi";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x01f00c0c 0x38>;
+ interrupts = <0 32 4>;
+ };
+
cpucfg@01f01c00 {
compatible = "allwinner,sun6i-a31-cpuconfig";
reg = <0x01f01c00 0x300>;
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -401,6 +401,14 @@
#size-cells = <1>;
ranges;
+ nmi_intc: interrupt-controller@01c00030 {
+ compatible = "allwinner,sun7i-a20-sc-nmi";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x01c00030 0x0c>;
+ interrupts = <0 0 4>;
+ };
+
spi0: spi@01c05000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c05000 0x1000>;

View file

@ -1,502 +0,0 @@
From 509326e0138b762067904c0c60f818e9bdba4cd4 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Sat, 1 Mar 2014 17:45:46 +0100
Subject: [PATCH] mfd: AXP20x: Add mfd driver for AXP20x PMIC
This patch introduces the preliminary support for PMICs X-Powers AXP202
and AXP209. The AXP209 and AXP202 are the PMUs (Power Management Unit)
used by A10, A13 and A20 SoCs and developed by X-Powers, a sister company
of Allwinner.
The core enables support for two subsystems:
- PEK (Power Enable Key)
- Regulators
Signed-off-by: Carlo Caione <carlo@caione.org>
---
arch/arm/configs/sunxi_defconfig | 1 +
drivers/mfd/Kconfig | 12 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/axp20x.c | 250 +++++++++++++++++++++++++++++++++++++++
include/linux/mfd/axp20x.h | 180 ++++++++++++++++++++++++++++
5 files changed, 444 insertions(+)
create mode 100644 drivers/mfd/axp20x.c
create mode 100644 include/linux/mfd/axp20x.h
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -55,6 +55,7 @@ CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
+CONFIG_MFD_AXP20X=y
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -59,6 +59,18 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the
functionality of the device.
+config MFD_AXP20X
+ bool "X-Powers AXP20X"
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ depends on I2C=y
+ help
+ If you say Y here you get support for the AXP20X.
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the
+ functionality of the device.
+
config MFD_CROS_EC
tristate "ChromeOS Embedded Controller"
select MFD_CORE
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-irq.
obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
+obj-$(CONFIG_MFD_AXP20X) += axp20x.o
obj-$(CONFIG_MFD_LP3943) += lp3943.o
obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
--- /dev/null
+++ b/drivers/mfd/axp20x.c
@@ -0,0 +1,250 @@
+/*
+ * axp20x.c - mfd core driver for the X-Powers AXP202 and AXP209
+ *
+ * Author: Carlo Caione <carlo@caione.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/mfd/core.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#define AXP20X_OFF 0x80
+
+static const struct regmap_range axp20x_writeable_ranges[] = {
+ regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+ regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
+};
+
+static const struct regmap_range axp20x_volatile_ranges[] = {
+ regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+};
+
+static const struct regmap_access_table axp20x_writeable_table = {
+ .yes_ranges = axp20x_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges),
+};
+
+static const struct regmap_access_table axp20x_volatile_table = {
+ .yes_ranges = axp20x_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
+};
+
+static struct resource axp20x_pek_resources[] = {
+ {
+ .name = "PEK_DBR",
+ .start = AXP20X_IRQ_PEK_RIS_EDGE,
+ .end = AXP20X_IRQ_PEK_RIS_EDGE,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "PEK_DBF",
+ .start = AXP20X_IRQ_PEK_FAL_EDGE,
+ .end = AXP20X_IRQ_PEK_FAL_EDGE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct regmap_config axp20x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp20x_writeable_table,
+ .volatile_table = &axp20x_volatile_table,
+ .max_register = AXP20X_FG_RES,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+#define AXP20X_IRQ(_irq, _off, _mask) \
+ [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
+
+static const struct regmap_irq axp20x_regmap_irqs[] = {
+ AXP20X_IRQ(ACIN_OVER_V, 0, 7),
+ AXP20X_IRQ(ACIN_PLUGIN, 0, 6),
+ AXP20X_IRQ(ACIN_REMOVAL, 0, 5),
+ AXP20X_IRQ(VBUS_OVER_V, 0, 4),
+ AXP20X_IRQ(VBUS_PLUGIN, 0, 3),
+ AXP20X_IRQ(VBUS_REMOVAL, 0, 2),
+ AXP20X_IRQ(VBUS_V_LOW, 0, 1),
+ AXP20X_IRQ(BATT_PLUGIN, 1, 7),
+ AXP20X_IRQ(BATT_REMOVAL, 1, 6),
+ AXP20X_IRQ(BATT_ENT_ACT_MODE, 1, 5),
+ AXP20X_IRQ(BATT_EXIT_ACT_MODE, 1, 4),
+ AXP20X_IRQ(CHARG, 1, 3),
+ AXP20X_IRQ(CHARG_DONE, 1, 2),
+ AXP20X_IRQ(BATT_TEMP_HIGH, 1, 1),
+ AXP20X_IRQ(BATT_TEMP_LOW, 1, 0),
+ AXP20X_IRQ(DIE_TEMP_HIGH, 2, 7),
+ AXP20X_IRQ(CHARG_I_LOW, 2, 6),
+ AXP20X_IRQ(DCDC1_V_LONG, 2, 5),
+ AXP20X_IRQ(DCDC2_V_LONG, 2, 4),
+ AXP20X_IRQ(DCDC3_V_LONG, 2, 3),
+ AXP20X_IRQ(PEK_SHORT, 2, 1),
+ AXP20X_IRQ(PEK_LONG, 2, 0),
+ AXP20X_IRQ(N_OE_PWR_ON, 3, 7),
+ AXP20X_IRQ(N_OE_PWR_OFF, 3, 6),
+ AXP20X_IRQ(VBUS_VALID, 3, 5),
+ AXP20X_IRQ(VBUS_NOT_VALID, 3, 4),
+ AXP20X_IRQ(VBUS_SESS_VALID, 3, 3),
+ AXP20X_IRQ(VBUS_SESS_END, 3, 2),
+ AXP20X_IRQ(LOW_PWR_LVL1, 3, 1),
+ AXP20X_IRQ(LOW_PWR_LVL2, 3, 0),
+ AXP20X_IRQ(TIMER, 4, 7),
+ AXP20X_IRQ(PEK_RIS_EDGE, 4, 6),
+ AXP20X_IRQ(PEK_FAL_EDGE, 4, 5),
+ AXP20X_IRQ(GPIO3_INPUT, 4, 3),
+ AXP20X_IRQ(GPIO2_INPUT, 4, 2),
+ AXP20X_IRQ(GPIO1_INPUT, 4, 1),
+ AXP20X_IRQ(GPIO0_INPUT, 4, 0),
+};
+
+static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
+ .name = "axp20x_irq_chip",
+ .status_base = AXP20X_IRQ1_STATE,
+ .ack_base = AXP20X_IRQ1_STATE,
+ .mask_base = AXP20X_IRQ1_EN,
+ .num_regs = 5,
+ .irqs = axp20x_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
+ .mask_invert = true,
+ .init_ack_masked = true,
+};
+
+static struct mfd_cell axp20x_cells[] = {
+ {
+ .name = "axp20x-pek",
+ .of_compatible = "x-powers,axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp20x_pek_resources),
+ .resources = axp20x_pek_resources,
+ }, {
+ .name = "axp20x-regulator",
+ },
+};
+
+const struct of_device_id axp20x_of_match[] = {
+ { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID },
+ { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID },
+ { },
+};
+
+static struct axp20x_dev *axp20x_pm_power_off;
+static void axp20x_power_off(void)
+{
+ regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
+ AXP20X_OFF);
+}
+
+static int axp20x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct axp20x_dev *axp20x;
+ const struct of_device_id *of_id;
+ struct device_node *node = i2c->dev.of_node;
+ int ret;
+
+ axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
+ if (!axp20x)
+ return -ENOMEM;
+
+ of_id = of_match_device(axp20x_of_match, &i2c->dev);
+ if (!of_id) {
+ dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
+ return -ENODEV;
+ }
+ axp20x->variant = (int) of_id->data;
+
+ axp20x->i2c_client = i2c;
+ axp20x->dev = &i2c->dev;
+ dev_set_drvdata(axp20x->dev, axp20x);
+
+ axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
+ if (IS_ERR(axp20x->regmap)) {
+ ret = PTR_ERR(axp20x->regmap);
+ dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+
+ axp20x->irq = i2c->irq;
+ ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
+ IRQF_ONESHOT | IRQF_SHARED, -1,
+ &axp20x_regmap_irq_chip,
+ &axp20x->regmap_irqc);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
+ return ret;
+ }
+
+ ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
+ ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
+ goto mfd_err;
+ }
+
+ axp20x->pm_off = of_property_read_bool(node, "axp,system-power-controller");
+
+ if (axp20x->pm_off && !pm_power_off) {
+ axp20x_pm_power_off = axp20x;
+ pm_power_off = axp20x_power_off;
+ }
+
+ dev_info(&i2c->dev, "AXP20X driver loaded\n");
+
+ return 0;
+
+mfd_err:
+ regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
+
+ return ret;
+}
+
+static int axp20x_i2c_remove(struct i2c_client *i2c)
+{
+ struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
+
+ if (axp20x == axp20x_pm_power_off) {
+ axp20x_pm_power_off = NULL;
+ pm_power_off = NULL;
+ }
+
+ mfd_remove_devices(axp20x->dev);
+ regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc);
+
+ return 0;
+}
+
+static const struct i2c_device_id axp20x_i2c_id[] = {
+ { "axp202", AXP202_ID },
+ { "axp209", AXP209_ID },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
+
+static struct i2c_driver axp20x_i2c_driver = {
+ .driver = {
+ .name = "axp20x",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(axp20x_of_match),
+ },
+ .probe = axp20x_i2c_probe,
+ .remove = axp20x_i2c_remove,
+ .id_table = axp20x_i2c_id,
+};
+
+module_i2c_driver(axp20x_i2c_driver);
+
+MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/include/linux/mfd/axp20x.h
@@ -0,0 +1,180 @@
+/*
+ * Functions to access AXP20X power management chip.
+ *
+ * Copyright (C) 2013, Carlo Caione <carlo@caione.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MFD_AXP20X_H
+#define __LINUX_MFD_AXP20X_H
+
+#define AXP202_ID 0
+#define AXP209_ID 1
+
+#define AXP20X_DATACACHE(m) (0x04 + (m))
+
+/* Power supply */
+#define AXP20X_PWR_INPUT_STATUS 0x00
+#define AXP20X_PWR_OP_MODE 0x01
+#define AXP20X_USB_OTG_STATUS 0x02
+#define AXP20X_PWR_OUT_CTRL 0x12
+#define AXP20X_DCDC2_V_OUT 0x23
+#define AXP20X_DCDC2_LDO3_V_SCAL 0x25
+#define AXP20X_DCDC3_V_OUT 0x27
+#define AXP20X_LDO24_V_OUT 0x28
+#define AXP20X_LDO3_V_OUT 0x29
+#define AXP20X_VBUS_IPSOUT_MGMT 0x30
+#define AXP20X_V_OFF 0x31
+#define AXP20X_OFF_CTRL 0x32
+#define AXP20X_CHRG_CTRL1 0x33
+#define AXP20X_CHRG_CTRL2 0x34
+#define AXP20X_CHRG_BAK_CTRL 0x35
+#define AXP20X_PEK_KEY 0x36
+#define AXP20X_DCDC_FREQ 0x37
+#define AXP20X_V_LTF_CHRG 0x38
+#define AXP20X_V_HTF_CHRG 0x39
+#define AXP20X_APS_WARN_L1 0x3a
+#define AXP20X_APS_WARN_L2 0x3b
+#define AXP20X_V_LTF_DISCHRG 0x3c
+#define AXP20X_V_HTF_DISCHRG 0x3d
+
+/* Interrupt */
+#define AXP20X_IRQ1_EN 0x40
+#define AXP20X_IRQ2_EN 0x41
+#define AXP20X_IRQ3_EN 0x42
+#define AXP20X_IRQ4_EN 0x43
+#define AXP20X_IRQ5_EN 0x44
+#define AXP20X_IRQ1_STATE 0x48
+#define AXP20X_IRQ2_STATE 0x49
+#define AXP20X_IRQ3_STATE 0x4a
+#define AXP20X_IRQ4_STATE 0x4b
+#define AXP20X_IRQ5_STATE 0x4c
+
+/* ADC */
+#define AXP20X_ACIN_V_ADC_H 0x56
+#define AXP20X_ACIN_V_ADC_L 0x57
+#define AXP20X_ACIN_I_ADC_H 0x58
+#define AXP20X_ACIN_I_ADC_L 0x59
+#define AXP20X_VBUS_V_ADC_H 0x5a
+#define AXP20X_VBUS_V_ADC_L 0x5b
+#define AXP20X_VBUS_I_ADC_H 0x5c
+#define AXP20X_VBUS_I_ADC_L 0x5d
+#define AXP20X_TEMP_ADC_H 0x5e
+#define AXP20X_TEMP_ADC_L 0x5f
+#define AXP20X_TS_IN_H 0x62
+#define AXP20X_TS_IN_L 0x63
+#define AXP20X_GPIO0_V_ADC_H 0x64
+#define AXP20X_GPIO0_V_ADC_L 0x65
+#define AXP20X_GPIO1_V_ADC_H 0x66
+#define AXP20X_GPIO1_V_ADC_L 0x67
+#define AXP20X_PWR_BATT_H 0x70
+#define AXP20X_PWR_BATT_M 0x71
+#define AXP20X_PWR_BATT_L 0x72
+#define AXP20X_BATT_V_H 0x78
+#define AXP20X_BATT_V_L 0x79
+#define AXP20X_BATT_CHRG_I_H 0x7a
+#define AXP20X_BATT_CHRG_I_L 0x7b
+#define AXP20X_BATT_DISCHRG_I_H 0x7c
+#define AXP20X_BATT_DISCHRG_I_L 0x7d
+#define AXP20X_IPSOUT_V_HIGH_H 0x7e
+#define AXP20X_IPSOUT_V_HIGH_L 0x7f
+
+/* Power supply */
+#define AXP20X_DCDC_MODE 0x80
+#define AXP20X_ADC_EN1 0x82
+#define AXP20X_ADC_EN2 0x83
+#define AXP20X_ADC_RATE 0x84
+#define AXP20X_GPIO10_IN_RANGE 0x85
+#define AXP20X_GPIO1_ADC_IRQ_RIS 0x86
+#define AXP20X_GPIO1_ADC_IRQ_FAL 0x87
+#define AXP20X_TIMER_CTRL 0x8a
+#define AXP20X_VBUS_MON 0x8b
+#define AXP20X_OVER_TMP 0x8f
+
+/* GPIO */
+#define AXP20X_GPIO0_CTRL 0x90
+#define AXP20X_LDO5_V_OUT 0x91
+#define AXP20X_GPIO1_CTRL 0x92
+#define AXP20X_GPIO2_CTRL 0x93
+#define AXP20X_GPIO20_SS 0x94
+#define AXP20X_GPIO3_CTRL 0x95
+
+/* Battery */
+#define AXP20X_CHRG_CC_31_24 0xb0
+#define AXP20X_CHRG_CC_23_16 0xb1
+#define AXP20X_CHRG_CC_15_8 0xb2
+#define AXP20X_CHRG_CC_7_0 0xb3
+#define AXP20X_DISCHRG_CC_31_24 0xb4
+#define AXP20X_DISCHRG_CC_23_16 0xb5
+#define AXP20X_DISCHRG_CC_15_8 0xb6
+#define AXP20X_DISCHRG_CC_7_0 0xb7
+#define AXP20X_CC_CTRL 0xb8
+#define AXP20X_FG_RES 0xb9
+
+/* Regulators IDs */
+enum {
+ AXP20X_LDO1 = 0,
+ AXP20X_LDO2,
+ AXP20X_LDO3,
+ AXP20X_LDO4,
+ AXP20X_LDO5,
+ AXP20X_DCDC2,
+ AXP20X_DCDC3,
+ AXP20X_REG_ID_MAX,
+};
+
+/* IRQs */
+enum {
+ AXP20X_IRQ_ACIN_OVER_V = 1,
+ AXP20X_IRQ_ACIN_PLUGIN,
+ AXP20X_IRQ_ACIN_REMOVAL,
+ AXP20X_IRQ_VBUS_OVER_V,
+ AXP20X_IRQ_VBUS_PLUGIN,
+ AXP20X_IRQ_VBUS_REMOVAL,
+ AXP20X_IRQ_VBUS_V_LOW,
+ AXP20X_IRQ_BATT_PLUGIN,
+ AXP20X_IRQ_BATT_REMOVAL,
+ AXP20X_IRQ_BATT_ENT_ACT_MODE,
+ AXP20X_IRQ_BATT_EXIT_ACT_MODE,
+ AXP20X_IRQ_CHARG,
+ AXP20X_IRQ_CHARG_DONE,
+ AXP20X_IRQ_BATT_TEMP_HIGH,
+ AXP20X_IRQ_BATT_TEMP_LOW,
+ AXP20X_IRQ_DIE_TEMP_HIGH,
+ AXP20X_IRQ_CHARG_I_LOW,
+ AXP20X_IRQ_DCDC1_V_LONG,
+ AXP20X_IRQ_DCDC2_V_LONG,
+ AXP20X_IRQ_DCDC3_V_LONG,
+ AXP20X_IRQ_PEK_SHORT = 22,
+ AXP20X_IRQ_PEK_LONG,
+ AXP20X_IRQ_N_OE_PWR_ON,
+ AXP20X_IRQ_N_OE_PWR_OFF,
+ AXP20X_IRQ_VBUS_VALID,
+ AXP20X_IRQ_VBUS_NOT_VALID,
+ AXP20X_IRQ_VBUS_SESS_VALID,
+ AXP20X_IRQ_VBUS_SESS_END,
+ AXP20X_IRQ_LOW_PWR_LVL1,
+ AXP20X_IRQ_LOW_PWR_LVL2,
+ AXP20X_IRQ_TIMER,
+ AXP20X_IRQ_PEK_RIS_EDGE,
+ AXP20X_IRQ_PEK_FAL_EDGE,
+ AXP20X_IRQ_GPIO3_INPUT,
+ AXP20X_IRQ_GPIO2_INPUT,
+ AXP20X_IRQ_GPIO1_INPUT,
+ AXP20X_IRQ_GPIO0_INPUT,
+};
+
+struct axp20x_dev {
+ struct device *dev;
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *regmap_irqc;
+ int variant;
+ int irq;
+ bool pm_off;
+};
+
+#endif /* __LINUX_MFD_AXP20X_H */

View file

@ -1,327 +0,0 @@
From 656b9ff9781aa3ffeb4231f32dfc545c92d04a12 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Sat, 1 Mar 2014 17:45:49 +0100
Subject: [PATCH] input: misc: Add driver for AXP20x Power Enable Key
This patch add support for the Power Enable Key found on MFD AXP202 and
AXP209. Besides the basic support for the button, the driver adds two
entries in sysfs to configure the time delay for power on/off.
Signed-off-by: Carlo Caione <carlo@caione.org>
---
arch/arm/configs/sunxi_defconfig | 2 +
drivers/input/misc/Kconfig | 11 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/axp20x-pek.c | 265 +++++++++++++++++++++++++++++++++++++++
4 files changed, 279 insertions(+)
create mode 100644 drivers/input/misc/axp20x-pek.c
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -40,6 +40,8 @@ CONFIG_SUN4I_EMAC=y
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AXP20X_PEK=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=8
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -393,6 +393,17 @@ config INPUT_RETU_PWRBUTTON
To compile this driver as a module, choose M here. The module will
be called retu-pwrbutton.
+config INPUT_AXP20X_PEK
+ tristate "X-Powers AXP20X power button driver"
+ depends on MFD_AXP20X
+ help
+ Say Y here if you want to enable power key reporting via the
+ AXP20X PMIC.
+
+ To compile this driver as a module, choose M here. The module will
+ be called axp20x-pek.
+
+
config INPUT_TWL4030_PWRBUTTON
tristate "TWL4030 Power button Driver"
depends on TWL4030_CORE
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_INPUT_POWERMATE) += powerm
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
+obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
--- /dev/null
+++ b/drivers/input/misc/axp20x-pek.c
@@ -0,0 +1,265 @@
+/*
+ * axp20x power button driver.
+ *
+ * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * 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/errno.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define AXP20X_PEK_STARTUP_MASK (0xc0)
+#define AXP20X_PEK_SHUTDOWN_MASK (0x03)
+
+static const char const *startup_time[] = { "128mS", "3S" , "1S", "2S" };
+static const char const *shutdown_time[] = { "4S", "6S" , "8S", "10S" };
+
+struct axp20x_pek {
+ struct axp20x_dev *axp20x;
+ struct input_dev *input;
+ int irq_dbr;
+ int irq_dbf;
+};
+
+struct axp20x_pek_ext_attr {
+ const char const **str;
+ unsigned int mask;
+};
+
+static struct axp20x_pek_ext_attr axp20x_pek_startup_ext_attr = {
+ .str = startup_time,
+ .mask = AXP20X_PEK_STARTUP_MASK,
+};
+
+static struct axp20x_pek_ext_attr axp20x_pek_shutdown_ext_attr = {
+ .str = shutdown_time,
+ .mask = AXP20X_PEK_SHUTDOWN_MASK,
+};
+
+static struct axp20x_pek_ext_attr *get_axp_ext_attr(struct device_attribute *attr)
+{
+ return container_of(attr, struct dev_ext_attribute, attr)->var;
+}
+
+ssize_t axp20x_show_ext_attr(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+ struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
+ unsigned int val;
+ int ret, i;
+ int cnt = 0;
+
+ ret = regmap_read(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= axp20x_ea->mask;
+ val >>= ffs(axp20x_ea->mask) - 1;
+
+ for (i = 0; i < 4; i++) {
+ if (val == i)
+ cnt += sprintf(buf + cnt, "[%s] ", axp20x_ea->str[i]);
+ else
+ cnt += sprintf(buf + cnt, "%s ", axp20x_ea->str[i]);
+ }
+
+ cnt += sprintf(buf + cnt, "\n");
+
+ return cnt;
+}
+
+ssize_t axp20x_store_ext_attr(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+ struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr);
+ char val_str[20];
+ int ret, i;
+ size_t len;
+
+ val_str[sizeof(val_str) - 1] = '\0';
+ strncpy(val_str, buf, sizeof(val_str) - 1);
+ len = strlen(val_str);
+
+ if (len && val_str[len - 1] == '\n')
+ val_str[len - 1] = '\0';
+
+ for (i = 0; i < 4; i++) {
+ if (!strcmp(val_str, axp20x_ea->str[i])) {
+ ret = regmap_update_bits(axp20x_pek->axp20x->regmap,
+ AXP20X_PEK_KEY,
+ axp20x_ea->mask, i);
+ if (ret != 0)
+ return -EINVAL;
+ return count;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static struct dev_ext_attribute axp20x_dev_attr_startup = {
+ .attr = __ATTR(startup, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
+ .var = &axp20x_pek_startup_ext_attr
+};
+
+static struct dev_ext_attribute axp20x_dev_attr_shutdown = {
+ __ATTR(shutdown, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr),
+ &axp20x_pek_shutdown_ext_attr
+};
+
+static struct attribute *dev_attrs[] = {
+ &axp20x_dev_attr_startup.attr.attr,
+ &axp20x_dev_attr_shutdown.attr.attr,
+ NULL,
+};
+
+static struct attribute_group dev_attr_group = {
+ .attrs = dev_attrs,
+};
+
+static const struct attribute_group *dev_attr_groups[] = {
+ &dev_attr_group,
+ NULL,
+};
+
+static irqreturn_t axp20x_pek_irq(int irq, void *pwr)
+{
+ struct input_dev *idev = pwr;
+ struct axp20x_pek *axp20x_pek = input_get_drvdata(idev);
+
+ if (irq == axp20x_pek->irq_dbr)
+ input_report_key(idev, KEY_POWER, true);
+ else if (irq == axp20x_pek->irq_dbf)
+ input_report_key(idev, KEY_POWER, false);
+
+ input_sync(idev);
+
+ return IRQ_HANDLED;
+}
+
+static int axp20x_pek_probe(struct platform_device *pdev)
+{
+ struct axp20x_pek *axp20x_pek;
+ struct axp20x_dev *axp20x;
+ struct input_dev *idev;
+ int error;
+
+ axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
+ GFP_KERNEL);
+ if (!axp20x_pek)
+ return -ENOMEM;
+
+ axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
+ axp20x = axp20x_pek->axp20x;
+
+ axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
+ if (axp20x_pek->irq_dbr < 0) {
+ dev_err(&pdev->dev, "No IRQ for PEK_DBR, error=%d\n",
+ axp20x_pek->irq_dbr);
+ return axp20x_pek->irq_dbr;
+ }
+ axp20x_pek->irq_dbr = regmap_irq_get_virq(axp20x->regmap_irqc,
+ axp20x_pek->irq_dbr);
+
+ axp20x_pek->irq_dbf = platform_get_irq_byname(pdev, "PEK_DBF");
+ if (axp20x_pek->irq_dbf < 0) {
+ dev_err(&pdev->dev, "No IRQ for PEK_DBF, error=%d\n",
+ axp20x_pek->irq_dbf);
+ return axp20x_pek->irq_dbf;
+ }
+ axp20x_pek->irq_dbf = regmap_irq_get_virq(axp20x->regmap_irqc,
+ axp20x_pek->irq_dbf);
+
+ axp20x_pek->input = devm_input_allocate_device(&pdev->dev);
+ if (!axp20x_pek->input)
+ return -ENOMEM;
+
+ idev = axp20x_pek->input;
+
+ idev->name = "axp20x-pek";
+ idev->phys = "m1kbd/input2";
+ idev->dev.parent = &pdev->dev;
+
+ input_set_capability(idev, EV_KEY, KEY_POWER);
+
+ input_set_drvdata(idev, axp20x_pek);
+
+ error = devm_request_threaded_irq(&pdev->dev, axp20x_pek->irq_dbr,
+ NULL, axp20x_pek_irq, 0,
+ "axp20x-pek-dbr", idev);
+ if (error) {
+ dev_err(axp20x->dev, "Failed to request dbr IRQ#%d: %d\n",
+ axp20x_pek->irq_dbr, error);
+
+ return error;
+ }
+
+ error = devm_request_threaded_irq(&pdev->dev, axp20x_pek->irq_dbf,
+ NULL, axp20x_pek_irq, 0,
+ "axp20x-pek-dbf", idev);
+ if (error) {
+ dev_err(axp20x->dev, "Failed to request dbf IRQ#%d: %d\n",
+ axp20x_pek->irq_dbf, error);
+ return error;
+ }
+
+ idev->dev.groups = dev_attr_groups;
+ error = input_register_device(idev);
+ if (error) {
+ dev_err(axp20x->dev, "Can't register input device: %d\n", error);
+ return error;
+ }
+
+ platform_set_drvdata(pdev, axp20x_pek);
+
+ return 0;
+}
+
+static int axp20x_pek_remove(struct platform_device *pdev)
+{
+ struct axp20x_pek *axp20x_pek = platform_get_drvdata(pdev);
+
+ input_unregister_device(axp20x_pek->input);
+
+ return 0;
+}
+
+static const struct of_device_id axp20x_pek_match[] = {
+ { .compatible = "x-powers,axp20x-pek", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, axp20x_pek_match);
+
+static struct platform_driver axp20x_pek_driver = {
+ .probe = axp20x_pek_probe,
+ .remove = axp20x_pek_remove,
+ .driver = {
+ .name = "axp20x-pek",
+ .owner = THIS_MODULE,
+ .of_match_table = axp20x_pek_match,
+ },
+};
+module_platform_driver(axp20x_pek_driver);
+
+MODULE_DESCRIPTION("axp20x Power Button");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_LICENSE("GPL");

View file

@ -1,402 +0,0 @@
From c3af279a9031b3375d3e5a684619c1adbbe30da9 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Sat, 1 Mar 2014 17:45:51 +0100
Subject: [PATCH] regulator: AXP20x: Add support for regulators subsystem
AXP202 and AXP209 come with two synchronous step-down DC-DCs and five
LDOs. This patch introduces basic support for those regulators.
Signed-off-by: Carlo Caione <carlo@caione.org>
---
arch/arm/configs/sunxi_defconfig | 1 +
drivers/regulator/Kconfig | 7 +
drivers/regulator/Makefile | 1 +
drivers/regulator/axp20x-regulator.c | 349 +++++++++++++++++++++++++++++++++++
4 files changed, 358 insertions(+)
create mode 100644 drivers/regulator/axp20x-regulator.c
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -72,3 +72,4 @@ CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NLS=y
CONFIG_PRINTK_TIME=y
+CONFIG_REGULATOR_AXP20X=y
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -139,6 +139,13 @@ config REGULATOR_AS3722
AS3722 PMIC. This will enable support for all the software
controllable DCDC/LDO regulators.
+config REGULATOR_AXP20X
+ tristate "X-POWERS AXP20X PMIC Regulators"
+ depends on MFD_AXP20X
+ help
+ This driver provides support for the voltage regulators on the
+ AXP20X PMIC.
+
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
+obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
--- /dev/null
+++ b/drivers/regulator/axp20x-regulator.c
@@ -0,0 +1,349 @@
+/*
+ * axp20x regulators driver.
+ *
+ * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/regmap.h>
+
+#define AXP20X_IO_ENABLED (0x03)
+
+#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
+#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
+
+#define AXP20X_FREQ_DCDC_MASK (0x0f)
+
+struct axp20x_regulators {
+ struct regulator_desc rdesc[AXP20X_REG_ID_MAX];
+ struct regulator_dev *rdev[AXP20X_REG_ID_MAX];
+ struct axp20x_dev *axp20x;
+};
+
+#define AXP20X_DESC(_id, _min, _max, _step, _vreg, _vmask, _ereg, _emask) \
+ [AXP20X_##_id] = { \
+ .name = #_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = AXP20X_##_id, \
+ .n_voltages = (((_max) - (_min)) / (_step) + 1), \
+ .owner = THIS_MODULE, \
+ .min_uV = (_min) * 1000, \
+ .uV_step = (_step) * 1000, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .ops = &axp20x_ops, \
+ }
+
+#define AXP20X_DESC_IO(_id, _min, _max, _step, _vreg, _vmask, _ereg, _emask) \
+ [AXP20X_##_id] = { \
+ .name = #_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = AXP20X_##_id, \
+ .n_voltages = (((_max) - (_min)) / (_step) + 1), \
+ .owner = THIS_MODULE, \
+ .min_uV = (_min) * 1000, \
+ .uV_step = (_step) * 1000, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .ops = &axp20x_ops_io, \
+ }
+
+#define AXP20X_DESC_FIXED(_id, _volt) \
+ [AXP20X_##_id] = { \
+ .name = #_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = AXP20X_##_id, \
+ .n_voltages = 1, \
+ .owner = THIS_MODULE, \
+ .min_uV = (_volt) * 1000, \
+ .ops = &axp20x_ops, \
+ }
+
+#define AXP20X_DESC_TABLE(_id, _table, _vreg, _vmask, _ereg, _emask) \
+ [AXP20X_##_id] = { \
+ .name = #_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = AXP20X_##_id, \
+ .n_voltages = ARRAY_SIZE(_table), \
+ .owner = THIS_MODULE, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .volt_table = (_table), \
+ .ops = &axp20x_ops_table, \
+ }
+
+static int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000, 1700000,
+ 1800000, 1900000, 2000000, 2500000, 2700000, 2800000,
+ 3000000, 3100000, 3200000, 3300000 };
+
+static int axp20x_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ return regulator_set_voltage_sel_regmap(rdev, 0);
+}
+
+static int axp20x_io_enable_regmap(struct regulator_dev *rdev)
+{
+ return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ rdev->desc->enable_mask, AXP20X_IO_ENABLED);
+}
+
+static int axp109_io_is_enabled_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->enable_mask;
+ return (val == AXP20X_IO_ENABLED);
+}
+
+static struct regulator_ops axp20x_ops_table = {
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = regulator_enable_regmap,
+ .set_suspend_disable = regulator_disable_regmap,
+ .set_suspend_voltage = axp20x_set_suspend_voltage,
+};
+
+
+static struct regulator_ops axp20x_ops = {
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = regulator_enable_regmap,
+ .set_suspend_disable = regulator_disable_regmap,
+ .set_suspend_voltage = axp20x_set_suspend_voltage,
+};
+
+static struct regulator_ops axp20x_ops_io = {
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .enable = axp20x_io_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = axp109_io_is_enabled_regmap,
+ .set_suspend_enable = regulator_enable_regmap,
+ .set_suspend_disable = regulator_disable_regmap,
+ .set_suspend_voltage = axp20x_set_suspend_voltage,
+};
+
+static struct regulator_desc axp20x_regulators[] = {
+ AXP20X_DESC(DCDC2, 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
+ AXP20X_PWR_OUT_CTRL, 0x10),
+ AXP20X_DESC(DCDC3, 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
+ AXP20X_PWR_OUT_CTRL, 0x02),
+ AXP20X_DESC_FIXED(LDO1, 1300),
+ AXP20X_DESC(LDO2, 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
+ AXP20X_PWR_OUT_CTRL, 0x04),
+ AXP20X_DESC(LDO3, 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
+ AXP20X_PWR_OUT_CTRL, 0x40),
+ AXP20X_DESC_TABLE(LDO4, axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
+ AXP20X_PWR_OUT_CTRL, 0x08),
+ AXP20X_DESC_IO(LDO5, 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
+ AXP20X_GPIO0_CTRL, 0x07),
+};
+
+#define AXP_MATCH(_name, _id) \
+ [AXP20X_##_id] = { \
+ .name = #_name, \
+ .driver_data = (void *) &axp20x_regulators[AXP20X_##_id], \
+ }
+
+static struct of_regulator_match axp20x_matches[] = {
+ AXP_MATCH(dcdc2, DCDC2),
+ AXP_MATCH(dcdc3, DCDC3),
+ AXP_MATCH(ldo1, LDO1),
+ AXP_MATCH(ldo2, LDO2),
+ AXP_MATCH(ldo3, LDO3),
+ AXP_MATCH(ldo4, LDO4),
+ AXP_MATCH(ldo5, LDO5),
+};
+
+static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
+{
+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+
+ if (dcdcfreq < 750)
+ dcdcfreq = 750;
+
+ if (dcdcfreq > 1875)
+ dcdcfreq = 1875;
+
+ dcdcfreq = (dcdcfreq - 750) / 75;
+
+ return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
+ AXP20X_FREQ_DCDC_MASK, dcdcfreq);
+}
+
+static int axp20x_regulator_parse_dt(struct platform_device *pdev)
+{
+ struct device_node *np, *regulators;
+ int ret;
+ u32 dcdcfreq;
+
+ np = of_node_get(pdev->dev.parent->of_node);
+ if (!np)
+ return 0;
+
+ regulators = of_find_node_by_name(np, "regulators");
+ if (!regulators) {
+ dev_err(&pdev->dev, "regulators node not found\n");
+ return -EINVAL;
+ }
+
+ ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches,
+ ARRAY_SIZE(axp20x_matches));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
+ ret);
+ return ret;
+ }
+
+ dcdcfreq = 0x08;
+ of_property_read_u32(regulators, "dcdc-freq", &dcdcfreq);
+ ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
+ return ret;
+ }
+
+ of_node_put(regulators);
+
+ return 0;
+}
+
+static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
+{
+ unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
+
+ if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
+ return -EINVAL;
+
+ if (id == AXP20X_DCDC3)
+ mask = AXP20X_WORKMODE_DCDC3_MASK;
+
+ return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
+}
+
+static int axp20x_regulator_probe(struct platform_device *pdev)
+{
+ struct axp20x_regulators *pmic;
+ struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_config config = { };
+ struct regulator_init_data *init_data;
+ int ret, i;
+ u32 workmode;
+
+ ret = axp20x_regulator_parse_dt(pdev);
+ if (ret)
+ return ret;
+
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic) {
+ dev_err(&pdev->dev, "Failed to alloc pmic\n");
+ return -ENOMEM;
+ }
+
+ pmic->axp20x = axp20x;
+ memcpy(pmic->rdesc, axp20x_regulators, sizeof(pmic->rdesc));
+ platform_set_drvdata(pdev, pmic);
+
+ for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
+ init_data = axp20x_matches[i].init_data;
+ if (!init_data)
+ continue;
+
+ config.dev = &pdev->dev;
+ config.init_data = init_data;
+ config.driver_data = pmic;
+ config.regmap = axp20x->regmap;
+ config.of_node = axp20x_matches[i].of_node;
+
+ pmic->rdev[i] = regulator_register(&pmic->rdesc[i], &config);
+ if (IS_ERR(pmic->rdev[i])) {
+ ret = PTR_ERR(pmic->rdev[i]);
+ dev_err(&pdev->dev, "Failed to register %s\n",
+ pmic->rdesc[i].name);
+
+ while (--i >= 0)
+ regulator_unregister(pmic->rdev[i]);
+
+ return ret;
+ }
+
+ ret = of_property_read_u32(axp20x_matches[i].of_node, "dcdc-workmode",
+ &workmode);
+ if (!ret) {
+ ret = axp20x_set_dcdc_workmode(pmic->rdev[i], i, workmode);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to set workmode on %s\n",
+ pmic->rdesc[i].name);
+ }
+ }
+
+ return 0;
+}
+
+static int axp20x_regulator_remove(struct platform_device *pdev)
+{
+ struct axp20x_regulators *pmic = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < AXP20X_REG_ID_MAX; i++)
+ regulator_unregister(pmic->rdev[i]);
+
+ return 0;
+}
+
+static struct platform_driver axp20x_regulator_driver = {
+ .probe = axp20x_regulator_probe,
+ .remove = axp20x_regulator_remove,
+ .driver = {
+ .name = "axp20x-regulator",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init axp20x_regulator_init(void)
+{
+ return platform_driver_register(&axp20x_regulator_driver);
+}
+
+subsys_initcall(axp20x_regulator_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");

View file

@ -1,77 +0,0 @@
From 7b42dc4ff2cca887e0c6e1ad291d65b30e64dd92 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 5 Mar 2014 20:30:41 +0100
Subject: [PATCH] ARM: sunxi: dt: Add x-powers-axp209.dtsi file
This dtsi describes the axp209 PMIC, and is to be included from inside
the i2c controller node to which the axp209 is connected.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/x-powers-axp209.dtsi | 60 ++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 arch/arm/boot/dts/x-powers-axp209.dtsi
--- /dev/null
+++ b/arch/arm/boot/dts/x-powers-axp209.dtsi
@@ -0,0 +1,60 @@
+/*
+ * x-powers,axp209 common code to be include from inside the axp209 node
+ *
+ * Copyright 2014 - Carlo Caione <carlo@caione.org>
+ *
+ * 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
+ */
+
+ compatible = "x-powers,axp209";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ regulators {
+ dcdc-freq = "8";
+
+ axp_dcdc2: dcdc2 {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <2275000>;
+ dcdc-workmode = <0>;
+ regulator-always-on;
+ };
+
+ axp_dcdc3: dcdc3 {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3500000>;
+ dcdc-workmode = <0>;
+ regulator-always-on;
+ };
+
+ axp_ldo1: ldo1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ axp_ldo2: ldo2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ axp_ldo3: ldo3 {
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <3500000>;
+ };
+
+ axp_ldo4: ldo4 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ axp_ldo5: ldo5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };

View file

@ -1,35 +0,0 @@
From c792a05efcfebcf94ba925135a778961700965f5 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@caione.org>
Date: Sat, 1 Mar 2014 17:45:48 +0100
Subject: [PATCH] ARM: sun7i: dt: Add AXP209 support to the cubieboard2
AXP209 is the PMU used by Cubieboard2. This patch enables the AXP209
support in the dts file.
This patch requires: "ARM: sun7i/sun6i: irqchip: Add irqchip driver for
NMI controller"
Signed-off-by: Carlo Caione <carlo@caione.org>
---
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -74,6 +74,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
i2c1: i2c@01c2b000 {

View file

@ -1,142 +0,0 @@
From d14c5523653ca6ce9f1487922c8ab4e571d17b62 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 11 Mar 2014 16:51:44 +0100
Subject: [PATCH] ARM: sun4i: dt: Add AXP209 support to various boards
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10-a1000.dts | 9 +++++++++
arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 9 +++++++++
arch/arm/boot/dts/sun4i-a10-hackberry.dts | 15 +++++++++++++++
arch/arm/boot/dts/sun4i-a10-inet97fv2.dts | 9 +++++++++
arch/arm/boot/dts/sun4i-a10-mini-xplus.dts | 15 +++++++++++++++
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts | 15 +++++++++++++++
arch/arm/boot/dts/sun4i-a10-pcduino.dts | 9 +++++++++
7 files changed, 81 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -65,6 +65,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
};
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -88,6 +88,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
i2c1: i2c@01c2b000 {
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
@@ -82,6 +82,21 @@
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
+ };
};
regulators {
--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
@@ -55,6 +55,21 @@
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
+ };
};
reg_usb1_vbus: usb1-vbus {
--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
@@ -90,6 +90,21 @@
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
+ };
};
leds {
--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
@@ -74,6 +74,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupts = <0>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
};

View file

@ -1,49 +0,0 @@
From 886f41537ad5e873caee522704e96e844a485961 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 5 Mar 2014 20:41:17 +0100
Subject: [PATCH] ARM: sun7i: dt: Add AXP209 support to cubietruck
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 10 ++++++++++
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 10 ++++++++++
2 files changed, 20 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -89,6 +89,16 @@
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
i2c0: i2c@01c2ac00 {
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -127,6 +127,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp: axp20x@34 {
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ axp,system-power-controller;
+
+ /include/ "x-powers-axp209.dtsi"
+ };
};
i2c1: i2c@01c2b000 {

View file

@ -1,40 +0,0 @@
From 505ad20db47442ae2650a41eca0a7a869aace789 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 5 Mar 2014 20:40:44 +0100
Subject: [PATCH] ARM: sun5i: dt: Add address- and size-cells info to i2c
controller nodes
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun5i-a13.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -503,6 +503,8 @@
clocks = <&apb1_gates 0>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c1: i2c@01c2b000 {
@@ -512,6 +514,8 @@
clocks = <&apb1_gates 1>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c2: i2c@01c2b400 {
@@ -521,6 +525,8 @@
clocks = <&apb1_gates 2>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
timer@01c60000 {

View file

@ -1,58 +0,0 @@
From 338560ad44f2e8b6f4eb095567830b6c78b35ba2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 5 Mar 2014 20:40:57 +0100
Subject: [PATCH] ARM: sun7i: dt: Add address- and size-cells info to i2c
controller nodes
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun7i-a20.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -848,6 +848,8 @@
clocks = <&apb1_gates 0>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c1: i2c@01c2b000 {
@@ -857,6 +859,8 @@
clocks = <&apb1_gates 1>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c2: i2c@01c2b400 {
@@ -866,6 +870,8 @@
clocks = <&apb1_gates 2>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c3: i2c@01c2b800 {
@@ -875,6 +881,8 @@
clocks = <&apb1_gates 3>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c4: i2c@01c2bc00 {
@@ -884,6 +892,8 @@
clocks = <&apb1_gates 15>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
gmac: ethernet@01c50000 {

View file

@ -1,40 +0,0 @@
From 46d3d005e5f91d8221676cbb6307e790d4b63345 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 5 Mar 2014 20:40:26 +0100
Subject: [PATCH] ARM: sun4i: dt: Add address- and size-cells info to i2c
controller nodes
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun4i-a10.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -712,6 +712,8 @@
clocks = <&apb1_gates 0>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c1: i2c@01c2b000 {
@@ -721,6 +723,8 @@
clocks = <&apb1_gates 1>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
i2c2: i2c@01c2b400 {
@@ -730,6 +734,8 @@
clocks = <&apb1_gates 2>;
clock-frequency = <100000>;
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
};
};

View file

@ -1,43 +0,0 @@
From 6267355f0e513bed9a5009924abc7a1e7de22ab3 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Mon, 6 Jan 2014 13:58:12 +0800
Subject: [PATCH] arm: sun7i: cubietruck: Enable the i2c controllers
The Cubietruck makes use of the first three i2c controllers found on the
Allwinner A20; i2c-0 is used internally for the PMIC, i2c-1 is exposed on
the board headers, and i2c-2 is used for DDC on the VGA connector. This
patch enables them in the device tree.
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-cubietruck.dts | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -130,6 +130,24 @@
reg = <1>;
};
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+ };
+
+ i2c1: i2c@01c2b000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_a>;
+ status = "okay";
+ };
+
+ i2c2: i2c@01c2b400 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_a>;
+ status = "okay";
+ };
};
leds {

View file

@ -1,36 +0,0 @@
From 81b745ee30dc7cd230f924f6263879f1b7ffbc0c Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Thu, 13 Mar 2014 16:14:13 +0100
Subject: [PATCH] clk: sunxi: Remove calls to clk_put
Callers of clk_put must disable the clock first. This also means that as long
as the clock is enabled the driver should hold a reference to that clock.
Hence, the call to clk_put here are bogus and should be removed.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/clk/sunxi/clk-sunxi.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1325,17 +1325,13 @@ static void __init sunxi_clock_protect(v
/* memory bus clock - sun5i+ */
clk = clk_get(NULL, "mbus");
- if (!IS_ERR(clk)) {
+ if (!IS_ERR(clk))
clk_prepare_enable(clk);
- clk_put(clk);
- }
/* DDR clock - sun4i+ */
clk = clk_get(NULL, "pll5_ddr");
- if (!IS_ERR(clk)) {
+ if (!IS_ERR(clk))
clk_prepare_enable(clk);
- clk_put(clk);
- }
}
static void __init sunxi_init_clocks(void)

View file

@ -1,148 +0,0 @@
From 5f6f6af41e39677c9b722376a4088d10732cdd44 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 17 Jan 2014 14:47:26 +0800
Subject: [PATCH] net: rfkill: gpio: fix gpio name buffer size off by 1
snprintf should be passed the complete size of the buffer, including
the space for '\0'. The previous code resulted in the *_reset and
*_shutdown strings being truncated.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
net/rfkill/rfkill-gpio.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
+#include <linux/of_gpio.h>
#include <linux/rfkill-gpio.h>
@@ -39,6 +40,7 @@ struct rfkill_gpio_data {
char *reset_name;
char *shutdown_name;
struct clk *clk;
+ int clk_frequency;
bool clk_enabled;
};
@@ -51,15 +53,15 @@ static int rfkill_gpio_set_power(void *d
gpiod_set_value(rfkill->shutdown_gpio, 0);
gpiod_set_value(rfkill->reset_gpio, 0);
if (!IS_ERR(rfkill->clk) && rfkill->clk_enabled)
- clk_disable(rfkill->clk);
+ clk_disable_unprepare(rfkill->clk);
} else {
if (!IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
- clk_enable(rfkill->clk);
+ clk_prepare_enable(rfkill->clk);
gpiod_set_value(rfkill->reset_gpio, 1);
gpiod_set_value(rfkill->shutdown_gpio, 1);
}
- rfkill->clk_enabled = blocked;
+ rfkill->clk_enabled = !blocked;
return 0;
}
@@ -83,6 +85,19 @@ static int rfkill_gpio_acpi_probe(struct
return 0;
}
+static int rfkill_gpio_dt_probe(struct device *dev,
+ struct rfkill_gpio_data *rfkill)
+{
+ struct device_node * np = dev->of_node;
+
+ rfkill->name = np->name;
+ of_property_read_string(np, "rfkill-name", &rfkill->name);
+ of_property_read_u32(np, "rfkill-type", &rfkill->type);
+ of_property_read_u32(np, "clock-frequency", &rfkill->clk_frequency);
+
+ return 0;
+}
+
static int rfkill_gpio_probe(struct platform_device *pdev)
{
struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -100,6 +115,10 @@ static int rfkill_gpio_probe(struct plat
ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
if (ret)
return ret;
+ } else if (&pdev->dev.of_node) {
+ ret = rfkill_gpio_dt_probe(&pdev->dev, rfkill);
+ if (ret)
+ return ret;
} else if (pdata) {
clk_name = pdata->power_clk_name;
rfkill->name = pdata->name;
@@ -117,10 +136,12 @@ static int rfkill_gpio_probe(struct plat
if (!rfkill->shutdown_name)
return -ENOMEM;
- snprintf(rfkill->reset_name, len + 6 , "%s_reset", rfkill->name);
- snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", rfkill->name);
+ snprintf(rfkill->reset_name, len + 7 , "%s_reset", rfkill->name);
+ snprintf(rfkill->shutdown_name, len + 10, "%s_shutdown", rfkill->name);
rfkill->clk = devm_clk_get(&pdev->dev, clk_name);
+ if (!IS_ERR(rfkill->clk) && rfkill->clk_frequency > 0)
+ clk_set_rate(rfkill->clk, rfkill->clk_frequency);
gpio = devm_gpiod_get_index(&pdev->dev, rfkill->reset_name, 0);
if (!IS_ERR(gpio)) {
@@ -189,6 +210,11 @@ static const struct acpi_device_id rfkil
{ },
};
+static const struct of_device_id rfkill_of_match[] = {
+ { .compatible = "rfkill-gpio", },
+ {},
+};
+
static struct platform_driver rfkill_gpio_driver = {
.probe = rfkill_gpio_probe,
.remove = rfkill_gpio_remove,
@@ -196,6 +222,7 @@ static struct platform_driver rfkill_gpi
.name = "rfkill_gpio",
.owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rfkill_acpi_match),
+ .of_match_table = of_match_ptr(rfkill_of_match),
},
};
--- /dev/null
+++ b/Documentation/devicetree/bindings/rfkill/rfkill-gpio.txt
@@ -0,0 +1,28 @@
+GPIO controlled RFKILL devices
+
+Required properties:
+- compatible : Must be "rfkill-gpio".
+- rfkill-name : Name of RFKILL device
+- rfkill-type : Type of RFKILL device: 1 for WiFi, 2 for BlueTooth
+- NAME_shutdown-gpios : GPIO phandle to shutdown control
+ (phandle must be the second)
+- NAME_reset-gpios : GPIO phandle to reset control
+
+NAME must match the rfkill-name property. NAME_shutdown-gpios or
+NAME_reset-gpios, or both, must be defined.
+
+Optional properties:
+- clocks : phandle to clock to enable/disable
+- clock-frequency : clock rate to set for the given clock
+
+Example:
+
+ rfkill_bt: rfkill@0 {
+ compatible = "rfkill-gpio";
+ rfkill-name = "bluetooth";
+ rfkill-type = <2>;
+ bluetooth_shutdown-gpios = <0>, <&pio 7 18 0>;
+ bluetooth_reset-gpios = <&pio 7 24 0>;
+ clocks = <&clk_out_a>;
+ clock-frequency = <32678>;
+ };

View file

@ -1,32 +0,0 @@
From df25859babd9c164a61e86d953d5c88400009a14 Mon Sep 17 00:00:00 2001
From: Hante Meuleman <meuleman@broadcom.com>
Date: Wed, 29 Jan 2014 15:32:16 +0100
Subject: [PATCH] brcmfmac: fix sdio sending of large buffers.
the function brcmf_sdiod_ramrw is supposed to be able to send
large blobs of data. However inside the loop the skb->len field
did not correctly get reset each round. As a result only small
blobs could be sent. This patch fixes this problem.
Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -827,7 +827,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
}
if (!write)
memcpy(data, pkt->data, dsize);
- skb_trim(pkt, dsize);
+ skb_trim(pkt, 0);
/* Adjust for next transfer (if any) */
size -= dsize;

View file

@ -1,64 +0,0 @@
From 3eee5fd6d045dc744f98fd684258e3fdfa667fd6 Mon Sep 17 00:00:00 2001
From: Arend van Spriel <arend@broadcom.com>
Date: Tue, 25 Feb 2014 20:30:27 +0100
Subject: [PATCH] brcmfmac: fix use of skb control buffer in SDIO driver part
The SDIO driver has a 16-bit field defined in the skbuff control buffer.
However, it is accessed as a u32 overwriting other control info. Another
issue is that the field is not initialized for networking packets, but
the control buffer content is unspecified as other networking layers can
use it.
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1955,7 +1955,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru
memcpy(pkt_pad->data,
pkt->data + pkt->len - tail_chop,
tail_chop);
- *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
+ *(u16 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
skb_trim(pkt, pkt->len - tail_chop);
skb_trim(pkt_pad, tail_pad + tail_chop);
__skb_queue_after(pktq, pkt, pkt_pad);
@@ -2003,7 +2003,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio
* already properly aligned and does not
* need an sdpcm header.
*/
- if (*(u32 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
+ if (*(u16 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
continue;
/* align packet data pointer */
@@ -2067,11 +2067,11 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio
u8 *hdr;
u32 dat_offset;
u16 tail_pad;
- u32 dummy_flags, chop_len;
+ u16 dummy_flags, chop_len;
struct sk_buff *pkt_next, *tmp, *pkt_prev;
skb_queue_walk_safe(pktq, pkt_next, tmp) {
- dummy_flags = *(u32 *)(pkt_next->cb);
+ dummy_flags = *(u16 *)(pkt_next->cb);
if (dummy_flags & ALIGN_SKB_FLAG) {
chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK;
if (chop_len) {
@@ -2554,6 +2554,8 @@ static int brcmf_sdio_bus_txdata(struct
/* Priority based enq */
spin_lock_irqsave(&bus->txqlock, flags);
+ /* reset bus_flags in packet cb */
+ *(u16 *)(pkt->cb) = 0;
if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
skb_pull(pkt, bus->tx_hdrlen);
brcmf_err("out of bus->txq !!!\n");

View file

@ -1,91 +0,0 @@
From 3e7fc7d394db0783996519f2d5affde5152a628e Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Thu, 26 Dec 2013 17:14:33 +0800
Subject: [PATCH] ARM: dts: sun7i: add WiFi module to Cubietruck DTS
The CubieTruck has an AMPAK AP6210 WiFi+Bluetooth module. The WiFi
part is a BCM43362 IC connected to MMC2 in the A20 SoC via SDIO.
The IC also takes a 32.768 KHz low power clock input, and a power
enable signal via GPIO.
The WiFi module supports out-of-band interrupt signaling via GPIO,
but this is not supported in this patch.
---
arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 47 ++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -28,6 +28,23 @@
status = "okay";
};
+ mmc3: mmc@01c12000 {
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&mmc3_pins_a>;
+ pinctrl-1 = <&wifi_host_wake_pin>;
+ vmmc-supply = <&reg_vmmc3>;
+ non-removable;
+ status = "okay";
+
+ brcmf: bcrmf@0 {
+ /* out of band interrupt not working */
+ /* compatible = "broadcom,bcm43362"; */
+ interrupt-parent = <&pio>;
+ interrupts = <10 2>; /* EINT10 */
+ status = "okay";
+ };
+ };
+
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
@@ -56,6 +73,18 @@
};
pinctrl@01c20800 {
+ mmc3_pins_a: mmc3@0 {
+ /* AP6210 requires pull-up */
+ allwinner,pull = <1>;
+ };
+
+ vmmc3_pin_cubietruck: vmmc3_pin@0 {
+ allwinner,pins = "PH9";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
ahci_pwr_pin_cubietruck: ahci_pwr_pin@1 {
allwinner,pins = "PH12";
allwinner,function = "gpio_out";
@@ -99,6 +128,13 @@
/include/ "x-powers-axp209.dtsi"
};
+
+ wifi_host_wake_pin: wifi_host_wake_pin@0 {
+ allwinner,pins = "PH10";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
i2c0: i2c@01c2ac00 {
@@ -189,4 +225,15 @@
reg_usb2_vbus: usb2-vbus {
status = "okay";
};
+
+ reg_vmmc3: vmmc3 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&vmmc3_pin_cubietruck>;
+ regulator-name = "vmmc3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpio = <&pio 7 9 0>;
+ };
};

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