sunxi: drop 3.14 support
Signed-off-by: John Crispin <blogic@openwrt.org> SVN-Revision: 44824
This commit is contained in:
parent
eb396d6569
commit
c0a15a57bd
128 changed files with 0 additions and 19237 deletions
|
@ -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
|
|
@ -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 {
|
|
@ -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>;
|
|
@ -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 {
|
|
@ -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>;
|
|
@ -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";
|
|
@ -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";
|
||||
+ };
|
||||
+ };
|
||||
+};
|
|
@ -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>;
|
|
@ -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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci0: usb@01c14000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci0: usb@01c14400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ahci: sata@01c18000 {
|
||||
+ target-supply = <®_ahci_5v>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci1: usb@01c1c000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci1: usb@01c1c400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ pinctrl@01c20800 {
|
||||
+ ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 {
|
||||
+ allwinner,pins = "PC3";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <0>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+
|
||||
+ led_pins_olinuxinolime: led_pins@0 {
|
||||
+ allwinner,pins = "PH2";
|
||||
+ allwinner,function = "gpio_out";
|
||||
+ allwinner,drive = <1>;
|
||||
+ allwinner,pull = <0>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ uart0: serial@01c28000 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&uart0_pins_a>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&led_pins_olinuxinolime>;
|
||||
+
|
||||
+ green {
|
||||
+ label = "a10-olinuxino-lime:green:usr";
|
||||
+ gpios = <&pio 7 2 0>;
|
||||
+ default-state = "on";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ reg_ahci_5v: ahci-5v {
|
||||
+ pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>;
|
||||
+ gpio = <&pio 2 3 0>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ reg_usb1_vbus: usb1-vbus {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ reg_usb2_vbus: usb2-vbus {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+};
|
|
@ -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 {
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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";
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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>;
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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;
|
|
@ -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";
|
|
@ -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";
|
|
@ -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";
|
|
@ -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[] = {
|
|
@ -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);
|
||||
}
|
|
@ -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++;
|
||||
}
|
|
@ -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)
|
|
@ -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>;
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -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";
|
||||
+ };
|
||||
+};
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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");
|
|
@ -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");
|
|
@ -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
|
|
@ -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 {
|
|
@ -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";
|
|
@ -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 = <®_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>;
|
|
@ -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 = <®_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 = <®_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 = <®_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>;
|
|
@ -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);
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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*/ }
|
||||
};
|
||||
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci0: usb@01c14000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci0: usb@01c14400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ ehci1: usb@01c1c000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci1: usb@01c1c400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
led_pins_cubieboard: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
@@ -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";
|
||||
+ };
|
||||
};
|
|
@ -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 = <®_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 = <®_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";
|
||||
+ };
|
||||
};
|
|
@ -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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci0: usb@01c14000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci0: usb@01c14400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ ehci1: usb@01c1c000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci1: usb@01c1c400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
ahci_pwr_pin_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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_usb2_vbus>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ehci0: usb@01c14000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci0: usb@01c14400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
ahci: sata@01c18000 {
|
||||
target-supply = <®_ahci_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+ ehci1: usb@01c1c000 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
+ ohci1: usb@01c1c400 {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+
|
||||
pinctrl@01c20800 {
|
||||
led_pins_cubieboard2: led_pins@0 {
|
||||
allwinner,pins = "PH20", "PH21";
|
||||
@@ -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 = <®_usb1_vbus>;
|
||||
+ usb2_vbus-supply = <®_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";
|
||||
+ };
|
||||
};
|
|
@ -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");
|
|
@ -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);
|
|
@ -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");
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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>;
|
|
@ -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);
|
|
@ -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));
|
|
@ -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,
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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,},
|
||||
{}
|
||||
};
|
||||
|
|
@ -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,},
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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,},
|
|
@ -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,
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 = <®_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");
|
|
@ -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);
|
||||
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
|
@ -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 },
|
|
@ -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", },
|
||||
{}
|
||||
};
|
|
@ -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" },
|
||||
{ },
|
||||
};
|
|
@ -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
|
@ -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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_usb2_vbus>;
|
|
@ -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 = <®_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 = <®_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 {
|
|
@ -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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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 {
|
|
@ -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);
|
|
@ -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>;
|
|
@ -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 */
|
|
@ -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");
|
|
@ -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");
|
|
@ -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>;
|
||||
+ };
|
||||
+ };
|
|
@ -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 {
|
|
@ -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"
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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 {
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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 {
|
|
@ -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)
|
|
@ -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>;
|
||||
+ };
|
|
@ -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;
|
|
@ -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");
|
|
@ -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 = <®_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 = <®_usb1_vbus>;
|
||||
usb2_vbus-supply = <®_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
Loading…
Reference in a new issue