ipq806x: copy files from 4.14 to 4.19
This copies files from files-4.14 to files-4.19 directory in order to get clear diffs for any changes done from now on. Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com> [added missing commit description, refreshed ea8500 and wpq864 DTS] Signed-off-by: Petr Štetiar <ynezz@true.cz>
This commit is contained in:
		 Ansuel Smith
					Ansuel Smith
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						Petr Štetiar
					
				
			
						parent
						
							b1e8a390ea
						
					
				
				
					commit
					c5d2f3c476
				
			
							
								
								
									
										489
									
								
								target/linux/ipq806x/config-4.19
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										489
									
								
								target/linux/ipq806x/config-4.19
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,489 @@ | |||||||
|  | CONFIG_ALIGNMENT_TRAP=y | ||||||
|  | # CONFIG_AMBA_PL08X is not set | ||||||
|  | # CONFIG_APQ_GCC_8084 is not set | ||||||
|  | # CONFIG_APQ_MMCC_8084 is not set | ||||||
|  | CONFIG_AR8216_PHY=y | ||||||
|  | CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||||
|  | CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||||
|  | CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y | ||||||
|  | CONFIG_ARCH_HAS_SG_CHAIN=y | ||||||
|  | CONFIG_ARCH_HAS_TICK_BROADCAST=y | ||||||
|  | CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y | ||||||
|  | CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||||
|  | # CONFIG_ARCH_MDM9615 is not set | ||||||
|  | CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||||
|  | CONFIG_ARCH_MSM8960=y | ||||||
|  | CONFIG_ARCH_MSM8974=y | ||||||
|  | CONFIG_ARCH_MSM8X60=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=0 | ||||||
|  | CONFIG_ARCH_QCOM=y | ||||||
|  | # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set | ||||||
|  | # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set | ||||||
|  | CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y | ||||||
|  | CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y | ||||||
|  | CONFIG_ARCH_SUPPORTS_UPROBES=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_AMBA=y | ||||||
|  | CONFIG_ARM_APPENDED_DTB=y | ||||||
|  | CONFIG_ARM_ARCH_TIMER=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 is not set | ||||||
|  | CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y | ||||||
|  | CONFIG_ARM_CPUIDLE=y | ||||||
|  | CONFIG_ARM_CPU_SUSPEND=y | ||||||
|  | # CONFIG_ARM_CPU_TOPOLOGY is not set | ||||||
|  | CONFIG_ARM_GIC=y | ||||||
|  | CONFIG_ARM_HAS_SG_CHAIN=y | ||||||
|  | CONFIG_ARM_L1_CACHE_SHIFT=6 | ||||||
|  | CONFIG_ARM_L1_CACHE_SHIFT_6=y | ||||||
|  | # CONFIG_ARM_LPAE is not set | ||||||
|  | CONFIG_ARM_PATCH_IDIV=y | ||||||
|  | CONFIG_ARM_PATCH_PHYS_VIRT=y | ||||||
|  | CONFIG_ARM_QCOM_CPUFREQ=y | ||||||
|  | CONFIG_ARM_QCOM_CPUIDLE=y | ||||||
|  | # CONFIG_ARM_SMMU is not set | ||||||
|  | # CONFIG_ARM_SP805_WATCHDOG is not set | ||||||
|  | CONFIG_ARM_THUMB=y | ||||||
|  | # CONFIG_ARM_THUMBEE is not set | ||||||
|  | CONFIG_ARM_UNWIND=y | ||||||
|  | CONFIG_ARM_VIRT_EXT=y | ||||||
|  | # CONFIG_BINFMT_FLAT is not set | ||||||
|  | CONFIG_BLK_DEV_LOOP=y | ||||||
|  | CONFIG_BLK_MQ_PCI=y | ||||||
|  | # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set | ||||||
|  | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 | ||||||
|  | CONFIG_BOUNCE=y | ||||||
|  | CONFIG_BUS_TOPOLOGY_ADHOC=y | ||||||
|  | # CONFIG_CACHE_L2X0 is not set | ||||||
|  | CONFIG_CLKDEV_LOOKUP=y | ||||||
|  | CONFIG_CLKSRC_OF=y | ||||||
|  | CONFIG_CLKSRC_PROBE=y | ||||||
|  | CONFIG_CLKSRC_QCOM=y | ||||||
|  | CONFIG_CLONE_BACKWARDS=y | ||||||
|  | CONFIG_COMMON_CLK=y | ||||||
|  | CONFIG_COMMON_CLK_QCOM=y | ||||||
|  | CONFIG_CPUFREQ_DT=y | ||||||
|  | CONFIG_CPUFREQ_DT_PLATDEV=y | ||||||
|  | CONFIG_CPU_32v6K=y | ||||||
|  | CONFIG_CPU_32v7=y | ||||||
|  | CONFIG_CPU_ABRT_EV7=y | ||||||
|  | # CONFIG_CPU_BIG_ENDIAN is not set | ||||||
|  | # 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_FREQ=y | ||||||
|  | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | ||||||
|  | # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set | ||||||
|  | CONFIG_CPU_FREQ_GOV_ATTR_SET=y | ||||||
|  | CONFIG_CPU_FREQ_GOV_COMMON=y | ||||||
|  | # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set | ||||||
|  | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||||||
|  | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||||||
|  | # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set | ||||||
|  | # CONFIG_CPU_FREQ_GOV_USERSPACE is not set | ||||||
|  | CONFIG_CPU_FREQ_STAT=y | ||||||
|  | CONFIG_CPU_HAS_ASID=y | ||||||
|  | # CONFIG_CPU_ICACHE_DISABLE is not set | ||||||
|  | CONFIG_CPU_IDLE=y | ||||||
|  | CONFIG_CPU_IDLE_GOV_LADDER=y | ||||||
|  | CONFIG_CPU_IDLE_GOV_MENU=y | ||||||
|  | CONFIG_CPU_PABRT_V7=y | ||||||
|  | CONFIG_CPU_PM=y | ||||||
|  | CONFIG_CPU_RMAP=y | ||||||
|  | CONFIG_CPU_THERMAL=y | ||||||
|  | CONFIG_CPU_TLB_V7=y | ||||||
|  | CONFIG_CPU_V7=y | ||||||
|  | CONFIG_CRC16=y | ||||||
|  | # CONFIG_CRC32_SARWATE is not set | ||||||
|  | CONFIG_CRC32_SLICEBY8=y | ||||||
|  | CONFIG_CRYPTO_AEAD=y | ||||||
|  | CONFIG_CRYPTO_AEAD2=y | ||||||
|  | CONFIG_CRYPTO_DEFLATE=y | ||||||
|  | CONFIG_CRYPTO_DRBG=y | ||||||
|  | CONFIG_CRYPTO_DRBG_HMAC=y | ||||||
|  | CONFIG_CRYPTO_DRBG_MENU=y | ||||||
|  | CONFIG_CRYPTO_HASH=y | ||||||
|  | CONFIG_CRYPTO_HASH2=y | ||||||
|  | CONFIG_CRYPTO_HMAC=y | ||||||
|  | CONFIG_CRYPTO_HW=y | ||||||
|  | CONFIG_CRYPTO_JITTERENTROPY=y | ||||||
|  | CONFIG_CRYPTO_LZO=y | ||||||
|  | CONFIG_CRYPTO_MANAGER=y | ||||||
|  | CONFIG_CRYPTO_MANAGER2=y | ||||||
|  | CONFIG_CRYPTO_NULL2=y | ||||||
|  | CONFIG_CRYPTO_RNG=y | ||||||
|  | CONFIG_CRYPTO_RNG2=y | ||||||
|  | CONFIG_CRYPTO_RNG_DEFAULT=y | ||||||
|  | CONFIG_CRYPTO_SHA256=y | ||||||
|  | CONFIG_CRYPTO_WORKQUEUE=y | ||||||
|  | CONFIG_DCACHE_WORD_ACCESS=y | ||||||
|  | CONFIG_DEBUG_GPIO=y | ||||||
|  | # CONFIG_DEBUG_UART_8250 is not set | ||||||
|  | CONFIG_DEBUG_UNCOMPRESS=y | ||||||
|  | # CONFIG_DEBUG_USER is not set | ||||||
|  | CONFIG_DMADEVICES=y | ||||||
|  | CONFIG_DMA_ENGINE=y | ||||||
|  | CONFIG_DMA_OF=y | ||||||
|  | CONFIG_DMA_VIRTUAL_CHANNELS=y | ||||||
|  | CONFIG_DTC=y | ||||||
|  | CONFIG_DT_IDLE_STATES=y | ||||||
|  | # CONFIG_DWMAC_DWC_QOS_ETH is not set | ||||||
|  | # CONFIG_DWMAC_GENERIC is not set | ||||||
|  | CONFIG_DWMAC_IPQ806X=y | ||||||
|  | CONFIG_DYNAMIC_DEBUG=y | ||||||
|  | CONFIG_EARLY_PRINTK=y | ||||||
|  | CONFIG_EDAC_ATOMIC_SCRUB=y | ||||||
|  | CONFIG_EDAC_SUPPORT=y | ||||||
|  | CONFIG_ETHERNET_PACKET_MANGLE=y | ||||||
|  | CONFIG_FIXED_PHY=y | ||||||
|  | CONFIG_FIX_EARLYCON_MEM=y | ||||||
|  | CONFIG_GENERIC_ALLOCATOR=y | ||||||
|  | CONFIG_GENERIC_BUG=y | ||||||
|  | CONFIG_GENERIC_CLOCKEVENTS=y | ||||||
|  | CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y | ||||||
|  | CONFIG_GENERIC_EARLY_IOREMAP=y | ||||||
|  | CONFIG_GENERIC_IDLE_POLL_SETUP=y | ||||||
|  | CONFIG_GENERIC_IO=y | ||||||
|  | CONFIG_GENERIC_IRQ_SHOW=y | ||||||
|  | CONFIG_GENERIC_IRQ_SHOW_LEVEL=y | ||||||
|  | CONFIG_GENERIC_MSI_IRQ=y | ||||||
|  | CONFIG_GENERIC_MSI_IRQ_DOMAIN=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_GENERIC_TIME_VSYSCALL=y | ||||||
|  | CONFIG_GPIOLIB=y | ||||||
|  | CONFIG_GPIOLIB_IRQCHIP=y | ||||||
|  | CONFIG_GPIO_SYSFS=y | ||||||
|  | CONFIG_HANDLE_DOMAIN_IRQ=y | ||||||
|  | CONFIG_HARDEN_BRANCH_PREDICTOR=y | ||||||
|  | CONFIG_HARDIRQS_SW_RESEND=y | ||||||
|  | CONFIG_HAS_DMA=y | ||||||
|  | CONFIG_HAS_IOMEM=y | ||||||
|  | CONFIG_HAS_IOPORT_MAP=y | ||||||
|  | # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||||
|  | CONFIG_HAVE_ARCH_AUDITSYSCALL=y | ||||||
|  | CONFIG_HAVE_ARCH_BITREVERSE=y | ||||||
|  | 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_ARM_SMCCC=y | ||||||
|  | # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||||
|  | CONFIG_HAVE_CBPF_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_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_IDE=y | ||||||
|  | CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||||
|  | CONFIG_HAVE_MEMBLOCK=y | ||||||
|  | CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||||
|  | CONFIG_HAVE_NET_DSA=y | ||||||
|  | CONFIG_HAVE_OPROFILE=y | ||||||
|  | CONFIG_HAVE_OPTPROBES=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_HWSPINLOCK=y | ||||||
|  | CONFIG_HWSPINLOCK_QCOM=y | ||||||
|  | CONFIG_HW_RANDOM=y | ||||||
|  | CONFIG_HW_RANDOM_MSM=y | ||||||
|  | CONFIG_HZ_FIXED=0 | ||||||
|  | CONFIG_I2C=y | ||||||
|  | CONFIG_I2C_BOARDINFO=y | ||||||
|  | CONFIG_I2C_CHARDEV=y | ||||||
|  | CONFIG_I2C_HELPER_AUTO=y | ||||||
|  | CONFIG_I2C_QUP=y | ||||||
|  | CONFIG_INITRAMFS_SOURCE="" | ||||||
|  | CONFIG_IOMMU_HELPER=y | ||||||
|  | # CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set | ||||||
|  | # CONFIG_IOMMU_IO_PGTABLE_LPAE is not set | ||||||
|  | CONFIG_IOMMU_SUPPORT=y | ||||||
|  | # CONFIG_IPQ_GCC_4019 is not set | ||||||
|  | CONFIG_IPQ_GCC_806X=y | ||||||
|  | # CONFIG_IPQ_GCC_8074 is not set | ||||||
|  | # CONFIG_IPQ_LCC_806X is not set | ||||||
|  | CONFIG_IRQCHIP=y | ||||||
|  | CONFIG_IRQ_DOMAIN=y | ||||||
|  | CONFIG_IRQ_DOMAIN_HIERARCHY=y | ||||||
|  | CONFIG_IRQ_FORCED_THREADING=y | ||||||
|  | CONFIG_IRQ_WORK=y | ||||||
|  | CONFIG_KPSS_XCC=y | ||||||
|  | CONFIG_KRAITCC=y | ||||||
|  | CONFIG_KRAIT_CLOCKS=y | ||||||
|  | CONFIG_KRAIT_L2_ACCESSORS=y | ||||||
|  | CONFIG_LIBFDT=y | ||||||
|  | CONFIG_LOCKUP_DETECTOR=y | ||||||
|  | CONFIG_LOCK_SPIN_ON_OWNER=y | ||||||
|  | CONFIG_LZO_COMPRESS=y | ||||||
|  | CONFIG_LZO_DECOMPRESS=y | ||||||
|  | CONFIG_MDIO_BITBANG=y | ||||||
|  | CONFIG_MDIO_BOARDINFO=y | ||||||
|  | CONFIG_MDIO_GPIO=y | ||||||
|  | # CONFIG_MDM_GCC_9615 is not set | ||||||
|  | # CONFIG_MDM_LCC_9615 is not set | ||||||
|  | # CONFIG_MFD_MAX77620 is not set | ||||||
|  | CONFIG_MFD_QCOM_RPM=y | ||||||
|  | # CONFIG_MFD_SPMI_PMIC is not set | ||||||
|  | CONFIG_MFD_SYSCON=y | ||||||
|  | CONFIG_MIGHT_HAVE_CACHE_L2X0=y | ||||||
|  | CONFIG_MIGHT_HAVE_PCI=y | ||||||
|  | CONFIG_MMC=y | ||||||
|  | CONFIG_MMC_ARMMMCI=y | ||||||
|  | CONFIG_MMC_BLOCK=y | ||||||
|  | CONFIG_MMC_BLOCK_MINORS=16 | ||||||
|  | CONFIG_MMC_QCOM_DML=y | ||||||
|  | CONFIG_MMC_SDHCI=y | ||||||
|  | CONFIG_MMC_SDHCI_MSM=y | ||||||
|  | # CONFIG_MMC_SDHCI_PCI is not set | ||||||
|  | CONFIG_MMC_SDHCI_PLTFM=y | ||||||
|  | # CONFIG_MMC_TIFM_SD is not set | ||||||
|  | CONFIG_MODULES_USE_ELF_REL=y | ||||||
|  | CONFIG_MSM_BUS_SCALING=y | ||||||
|  | CONFIG_MSM_GCC_8660=y | ||||||
|  | # CONFIG_MSM_GCC_8916 is not set | ||||||
|  | # CONFIG_MSM_GCC_8960 is not set | ||||||
|  | # CONFIG_MSM_GCC_8974 is not set | ||||||
|  | # CONFIG_MSM_GCC_8994 is not set | ||||||
|  | # CONFIG_MSM_GCC_8996 is not set | ||||||
|  | # CONFIG_MSM_IOMMU is not set | ||||||
|  | # CONFIG_MSM_LCC_8960 is not set | ||||||
|  | # CONFIG_MSM_MMCC_8960 is not set | ||||||
|  | # CONFIG_MSM_MMCC_8974 is not set | ||||||
|  | # CONFIG_MSM_MMCC_8996 is not set | ||||||
|  | CONFIG_MTD_CMDLINE_PARTS=y | ||||||
|  | CONFIG_MTD_M25P80=y | ||||||
|  | CONFIG_MTD_NAND=y | ||||||
|  | CONFIG_MTD_NAND_ECC=y | ||||||
|  | CONFIG_MTD_NAND_QCOM=y | ||||||
|  | # CONFIG_MTD_PHYSMAP_OF_VERSATILE is not set | ||||||
|  | CONFIG_MTD_QCOM_SMEM_PARTS=y | ||||||
|  | CONFIG_MTD_SPI_NOR=y | ||||||
|  | CONFIG_MTD_SPLIT_FIRMWARE=y | ||||||
|  | CONFIG_MTD_SPLIT_FIT_FW=y | ||||||
|  | CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||||
|  | CONFIG_MTD_UBI=y | ||||||
|  | CONFIG_MTD_UBI_BEB_LIMIT=20 | ||||||
|  | CONFIG_MTD_UBI_BLOCK=y | ||||||
|  | # CONFIG_MTD_UBI_FASTMAP is not set | ||||||
|  | # CONFIG_MTD_UBI_GLUEBI is not set | ||||||
|  | CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||||||
|  | CONFIG_MULTI_IRQ_HANDLER=y | ||||||
|  | CONFIG_MUTEX_SPIN_ON_OWNER=y | ||||||
|  | CONFIG_NEED_DMA_MAP_STATE=y | ||||||
|  | CONFIG_NEON=y | ||||||
|  | CONFIG_NET_DSA=y | ||||||
|  | CONFIG_NET_DSA_HWMON=y | ||||||
|  | CONFIG_NET_DSA_QCA8K=y | ||||||
|  | CONFIG_NET_DSA_TAG_QCA=y | ||||||
|  | CONFIG_NET_FLOW_LIMIT=y | ||||||
|  | CONFIG_NET_PTP_CLASSIFY=y | ||||||
|  | CONFIG_NET_SWITCHDEV=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=2 | ||||||
|  | CONFIG_NVMEM=y | ||||||
|  | CONFIG_OF=y | ||||||
|  | CONFIG_OF_ADDRESS=y | ||||||
|  | CONFIG_OF_ADDRESS_PCI=y | ||||||
|  | CONFIG_OF_EARLY_FLATTREE=y | ||||||
|  | CONFIG_OF_FLATTREE=y | ||||||
|  | CONFIG_OF_GPIO=y | ||||||
|  | CONFIG_OF_IRQ=y | ||||||
|  | CONFIG_OF_MDIO=y | ||||||
|  | CONFIG_OF_NET=y | ||||||
|  | CONFIG_OF_PCI=y | ||||||
|  | CONFIG_OF_PCI_IRQ=y | ||||||
|  | CONFIG_OF_RESERVED_MEM=y | ||||||
|  | CONFIG_OLD_SIGACTION=y | ||||||
|  | CONFIG_OLD_SIGSUSPEND3=y | ||||||
|  | CONFIG_PADATA=y | ||||||
|  | CONFIG_PAGE_OFFSET=0xC0000000 | ||||||
|  | CONFIG_PCI=y | ||||||
|  | CONFIG_PCIEAER=y | ||||||
|  | CONFIG_PCIEPORTBUS=y | ||||||
|  | CONFIG_PCIE_DW=y | ||||||
|  | CONFIG_PCIE_QCOM=y | ||||||
|  | CONFIG_PCI_DEBUG=y | ||||||
|  | CONFIG_PCI_DISABLE_COMMON_QUIRKS=y | ||||||
|  | CONFIG_PCI_DOMAINS=y | ||||||
|  | CONFIG_PCI_DOMAINS_GENERIC=y | ||||||
|  | CONFIG_PCI_MSI=y | ||||||
|  | CONFIG_PCI_MSI_IRQ_DOMAIN=y | ||||||
|  | CONFIG_PERF_USE_VMALLOC=y | ||||||
|  | CONFIG_PGTABLE_LEVELS=2 | ||||||
|  | CONFIG_PHYLIB=y | ||||||
|  | # CONFIG_PHY_QCOM_APQ8064_SATA is not set | ||||||
|  | CONFIG_PHY_QCOM_IPQ806X_SATA=y | ||||||
|  | # CONFIG_PHY_QCOM_QMP is not set | ||||||
|  | # CONFIG_PHY_QCOM_QUSB2 is not set | ||||||
|  | # CONFIG_PHY_QCOM_UFS is not set | ||||||
|  | CONFIG_PINCTRL=y | ||||||
|  | # CONFIG_PINCTRL_APQ8064 is not set | ||||||
|  | # CONFIG_PINCTRL_APQ8084 is not set | ||||||
|  | # CONFIG_PINCTRL_IPQ4019 is not set | ||||||
|  | CONFIG_PINCTRL_IPQ8064=y | ||||||
|  | # CONFIG_PINCTRL_IPQ8074 is not set | ||||||
|  | # CONFIG_PINCTRL_MDM9615 is not set | ||||||
|  | CONFIG_PINCTRL_MSM=y | ||||||
|  | # CONFIG_PINCTRL_MSM8660 is not set | ||||||
|  | # CONFIG_PINCTRL_MSM8916 is not set | ||||||
|  | # CONFIG_PINCTRL_MSM8960 is not set | ||||||
|  | # CONFIG_PINCTRL_MSM8994 is not set | ||||||
|  | # CONFIG_PINCTRL_MSM8996 is not set | ||||||
|  | # CONFIG_PINCTRL_MSM8X74 is not set | ||||||
|  | # CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set | ||||||
|  | # CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set | ||||||
|  | # CONFIG_PL330_DMA is not set | ||||||
|  | CONFIG_PM_OPP=y | ||||||
|  | CONFIG_POWER_RESET=y | ||||||
|  | # CONFIG_POWER_RESET_BRCMKONA is not set | ||||||
|  | CONFIG_POWER_RESET_MSM=y | ||||||
|  | CONFIG_POWER_SUPPLY=y | ||||||
|  | CONFIG_PPS=y | ||||||
|  | CONFIG_PRINTK_TIME=y | ||||||
|  | CONFIG_PTP_1588_CLOCK=y | ||||||
|  | CONFIG_QCOM_ADM=y | ||||||
|  | CONFIG_QCOM_BAM_DMA=y | ||||||
|  | CONFIG_QCOM_CLK_RPM=y | ||||||
|  | # CONFIG_QCOM_EBI2 is not set | ||||||
|  | CONFIG_QCOM_GDSC=y | ||||||
|  | CONFIG_QCOM_GSBI=y | ||||||
|  | CONFIG_QCOM_HFPLL=y | ||||||
|  | # CONFIG_QCOM_IOMMU is not set | ||||||
|  | CONFIG_QCOM_PM=y | ||||||
|  | # CONFIG_QCOM_Q6V5_PIL is not set | ||||||
|  | CONFIG_QCOM_QFPROM=y | ||||||
|  | CONFIG_QCOM_RPMCC=y | ||||||
|  | CONFIG_QCOM_SCM=y | ||||||
|  | CONFIG_QCOM_SCM_32=y | ||||||
|  | # CONFIG_QCOM_SMD is not set | ||||||
|  | CONFIG_QCOM_SMEM=y | ||||||
|  | # CONFIG_QCOM_SMP2P is not set | ||||||
|  | # CONFIG_QCOM_SMSM is not set | ||||||
|  | CONFIG_QCOM_TCSR=y | ||||||
|  | CONFIG_QCOM_TSENS=y | ||||||
|  | # CONFIG_QCOM_WCNSS_PIL is not set | ||||||
|  | CONFIG_QCOM_WDT=y | ||||||
|  | # CONFIG_QRTR is not set | ||||||
|  | CONFIG_RAS=y | ||||||
|  | CONFIG_RATIONAL=y | ||||||
|  | CONFIG_RCU_CPU_STALL_TIMEOUT=21 | ||||||
|  | CONFIG_RCU_STALL_COMMON=y | ||||||
|  | CONFIG_REGMAP=y | ||||||
|  | CONFIG_REGMAP_I2C=y | ||||||
|  | CONFIG_REGMAP_MMIO=y | ||||||
|  | CONFIG_REGMAP_SPI=y | ||||||
|  | CONFIG_REGULATOR=y | ||||||
|  | CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||||||
|  | CONFIG_REGULATOR_QCOM_RPM=y | ||||||
|  | # CONFIG_REGULATOR_QCOM_SPMI is not set | ||||||
|  | CONFIG_RESET_CONTROLLER=y | ||||||
|  | CONFIG_RFS_ACCEL=y | ||||||
|  | # CONFIG_RPMSG_QCOM_SMD is not set | ||||||
|  | CONFIG_RPS=y | ||||||
|  | CONFIG_RTC_CLASS=y | ||||||
|  | # CONFIG_RTC_DRV_CMOS is not set | ||||||
|  | CONFIG_RTC_I2C_AND_SPI=y | ||||||
|  | CONFIG_RWSEM_SPIN_ON_OWNER=y | ||||||
|  | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||||||
|  | # CONFIG_SCHED_INFO is not set | ||||||
|  | # CONFIG_SCSI_DMA is not set | ||||||
|  | # CONFIG_SERIAL_AMBA_PL011 is not set | ||||||
|  | CONFIG_SERIAL_MSM=y | ||||||
|  | CONFIG_SERIAL_MSM_CONSOLE=y | ||||||
|  | CONFIG_SMP=y | ||||||
|  | CONFIG_SMP_ON_UP=y | ||||||
|  | CONFIG_SPARSE_IRQ=y | ||||||
|  | CONFIG_SPI=y | ||||||
|  | # CONFIG_SPI_CADENCE_QUADSPI is not set | ||||||
|  | CONFIG_SPI_MASTER=y | ||||||
|  | CONFIG_SPI_QUP=y | ||||||
|  | CONFIG_SPMI=y | ||||||
|  | CONFIG_SPMI_MSM_PMIC_ARB=y | ||||||
|  | CONFIG_SRCU=y | ||||||
|  | CONFIG_STMMAC_ETH=y | ||||||
|  | CONFIG_STMMAC_PLATFORM=y | ||||||
|  | CONFIG_SWCONFIG=y | ||||||
|  | CONFIG_SWCONFIG_LEDS=y | ||||||
|  | CONFIG_SWIOTLB=y | ||||||
|  | CONFIG_SWPHY=y | ||||||
|  | CONFIG_SWP_EMULATE=y | ||||||
|  | CONFIG_SYS_SUPPORTS_APM_EMULATION=y | ||||||
|  | CONFIG_THERMAL=y | ||||||
|  | CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y | ||||||
|  | CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 | ||||||
|  | CONFIG_THERMAL_GOV_STEP_WISE=y | ||||||
|  | CONFIG_THERMAL_HWMON=y | ||||||
|  | CONFIG_THERMAL_OF=y | ||||||
|  | # CONFIG_THUMB2_KERNEL is not set | ||||||
|  | CONFIG_TICK_CPU_ACCOUNTING=y | ||||||
|  | CONFIG_TREE_RCU=y | ||||||
|  | CONFIG_UBIFS_FS=y | ||||||
|  | CONFIG_UBIFS_FS_ADVANCED_COMPR=y | ||||||
|  | CONFIG_UBIFS_FS_LZO=y | ||||||
|  | CONFIG_UBIFS_FS_ZLIB=y | ||||||
|  | CONFIG_UEVENT_HELPER_PATH="" | ||||||
|  | CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" | ||||||
|  | CONFIG_USB=y | ||||||
|  | CONFIG_USB_COMMON=y | ||||||
|  | # CONFIG_USB_EHCI_HCD is not set | ||||||
|  | # CONFIG_USB_QCOM_8X16_PHY is not set | ||||||
|  | CONFIG_USB_SUPPORT=y | ||||||
|  | # CONFIG_USB_UHCI_HCD is not set | ||||||
|  | CONFIG_USE_OF=y | ||||||
|  | CONFIG_VDSO=y | ||||||
|  | CONFIG_VECTORS_BASE=0xffff0000 | ||||||
|  | CONFIG_VFP=y | ||||||
|  | CONFIG_VFPv3=y | ||||||
|  | CONFIG_WATCHDOG_CORE=y | ||||||
|  | CONFIG_XPS=y | ||||||
|  | CONFIG_XZ_DEC_ARM=y | ||||||
|  | CONFIG_XZ_DEC_BCJ=y | ||||||
|  | CONFIG_ZBOOT_ROM_BSS=0 | ||||||
|  | CONFIG_ZBOOT_ROM_TEXT=0 | ||||||
|  | CONFIG_ZLIB_DEFLATE=y | ||||||
|  | CONFIG_ZLIB_INFLATE=y | ||||||
| @@ -0,0 +1,248 @@ | |||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Qualcomm IPQ8064/AP148"; | ||||||
|  | 	compatible = "qcom,ipq8064-ap148", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				pins = "gpio12", "gpio13"; | ||||||
|  | 				function = "gsbi4"; | ||||||
|  | 				bias-disable; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-none; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			/* | ||||||
|  | 			* The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			* On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			* RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			* i2c failure for the RPM. | ||||||
|  | 			*/ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi4: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 				spi-max-frequency = <50000000>; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 0>; | ||||||
|  |  | ||||||
|  | 				flash: m25p80@0 { | ||||||
|  | 					compatible = "s25fl256s1"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <50000000>; | ||||||
|  | 					reg = <0>; | ||||||
|  |  | ||||||
|  | 					partitions { | ||||||
|  | 						compatible = "qcom,smem"; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "qcom,smem"; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,277 @@ | |||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Qualcomm IPQ8064/AP161"; | ||||||
|  | 	compatible = "qcom,ipq8064-ap161", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		linux,stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				pins = "gpio12", "gpio13"; | ||||||
|  | 				function = "gsbi4"; | ||||||
|  | 				bias-disable; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-none; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio2", "gpio27", "gpio28", | ||||||
|  | 						"gpio29", "gpio30", "gpio31", | ||||||
|  | 						"gpio32", "gpio51", "gpio52", | ||||||
|  | 						"gpio59", "gpio60", "gpio61", | ||||||
|  | 						"gpio62" , "gpio66"; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			/* | ||||||
|  | 			* The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			* On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			* RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			* i2c failure for the RPM. | ||||||
|  | 			*/ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi4: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 				spi-max-frequency = <50000000>; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 0>; | ||||||
|  |  | ||||||
|  | 				flash: m25p80@0 { | ||||||
|  | 					compatible = "s25fl256s1"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <50000000>; | ||||||
|  | 					reg = <0>; | ||||||
|  |  | ||||||
|  | 					partitions { | ||||||
|  | 						compatible = "qcom,smem"; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie2: pci@1b900000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "qcom,smem"; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x20080     /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 				qca,phy-rgmii-en; | ||||||
|  | 				qca,txclk-delay-en; | ||||||
|  | 				qca,rxclk-delay-en; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy3: ethernet-phy@3 { | ||||||
|  | 				device_type = "ethernet-phy"; | ||||||
|  | 				reg = <3>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac0: ethernet@37000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <0>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,494 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "TP-Link Archer C2600"; | ||||||
|  | 	compatible = "tplink,c2600", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &general; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &general; | ||||||
|  | 		label-mac-device = &gmac2; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio16", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio7", "gpio8", "gpio9", "gpio26", "gpio33", | ||||||
|  | 					       "gpio53", "gpio66"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				data { | ||||||
|  | 					pins = "gpio18", "gpio19"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				cs { | ||||||
|  | 					pins = "gpio20"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio21"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb0_pwr_en_pin: usb0_pwr_en_pin { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio25"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb1_pwr_en_pin: usb1_pwr_en_pin { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio23"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi5: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 				flash: m25p80@0 { | ||||||
|  | 					compatible = "jedec,spi-nor"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <50000000>; | ||||||
|  | 					reg = <0>; | ||||||
|  |  | ||||||
|  | 					SBL1@0 { | ||||||
|  | 						label = "SBL1"; | ||||||
|  | 						reg = <0x0 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					MIBIB@20000 { | ||||||
|  | 						label = "MIBIB"; | ||||||
|  | 						reg = <0x20000 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL2@40000 { | ||||||
|  | 						label = "SBL2"; | ||||||
|  | 						reg = <0x40000 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL3@60000 { | ||||||
|  | 						label = "SBL3"; | ||||||
|  | 						reg = <0x60000 0x30000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					DDRCONFIG@90000 { | ||||||
|  | 						label = "DDRCONFIG"; | ||||||
|  | 						reg = <0x90000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SSD@a0000 { | ||||||
|  | 						label = "SSD"; | ||||||
|  | 						reg = <0xa0000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					TZ@b0000 { | ||||||
|  | 						label = "TZ"; | ||||||
|  | 						reg = <0xb0000 0x30000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					RPM@e0000 { | ||||||
|  | 						label = "RPM"; | ||||||
|  | 						reg = <0xe0000 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					fs-uboot@100000 { | ||||||
|  | 						label = "fs-uboot"; | ||||||
|  | 						reg = <0x100000 0x70000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					uboot-env@170000 { | ||||||
|  | 						label = "uboot-env"; | ||||||
|  | 						reg = <0x170000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					radio@1b0000 { | ||||||
|  | 						label = "radio"; | ||||||
|  | 						reg = <0x1b0000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					os-image@1f0000 { | ||||||
|  | 						label = "os-image"; | ||||||
|  | 						reg = <0x1f0000 0x400000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					rootfs@5f0000 { | ||||||
|  | 						label = "rootfs"; | ||||||
|  | 						reg = <0x5f0000 0x1900000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					defaultmac: default-mac@1ef0000 { | ||||||
|  | 						label = "default-mac"; | ||||||
|  | 						reg = <0x1ef0000 0x00200>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					pin@1ef0200 { | ||||||
|  | 						label = "pin"; | ||||||
|  | 						reg = <0x1ef0200 0x00200>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					product-info@1ef0400 { | ||||||
|  | 						label = "product-info"; | ||||||
|  | 						reg = <0x1ef0400 0x0fc00>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					partition-table@1f00000 { | ||||||
|  | 						label = "partition-table"; | ||||||
|  | 						reg = <0x1f00000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					soft-version@1f10000 { | ||||||
|  | 						label = "soft-version"; | ||||||
|  | 						reg = <0x1f10000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					support-list@1f20000 { | ||||||
|  | 						label = "support-list"; | ||||||
|  | 						reg = <0x1f20000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					profile@1f30000 { | ||||||
|  | 						label = "profile"; | ||||||
|  | 						reg = <0x1f30000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					default-config@1f40000 { | ||||||
|  | 						label = "default-config"; | ||||||
|  | 						reg = <0x1f40000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					user-config@1f50000 { | ||||||
|  | 						label = "user-config"; | ||||||
|  | 						reg = <0x1f50000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					qos-db@1f90000 { | ||||||
|  | 						label = "qos-db"; | ||||||
|  | 						reg = <0x1f90000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					usb-config@1fd0000 { | ||||||
|  | 						label = "usb-config"; | ||||||
|  | 						reg = <0x1fd0000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					log@1fe0000 { | ||||||
|  | 						label = "log"; | ||||||
|  | 						reg = <0x1fe0000 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb0_pwr_en_pin>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb1_pwr_en_pin>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&defaultmac 0x8>; | ||||||
|  | 			mtd-mac-address-increment = <1>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&defaultmac 0x8>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 49 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		ledswitch { | ||||||
|  | 			label = "ledswitch"; | ||||||
|  | 			gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_LIGHTS_TOGGLE>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		lan { | ||||||
|  | 			label = "c2600:white:lan"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb4 { | ||||||
|  | 			label = "c2600:white:usb_4"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb2 { | ||||||
|  | 			label = "c2600:white:usb_2"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "c2600:white:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_amber { | ||||||
|  | 			label = "c2600:amber:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_white { | ||||||
|  | 			label = "c2600:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 33 GPIO_ACTIVE_LOW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "c2600:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		general: general { | ||||||
|  | 			label = "c2600:white:general"; | ||||||
|  | 			gpios = <&qcom_pinmux 66 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,408 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Netgear Nighthawk X4 D7800"; | ||||||
|  | 	compatible = "netgear,d7800", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0xe000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power_white; | ||||||
|  | 		led-failsafe = &power_amber; | ||||||
|  | 		led-running = &power_white; | ||||||
|  | 		led-upgrade = &power_amber; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		bootargs = "rootfstype=squashfs noinitrd"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", | ||||||
|  | 						"gpio24","gpio26", "gpio53", "gpio64"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb0_pwr_en_pins: usb0_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio15"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb1_pwr_en_pins: usb1_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio16", "gpio68"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			ports-implemented = <0x1>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb0_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb1_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&pcie0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&pcie1_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					qcadata@0 { | ||||||
|  | 						label = "qcadata"; | ||||||
|  | 						reg = <0x0000000 0x0c80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@c80000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0c80000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@1180000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x1180000 0x0080000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					art: art@1200000 { | ||||||
|  | 						label = "art"; | ||||||
|  | 						reg = <0x1200000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					artbak: art@1340000 { | ||||||
|  | 						label = "artbak"; | ||||||
|  | 						reg = <0x1340000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					kernel@1480000 { | ||||||
|  | 						label = "kernel"; | ||||||
|  | 						reg = <0x1480000 0x0400000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi@1880000 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x1880000 0x1C00000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					netgear@3480000 { | ||||||
|  | 						label = "netgear"; | ||||||
|  | 						reg = <0x3480000 0x4480000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					reserve@7900000 { | ||||||
|  | 						label = "reserve"; | ||||||
|  | 						reg = <0x7900000 0x0700000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			phy-handle = <&phy4>; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 6>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		usb1 { | ||||||
|  | 			label = "d7800:white:usb1"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb2 { | ||||||
|  | 			label = "d7800:white:usb2"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_amber: power_amber { | ||||||
|  | 			label = "d7800:amber:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_white { | ||||||
|  | 			label = "d7800:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_amber { | ||||||
|  | 			label = "d7800:amber:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "d7800:white:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		esata { | ||||||
|  | 			label = "d7800:white:esata"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_white: power_white { | ||||||
|  | 			label = "d7800:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "d7800:white:wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,232 @@ | |||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Qualcomm IPQ8064/DB149"; | ||||||
|  | 	compatible = "qcom,ipq8064-db149", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	alias { | ||||||
|  | 		serial0 = &uart2; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				pins = "gpio12", "gpio13"; | ||||||
|  | 				function = "gsbi4"; | ||||||
|  | 				bias-disable; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-none; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii0_pins: rgmii0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio2", "gpio66"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi2: gsbi@12480000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			uart2: serial@12490000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi4: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 				spi-max-frequency = <50000000>; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 0>; | ||||||
|  |  | ||||||
|  | 				flash: m25p80@0 { | ||||||
|  | 					compatible = "s25fl256s1"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <50000000>; | ||||||
|  | 					reg = <0>; | ||||||
|  | 					m25p,fast-read; | ||||||
|  |  | ||||||
|  | 					partition@0 { | ||||||
|  | 						label = "lowlevel_init"; | ||||||
|  | 						reg = <0x0 0x1b0000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					partition@1 { | ||||||
|  | 						label = "u-boot"; | ||||||
|  | 						reg = <0x1b0000 0x80000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					partition@2 { | ||||||
|  | 						label = "u-boot-env"; | ||||||
|  | 						reg = <0x230000 0x40000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					partition@3 { | ||||||
|  | 						label = "caldata"; | ||||||
|  | 						reg = <0x270000 0x40000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					partition@4 { | ||||||
|  | 						label = "firmware"; | ||||||
|  | 						reg = <0x2b0000 0x1d50000>; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie2: pci@1b900000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 				>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy6: ethernet-phy@6 { | ||||||
|  | 				reg = <6>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy7: ethernet-phy@7 { | ||||||
|  | 				reg = <7>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac0: ethernet@37000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <0>; | ||||||
|  | 			phy-handle = <&phy4>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  | 			phy-handle = <&phy6>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac3: ethernet@37600000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <3>; | ||||||
|  | 			phy-handle = <&phy7>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,400 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Linksys EA8500 WiFi Router"; | ||||||
|  | 	compatible = "linksys,ea8500", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &power; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &power; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		bootargs = "console=ttyMSM0,115200n8"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 		append-rootblock = "ubi.mtd=";  /* append to bootargs adding the root deviceblock nbr from bootloader */ | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio65", "gpio67", "gpio68"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio53", "gpio54"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie2: pci@1b900000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					SBL1@0 { | ||||||
|  | 						label = "SBL1"; | ||||||
|  | 						reg = <0x0000000 0x0040000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					MIBIB@40000 { | ||||||
|  | 						label = "MIBIB"; | ||||||
|  | 						reg = <0x0040000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL2@180000 { | ||||||
|  | 						label = "SBL2"; | ||||||
|  | 						reg = <0x0180000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL3@2c0000 { | ||||||
|  | 						label = "SBL3"; | ||||||
|  | 						reg = <0x02c0000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					DDRCONFIG@540000 { | ||||||
|  | 						label = "DDRCONFIG"; | ||||||
|  | 						reg = <0x0540000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SSD@660000 { | ||||||
|  | 						label = "SSD"; | ||||||
|  | 						reg = <0x0660000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					TZ@780000 { | ||||||
|  | 						label = "TZ"; | ||||||
|  | 						reg = <0x0780000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					RPM@a00000 { | ||||||
|  | 						label = "RPM"; | ||||||
|  | 						reg = <0x0a00000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					art: art@c80000 { | ||||||
|  | 						label = "art"; | ||||||
|  | 						reg = <0x0c80000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@dc0000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0dc0000 0x0100000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					u_env@ec0000 { | ||||||
|  | 						label = "u_env"; | ||||||
|  | 						reg = <0x0ec0000 0x0040000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					s_env@f00000 { | ||||||
|  | 						label = "s_env"; | ||||||
|  | 						reg = <0x0f00000 0x0040000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					devinfo@f40000 { | ||||||
|  | 						label = "devinfo"; | ||||||
|  | 						reg = <0x0f40000 0x0040000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					linux@f80000 { | ||||||
|  | 						label = "kernel1"; | ||||||
|  | 						reg = <0x0f80000 0x2800000>;  /* 3 MB spill to rootfs*/ | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					rootfs@1280000 { | ||||||
|  | 						label = "rootfs1"; | ||||||
|  | 						reg = <0x1280000 0x2500000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					linux2@3780000 { | ||||||
|  | 						label = "kernel2"; | ||||||
|  | 						reg = <0x3780000 0x2800000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					rootfs2@3a80000 { | ||||||
|  | 						label = "rootfs2"; | ||||||
|  | 						reg = <0x3a80000 0x2500000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					syscfg@5f80000 { | ||||||
|  | 						label = "syscfg"; | ||||||
|  | 						reg = <0x5f80000 0x2080000>; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  | 			qcom,phy_mdio_addr = <4>; | ||||||
|  | 			qcom,poll_required = <1>; | ||||||
|  | 			qcom,rgmii_delay = <0>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 		//lan | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  | 			qcom,phy_mdio_addr = <0>;	/* none */ | ||||||
|  | 			qcom,poll_required = <0>;	/* no polling */ | ||||||
|  | 			qcom,rgmii_delay = <0>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		adm_dma: dma@18300000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 67 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART >; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "ea8500:green:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "ea8500:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "ea8500:green:wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
| @@ -0,0 +1,382 @@ | |||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  | #include <dt-bindings/soc/qcom,tcsr.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Netgear Nighthawk X4 R7500"; | ||||||
|  | 	compatible = "netgear,r7500", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0xe000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power_white; | ||||||
|  | 		led-failsafe = &power_amber; | ||||||
|  | 		led-running = &power_white; | ||||||
|  | 		led-upgrade = &power_amber; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		bootargs = "rootfstype=squashfs noinitrd"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", | ||||||
|  | 						"gpio24","gpio26", "gpio53", "gpio64"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			clocks = <&gcc USB30_0_UTMI_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			clocks = <&gcc USB30_0_MASTER_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			clocks = <&gcc USB30_1_UTMI_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			clocks = <&gcc USB30_1_MASTER_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			clocks = <&gcc USB30_1_MASTER_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			clocks = <&gcc USB30_0_MASTER_CLK>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					qcadata@0 { | ||||||
|  | 						label = "qcadata"; | ||||||
|  | 						reg = <0x0000000 0x0c80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@c80000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0c80000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@1180000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x1180000 0x0080000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					art: art@1200000 { | ||||||
|  | 						label = "art"; | ||||||
|  | 						reg = <0x1200000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					kernel@1340000 { | ||||||
|  | 						label = "kernel"; | ||||||
|  | 						reg = <0x1340000 0x0400000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi@1740000 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x1740000 0x1600000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					netgear@2d40000 { | ||||||
|  | 						label = "netgear"; | ||||||
|  | 						reg = <0x2d40000 0x0c00000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					reserve@3940000 { | ||||||
|  | 						label = "reserve"; | ||||||
|  | 						reg = <0x3940000 0x46c0000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 6>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		usb1 { | ||||||
|  | 			label = "r7500:white:usb1"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb2 { | ||||||
|  | 			label = "r7500:white:usb2"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_amber: power_amber { | ||||||
|  | 			label = "r7500:amber:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_white { | ||||||
|  | 			label = "r7500:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_amber { | ||||||
|  | 			label = "r7500:amber:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "r7500:white:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		esata { | ||||||
|  | 			label = "r7500:white:esata"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_white: power_white { | ||||||
|  | 			label = "r7500:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "r7500:white:wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &tcsr { | ||||||
|  | 	qcom,usb-ctrl-select = <TCSR_USB_SELECT_USB3_DUAL>; | ||||||
|  | 	compatible = "qcom,tcsr"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,407 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Netgear Nighthawk X4 R7500v2"; | ||||||
|  | 	compatible = "netgear,r7500v2", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		rsvd@5fe00000 { | ||||||
|  | 			reg = <0x5fe00000 0x200000>; | ||||||
|  | 			reusable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &power; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &power; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		bootargs = "rootfstype=squashfs noinitrd"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", | ||||||
|  | 						"gpio24","gpio26", "gpio53", "gpio64"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb0_pwr_en_pins: usb0_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio15"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb1_pwr_en_pins: usb1_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio16", "gpio68"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb0_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb1_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; | ||||||
|  | 			pinctrl-0 = <&pcie0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; | ||||||
|  | 			pinctrl-0 = <&pcie1_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					qcadata@0 { | ||||||
|  | 						label = "qcadata"; | ||||||
|  | 						reg = <0x0000000 0x0c80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@c80000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0c80000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@1180000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x1180000 0x0080000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					art: art@1200000 { | ||||||
|  | 						label = "art"; | ||||||
|  | 						reg = <0x1200000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					artbak: art@1340000 { | ||||||
|  | 						label = "artbak"; | ||||||
|  | 						reg = <0x1340000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					kernel@1480000 { | ||||||
|  | 						label = "kernel"; | ||||||
|  | 						reg = <0x1480000 0x0400000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi@1880000 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x1880000 0x6080000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					reserve@7900000 { | ||||||
|  | 						label = "reserve"; | ||||||
|  | 						reg = <0x7900000 0x0700000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 6>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		usb1 { | ||||||
|  | 			label = "r7500v2:amber:usb1"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb3 { | ||||||
|  | 			label = "r7500v2:amber:usb3"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		status { | ||||||
|  | 			label = "r7500v2:amber:status"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		internet { | ||||||
|  | 			label = "r7500v2:white:internet"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan { | ||||||
|  | 			label = "r7500v2:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "r7500v2:white:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		esata { | ||||||
|  | 			label = "r7500v2:white:esata"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "r7500v2:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "r7500v2:white:wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	soc: soc { | ||||||
|  |  | ||||||
|  | 		ss_phy_0: phy@110f8830 { | ||||||
|  | 			rx_eq = <2>; | ||||||
|  | 			tx_deamp_3_5db = <32>; | ||||||
|  | 			mpll = <0xa0>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		ss_phy_1: phy@100f8830 { | ||||||
|  | 			rx_eq = <2>; | ||||||
|  | 			tx_deamp_3_5db = <32>; | ||||||
|  | 			mpll = <0xa0>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			phy-tx0-term-offset = <0>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			phy-tx0-term-offset = <0>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie2: pci@1b900000 { | ||||||
|  | 			phy-tx0-term-offset = <0>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,417 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "TP-Link Archer VR2600v"; | ||||||
|  | 	compatible = "tplink,vr2600v", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &general; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &general; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio7", "gpio8", "gpio9", "gpio16", "gpio17", | ||||||
|  | 						"gpio26", "gpio53", "gpio56", "gpio66"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio54", "gpio64", "gpio65", "gpio67", "gpio68"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				data { | ||||||
|  | 					pins = "gpio18", "gpio19"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				cs { | ||||||
|  | 					pins = "gpio20"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio21"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi4: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 				flash: W25Q128@0 { | ||||||
|  | 					compatible = "jedec,spi-nor"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <50000000>; | ||||||
|  | 					reg = <0>; | ||||||
|  |  | ||||||
|  | 					SBL1@0 { | ||||||
|  | 						label = "SBL1"; | ||||||
|  | 						reg = <0x0 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					MIBIB@20000 { | ||||||
|  | 						label = "MIBIB"; | ||||||
|  | 						reg = <0x20000 0x20000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL2@40000 { | ||||||
|  | 						label = "SBL2"; | ||||||
|  | 						reg = <0x40000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL3@80000 { | ||||||
|  | 						label = "SBL3"; | ||||||
|  | 						reg = <0x80000 0x80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					DDRCONFIG@100000 { | ||||||
|  | 						label = "DDRCONFIG"; | ||||||
|  | 						reg = <0x100000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SSD@110000 { | ||||||
|  | 						label = "SSD"; | ||||||
|  | 						reg = <0x110000 0x10000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					TZ@120000 { | ||||||
|  | 						label = "TZ"; | ||||||
|  | 						reg = <0x120000 0x80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					RPM@1a0000 { | ||||||
|  | 						label = "RPM"; | ||||||
|  | 						reg = <0x1a0000 0x80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@220000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x220000 0x80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@2a0000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x2a0000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					OLDART@2e0000 { | ||||||
|  | 						label = "OLDART"; | ||||||
|  | 						reg = <0x2e0000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					kernel@320000 { | ||||||
|  | 						label = "kernel"; | ||||||
|  | 						reg = <0x320000 0x300000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					rootfs@620000 { | ||||||
|  | 						label = "rootfs"; | ||||||
|  | 						reg = <0x620000 0x960000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					defaultmac: default-mac@0xfaf100 { | ||||||
|  | 						label = "default-mac"; | ||||||
|  | 						reg = <0xfaf100 0x00200>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ART@fc0000 { | ||||||
|  | 						label = "ART"; | ||||||
|  | 						reg = <0xfc0000 0x40000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&defaultmac 0>; | ||||||
|  | 			mtd-mac-address-increment = <1>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&defaultmac 0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		dect { | ||||||
|  | 			label = "dect"; | ||||||
|  | 			gpios = <&qcom_pinmux 67 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_PHONE>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		ledswitch { | ||||||
|  | 			label = "ledswitch"; | ||||||
|  | 			gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_LIGHTS_TOGGLE>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		dsl { | ||||||
|  | 			label = "vr2600v:white:dsl"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb { | ||||||
|  | 			label = "vr2600v:white:usb"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		lan { | ||||||
|  | 			label = "vr2600v:white:lan"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan2g { | ||||||
|  | 			label = "vr2600v:white:wlan2g"; | ||||||
|  | 			gpios = <&qcom_pinmux 16 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan5g { | ||||||
|  | 			label = "vr2600v:white:wlan5g"; | ||||||
|  | 			gpios = <&qcom_pinmux 17 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "vr2600v:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phone { | ||||||
|  | 			label = "vr2600v:white:phone"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan { | ||||||
|  | 			label = "vr2600v:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 56 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		general: general { | ||||||
|  | 			label = "vr2600v:white:general"; | ||||||
|  | 			gpios = <&qcom_pinmux 66 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,442 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "NEC Aterm WG2600HP"; | ||||||
|  | 	compatible = "nec,wg2600hp", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power_green; | ||||||
|  | 		led-failsafe = &power_red; | ||||||
|  | 		led-running = &power_green; | ||||||
|  | 		led-upgrade = &power_green; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x06000000  /* PAD0_MODE */ | ||||||
|  | 					0x0000c 0x00080080  /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0x0006a545  /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x0000004e  /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x0000004e  /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		bridge { | ||||||
|  | 			label = "bridge"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_0>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		converter { | ||||||
|  | 			label = "converter"; | ||||||
|  | 			gpios = <&qcom_pinmux 25 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_0>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		converter_green { | ||||||
|  | 			label = "wg2600hp:green:converter"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_red: power_red { | ||||||
|  | 			label = "wg2600hp:red:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		active_green { | ||||||
|  | 			label = "wg2600hp:green:active"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		active_red { | ||||||
|  | 			label = "wg2600hp:red:active"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_green: power_green { | ||||||
|  | 			label = "wg2600hp:green:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 14 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		converter_red { | ||||||
|  | 			label = "wg2600hp:red:converter"; | ||||||
|  | 			gpios = <&qcom_pinmux 15 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan2g_green { | ||||||
|  | 			label = "wg2600hp:green:wlan2g"; | ||||||
|  | 			gpios = <&qcom_pinmux 55 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan2g_red { | ||||||
|  | 			label = "wg2600hp:red:wlan2g"; | ||||||
|  | 			gpios = <&qcom_pinmux 56 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan5g_green { | ||||||
|  | 			label = "wg2600hp:green:wlan5g"; | ||||||
|  | 			gpios = <&qcom_pinmux 57 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wlan5g_red { | ||||||
|  | 			label = "wg2600hp:red:wlan5g"; | ||||||
|  | 			gpios = <&qcom_pinmux 58 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		tv_green { | ||||||
|  | 			label = "wg2600hp:green:tv"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		tv_red { | ||||||
|  | 			label = "wg2600hp:red:tv"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac1 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "rgmii"; | ||||||
|  | 	qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 	mtd-mac-address = <&PRODUCTDATA 6>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac2 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "sgmii"; | ||||||
|  | 	qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 	mtd-mac-address = <&PRODUCTDATA 0>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4_serial { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi5 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  |  | ||||||
|  | 	spi@1a280000 { | ||||||
|  | 		status = "okay"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&spi_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 		flash@0 { | ||||||
|  | 			compatible = "jedec,spi-nor"; | ||||||
|  | 			spi-max-frequency = <50000000>; | ||||||
|  | 			reg = <0>; | ||||||
|  |  | ||||||
|  | 			partitions { | ||||||
|  | 				compatible = "fixed-partitions"; | ||||||
|  | 				#address-cells = <1>; | ||||||
|  | 				#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 				SBL1@0 { | ||||||
|  | 					label = "SBL1"; | ||||||
|  | 					reg = <0x0 0x20000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				MIBIB@20000 { | ||||||
|  | 					label = "MIBIB"; | ||||||
|  | 					reg = <0x20000 0x20000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SBL2@40000 { | ||||||
|  | 					label = "SBL2"; | ||||||
|  | 					reg = <0x40000 0x40000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SBL3@80000 { | ||||||
|  | 					label = "SBL3"; | ||||||
|  | 					reg = <0x80000 0x80000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				DDRCONFIG@100000 { | ||||||
|  | 					label = "DDRCONFIG"; | ||||||
|  | 					reg = <0x100000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SSD@110000 { | ||||||
|  | 					label = "SSD"; | ||||||
|  | 					reg = <0x110000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				TZ@120000 { | ||||||
|  | 					label = "TZ"; | ||||||
|  | 					reg = <0x120000 0x80000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				RPM@1a0000 { | ||||||
|  | 					label = "RPM"; | ||||||
|  | 					reg = <0x1a0000 0x80000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				APPSBL@220000 { | ||||||
|  | 					label = "APPSBL"; | ||||||
|  | 					reg = <0x220000 0x80000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				APPSBLENV@2a0000 { | ||||||
|  | 					label = "APPSBLENV"; | ||||||
|  | 					reg = <0x2a0000 0x10000>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				PRODUCTDATA: PRODUCTDATA@2b0000 { | ||||||
|  | 					label = "PRODUCTDATA"; | ||||||
|  | 					reg = <0x2b0000 0x30000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				ART@2e0000 { | ||||||
|  | 					label = "ART"; | ||||||
|  | 					reg = <0x2e0000 0x40000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				TP@320000 { | ||||||
|  | 					label = "TP"; | ||||||
|  | 					reg = <0x320000 0x40000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				TINY@360000 { | ||||||
|  | 					label = "TINY"; | ||||||
|  | 					reg = <0x360000 0x500000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				firmware@860000 { | ||||||
|  | 					compatible = "denx,uimage"; | ||||||
|  | 					label = "firmware"; | ||||||
|  | 					reg = <0x860000 0x17a0000>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_0 {		/* USB3 port 0 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_0 {		/* USB3 port 0 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_1 {		/* USB3 port 1 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_1 {		/* USB3 port 1 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &usb3_0 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&usb_pwr_en_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &usb3_1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie0 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	force_gen1 = <1>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &qcom_pinmux { | ||||||
|  | 	button_pins: button_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio16", "gpio54", "gpio24", "gpio25"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	i2c4_pins: i2c4_pinmux { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio12", "gpio13"; | ||||||
|  | 			function = "gsbi4"; | ||||||
|  | 			drive-strength = <12>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	led_pins: led_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio6", "gpio7", "gpio8", "gpio9", "gpio14", | ||||||
|  | 				"gpio15", "gpio55", "gpio56", "gpio57", "gpio58", | ||||||
|  | 				"gpio64", "gpio65"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	spi_pins: spi_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 			function = "gsbi5"; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		data { | ||||||
|  | 			pins = "gpio18", "gpio19"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		cs { | ||||||
|  | 			pins = "gpio20"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		clk { | ||||||
|  | 			pins = "gpio21"; | ||||||
|  | 			drive-strength = <12>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	mdio0_pins: mdio0_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio0", "gpio1"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	rgmii2_pins: rgmii2_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 			       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 			function = "rgmii2"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	usb_pwr_en_pins: usb_pwr_en_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio22"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 			output-high; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,568 @@ | |||||||
|  | /* | ||||||
|  |  *  BSD LICENSE | ||||||
|  |  * | ||||||
|  |  *  Copyright (C) 2017 Christian Mehlis <christian@m3hlis.de> | ||||||
|  |  *  Copyright (C) 2018 Mathias Kresin <dev@kresin.me> | ||||||
|  |  *  All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Redistribution and use in source and binary forms, with or without | ||||||
|  |  *  modification, are permitted provided that the following conditions | ||||||
|  |  *  are met: | ||||||
|  |  * | ||||||
|  |  *    1. Redistributions of source code must retain the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer. | ||||||
|  |  *    2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *       notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *       documentation and/or other materials provided with the distribution. | ||||||
|  |  *    3. Neither the names of the copyright holders nor the names of any | ||||||
|  |  *       contributors may be used to endorse or promote products derived | ||||||
|  |  *       from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||
|  |  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||
|  |  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||
|  |  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||
|  |  *  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||
|  |  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||
|  |  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||
|  |  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||
|  |  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  |  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "qcom-ipq8064-v1.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  | #include <dt-bindings/soc/qcom,tcsr.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	compatible = "compex,wpq864", "qcom,ipq8064"; | ||||||
|  | 	model = "Compex WPQ864"; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		ethernet0 = &gmac1; | ||||||
|  | 		ethernet1 = &gmac0; | ||||||
|  |  | ||||||
|  | 		led-boot = &led_pass; | ||||||
|  | 		led-failsafe = &led_fail; | ||||||
|  | 		led-running = &led_pass; | ||||||
|  | 		led-upgrade = &led_pass; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		rpm@108000 { | ||||||
|  | 			pinctrl-0 = <&rpm_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "okay"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mt29f2g08abbeah4@0 { | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				reg = <0>; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					SBL1@0 { | ||||||
|  | 						label = "SBL1"; | ||||||
|  | 						reg = <0x0000000 0x0040000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					MIBIB@40000 { | ||||||
|  | 						label = "MIBIB"; | ||||||
|  | 						reg = <0x0040000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL2@180000 { | ||||||
|  | 						label = "SBL2"; | ||||||
|  | 						reg = <0x0180000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL3@2c0000 { | ||||||
|  | 						label = "SBL3"; | ||||||
|  | 						reg = <0x02c0000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					DDRCONFIG@540000 { | ||||||
|  | 						label = "DDRCONFIG"; | ||||||
|  | 						reg = <0x0540000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SSD@660000 { | ||||||
|  | 						label = "SSD"; | ||||||
|  | 						reg = <0x0660000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					TZ@780000 { | ||||||
|  | 						label = "TZ"; | ||||||
|  | 						reg = <0x0780000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					RPM@a00000 { | ||||||
|  | 						label = "RPM"; | ||||||
|  | 						reg = <0x0a00000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@c80000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0c80000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@1180000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x1180000 0x0080000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ART@1200000 { | ||||||
|  | 						label = "ART"; | ||||||
|  | 						reg = <0x1200000 0x0140000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi@1340000 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x1340000 0x4000000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					BOOTCONFIG@5340000 { | ||||||
|  | 						label = "BOOTCONFIG"; | ||||||
|  | 						reg = <0x5340000 0x0060000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL2-1@53a0000- { | ||||||
|  | 						label = "SBL2_1"; | ||||||
|  | 						reg = <0x53a0000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SBL3-1@54e0000 { | ||||||
|  | 						label = "SBL3_1"; | ||||||
|  | 						reg = <0x54e0000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					DDRCONFIG-1@5760000 { | ||||||
|  | 						label = "DDRCONFIG_1"; | ||||||
|  | 						reg = <0x5760000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					SSD-1@5880000 { | ||||||
|  | 						label = "SSD_1"; | ||||||
|  | 						reg = <0x5880000 0x0120000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					TZ-1@59a0000 { | ||||||
|  | 						label = "TZ_1"; | ||||||
|  | 						reg = <0x59a0000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					RPM-1@5c20000 { | ||||||
|  | 						label = "RPM_1"; | ||||||
|  | 						reg = <0x5c20000 0x0280000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					BOOTCONFIG1@5ea0000 { | ||||||
|  | 						label = "BOOTCONFIG1"; | ||||||
|  | 						reg = <0x5ea0000 0x0060000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL-1@5f00000 { | ||||||
|  | 						label = "APPSBL_1"; | ||||||
|  | 						reg = <0x5f00000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi-1@6400000 { | ||||||
|  | 						label = "ubi_1"; | ||||||
|  | 						reg = <0x6400000 0x4000000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					unused@a400000 { | ||||||
|  | 						label = "unused"; | ||||||
|  | 						reg = <0xa400000 0x5c00000>; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	mdio0: mdio { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <0>; | ||||||
|  |  | ||||||
|  | 		compatible = "virtual,mdio-gpio"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 		ethernet-phy@0 { | ||||||
|  | 			reg = <0>; | ||||||
|  | 			qca,ar8327-initvals = < | ||||||
|  | 				0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 				0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 				0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 				0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 				0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 				0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 				0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 				>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		ethernet-phy@4 { | ||||||
|  | 			reg = <4>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		rss4 { | ||||||
|  | 			label = "wpq864:green:rss4"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		rss3 { | ||||||
|  | 			label = "wpq864:green:rss3"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		rss2 { | ||||||
|  | 			label = "wpq864:orange:rss2"; | ||||||
|  | 			gpios = <&qcom_pinmux 25 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		rss1 { | ||||||
|  | 			label = "wpq864:red:rss1"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		led_pass: pass { | ||||||
|  | 			label = "wpq864:green:pass"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		led_fail: fail { | ||||||
|  | 			label = "wpq864:green:fail"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb { | ||||||
|  | 			label = "wpq864:green:usb"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb-pcie { | ||||||
|  | 			label = "wpq864:green:usb-pcie"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	beeper { | ||||||
|  | 		compatible = "gpio-beeper"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&beeper_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		gpios = <&qcom_pinmux 55 GPIO_ACTIVE_HIGH>; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac1 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "rgmii"; | ||||||
|  | 	qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac2 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "sgmii"; | ||||||
|  | 	qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4_serial { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&uart0_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi5 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  |  | ||||||
|  | 	spi@1a280000 { | ||||||
|  | 		status = "okay"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&spi_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 		s25fl256s1@0 { | ||||||
|  | 			compatible = "jedec,spi-nor"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <1>; | ||||||
|  | 			reg = <0>; | ||||||
|  | 			spi-max-frequency = <50000000>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_0 {		/* USB3 port 0 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_1 {		/* USB3 port 1 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_0 {		/* USB3 port 0 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	rx_eq = <2>; | ||||||
|  | 	tx_deamp_3_5db = <32>; | ||||||
|  | 	mpll = <160>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_1 {		/* USB3 port 1 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	rx_eq = <2>; | ||||||
|  | 	tx_deamp_3_5db = <32>; | ||||||
|  | 	mpll = <160>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie0 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	/delete-property/ pinctrl-0; | ||||||
|  | 	/delete-property/ pinctrl-names; | ||||||
|  | 	/delete-property/ perst-gpios; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie2 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	/delete-property/ pinctrl-0; | ||||||
|  | 	/delete-property/ pinctrl-names; | ||||||
|  | 	/delete-property/ perst-gpios; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &qcom_pinmux { | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  | 	pinctrl-0 = <&state_default>; | ||||||
|  |  | ||||||
|  | 	state_default: pinctrl0 { | ||||||
|  | 		pcie0_pcie2_perst { | ||||||
|  | 			pins = "gpio3"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-disable; | ||||||
|  | 			output-high; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	led_pins: led_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio7", "gpio8", "gpio9", "gpio22", | ||||||
|  | 			       "gpio23", "gpio24", "gpio25", "gpio53"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	button_pins: button_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio54"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	beeper_pins: beeper_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio55"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	rpm_pins: rpm_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio12", "gpio13"; | ||||||
|  | 			function = "gsbi4"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	uart0_pins: uart0_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio10", "gpio11"; | ||||||
|  | 			function = "gsbi4"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	spi_pins: spi_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio18", "gpio19"; | ||||||
|  | 			function = "gsbi5"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		clk { | ||||||
|  | 			pins = "gpio21"; | ||||||
|  | 			function = "gsbi5"; | ||||||
|  | 			drive-strength = <12>; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		cs { | ||||||
|  | 			pins = "gpio20"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	nand_pins: nand_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio34", "gpio35", "gpio36", "gpio37", | ||||||
|  | 			       "gpio38", "gpio39", "gpio40", "gpio41", | ||||||
|  | 			       "gpio42", "gpio43", "gpio44", "gpio45", | ||||||
|  | 			       "gpio46", "gpio47"; | ||||||
|  | 			function = "nand"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pullups { | ||||||
|  | 			pins = "gpio39"; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		hold { | ||||||
|  | 			pins = "gpio40", "gpio41", "gpio42", "gpio43", | ||||||
|  | 			       "gpio44", "gpio45", "gpio46", "gpio47"; | ||||||
|  | 			bias-bus-hold; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	mdio0_pins: mdio0_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio0", "gpio1"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	rgmii2_pins: rgmii2_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio27", "gpio28", "gpio29", "gpio30", | ||||||
|  | 			       "gpio31", "gpio32", "gpio51", "gpio52", | ||||||
|  | 			       "gpio59", "gpio60", "gpio61", "gpio62"; | ||||||
|  | 			function = "rgmii2"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &usb3_0 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | &usb3_1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &tcsr { | ||||||
|  | 	qcom,usb-ctrl-select = <TCSR_USB_SELECT_USB3_DUAL>; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,535 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later OR MIT | ||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Buffalo WXR-2533DHP"; | ||||||
|  | 	compatible = "buffalo,wxr-2533dhp", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@42000000 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &diag; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &power; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		/* use "ubi_rootfs" volume in "ubi" partition as rootfs */ | ||||||
|  | 		bootargs = "ubi.block=0,1 root=/dev/ubiblock0_1 rootfstype=squashfs"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "okay"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					ubi@0 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x0000000 0x4000000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					rootfs_1@4000000 { | ||||||
|  | 						label = "rootfs_1"; | ||||||
|  | 						reg = <0x4000000 0x4000000>; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>, | ||||||
|  | 				<&qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x07600000  /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x01000000  /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x00000080  /* PAD6_MODE */ | ||||||
|  | 					0x00050 0xcc35cc35  /* LED_CTRL0 */ | ||||||
|  | 					0x00054 0xca35ca35  /* LED_CTRL1 */ | ||||||
|  | 					0x00058 0xc935c935  /* LED_CTRL2 */ | ||||||
|  | 					0x0005c 0x03ffff00  /* LED_CTRL3 */ | ||||||
|  | 					0x000e4 0x0006a545  /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x0000007e  /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x0000007e  /* PORT6_STATUS */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		usb { | ||||||
|  | 			label = "wxr-2533dhp:green:usb"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			linux,default-trigger = "usbport"; | ||||||
|  | 			trigger-sources = <&hub_port0 &hub_port1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		guestport { | ||||||
|  | 			label = "wxr-2533dhp:green:guestport"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		diag: diag { | ||||||
|  | 			label = "wxr-2533dhp:orange:diag"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		internet_orange { | ||||||
|  | 			label = "wxr-2533dhp:orange:internet"; | ||||||
|  | 			gpios = <&qcom_pinmux 16 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		internet_white { | ||||||
|  | 			label = "wxr-2533dhp:white:internet"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wireless_orange { | ||||||
|  | 			label = "wxr-2533dhp:orange:wireless"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wireless_white { | ||||||
|  | 			label = "wxr-2533dhp:white:wireless"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		router_orange { | ||||||
|  | 			label = "wxr-2533dhp:orange:router"; | ||||||
|  | 			gpios = <&qcom_pinmux 25 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		router_white { | ||||||
|  | 			label = "wxr-2533dhp:white:router"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "wxr-2533dhp:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		power { | ||||||
|  | 			label = "power"; | ||||||
|  | 			gpios = <&qcom_pinmux 58 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_POWER>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		eject { | ||||||
|  | 			label = "eject"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_EJECTCD>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		guest { | ||||||
|  | 			label = "guest"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_0>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		ap { | ||||||
|  | 			label = "ap"; | ||||||
|  | 			gpios = <&qcom_pinmux 55 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_1>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		router { | ||||||
|  | 			label = "router"; | ||||||
|  | 			gpios = <&qcom_pinmux 56 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_1>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		auto { | ||||||
|  | 			label = "auto"; | ||||||
|  | 			gpios = <&qcom_pinmux 57 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <BTN_1>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac1 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "rgmii"; | ||||||
|  | 	qcom,id = <1>; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 	mtd-mac-address = <&ART 6>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gmac2 { | ||||||
|  | 	status = "ok"; | ||||||
|  |  | ||||||
|  | 	phy-mode = "sgmii"; | ||||||
|  | 	qcom,id = <2>; | ||||||
|  |  | ||||||
|  | 	mtd-mac-address = <&ART 0>; | ||||||
|  |  | ||||||
|  | 	fixed-link { | ||||||
|  | 		speed = <1000>; | ||||||
|  | 		full-duplex; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi4_serial { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&uart0_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &gsbi5 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  |  | ||||||
|  | 	spi@1a280000 { | ||||||
|  | 		status = "okay"; | ||||||
|  |  | ||||||
|  | 		pinctrl-0 = <&spi_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 		flash@0 { | ||||||
|  | 			compatible = "jedec,spi-nor"; | ||||||
|  | 			spi-max-frequency = <50000000>; | ||||||
|  | 			reg = <0>; | ||||||
|  |  | ||||||
|  | 			partitions { | ||||||
|  | 				compatible = "fixed-partitions"; | ||||||
|  | 				#address-cells = <1>; | ||||||
|  | 				#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 				SBL1@0 { | ||||||
|  | 					label = "SBL1"; | ||||||
|  | 					reg = <0x0 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				MIBIB@10000 { | ||||||
|  | 					label = "MIBIB"; | ||||||
|  | 					reg = <0x10000 0x20000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SBL2@30000 { | ||||||
|  | 					label = "SBL2"; | ||||||
|  | 					reg = <0x30000 0x30000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SBL3@60000 { | ||||||
|  | 					label = "SBL3"; | ||||||
|  | 					reg = <0x60000 0x30000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				DDRCONFIG@90000 { | ||||||
|  | 					label = "DDRCONFIG"; | ||||||
|  | 					reg = <0x90000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				SSD@a0000 { | ||||||
|  | 					label = "SSD"; | ||||||
|  | 					reg = <0xa0000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				TZ@b0000 { | ||||||
|  | 					label = "TZ"; | ||||||
|  | 					reg = <0xb0000 0x30000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				RPM@e0000 { | ||||||
|  | 					label = "RPM"; | ||||||
|  | 					reg = <0xe0000 0x20000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				APPSBL@100000 { | ||||||
|  | 					label = "APPSBL"; | ||||||
|  | 					reg = <0x100000 0x70000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				APPSBLENV@170000 { | ||||||
|  | 					label = "APPSBLENV"; | ||||||
|  | 					reg = <0x170000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				ART: ART@180000 { | ||||||
|  | 					label = "ART"; | ||||||
|  | 					reg = <0x180000 0x40000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				BOOTCONFIG@1c0000 { | ||||||
|  | 					label = "BOOTCONFIG"; | ||||||
|  | 					reg = <0x1c0000 0x10000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				APPSBL_1@1d0000 { | ||||||
|  | 					label = "APPSBL_1"; | ||||||
|  | 					reg = <0x1d0000 0x70000>; | ||||||
|  | 					read-only; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_0 {		/* USB3 port 0 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_0 {		/* USB3 port 0 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &hs_phy_1 {		/* USB3 port 1 HS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &ss_phy_1 {		/* USB3 port 1 SS phy */ | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &usb3_0 { | ||||||
|  | 	status = "okay"; | ||||||
|  |  | ||||||
|  | 	pinctrl-0 = <&usb_pwr_en_pins>; | ||||||
|  | 	pinctrl-names = "default"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &usb3_1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &dwc3_0 { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <0>; | ||||||
|  |  | ||||||
|  | 	hub_port0: port@1 { | ||||||
|  | 		reg = <1>; | ||||||
|  | 		#trigger-source-cells = <0>; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &dwc3_1 { | ||||||
|  | 	#address-cells = <1>; | ||||||
|  | 	#size-cells = <0>; | ||||||
|  |  | ||||||
|  | 	hub_port1: port@1 { | ||||||
|  | 		reg = <1>; | ||||||
|  | 		#trigger-source-cells = <0>; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie0 { | ||||||
|  | 	status = "okay"; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &pcie1 { | ||||||
|  | 	status = "okay"; | ||||||
|  | 	force_gen1 = <1>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &qcom_pinmux { | ||||||
|  | 	button_pins: button_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio6", "gpio54", "gpio55", "gpio56", "gpio57", | ||||||
|  | 				"gpio58", "gpio64", "gpio65"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	led_pins: led_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio7", "gpio8", "gpio9", "gpio16", "gpio22", | ||||||
|  | 				"gpio23", "gpio24", "gpio25", "gpio26", "gpio53"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	uart0_pins: uart0_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio10", "gpio11"; | ||||||
|  | 			function = "gsbi4"; | ||||||
|  | 			drive-strength = <12>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	spi_pins: spi_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 			function = "gsbi5"; | ||||||
|  | 			bias-pull-down; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		data { | ||||||
|  | 			pins = "gpio18", "gpio19"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		cs{ | ||||||
|  | 			pins = "gpio20"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		clk { | ||||||
|  | 			pins = "gpio21"; | ||||||
|  | 			drive-strength = <12>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	mdio0_pins: mdio0_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio0", "gpio1"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	nand_pins: nand_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 			       "gpio37", "gpio38", "gpio39", | ||||||
|  | 			       "gpio40", "gpio41", "gpio42", | ||||||
|  | 			       "gpio43", "gpio44", "gpio45", | ||||||
|  | 			       "gpio46", "gpio47"; | ||||||
|  | 			function = "nand"; | ||||||
|  | 			drive-strength = <10>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pullups { | ||||||
|  | 			pins = "gpio39"; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		hold { | ||||||
|  | 			pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 			       "gpio43", "gpio44", "gpio45", | ||||||
|  | 			       "gpio46", "gpio47"; | ||||||
|  | 			bias-bus-hold; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	rgmii2_pins: rgmii2_pins { | ||||||
|  | 		mux { | ||||||
|  | 			pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 			       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 			function = "rgmii2"; | ||||||
|  | 			drive-strength = <8>; | ||||||
|  | 			bias-disable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	usb_pwr_en_pins: usb_pwr_en_pins { | ||||||
|  | 		mux{ | ||||||
|  | 			pins = "gpio68"; | ||||||
|  | 			function = "gpio"; | ||||||
|  | 			drive-strength = <2>; | ||||||
|  | 			bias-pull-up; | ||||||
|  | 			output-high; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
							
								
								
									
										1410
									
								
								target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064.dtsi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1410
									
								
								target/linux/ipq806x/files-4.19/arch/arm/boot/dts/qcom-ipq8064.dtsi
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,386 @@ | |||||||
|  | #include "qcom-ipq8065.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "ZyXEL NBG6817"; | ||||||
|  | 	compatible = "zyxel,nbg6817", "qcom,ipq8065"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  | 		sdcc1 = &sdcc1; | ||||||
|  |  | ||||||
|  | 		led-boot = &power; | ||||||
|  | 		led-failsafe = &power; | ||||||
|  | 		led-running = &power; | ||||||
|  | 		led-upgrade = &power; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		bootargs = "rootfstype=squashfs,ext4 rootwait noinitrd"; | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 		append-rootblock = "root=/dev/mmcblk0p"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio53", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio9", "gpio26", "gpio33", "gpio64"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio1"; | ||||||
|  | 					input-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				tx { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32" ; | ||||||
|  | 					input-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-none; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				cs { | ||||||
|  | 					pins = "gpio20"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb0_pwr_en_pins: usb0_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio16", "gpio17"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				pwr { | ||||||
|  | 					pins = "gpio17"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				ovc { | ||||||
|  | 					pins = "gpio16"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb1_pwr_en_pins: usb1_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio14", "gpio15"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				pwr { | ||||||
|  | 					pins = "gpio14"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				ovc { | ||||||
|  | 					pins = "gpio15"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi5: gsbi@1a200000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_SPI>; | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			spi4: spi@1a280000 { | ||||||
|  | 				status = "ok"; | ||||||
|  |  | ||||||
|  | 				pinctrl-0 = <&spi_pins>; | ||||||
|  | 				pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 				cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; | ||||||
|  |  | ||||||
|  | 				flash: m25p80@0 { | ||||||
|  | 					compatible = "jedec,spi-nor"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  | 					spi-max-frequency = <51200000>; | ||||||
|  | 					reg = <0>; | ||||||
|  |  | ||||||
|  | 					partitions { | ||||||
|  | 						compatible = "qcom,smem"; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb0_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb1_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; | ||||||
|  | 			pinctrl-0 = <&pcie0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; | ||||||
|  | 			pinctrl-0 = <&pcie1_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					0x00970 0x1e864443  /* QM_PORT0_CTRL0 */ | ||||||
|  | 					0x00974 0x000001c6  /* QM_PORT0_CTRL1 */ | ||||||
|  | 					0x00978 0x19008643  /* QM_PORT1_CTRL0 */ | ||||||
|  | 					0x0097c 0x000001c6  /* QM_PORT1_CTRL1 */ | ||||||
|  | 					0x00980 0x19008643  /* QM_PORT2_CTRL0 */ | ||||||
|  | 					0x00984 0x000001c6  /* QM_PORT2_CTRL1 */ | ||||||
|  | 					0x00988 0x19008643  /* QM_PORT3_CTRL0 */ | ||||||
|  | 					0x0098c 0x000001c6  /* QM_PORT3_CTRL1 */ | ||||||
|  | 					0x00990 0x19008643  /* QM_PORT4_CTRL0 */ | ||||||
|  | 					0x00994 0x000001c6  /* QM_PORT4_CTRL1 */ | ||||||
|  | 					0x00998 0x1e864443  /* QM_PORT5_CTRL0 */ | ||||||
|  | 					0x0099c 0x000001c6  /* QM_PORT5_CTRL1 */ | ||||||
|  | 					0x009a0 0x1e864443  /* QM_PORT6_CTRL0 */ | ||||||
|  | 					0x009a4 0x000001c6  /* QM_PORT6_CTRL1 */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  | 			qcom,phy_mdio_addr = <4>; | ||||||
|  | 			qcom,poll_required = <0>; | ||||||
|  | 			qcom,rgmii_delay = <1>; | ||||||
|  | 			qcom,phy_mii_type = <0>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			qcom,irq = <255>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  | 			qcom,phy_mdio_addr = <0>;	/* none */ | ||||||
|  | 			qcom,poll_required = <0>;	/* no polling */ | ||||||
|  | 			qcom,rgmii_delay = <0>; | ||||||
|  | 			qcom,phy_mii_type = <1>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			qcom,irq = <258>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		amba { | ||||||
|  | 			sdcc1: sdcc@12400000 { | ||||||
|  | 				status = "okay"; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 			linux,input-type = <EV_SW>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		internet { | ||||||
|  | 			label = "nbg6817:white:internet"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power: power { | ||||||
|  | 			label = "nbg6817:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi2g { | ||||||
|  | 			label = "nbg6817:amber:wifi2g"; | ||||||
|  | 			gpios = <&qcom_pinmux 33 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		/* wifi2g amber from the manual is missing */ | ||||||
|  |  | ||||||
|  | 		wifi5g { | ||||||
|  | 			label = "nbg6817:amber:wifi5g"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		/* wifi5g amber from the manual is missing */ | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,513 @@ | |||||||
|  | #include "qcom-ipq8065.dtsi" | ||||||
|  |  | ||||||
|  | #include <dt-bindings/input/input.h> | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Netgear Nighthawk X4S R7800"; | ||||||
|  | 	compatible = "netgear,r7800", "qcom,ipq8065", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	memory@0 { | ||||||
|  | 		reg = <0x42000000 0x1e000000>; | ||||||
|  | 		device_type = "memory"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	reserved-memory { | ||||||
|  | 		#address-cells = <1>; | ||||||
|  | 		#size-cells = <1>; | ||||||
|  | 		ranges; | ||||||
|  | 		rsvd@41200000 { | ||||||
|  | 			reg = <0x41200000 0x300000>; | ||||||
|  | 			no-map; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		rsvd@5fe00000 { | ||||||
|  | 			reg = <0x5fe00000 0x200000>; | ||||||
|  | 			reusable; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	aliases { | ||||||
|  | 		serial0 = &gsbi4_serial; | ||||||
|  | 		mdio-gpio0 = &mdio0; | ||||||
|  |  | ||||||
|  | 		led-boot = &power_white; | ||||||
|  | 		led-failsafe = &power_amber; | ||||||
|  | 		led-running = &power_white; | ||||||
|  | 		led-upgrade = &power_amber; | ||||||
|  | 		label-mac-device = &gmac2; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	chosen { | ||||||
|  | 		stdout-path = "serial0:115200n8"; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc { | ||||||
|  | 		pinmux@800000 { | ||||||
|  | 			button_pins: button_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio6", "gpio54", "gpio65"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <2>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			i2c4_pins: i2c4_pinmux { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio12", "gpio13"; | ||||||
|  | 					function = "gsbi4"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			led_pins: led_pins { | ||||||
|  | 				pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", | ||||||
|  | 					"gpio24","gpio26", "gpio53", "gpio64"; | ||||||
|  | 				function = "gpio"; | ||||||
|  | 				drive-strength = <2>; | ||||||
|  | 				bias-pull-down; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			nand_pins: nand_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio34", "gpio35", "gpio36", | ||||||
|  | 					       "gpio37", "gpio38", "gpio39", | ||||||
|  | 					       "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					function = "nand"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  | 				pullups { | ||||||
|  | 					pins = "gpio39"; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  | 				hold { | ||||||
|  | 					pins = "gpio40", "gpio41", "gpio42", | ||||||
|  | 					       "gpio43", "gpio44", "gpio45", | ||||||
|  | 					       "gpio46", "gpio47"; | ||||||
|  | 					bias-bus-hold; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			mdio0_pins: mdio0_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio0", "gpio1"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio1"; | ||||||
|  | 					input-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			rgmii2_pins: rgmii2_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | 					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; | ||||||
|  | 					function = "rgmii2"; | ||||||
|  | 					drive-strength = <8>; | ||||||
|  | 					bias-disable; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				tx { | ||||||
|  | 					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32" ; | ||||||
|  | 					input-disable; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi_pins: spi_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio18", "gpio19", "gpio21"; | ||||||
|  | 					function = "gsbi5"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				data { | ||||||
|  | 					pins = "gpio18", "gpio19"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				cs { | ||||||
|  | 					pins = "gpio20"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio21"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			spi6_pins: spi6_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio55", "gpio56", "gpio58"; | ||||||
|  | 					function = "gsbi6"; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				mosi { | ||||||
|  | 					pins = "gpio55"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				miso { | ||||||
|  | 					pins = "gpio56"; | ||||||
|  | 					drive-strength = <14>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				cs { | ||||||
|  | 					pins = "gpio57"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-up; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				clk { | ||||||
|  | 					pins = "gpio58"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				reset { | ||||||
|  | 					pins = "gpio33"; | ||||||
|  | 					drive-strength = <10>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb0_pwr_en_pins: usb0_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio15"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			usb1_pwr_en_pins: usb1_pwr_en_pins { | ||||||
|  | 				mux { | ||||||
|  | 					pins = "gpio16", "gpio68"; | ||||||
|  | 					function = "gpio"; | ||||||
|  | 					drive-strength = <12>; | ||||||
|  | 					bias-pull-down; | ||||||
|  | 					output-high; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gsbi@16300000 { | ||||||
|  | 			qcom,mode = <GSBI_PROT_I2C_UART>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 			serial@16340000 { | ||||||
|  | 				status = "ok"; | ||||||
|  | 			}; | ||||||
|  | 			/* | ||||||
|  | 			 * The i2c device on gsbi4 should not be enabled. | ||||||
|  | 			 * On ipq806x designs gsbi4 i2c is meant for exclusive | ||||||
|  | 			 * RPM usage. Turning this on in kernel manifests as | ||||||
|  | 			 * i2c failure for the RPM. | ||||||
|  | 			 */ | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata-phy@1b400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		sata@29000000 { | ||||||
|  | 			ports-implemented = <0x1>; | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8800 {		/* USB3 port 1 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@100f8830 {		/* USB3 port 1 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8800 {		/* USB3 port 0 HS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		phy@110f8830 {		/* USB3 port 0 SS phy */ | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@0 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb0_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb30@1 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&usb1_pwr_en_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie0: pci@1b500000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		pcie1: pci@1b700000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			force_gen1 = <1>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		nand@1ac00000 { | ||||||
|  | 			status = "ok"; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&nand_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			cs0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				compatible = "qcom,nandcs"; | ||||||
|  |  | ||||||
|  | 				nand-ecc-strength = <4>; | ||||||
|  | 				nand-bus-width = <8>; | ||||||
|  | 				nand-ecc-step-size = <512>; | ||||||
|  |  | ||||||
|  | 				partitions { | ||||||
|  | 					compatible = "fixed-partitions"; | ||||||
|  | 					#address-cells = <1>; | ||||||
|  | 					#size-cells = <1>; | ||||||
|  |  | ||||||
|  | 					qcadata@0 { | ||||||
|  | 						label = "qcadata"; | ||||||
|  | 						reg = <0x0000000 0x0c80000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBL@c80000 { | ||||||
|  | 						label = "APPSBL"; | ||||||
|  | 						reg = <0x0c80000 0x0500000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					APPSBLENV@1180000 { | ||||||
|  | 						label = "APPSBLENV"; | ||||||
|  | 						reg = <0x1180000 0x0080000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					art: art@1200000 { | ||||||
|  | 						label = "art"; | ||||||
|  | 						reg = <0x1200000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					artbak: art@1340000 { | ||||||
|  | 						label = "artbak"; | ||||||
|  | 						reg = <0x1340000 0x0140000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					kernel@1480000 { | ||||||
|  | 						label = "kernel"; | ||||||
|  | 						reg = <0x1480000 0x0400000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					ubi@1880000 { | ||||||
|  | 						label = "ubi"; | ||||||
|  | 						reg = <0x1880000 0x6080000>; | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					reserve@7900000 { | ||||||
|  | 						label = "reserve"; | ||||||
|  | 						reg = <0x7900000 0x0700000>; | ||||||
|  | 						read-only; | ||||||
|  | 					}; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		mdio0: mdio { | ||||||
|  | 			compatible = "virtual,mdio-gpio"; | ||||||
|  | 			#address-cells = <1>; | ||||||
|  | 			#size-cells = <0>; | ||||||
|  | 			gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			pinctrl-0 = <&mdio0_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 			phy0: ethernet-phy@0 { | ||||||
|  | 				reg = <0>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x00004 0x7600000   /* PAD0_MODE */ | ||||||
|  | 					0x00008 0x1000000   /* PAD5_MODE */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					0x000e4 0xaa545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x000e0 0xc74164de  /* SGMII_CTRL */ | ||||||
|  | 					0x0007c 0x4e        /* PORT0_STATUS */ | ||||||
|  | 					0x00094 0x4e        /* PORT6_STATUS */ | ||||||
|  | 					0x00970 0x1e864443  /* QM_PORT0_CTRL0 */ | ||||||
|  | 					0x00974 0x000001c6  /* QM_PORT0_CTRL1 */ | ||||||
|  | 					0x00978 0x19008643  /* QM_PORT1_CTRL0 */ | ||||||
|  | 					0x0097c 0x000001c6  /* QM_PORT1_CTRL1 */ | ||||||
|  | 					0x00980 0x19008643  /* QM_PORT2_CTRL0 */ | ||||||
|  | 					0x00984 0x000001c6  /* QM_PORT2_CTRL1 */ | ||||||
|  | 					0x00988 0x19008643  /* QM_PORT3_CTRL0 */ | ||||||
|  | 					0x0098c 0x000001c6  /* QM_PORT3_CTRL1 */ | ||||||
|  | 					0x00990 0x19008643  /* QM_PORT4_CTRL0 */ | ||||||
|  | 					0x00994 0x000001c6  /* QM_PORT4_CTRL1 */ | ||||||
|  | 					0x00998 0x1e864443  /* QM_PORT5_CTRL0 */ | ||||||
|  | 					0x0099c 0x000001c6  /* QM_PORT5_CTRL1 */ | ||||||
|  | 					0x009a0 0x1e864443  /* QM_PORT6_CTRL0 */ | ||||||
|  | 					0x009a4 0x000001c6  /* QM_PORT6_CTRL1 */ | ||||||
|  | 					>; | ||||||
|  | 				qca,ar8327-vlans = < | ||||||
|  | 					0x1	0x5e	    /* VLAN1 Ports 1/2/3/4/6 */ | ||||||
|  | 					0x2	0x21	    /* VLAN2 Ports 0/5 */ | ||||||
|  | 				>; | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			phy4: ethernet-phy@4 { | ||||||
|  | 				reg = <4>; | ||||||
|  | 				qca,ar8327-initvals = < | ||||||
|  | 					0x000e4 0x6a545     /* MAC_POWER_SEL */ | ||||||
|  | 					0x0000c 0x80        /* PAD6_MODE */ | ||||||
|  | 					>; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac1: ethernet@37200000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "rgmii"; | ||||||
|  | 			qcom,id = <1>; | ||||||
|  | 			qcom,phy_mdio_addr = <4>; | ||||||
|  | 			qcom,poll_required = <0>; | ||||||
|  | 			qcom,rgmii_delay = <1>; | ||||||
|  | 			qcom,phy_mii_type = <0>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			qcom,irq = <255>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			pinctrl-0 = <&rgmii2_pins>; | ||||||
|  | 			pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 6>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		gmac2: ethernet@37400000 { | ||||||
|  | 			status = "ok"; | ||||||
|  | 			phy-mode = "sgmii"; | ||||||
|  | 			qcom,id = <2>; | ||||||
|  | 			qcom,phy_mdio_addr = <0>;	/* none */ | ||||||
|  | 			qcom,poll_required = <0>;	/* no polling */ | ||||||
|  | 			qcom,rgmii_delay = <0>; | ||||||
|  | 			qcom,phy_mii_type = <1>; | ||||||
|  | 			qcom,emulation = <0>; | ||||||
|  | 			qcom,irq = <258>; | ||||||
|  | 			mdiobus = <&mdio0>; | ||||||
|  |  | ||||||
|  | 			mtd-mac-address = <&art 0>; | ||||||
|  |  | ||||||
|  | 			fixed-link { | ||||||
|  | 				speed = <1000>; | ||||||
|  | 				full-duplex; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys"; | ||||||
|  | 		pinctrl-0 = <&button_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RFKILL>; | ||||||
|  | 			debounce-interval = <60>; | ||||||
|  | 			wakeup-source; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		reset { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 			debounce-interval = <60>; | ||||||
|  | 			wakeup-source; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; | ||||||
|  | 			linux,code = <KEY_WPS_BUTTON>; | ||||||
|  | 			debounce-interval = <60>; | ||||||
|  | 			wakeup-source; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	leds { | ||||||
|  | 		compatible = "gpio-leds"; | ||||||
|  | 		pinctrl-0 = <&led_pins>; | ||||||
|  | 		pinctrl-names = "default"; | ||||||
|  |  | ||||||
|  | 		power_white: power_white { | ||||||
|  | 			label = "r7800:white:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; | ||||||
|  | 			default-state = "keep"; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		power_amber: power_amber { | ||||||
|  | 			label = "r7800:amber:power"; | ||||||
|  | 			gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_white { | ||||||
|  | 			label = "r7800:white:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wan_amber { | ||||||
|  | 			label = "r7800:amber:wan"; | ||||||
|  | 			gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb1 { | ||||||
|  | 			label = "r7800:white:usb1"; | ||||||
|  | 			gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		usb2 { | ||||||
|  | 			label = "r7800:white:usb2"; | ||||||
|  | 			gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		esata { | ||||||
|  | 			label = "r7800:white:esata"; | ||||||
|  | 			gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wifi { | ||||||
|  | 			label = "r7800:white:wifi"; | ||||||
|  | 			gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		wps { | ||||||
|  | 			label = "r7800:white:wps"; | ||||||
|  | 			gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | &adm_dma { | ||||||
|  | 	status = "ok"; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,78 @@ | |||||||
|  | #include "qcom-ipq8064-v2.0.dtsi" | ||||||
|  |  | ||||||
|  | / { | ||||||
|  | 	model = "Qualcomm IPQ8065"; | ||||||
|  | 	compatible = "qcom,ipq8065", "qcom,ipq8064"; | ||||||
|  |  | ||||||
|  | 	qcom,pvs { | ||||||
|  | 		qcom,pvs-format-a; | ||||||
|  | 		qcom,speed0-pvs0-bin-v0 = | ||||||
|  | 			< 1725000000 1262500 >, | ||||||
|  | 			< 1400000000 1175000 >, | ||||||
|  | 			< 1000000000 1100000 >, | ||||||
|  | 			 < 800000000 1050000 >, | ||||||
|  | 			 < 600000000 1000000 >, | ||||||
|  | 			 < 384000000 975000 >; | ||||||
|  | 		qcom,speed0-pvs1-bin-v0 = | ||||||
|  | 			< 1725000000 1225000 >, | ||||||
|  | 			< 1400000000 1150000 >, | ||||||
|  | 			< 1000000000 1075000 >, | ||||||
|  | 			 < 800000000 1025000 >, | ||||||
|  | 			 < 600000000 975000 >, | ||||||
|  | 			 < 384000000 950000 >; | ||||||
|  | 		qcom,speed0-pvs2-bin-v0 = | ||||||
|  | 			< 1725000000 1200000 >, | ||||||
|  | 			< 1400000000 1125000 >, | ||||||
|  | 			< 1000000000 1050000 >, | ||||||
|  | 			 < 800000000 1000000 >, | ||||||
|  | 			 < 600000000 950000 >, | ||||||
|  | 			 < 384000000 925000 >; | ||||||
|  | 		qcom,speed0-pvs3-bin-v0 = | ||||||
|  | 			< 1725000000 1175000 >, | ||||||
|  | 			< 1400000000 1100000 >, | ||||||
|  | 			< 1000000000 1025000 >, | ||||||
|  | 			 < 800000000 975000 >, | ||||||
|  | 			 < 600000000 925000 >, | ||||||
|  | 			 < 384000000 900000 >; | ||||||
|  | 		qcom,speed0-pvs4-bin-v0 = | ||||||
|  | 			< 1725000000 1150000 >, | ||||||
|  | 			< 1400000000 1075000 >, | ||||||
|  | 			< 1000000000 1000000 >, | ||||||
|  | 			 < 800000000 950000 >, | ||||||
|  | 			 < 600000000 900000 >, | ||||||
|  | 			 < 384000000 875000 >; | ||||||
|  | 		qcom,speed0-pvs5-bin-v0 = | ||||||
|  | 			< 1725000000 1100000 >, | ||||||
|  | 			< 1400000000 1025000 >, | ||||||
|  | 			< 1000000000 950000 >, | ||||||
|  | 			 < 800000000 900000 >, | ||||||
|  | 			 < 600000000 850000 >, | ||||||
|  | 			 < 384000000 825000 >; | ||||||
|  | 		qcom,speed0-pvs6-bin-v0 = | ||||||
|  | 			< 1725000000 1050000 >, | ||||||
|  | 			< 1400000000 975000 >, | ||||||
|  | 			< 1000000000 900000 >, | ||||||
|  | 			 < 800000000 850000 >, | ||||||
|  | 			 < 600000000 800000 >, | ||||||
|  | 			 < 384000000 775000 >; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	soc: soc { | ||||||
|  |  | ||||||
|  | 		rpm@108000 { | ||||||
|  |  | ||||||
|  | 			regulators { | ||||||
|  |  | ||||||
|  | 				smb208_s2a: s2a { | ||||||
|  | 					regulator-min-microvolt = <775000>; | ||||||
|  | 					regulator-max-microvolt = <1275000>; | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				smb208_s2b: s2b { | ||||||
|  | 					regulator-min-microvolt = <775000>; | ||||||
|  | 					regulator-max-microvolt = <1275000>; | ||||||
|  | 				}; | ||||||
|  | 			}; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -0,0 +1,71 @@ | |||||||
|  | From 28d0ed88f536dd639adf1b0c7c08e04be3c8f294 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Thomas Pedersen <twp@codeaurora.org> | ||||||
|  | Date: Mon, 16 May 2016 17:58:50 -0700 | ||||||
|  | Subject: [PATCH 01/69] dtbindings: qcom_adm: Fix channel specifiers | ||||||
|  |  | ||||||
|  | Original patch from Andy Gross. | ||||||
|  |  | ||||||
|  | This patch removes the crci information from the dma | ||||||
|  | channel property.  At least one client device requires | ||||||
|  | using more than one CRCI value for a channel.  This does | ||||||
|  | not match the current binding and the crci information | ||||||
|  | needs to be removed. | ||||||
|  |  | ||||||
|  | Instead, the client device will provide this information | ||||||
|  | via other means. | ||||||
|  |  | ||||||
|  | Signed-off-by: Andy Gross <agross@codeaurora.org> | ||||||
|  | Signed-off-by: Thomas Pedersen <twp@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  Documentation/devicetree/bindings/dma/qcom_adm.txt | 16 ++++++---------- | ||||||
|  |  1 file changed, 6 insertions(+), 10 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/dma/qcom_adm.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/dma/qcom_adm.txt | ||||||
|  | @@ -4,8 +4,7 @@ Required properties: | ||||||
|  |  - compatible: must contain "qcom,adm" for IPQ/APQ8064 and MSM8960 | ||||||
|  |  - reg: Address range for DMA registers | ||||||
|  |  - interrupts: Should contain one interrupt shared by all channels | ||||||
|  | -- #dma-cells: must be <2>.  First cell denotes the channel number.  Second cell | ||||||
|  | -  denotes CRCI (client rate control interface) flow control assignment. | ||||||
|  | +- #dma-cells: must be <1>.  First cell denotes the channel number. | ||||||
|  |  - clocks: Should contain the core clock and interface clock. | ||||||
|  |  - clock-names: Must contain "core" for the core clock and "iface" for the | ||||||
|  |    interface clock. | ||||||
|  | @@ -22,7 +21,7 @@ Example: | ||||||
|  |  			compatible = "qcom,adm"; | ||||||
|  |  			reg = <0x18300000 0x100000>; | ||||||
|  |  			interrupts = <0 170 0>; | ||||||
|  | -			#dma-cells = <2>; | ||||||
|  | +			#dma-cells = <1>; | ||||||
|  |   | ||||||
|  |  			clocks = <&gcc ADM0_CLK>, <&gcc ADM0_PBUS_CLK>; | ||||||
|  |  			clock-names = "core", "iface"; | ||||||
|  | @@ -35,15 +34,12 @@ Example: | ||||||
|  |  			qcom,ee = <0>; | ||||||
|  |  		}; | ||||||
|  |   | ||||||
|  | -DMA clients must use the format descripted in the dma.txt file, using a three | ||||||
|  | +DMA clients must use the format descripted in the dma.txt file, using a two | ||||||
|  |  cell specifier for each channel. | ||||||
|  |   | ||||||
|  | -Each dmas request consists of 3 cells: | ||||||
|  | +Each dmas request consists of two cells: | ||||||
|  |   1. phandle pointing to the DMA controller | ||||||
|  |   2. channel number | ||||||
|  | - 3. CRCI assignment, if applicable.  If no CRCI flow control is required, use 0. | ||||||
|  | -    The CRCI is used for flow control.  It identifies the peripheral device that | ||||||
|  | -    is the source/destination for the transferred data. | ||||||
|  |   | ||||||
|  |  Example: | ||||||
|  |   | ||||||
|  | @@ -55,7 +51,7 @@ Example: | ||||||
|  |   | ||||||
|  |  		cs-gpios = <&qcom_pinmux 20 0>; | ||||||
|  |   | ||||||
|  | -		dmas = <&adm_dma 6 9>, | ||||||
|  | -			<&adm_dma 5 10>; | ||||||
|  | +		dmas = <&adm_dma 6>, | ||||||
|  | +			<&adm_dma 5>; | ||||||
|  |  		dma-names = "rx", "tx"; | ||||||
|  |  	}; | ||||||
| @@ -0,0 +1,966 @@ | |||||||
|  | From 563fa24db4e529c5a3311928d73a8a90531ee527 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Thomas Pedersen <twp@codeaurora.org> | ||||||
|  | Date: Mon, 16 May 2016 17:58:51 -0700 | ||||||
|  | Subject: [PATCH 02/69] dmaengine: Add ADM driver | ||||||
|  |  | ||||||
|  | Original patch by Andy Gross. | ||||||
|  |  | ||||||
|  | Add the DMA engine driver for the QCOM Application Data Mover (ADM) DMA | ||||||
|  | controller found in the MSM8x60 and IPQ/APQ8064 platforms. | ||||||
|  |  | ||||||
|  | The ADM supports both memory to memory transactions and memory | ||||||
|  | to/from peripheral device transactions.  The controller also provides flow | ||||||
|  | control capabilities for transactions to/from peripheral devices. | ||||||
|  |  | ||||||
|  | The initial release of this driver supports slave transfers to/from peripherals | ||||||
|  | and also incorporates CRCI (client rate control interface) flow control. | ||||||
|  |  | ||||||
|  | Signed-off-by: Andy Gross <agross@codeaurora.org> | ||||||
|  | Signed-off-by: Thomas Pedersen <twp@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/dma/qcom/Kconfig    |  10 + | ||||||
|  |  drivers/dma/qcom/Makefile   |   1 + | ||||||
|  |  drivers/dma/qcom/qcom_adm.c | 900 ++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 911 insertions(+) | ||||||
|  |  create mode 100644 drivers/dma/qcom/qcom_adm.c | ||||||
|  |  | ||||||
|  | --- a/drivers/dma/qcom/Kconfig | ||||||
|  | +++ b/drivers/dma/qcom/Kconfig | ||||||
|  | @@ -27,3 +27,13 @@ config QCOM_HIDMA | ||||||
|  |  	  (user to kernel, kernel to kernel, etc.).  It only supports | ||||||
|  |  	  memcpy interface. The core is not intended for general | ||||||
|  |  	  purpose slave DMA. | ||||||
|  | + | ||||||
|  | +config QCOM_ADM | ||||||
|  | +	tristate "Qualcomm ADM support" | ||||||
|  | +	depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM) | ||||||
|  | +	select DMA_ENGINE | ||||||
|  | +	select DMA_VIRTUAL_CHANNELS | ||||||
|  | +	---help--- | ||||||
|  | +	  Enable support for the Qualcomm ADM DMA controller.  This controller | ||||||
|  | +	  provides DMA capabilities for both general purpose and on-chip | ||||||
|  | +	  peripheral devices. | ||||||
|  | --- a/drivers/dma/qcom/Makefile | ||||||
|  | +++ b/drivers/dma/qcom/Makefile | ||||||
|  | @@ -4,3 +4,4 @@ obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mg | ||||||
|  |  hdma_mgmt-objs	 := hidma_mgmt.o hidma_mgmt_sys.o | ||||||
|  |  obj-$(CONFIG_QCOM_HIDMA) +=  hdma.o | ||||||
|  |  hdma-objs        := hidma_ll.o hidma.o hidma_dbg.o | ||||||
|  | +obj-$(CONFIG_QCOM_ADM) += qcom_adm.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/dma/qcom/qcom_adm.c | ||||||
|  | @@ -0,0 +1,914 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/interrupt.h> | ||||||
|  | +#include <linux/dma-mapping.h> | ||||||
|  | +#include <linux/scatterlist.h> | ||||||
|  | +#include <linux/device.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/of_address.h> | ||||||
|  | +#include <linux/of_irq.h> | ||||||
|  | +#include <linux/of_dma.h> | ||||||
|  | +#include <linux/reset.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/dmaengine.h> | ||||||
|  | + | ||||||
|  | +#include "../dmaengine.h" | ||||||
|  | +#include "../virt-dma.h" | ||||||
|  | + | ||||||
|  | +/* ADM registers - calculated from channel number and security domain */ | ||||||
|  | +#define ADM_CHAN_MULTI			0x4 | ||||||
|  | +#define ADM_CI_MULTI			0x4 | ||||||
|  | +#define ADM_CRCI_MULTI			0x4 | ||||||
|  | +#define ADM_EE_MULTI			0x800 | ||||||
|  | +#define ADM_CHAN_OFFS(chan)		(ADM_CHAN_MULTI * chan) | ||||||
|  | +#define ADM_EE_OFFS(ee)			(ADM_EE_MULTI * ee) | ||||||
|  | +#define ADM_CHAN_EE_OFFS(chan, ee)	(ADM_CHAN_OFFS(chan) + ADM_EE_OFFS(ee)) | ||||||
|  | +#define ADM_CHAN_OFFS(chan)		(ADM_CHAN_MULTI * chan) | ||||||
|  | +#define ADM_CI_OFFS(ci)			(ADM_CHAN_OFF(ci)) | ||||||
|  | +#define ADM_CH_CMD_PTR(chan, ee)	(ADM_CHAN_EE_OFFS(chan, ee)) | ||||||
|  | +#define ADM_CH_RSLT(chan, ee)		(0x40 + ADM_CHAN_EE_OFFS(chan, ee)) | ||||||
|  | +#define ADM_CH_FLUSH_STATE0(chan, ee)	(0x80 + ADM_CHAN_EE_OFFS(chan, ee)) | ||||||
|  | +#define ADM_CH_STATUS_SD(chan, ee)	(0x200 + ADM_CHAN_EE_OFFS(chan, ee)) | ||||||
|  | +#define ADM_CH_CONF(chan)		(0x240 + ADM_CHAN_OFFS(chan)) | ||||||
|  | +#define ADM_CH_RSLT_CONF(chan, ee)	(0x300 + ADM_CHAN_EE_OFFS(chan, ee)) | ||||||
|  | +#define ADM_SEC_DOMAIN_IRQ_STATUS(ee)	(0x380 + ADM_EE_OFFS(ee)) | ||||||
|  | +#define ADM_CI_CONF(ci)			(0x390 + ci * ADM_CI_MULTI) | ||||||
|  | +#define ADM_GP_CTL			0x3d8 | ||||||
|  | +#define ADM_CRCI_CTL(crci, ee)		(0x400 + crci * ADM_CRCI_MULTI + \ | ||||||
|  | +						ADM_EE_OFFS(ee)) | ||||||
|  | + | ||||||
|  | +/* channel status */ | ||||||
|  | +#define ADM_CH_STATUS_VALID	BIT(1) | ||||||
|  | + | ||||||
|  | +/* channel result */ | ||||||
|  | +#define ADM_CH_RSLT_VALID	BIT(31) | ||||||
|  | +#define ADM_CH_RSLT_ERR		BIT(3) | ||||||
|  | +#define ADM_CH_RSLT_FLUSH	BIT(2) | ||||||
|  | +#define ADM_CH_RSLT_TPD		BIT(1) | ||||||
|  | + | ||||||
|  | +/* channel conf */ | ||||||
|  | +#define ADM_CH_CONF_SHADOW_EN		BIT(12) | ||||||
|  | +#define ADM_CH_CONF_MPU_DISABLE		BIT(11) | ||||||
|  | +#define ADM_CH_CONF_PERM_MPU_CONF	BIT(9) | ||||||
|  | +#define ADM_CH_CONF_FORCE_RSLT_EN	BIT(7) | ||||||
|  | +#define ADM_CH_CONF_SEC_DOMAIN(ee)	(((ee & 0x3) << 4) | ((ee & 0x4) << 11)) | ||||||
|  | + | ||||||
|  | +/* channel result conf */ | ||||||
|  | +#define ADM_CH_RSLT_CONF_FLUSH_EN	BIT(1) | ||||||
|  | +#define ADM_CH_RSLT_CONF_IRQ_EN		BIT(0) | ||||||
|  | + | ||||||
|  | +/* CRCI CTL */ | ||||||
|  | +#define ADM_CRCI_CTL_MUX_SEL	BIT(18) | ||||||
|  | +#define ADM_CRCI_CTL_RST	BIT(17) | ||||||
|  | + | ||||||
|  | +/* CI configuration */ | ||||||
|  | +#define ADM_CI_RANGE_END(x)	(x << 24) | ||||||
|  | +#define ADM_CI_RANGE_START(x)	(x << 16) | ||||||
|  | +#define ADM_CI_BURST_4_WORDS	BIT(2) | ||||||
|  | +#define ADM_CI_BURST_8_WORDS	BIT(3) | ||||||
|  | + | ||||||
|  | +/* GP CTL */ | ||||||
|  | +#define ADM_GP_CTL_LP_EN	BIT(12) | ||||||
|  | +#define ADM_GP_CTL_LP_CNT(x)	(x << 8) | ||||||
|  | + | ||||||
|  | +/* Command pointer list entry */ | ||||||
|  | +#define ADM_CPLE_LP		BIT(31) | ||||||
|  | +#define ADM_CPLE_CMD_PTR_LIST	BIT(29) | ||||||
|  | + | ||||||
|  | +/* Command list entry */ | ||||||
|  | +#define ADM_CMD_LC		BIT(31) | ||||||
|  | +#define ADM_CMD_DST_CRCI(n)	(((n) & 0xf) << 7) | ||||||
|  | +#define ADM_CMD_SRC_CRCI(n)	(((n) & 0xf) << 3) | ||||||
|  | + | ||||||
|  | +#define ADM_CMD_TYPE_SINGLE	0x0 | ||||||
|  | +#define ADM_CMD_TYPE_BOX	0x3 | ||||||
|  | + | ||||||
|  | +#define ADM_CRCI_MUX_SEL	BIT(4) | ||||||
|  | +#define ADM_DESC_ALIGN		8 | ||||||
|  | +#define ADM_MAX_XFER		(SZ_64K-1) | ||||||
|  | +#define ADM_MAX_ROWS		(SZ_64K-1) | ||||||
|  | +#define ADM_MAX_CHANNELS	16 | ||||||
|  | + | ||||||
|  | +struct adm_desc_hw_box { | ||||||
|  | +	u32 cmd; | ||||||
|  | +	u32 src_addr; | ||||||
|  | +	u32 dst_addr; | ||||||
|  | +	u32 row_len; | ||||||
|  | +	u32 num_rows; | ||||||
|  | +	u32 row_offset; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct adm_desc_hw_single { | ||||||
|  | +	u32 cmd; | ||||||
|  | +	u32 src_addr; | ||||||
|  | +	u32 dst_addr; | ||||||
|  | +	u32 len; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct adm_async_desc { | ||||||
|  | +	struct virt_dma_desc vd; | ||||||
|  | +	struct adm_device *adev; | ||||||
|  | + | ||||||
|  | +	size_t length; | ||||||
|  | +	enum dma_transfer_direction dir; | ||||||
|  | +	dma_addr_t dma_addr; | ||||||
|  | +	size_t dma_len; | ||||||
|  | + | ||||||
|  | +	void *cpl; | ||||||
|  | +	dma_addr_t cp_addr; | ||||||
|  | +	u32 crci; | ||||||
|  | +	u32 mux; | ||||||
|  | +	u32 blk_size; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct adm_chan { | ||||||
|  | +	struct virt_dma_chan vc; | ||||||
|  | +	struct adm_device *adev; | ||||||
|  | + | ||||||
|  | +	/* parsed from DT */ | ||||||
|  | +	u32 id;			/* channel id */ | ||||||
|  | + | ||||||
|  | +	struct adm_async_desc *curr_txd; | ||||||
|  | +	struct dma_slave_config slave; | ||||||
|  | +	struct list_head node; | ||||||
|  | + | ||||||
|  | +	int error; | ||||||
|  | +	int initialized; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static inline struct adm_chan *to_adm_chan(struct dma_chan *common) | ||||||
|  | +{ | ||||||
|  | +	return container_of(common, struct adm_chan, vc.chan); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +struct adm_device { | ||||||
|  | +	void __iomem *regs; | ||||||
|  | +	struct device *dev; | ||||||
|  | +	struct dma_device common; | ||||||
|  | +	struct device_dma_parameters dma_parms; | ||||||
|  | +	struct adm_chan *channels; | ||||||
|  | + | ||||||
|  | +	u32 ee; | ||||||
|  | + | ||||||
|  | +	struct clk *core_clk; | ||||||
|  | +	struct clk *iface_clk; | ||||||
|  | + | ||||||
|  | +	struct reset_control *clk_reset; | ||||||
|  | +	struct reset_control *c0_reset; | ||||||
|  | +	struct reset_control *c1_reset; | ||||||
|  | +	struct reset_control *c2_reset; | ||||||
|  | +	int irq; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_free_chan - Frees dma resources associated with the specific channel | ||||||
|  | + * | ||||||
|  | + * Free all allocated descriptors associated with this channel | ||||||
|  | + * | ||||||
|  | + */ | ||||||
|  | +static void adm_free_chan(struct dma_chan *chan) | ||||||
|  | +{ | ||||||
|  | +	/* free all queued descriptors */ | ||||||
|  | +	vchan_free_chan_resources(to_virt_chan(chan)); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_get_blksize - Get block size from burst value | ||||||
|  | + * | ||||||
|  | + */ | ||||||
|  | +static int adm_get_blksize(unsigned int burst) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	switch (burst) { | ||||||
|  | +	case 16: | ||||||
|  | +	case 32: | ||||||
|  | +	case 64: | ||||||
|  | +	case 128: | ||||||
|  | +		ret = ffs(burst>>4) - 1; | ||||||
|  | +		break; | ||||||
|  | +	case 192: | ||||||
|  | +		ret = 4; | ||||||
|  | +		break; | ||||||
|  | +	case 256: | ||||||
|  | +		ret = 5; | ||||||
|  | +		break; | ||||||
|  | +	default: | ||||||
|  | +		ret = -EINVAL; | ||||||
|  | +		break; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_process_fc_descriptors - Process descriptors for flow controlled xfers | ||||||
|  | + * | ||||||
|  | + * @achan: ADM channel | ||||||
|  | + * @desc: Descriptor memory pointer | ||||||
|  | + * @sg: Scatterlist entry | ||||||
|  | + * @crci: CRCI value | ||||||
|  | + * @burst: Burst size of transaction | ||||||
|  | + * @direction: DMA transfer direction | ||||||
|  | + */ | ||||||
|  | +static void *adm_process_fc_descriptors(struct adm_chan *achan, | ||||||
|  | +	void *desc, struct scatterlist *sg, u32 crci, u32 burst, | ||||||
|  | +	enum dma_transfer_direction direction) | ||||||
|  | +{ | ||||||
|  | +	struct adm_desc_hw_box *box_desc = NULL; | ||||||
|  | +	struct adm_desc_hw_single *single_desc; | ||||||
|  | +	u32 remainder = sg_dma_len(sg); | ||||||
|  | +	u32 rows, row_offset, crci_cmd; | ||||||
|  | +	u32 mem_addr = sg_dma_address(sg); | ||||||
|  | +	u32 *incr_addr = &mem_addr; | ||||||
|  | +	u32 *src, *dst; | ||||||
|  | + | ||||||
|  | +	if (direction == DMA_DEV_TO_MEM) { | ||||||
|  | +		crci_cmd = ADM_CMD_SRC_CRCI(crci); | ||||||
|  | +		row_offset = burst; | ||||||
|  | +		src = &achan->slave.src_addr; | ||||||
|  | +		dst = &mem_addr; | ||||||
|  | +	} else { | ||||||
|  | +		crci_cmd = ADM_CMD_DST_CRCI(crci); | ||||||
|  | +		row_offset = burst << 16; | ||||||
|  | +		src = &mem_addr; | ||||||
|  | +		dst = &achan->slave.dst_addr; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	while (remainder >= burst) { | ||||||
|  | +		box_desc = desc; | ||||||
|  | +		box_desc->cmd = ADM_CMD_TYPE_BOX | crci_cmd; | ||||||
|  | +		box_desc->row_offset = row_offset; | ||||||
|  | +		box_desc->src_addr = *src; | ||||||
|  | +		box_desc->dst_addr = *dst; | ||||||
|  | + | ||||||
|  | +		rows = remainder / burst; | ||||||
|  | +		rows = min_t(u32, rows, ADM_MAX_ROWS); | ||||||
|  | +		box_desc->num_rows = rows << 16 | rows; | ||||||
|  | +		box_desc->row_len = burst << 16 | burst; | ||||||
|  | + | ||||||
|  | +		*incr_addr += burst * rows; | ||||||
|  | +		remainder -= burst * rows; | ||||||
|  | +		desc += sizeof(*box_desc); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* if leftover bytes, do one single descriptor */ | ||||||
|  | +	if (remainder) { | ||||||
|  | +		single_desc = desc; | ||||||
|  | +		single_desc->cmd = ADM_CMD_TYPE_SINGLE | crci_cmd; | ||||||
|  | +		single_desc->len = remainder; | ||||||
|  | +		single_desc->src_addr = *src; | ||||||
|  | +		single_desc->dst_addr = *dst; | ||||||
|  | +		desc += sizeof(*single_desc); | ||||||
|  | + | ||||||
|  | +		if (sg_is_last(sg)) | ||||||
|  | +			single_desc->cmd |= ADM_CMD_LC; | ||||||
|  | +	} else { | ||||||
|  | +		if (box_desc && sg_is_last(sg)) | ||||||
|  | +			box_desc->cmd |= ADM_CMD_LC; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return desc; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_process_non_fc_descriptors - Process descriptors for non-fc xfers | ||||||
|  | + * | ||||||
|  | + * @achan: ADM channel | ||||||
|  | + * @desc: Descriptor memory pointer | ||||||
|  | + * @sg: Scatterlist entry | ||||||
|  | + * @direction: DMA transfer direction | ||||||
|  | + */ | ||||||
|  | +static void *adm_process_non_fc_descriptors(struct adm_chan *achan, | ||||||
|  | +	void *desc, struct scatterlist *sg, | ||||||
|  | +	enum dma_transfer_direction direction) | ||||||
|  | +{ | ||||||
|  | +	struct adm_desc_hw_single *single_desc; | ||||||
|  | +	u32 remainder = sg_dma_len(sg); | ||||||
|  | +	u32 mem_addr = sg_dma_address(sg); | ||||||
|  | +	u32 *incr_addr = &mem_addr; | ||||||
|  | +	u32 *src, *dst; | ||||||
|  | + | ||||||
|  | +	if (direction == DMA_DEV_TO_MEM) { | ||||||
|  | +		src = &achan->slave.src_addr; | ||||||
|  | +		dst = &mem_addr; | ||||||
|  | +	} else { | ||||||
|  | +		src = &mem_addr; | ||||||
|  | +		dst = &achan->slave.dst_addr; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	do { | ||||||
|  | +		single_desc = desc; | ||||||
|  | +		single_desc->cmd = ADM_CMD_TYPE_SINGLE; | ||||||
|  | +		single_desc->src_addr = *src; | ||||||
|  | +		single_desc->dst_addr = *dst; | ||||||
|  | +		single_desc->len = (remainder > ADM_MAX_XFER) ? | ||||||
|  | +				ADM_MAX_XFER : remainder; | ||||||
|  | + | ||||||
|  | +		remainder -= single_desc->len; | ||||||
|  | +		*incr_addr += single_desc->len; | ||||||
|  | +		desc += sizeof(*single_desc); | ||||||
|  | +	} while (remainder); | ||||||
|  | + | ||||||
|  | +	/* set last command if this is the end of the whole transaction */ | ||||||
|  | +	if (sg_is_last(sg)) | ||||||
|  | +		single_desc->cmd |= ADM_CMD_LC; | ||||||
|  | + | ||||||
|  | +	return desc; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_prep_slave_sg - Prep slave sg transaction | ||||||
|  | + * | ||||||
|  | + * @chan: dma channel | ||||||
|  | + * @sgl: scatter gather list | ||||||
|  | + * @sg_len: length of sg | ||||||
|  | + * @direction: DMA transfer direction | ||||||
|  | + * @flags: DMA flags | ||||||
|  | + * @context: transfer context (unused) | ||||||
|  | + */ | ||||||
|  | +static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan, | ||||||
|  | +	struct scatterlist *sgl, unsigned int sg_len, | ||||||
|  | +	enum dma_transfer_direction direction, unsigned long flags, | ||||||
|  | +	void *context) | ||||||
|  | +{ | ||||||
|  | +	struct adm_chan *achan = to_adm_chan(chan); | ||||||
|  | +	struct adm_device *adev = achan->adev; | ||||||
|  | +	struct adm_async_desc *async_desc; | ||||||
|  | +	struct scatterlist *sg; | ||||||
|  | +	dma_addr_t cple_addr; | ||||||
|  | +	u32 i, burst; | ||||||
|  | +	u32 single_count = 0, box_count = 0, crci = 0; | ||||||
|  | +	void *desc; | ||||||
|  | +	u32 *cple; | ||||||
|  | +	int blk_size = 0; | ||||||
|  | + | ||||||
|  | +	if (!is_slave_direction(direction)) { | ||||||
|  | +		dev_err(adev->dev, "invalid dma direction\n"); | ||||||
|  | +		return NULL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * get burst value from slave configuration | ||||||
|  | +	 */ | ||||||
|  | +	burst = (direction == DMA_MEM_TO_DEV) ? | ||||||
|  | +		achan->slave.dst_maxburst : | ||||||
|  | +		achan->slave.src_maxburst; | ||||||
|  | + | ||||||
|  | +	/* if using flow control, validate burst and crci values */ | ||||||
|  | +	if (achan->slave.device_fc) { | ||||||
|  | + | ||||||
|  | +		blk_size = adm_get_blksize(burst); | ||||||
|  | +		if (blk_size < 0) { | ||||||
|  | +			dev_err(adev->dev, "invalid burst value: %d\n", | ||||||
|  | +				burst); | ||||||
|  | +			return ERR_PTR(-EINVAL); | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		crci = achan->slave.slave_id & 0xf; | ||||||
|  | +		if (!crci || achan->slave.slave_id > 0x1f) { | ||||||
|  | +			dev_err(adev->dev, "invalid crci value\n"); | ||||||
|  | +			return ERR_PTR(-EINVAL); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* iterate through sgs and compute allocation size of structures */ | ||||||
|  | +	for_each_sg(sgl, sg, sg_len, i) { | ||||||
|  | +		if (achan->slave.device_fc) { | ||||||
|  | +			box_count += DIV_ROUND_UP(sg_dma_len(sg) / burst, | ||||||
|  | +						  ADM_MAX_ROWS); | ||||||
|  | +			if (sg_dma_len(sg) % burst) | ||||||
|  | +				single_count++; | ||||||
|  | +		} else { | ||||||
|  | +			single_count += DIV_ROUND_UP(sg_dma_len(sg), | ||||||
|  | +						     ADM_MAX_XFER); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	async_desc = kzalloc(sizeof(*async_desc), GFP_ATOMIC); | ||||||
|  | +	if (!async_desc) | ||||||
|  | +		return ERR_PTR(-ENOMEM); | ||||||
|  | + | ||||||
|  | +	if (crci) | ||||||
|  | +		async_desc->mux = achan->slave.slave_id & ADM_CRCI_MUX_SEL ? | ||||||
|  | +					ADM_CRCI_CTL_MUX_SEL : 0; | ||||||
|  | +	async_desc->crci = crci; | ||||||
|  | +	async_desc->blk_size = blk_size; | ||||||
|  | +	async_desc->dma_len = single_count * sizeof(struct adm_desc_hw_single) + | ||||||
|  | +				box_count * sizeof(struct adm_desc_hw_box) + | ||||||
|  | +				sizeof(*cple) + 2 * ADM_DESC_ALIGN; | ||||||
|  | + | ||||||
|  | +	async_desc->cpl = kzalloc(async_desc->dma_len, GFP_ATOMIC); | ||||||
|  | +	if (!async_desc->cpl) | ||||||
|  | +		goto free; | ||||||
|  | + | ||||||
|  | +	async_desc->adev = adev; | ||||||
|  | + | ||||||
|  | +	/* both command list entry and descriptors must be 8 byte aligned */ | ||||||
|  | +	cple = PTR_ALIGN(async_desc->cpl, ADM_DESC_ALIGN); | ||||||
|  | +	desc = PTR_ALIGN(cple + 1, ADM_DESC_ALIGN); | ||||||
|  | + | ||||||
|  | +	for_each_sg(sgl, sg, sg_len, i) { | ||||||
|  | +		async_desc->length += sg_dma_len(sg); | ||||||
|  | + | ||||||
|  | +		if (achan->slave.device_fc) | ||||||
|  | +			desc = adm_process_fc_descriptors(achan, desc, sg, crci, | ||||||
|  | +							burst, direction); | ||||||
|  | +		else | ||||||
|  | +			desc = adm_process_non_fc_descriptors(achan, desc, sg, | ||||||
|  | +							   direction); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	async_desc->dma_addr = dma_map_single(adev->dev, async_desc->cpl, | ||||||
|  | +					      async_desc->dma_len, | ||||||
|  | +					      DMA_TO_DEVICE); | ||||||
|  | +	if (dma_mapping_error(adev->dev, async_desc->dma_addr)) | ||||||
|  | +		goto free; | ||||||
|  | + | ||||||
|  | +	cple_addr = async_desc->dma_addr + ((void *)cple - async_desc->cpl); | ||||||
|  | + | ||||||
|  | +	/* init cmd list */ | ||||||
|  | +	dma_sync_single_for_cpu(adev->dev, cple_addr, sizeof(*cple), | ||||||
|  | +				DMA_TO_DEVICE); | ||||||
|  | +	*cple = ADM_CPLE_LP; | ||||||
|  | +	*cple |= (async_desc->dma_addr + ADM_DESC_ALIGN) >> 3; | ||||||
|  | +	dma_sync_single_for_device(adev->dev, cple_addr, sizeof(*cple), | ||||||
|  | +				   DMA_TO_DEVICE); | ||||||
|  | + | ||||||
|  | +	return vchan_tx_prep(&achan->vc, &async_desc->vd, flags); | ||||||
|  | + | ||||||
|  | +free: | ||||||
|  | +	kfree(async_desc); | ||||||
|  | +	return ERR_PTR(-ENOMEM); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_terminate_all - terminate all transactions on a channel | ||||||
|  | + * @achan: adm dma channel | ||||||
|  | + * | ||||||
|  | + * Dequeues and frees all transactions, aborts current transaction | ||||||
|  | + * No callbacks are done | ||||||
|  | + * | ||||||
|  | + */ | ||||||
|  | +static int adm_terminate_all(struct dma_chan *chan) | ||||||
|  | +{ | ||||||
|  | +	struct adm_chan *achan = to_adm_chan(chan); | ||||||
|  | +	struct adm_device *adev = achan->adev; | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	LIST_HEAD(head); | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&achan->vc.lock, flags); | ||||||
|  | +	vchan_get_all_descriptors(&achan->vc, &head); | ||||||
|  | + | ||||||
|  | +	/* send flush command to terminate current transaction */ | ||||||
|  | +	writel_relaxed(0x0, | ||||||
|  | +		adev->regs + ADM_CH_FLUSH_STATE0(achan->id, adev->ee)); | ||||||
|  | + | ||||||
|  | +	spin_unlock_irqrestore(&achan->vc.lock, flags); | ||||||
|  | + | ||||||
|  | +	vchan_dma_desc_free_list(&achan->vc, &head); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int adm_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg) | ||||||
|  | +{ | ||||||
|  | +	struct adm_chan *achan = to_adm_chan(chan); | ||||||
|  | +	unsigned long flag; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&achan->vc.lock, flag); | ||||||
|  | +	memcpy(&achan->slave, cfg, sizeof(struct dma_slave_config)); | ||||||
|  | +	spin_unlock_irqrestore(&achan->vc.lock, flag); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_start_dma - start next transaction | ||||||
|  | + * @achan - ADM dma channel | ||||||
|  | + */ | ||||||
|  | +static void adm_start_dma(struct adm_chan *achan) | ||||||
|  | +{ | ||||||
|  | +	struct virt_dma_desc *vd = vchan_next_desc(&achan->vc); | ||||||
|  | +	struct adm_device *adev = achan->adev; | ||||||
|  | +	struct adm_async_desc *async_desc; | ||||||
|  | + | ||||||
|  | +	lockdep_assert_held(&achan->vc.lock); | ||||||
|  | + | ||||||
|  | +	if (!vd) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	list_del(&vd->node); | ||||||
|  | + | ||||||
|  | +	/* write next command list out to the CMD FIFO */ | ||||||
|  | +	async_desc = container_of(vd, struct adm_async_desc, vd); | ||||||
|  | +	achan->curr_txd = async_desc; | ||||||
|  | + | ||||||
|  | +	/* reset channel error */ | ||||||
|  | +	achan->error = 0; | ||||||
|  | + | ||||||
|  | +	if (!achan->initialized) { | ||||||
|  | +		/* enable interrupts */ | ||||||
|  | +		writel(ADM_CH_CONF_SHADOW_EN | | ||||||
|  | +		       ADM_CH_CONF_PERM_MPU_CONF | | ||||||
|  | +		       ADM_CH_CONF_MPU_DISABLE | | ||||||
|  | +		       ADM_CH_CONF_SEC_DOMAIN(adev->ee), | ||||||
|  | +		       adev->regs + ADM_CH_CONF(achan->id)); | ||||||
|  | + | ||||||
|  | +		writel(ADM_CH_RSLT_CONF_IRQ_EN | ADM_CH_RSLT_CONF_FLUSH_EN, | ||||||
|  | +			adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee)); | ||||||
|  | + | ||||||
|  | +		achan->initialized = 1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* set the crci block size if this transaction requires CRCI */ | ||||||
|  | +	if (async_desc->crci) { | ||||||
|  | +		writel(async_desc->mux | async_desc->blk_size, | ||||||
|  | +			adev->regs + ADM_CRCI_CTL(async_desc->crci, adev->ee)); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* make sure IRQ enable doesn't get reordered */ | ||||||
|  | +	wmb(); | ||||||
|  | + | ||||||
|  | +	/* write next command list out to the CMD FIFO */ | ||||||
|  | +	writel(ALIGN(async_desc->dma_addr, ADM_DESC_ALIGN) >> 3, | ||||||
|  | +		adev->regs + ADM_CH_CMD_PTR(achan->id, adev->ee)); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_dma_irq - irq handler for ADM controller | ||||||
|  | + * @irq: IRQ of interrupt | ||||||
|  | + * @data: callback data | ||||||
|  | + * | ||||||
|  | + * IRQ handler for the bam controller | ||||||
|  | + */ | ||||||
|  | +static irqreturn_t adm_dma_irq(int irq, void *data) | ||||||
|  | +{ | ||||||
|  | +	struct adm_device *adev = data; | ||||||
|  | +	u32 srcs, i; | ||||||
|  | +	struct adm_async_desc *async_desc; | ||||||
|  | +	unsigned long flags; | ||||||
|  | + | ||||||
|  | +	srcs = readl_relaxed(adev->regs + | ||||||
|  | +			ADM_SEC_DOMAIN_IRQ_STATUS(adev->ee)); | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < ADM_MAX_CHANNELS; i++) { | ||||||
|  | +		struct adm_chan *achan = &adev->channels[i]; | ||||||
|  | +		u32 status, result; | ||||||
|  | + | ||||||
|  | +		if (srcs & BIT(i)) { | ||||||
|  | +			status = readl_relaxed(adev->regs + | ||||||
|  | +				ADM_CH_STATUS_SD(i, adev->ee)); | ||||||
|  | + | ||||||
|  | +			/* if no result present, skip */ | ||||||
|  | +			if (!(status & ADM_CH_STATUS_VALID)) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			result = readl_relaxed(adev->regs + | ||||||
|  | +				ADM_CH_RSLT(i, adev->ee)); | ||||||
|  | + | ||||||
|  | +			/* no valid results, skip */ | ||||||
|  | +			if (!(result & ADM_CH_RSLT_VALID)) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			/* flag error if transaction was flushed or failed */ | ||||||
|  | +			if (result & (ADM_CH_RSLT_ERR | ADM_CH_RSLT_FLUSH)) | ||||||
|  | +				achan->error = 1; | ||||||
|  | + | ||||||
|  | +			spin_lock_irqsave(&achan->vc.lock, flags); | ||||||
|  | +			async_desc = achan->curr_txd; | ||||||
|  | + | ||||||
|  | +			achan->curr_txd = NULL; | ||||||
|  | + | ||||||
|  | +			if (async_desc) { | ||||||
|  | +				vchan_cookie_complete(&async_desc->vd); | ||||||
|  | + | ||||||
|  | +				/* kick off next DMA */ | ||||||
|  | +				adm_start_dma(achan); | ||||||
|  | +			} | ||||||
|  | + | ||||||
|  | +			spin_unlock_irqrestore(&achan->vc.lock, flags); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return IRQ_HANDLED; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_tx_status - returns status of transaction | ||||||
|  | + * @chan: dma channel | ||||||
|  | + * @cookie: transaction cookie | ||||||
|  | + * @txstate: DMA transaction state | ||||||
|  | + * | ||||||
|  | + * Return status of dma transaction | ||||||
|  | + */ | ||||||
|  | +static enum dma_status adm_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | ||||||
|  | +	struct dma_tx_state *txstate) | ||||||
|  | +{ | ||||||
|  | +	struct adm_chan *achan = to_adm_chan(chan); | ||||||
|  | +	struct virt_dma_desc *vd; | ||||||
|  | +	enum dma_status ret; | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	size_t residue = 0; | ||||||
|  | + | ||||||
|  | +	ret = dma_cookie_status(chan, cookie, txstate); | ||||||
|  | +	if (ret == DMA_COMPLETE || !txstate) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&achan->vc.lock, flags); | ||||||
|  | + | ||||||
|  | +	vd = vchan_find_desc(&achan->vc, cookie); | ||||||
|  | +	if (vd) | ||||||
|  | +		residue = container_of(vd, struct adm_async_desc, vd)->length; | ||||||
|  | + | ||||||
|  | +	spin_unlock_irqrestore(&achan->vc.lock, flags); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * residue is either the full length if it is in the issued list, or 0 | ||||||
|  | +	 * if it is in progress.  We have no reliable way of determining | ||||||
|  | +	 * anything inbetween | ||||||
|  | +	*/ | ||||||
|  | +	dma_set_residue(txstate, residue); | ||||||
|  | + | ||||||
|  | +	if (achan->error) | ||||||
|  | +		return DMA_ERROR; | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_issue_pending - starts pending transactions | ||||||
|  | + * @chan: dma channel | ||||||
|  | + * | ||||||
|  | + * Issues all pending transactions and starts DMA | ||||||
|  | + */ | ||||||
|  | +static void adm_issue_pending(struct dma_chan *chan) | ||||||
|  | +{ | ||||||
|  | +	struct adm_chan *achan = to_adm_chan(chan); | ||||||
|  | +	unsigned long flags; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&achan->vc.lock, flags); | ||||||
|  | + | ||||||
|  | +	if (vchan_issue_pending(&achan->vc) && !achan->curr_txd) | ||||||
|  | +		adm_start_dma(achan); | ||||||
|  | +	spin_unlock_irqrestore(&achan->vc.lock, flags); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * adm_dma_free_desc - free descriptor memory | ||||||
|  | + * @vd: virtual descriptor | ||||||
|  | + * | ||||||
|  | + */ | ||||||
|  | +static void adm_dma_free_desc(struct virt_dma_desc *vd) | ||||||
|  | +{ | ||||||
|  | +	struct adm_async_desc *async_desc = container_of(vd, | ||||||
|  | +			struct adm_async_desc, vd); | ||||||
|  | + | ||||||
|  | +	dma_unmap_single(async_desc->adev->dev, async_desc->dma_addr, | ||||||
|  | +			 async_desc->dma_len, DMA_TO_DEVICE); | ||||||
|  | +	kfree(async_desc->cpl); | ||||||
|  | +	kfree(async_desc); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan, | ||||||
|  | +	u32 index) | ||||||
|  | +{ | ||||||
|  | +	achan->id = index; | ||||||
|  | +	achan->adev = adev; | ||||||
|  | + | ||||||
|  | +	vchan_init(&achan->vc, &adev->common); | ||||||
|  | +	achan->vc.desc_free = adm_dma_free_desc; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int adm_dma_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct adm_device *adev; | ||||||
|  | +	struct resource *iores; | ||||||
|  | +	int ret; | ||||||
|  | +	u32 i; | ||||||
|  | + | ||||||
|  | +	adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); | ||||||
|  | +	if (!adev) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	adev->dev = &pdev->dev; | ||||||
|  | + | ||||||
|  | +	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | +	adev->regs = devm_ioremap_resource(&pdev->dev, iores); | ||||||
|  | +	if (IS_ERR(adev->regs)) | ||||||
|  | +		return PTR_ERR(adev->regs); | ||||||
|  | + | ||||||
|  | +	adev->irq = platform_get_irq(pdev, 0); | ||||||
|  | +	if (adev->irq < 0) | ||||||
|  | +		return adev->irq; | ||||||
|  | + | ||||||
|  | +	ret = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &adev->ee); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(adev->dev, "Execution environment unspecified\n"); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->core_clk = devm_clk_get(adev->dev, "core"); | ||||||
|  | +	if (IS_ERR(adev->core_clk)) | ||||||
|  | +		return PTR_ERR(adev->core_clk); | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(adev->core_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(adev->dev, "failed to prepare/enable core clock\n"); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->iface_clk = devm_clk_get(adev->dev, "iface"); | ||||||
|  | +	if (IS_ERR(adev->iface_clk)) { | ||||||
|  | +		ret = PTR_ERR(adev->iface_clk); | ||||||
|  | +		goto err_disable_core_clk; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(adev->iface_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(adev->dev, "failed to prepare/enable iface clock\n"); | ||||||
|  | +		goto err_disable_core_clk; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->clk_reset = devm_reset_control_get(&pdev->dev, "clk"); | ||||||
|  | +	if (IS_ERR(adev->clk_reset)) { | ||||||
|  | +		dev_err(adev->dev, "failed to get ADM0 reset\n"); | ||||||
|  | +		ret = PTR_ERR(adev->clk_reset); | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->c0_reset = devm_reset_control_get(&pdev->dev, "c0"); | ||||||
|  | +	if (IS_ERR(adev->c0_reset)) { | ||||||
|  | +		dev_err(adev->dev, "failed to get ADM0 C0 reset\n"); | ||||||
|  | +		ret = PTR_ERR(adev->c0_reset); | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->c1_reset = devm_reset_control_get(&pdev->dev, "c1"); | ||||||
|  | +	if (IS_ERR(adev->c1_reset)) { | ||||||
|  | +		dev_err(adev->dev, "failed to get ADM0 C1 reset\n"); | ||||||
|  | +		ret = PTR_ERR(adev->c1_reset); | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	adev->c2_reset = devm_reset_control_get(&pdev->dev, "c2"); | ||||||
|  | +	if (IS_ERR(adev->c2_reset)) { | ||||||
|  | +		dev_err(adev->dev, "failed to get ADM0 C2 reset\n"); | ||||||
|  | +		ret = PTR_ERR(adev->c2_reset); | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	reset_control_assert(adev->clk_reset); | ||||||
|  | +	reset_control_assert(adev->c0_reset); | ||||||
|  | +	reset_control_assert(adev->c1_reset); | ||||||
|  | +	reset_control_assert(adev->c2_reset); | ||||||
|  | + | ||||||
|  | +	reset_control_deassert(adev->clk_reset); | ||||||
|  | +	reset_control_deassert(adev->c0_reset); | ||||||
|  | +	reset_control_deassert(adev->c1_reset); | ||||||
|  | +	reset_control_deassert(adev->c2_reset); | ||||||
|  | + | ||||||
|  | +	adev->channels = devm_kcalloc(adev->dev, ADM_MAX_CHANNELS, | ||||||
|  | +				sizeof(*adev->channels), GFP_KERNEL); | ||||||
|  | + | ||||||
|  | +	if (!adev->channels) { | ||||||
|  | +		ret = -ENOMEM; | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* allocate and initialize channels */ | ||||||
|  | +	INIT_LIST_HEAD(&adev->common.channels); | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < ADM_MAX_CHANNELS; i++) | ||||||
|  | +		adm_channel_init(adev, &adev->channels[i], i); | ||||||
|  | + | ||||||
|  | +	/* reset CRCIs */ | ||||||
|  | +	for (i = 0; i < 16; i++) | ||||||
|  | +		writel(ADM_CRCI_CTL_RST, adev->regs + | ||||||
|  | +			ADM_CRCI_CTL(i, adev->ee)); | ||||||
|  | + | ||||||
|  | +	/* configure client interfaces */ | ||||||
|  | +	writel(ADM_CI_RANGE_START(0x40) | ADM_CI_RANGE_END(0xb0) | | ||||||
|  | +		ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(0)); | ||||||
|  | +	writel(ADM_CI_RANGE_START(0x2a) | ADM_CI_RANGE_END(0x2c) | | ||||||
|  | +		ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(1)); | ||||||
|  | +	writel(ADM_CI_RANGE_START(0x12) | ADM_CI_RANGE_END(0x28) | | ||||||
|  | +		ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(2)); | ||||||
|  | +	writel(ADM_GP_CTL_LP_EN | ADM_GP_CTL_LP_CNT(0xf), | ||||||
|  | +		adev->regs + ADM_GP_CTL); | ||||||
|  | + | ||||||
|  | +	ret = devm_request_irq(adev->dev, adev->irq, adm_dma_irq, | ||||||
|  | +			0, "adm_dma", adev); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | + | ||||||
|  | +	platform_set_drvdata(pdev, adev); | ||||||
|  | + | ||||||
|  | +	adev->common.dev = adev->dev; | ||||||
|  | +	adev->common.dev->dma_parms = &adev->dma_parms; | ||||||
|  | + | ||||||
|  | +	/* set capabilities */ | ||||||
|  | +	dma_cap_zero(adev->common.cap_mask); | ||||||
|  | +	dma_cap_set(DMA_SLAVE, adev->common.cap_mask); | ||||||
|  | +	dma_cap_set(DMA_PRIVATE, adev->common.cap_mask); | ||||||
|  | + | ||||||
|  | +	/* initialize dmaengine apis */ | ||||||
|  | +	adev->common.directions = BIT(DMA_DEV_TO_MEM | DMA_MEM_TO_DEV); | ||||||
|  | +	adev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; | ||||||
|  | +	adev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||||||
|  | +	adev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||||||
|  | +	adev->common.device_free_chan_resources = adm_free_chan; | ||||||
|  | +	adev->common.device_prep_slave_sg = adm_prep_slave_sg; | ||||||
|  | +	adev->common.device_issue_pending = adm_issue_pending; | ||||||
|  | +	adev->common.device_tx_status = adm_tx_status; | ||||||
|  | +	adev->common.device_terminate_all = adm_terminate_all; | ||||||
|  | +	adev->common.device_config = adm_slave_config; | ||||||
|  | + | ||||||
|  | +	ret = dma_async_device_register(&adev->common); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(adev->dev, "failed to register dma async device\n"); | ||||||
|  | +		goto err_disable_clks; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = of_dma_controller_register(pdev->dev.of_node, | ||||||
|  | +					 of_dma_xlate_by_chan_id, | ||||||
|  | +					 &adev->common); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_unregister_dma; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +err_unregister_dma: | ||||||
|  | +	dma_async_device_unregister(&adev->common); | ||||||
|  | +err_disable_clks: | ||||||
|  | +	clk_disable_unprepare(adev->iface_clk); | ||||||
|  | +err_disable_core_clk: | ||||||
|  | +	clk_disable_unprepare(adev->core_clk); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int adm_dma_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct adm_device *adev = platform_get_drvdata(pdev); | ||||||
|  | +	struct adm_chan *achan; | ||||||
|  | +	u32 i; | ||||||
|  | + | ||||||
|  | +	of_dma_controller_free(pdev->dev.of_node); | ||||||
|  | +	dma_async_device_unregister(&adev->common); | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < ADM_MAX_CHANNELS; i++) { | ||||||
|  | +		achan = &adev->channels[i]; | ||||||
|  | + | ||||||
|  | +		/* mask IRQs for this channel/EE pair */ | ||||||
|  | +		writel(0, adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee)); | ||||||
|  | + | ||||||
|  | +		adm_terminate_all(&adev->channels[i].vc.chan); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	devm_free_irq(adev->dev, adev->irq, adev); | ||||||
|  | + | ||||||
|  | +	clk_disable_unprepare(adev->core_clk); | ||||||
|  | +	clk_disable_unprepare(adev->iface_clk); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct of_device_id adm_of_match[] = { | ||||||
|  | +	{ .compatible = "qcom,adm", }, | ||||||
|  | +	{} | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, adm_of_match); | ||||||
|  | + | ||||||
|  | +static struct platform_driver adm_dma_driver = { | ||||||
|  | +	.probe = adm_dma_probe, | ||||||
|  | +	.remove = adm_dma_remove, | ||||||
|  | +	.driver = { | ||||||
|  | +		.name = "adm-dma-engine", | ||||||
|  | +		.of_match_table = adm_of_match, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +module_platform_driver(adm_dma_driver); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>"); | ||||||
|  | +MODULE_DESCRIPTION("QCOM ADM DMA engine driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | From 0c974b87829e007dc4fae94e20d488204e20e662 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 9 Mar 2017 08:16:10 +0100 | ||||||
|  | Subject: [PATCH 30/69] clk: Disable i2c device on gsbi4 | ||||||
|  |  | ||||||
|  | This patch was not annotated and comes from the v4.4 tree. | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/gcc-ipq806x.c | 5 +++-- | ||||||
|  |  1 file changed, 3 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | +++ b/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | @@ -294,7 +294,7 @@ static struct clk_rcg gsbi1_uart_src = { | ||||||
|  |  			.parent_names = gcc_pxo_pll8, | ||||||
|  |  			.num_parents = 2, | ||||||
|  |  			.ops = &clk_rcg_ops, | ||||||
|  | -			.flags = CLK_SET_PARENT_GATE, | ||||||
|  | +			.flags = CLK_SET_PARENT_GATE | CLK_IGNORE_UNUSED, | ||||||
|  |  		}, | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
|  | @@ -312,7 +312,7 @@ static struct clk_branch gsbi1_uart_clk | ||||||
|  |  			}, | ||||||
|  |  			.num_parents = 1, | ||||||
|  |  			.ops = &clk_branch_ops, | ||||||
|  | -			.flags = CLK_SET_RATE_PARENT, | ||||||
|  | +			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | ||||||
|  |  		}, | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
|  | @@ -890,6 +890,7 @@ static struct clk_branch gsbi1_h_clk = { | ||||||
|  |  		.hw.init = &(struct clk_init_data){ | ||||||
|  |  			.name = "gsbi1_h_clk", | ||||||
|  |  			.ops = &clk_branch_ops, | ||||||
|  | +			.flags = CLK_IGNORE_UNUSED, | ||||||
|  |  		}, | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
| @@ -0,0 +1,282 @@ | |||||||
|  | From d8eeb4de90e968ba32d956728c866f20752cf2c3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | Date: Thu, 9 Mar 2017 08:18:08 +0100 | ||||||
|  | Subject: [PATCH 31/69] mtd: add SMEM parser for QCOM platforms | ||||||
|  |  | ||||||
|  | On QCOM platforms using MTD devices storage (such as IPQ806x), SMEM is | ||||||
|  | used to store partition layout. This new parser can now be used to read | ||||||
|  | SMEM and use it to register an MTD layout according to its content. | ||||||
|  |  | ||||||
|  | Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/Kconfig          |   7 ++ | ||||||
|  |  drivers/mtd/Makefile         |   1 + | ||||||
|  |  drivers/mtd/qcom_smem_part.c | 228 +++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 236 insertions(+) | ||||||
|  |  create mode 100644 drivers/mtd/qcom_smem_part.c | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/Kconfig | ||||||
|  | +++ b/drivers/mtd/Kconfig | ||||||
|  | @@ -194,6 +194,13 @@ config MTD_MYLOADER_PARTS | ||||||
|  |  	  You will still need the parsing functions to be called by the driver | ||||||
|  |  	  for your particular device. It won't happen automatically. | ||||||
|  |   | ||||||
|  | +config MTD_QCOM_SMEM_PARTS | ||||||
|  | +	tristate "QCOM SMEM partitioning support" | ||||||
|  | +	depends on QCOM_SMEM | ||||||
|  | +	help | ||||||
|  | +	  This provides partitions parser for QCOM devices using SMEM | ||||||
|  | +	  such as IPQ806x. | ||||||
|  | + | ||||||
|  |  comment "User Modules And Translation Layers" | ||||||
|  |   | ||||||
|  |  # | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/mtd/qcom_smem_part.c | ||||||
|  | @@ -0,0 +1,235 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2015, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/device.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | + | ||||||
|  | +#include <linux/mtd/mtd.h> | ||||||
|  | +#include <linux/mtd/partitions.h> | ||||||
|  | +#include <linux/spi/spi.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | + | ||||||
|  | +#include <linux/soc/qcom/smem.h> | ||||||
|  | + | ||||||
|  | +/* Processor/host identifier for the application processor */ | ||||||
|  | +#define SMEM_HOST_APPS			0 | ||||||
|  | + | ||||||
|  | +/* SMEM items index */ | ||||||
|  | +#define SMEM_AARM_PARTITION_TABLE	9 | ||||||
|  | +#define SMEM_BOOT_FLASH_TYPE		421 | ||||||
|  | +#define SMEM_BOOT_FLASH_BLOCK_SIZE	424 | ||||||
|  | + | ||||||
|  | +/* SMEM Flash types */ | ||||||
|  | +#define SMEM_FLASH_NAND			2 | ||||||
|  | +#define SMEM_FLASH_SPI			6 | ||||||
|  | + | ||||||
|  | +#define SMEM_PART_NAME_SZ		16 | ||||||
|  | +#define SMEM_PARTS_MAX			32 | ||||||
|  | + | ||||||
|  | +struct smem_partition { | ||||||
|  | +	char name[SMEM_PART_NAME_SZ]; | ||||||
|  | +	__le32 start; | ||||||
|  | +	__le32 size; | ||||||
|  | +	__le32 attr; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct smem_partition_table { | ||||||
|  | +	u8 magic[8]; | ||||||
|  | +	__le32 version; | ||||||
|  | +	__le32 len; | ||||||
|  | +	struct smem_partition parts[SMEM_PARTS_MAX]; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* SMEM Magic values in partition table */ | ||||||
|  | +static const u8 SMEM_PTABLE_MAGIC[] = { | ||||||
|  | +	0xaa, 0x73, 0xee, 0x55, | ||||||
|  | +	0xdb, 0xbd, 0x5e, 0xe3, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int qcom_smem_get_flash_blksz(u64 **smem_blksz) | ||||||
|  | +{ | ||||||
|  | +	size_t size; | ||||||
|  | + | ||||||
|  | +	*smem_blksz = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_BLOCK_SIZE, | ||||||
|  | +			    	    &size); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(*smem_blksz)) { | ||||||
|  | +		pr_err("Unable to read flash blksz from SMEM\n"); | ||||||
|  | +		return -ENOENT; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (size != sizeof(**smem_blksz)) { | ||||||
|  | +		pr_err("Invalid flash blksz size in SMEM\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_smem_get_flash_type(u64 **smem_flash_type) | ||||||
|  | +{ | ||||||
|  | +	size_t size; | ||||||
|  | + | ||||||
|  | +	*smem_flash_type = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_TYPE, | ||||||
|  | +			    		&size); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(*smem_flash_type)) { | ||||||
|  | +		pr_err("Unable to read flash type from SMEM\n"); | ||||||
|  | +		return -ENOENT; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (size != sizeof(**smem_flash_type)) { | ||||||
|  | +		pr_err("Invalid flash type size in SMEM\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_smem_get_flash_partitions(struct smem_partition_table **pparts) | ||||||
|  | +{ | ||||||
|  | +	size_t size; | ||||||
|  | + | ||||||
|  | +	*pparts = qcom_smem_get(SMEM_HOST_APPS, SMEM_AARM_PARTITION_TABLE, | ||||||
|  | +				&size); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(*pparts)) { | ||||||
|  | +		pr_err("Unable to read partition table from SMEM\n"); | ||||||
|  | +		return -ENOENT; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int of_dev_node_match(struct device *dev, void *data) | ||||||
|  | +{ | ||||||
|  | +	return dev->of_node == data; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static bool is_spi_device(struct device_node *np) | ||||||
|  | +{ | ||||||
|  | +	struct device *dev; | ||||||
|  | + | ||||||
|  | +	dev = bus_find_device(&spi_bus_type, NULL, np, of_dev_node_match); | ||||||
|  | +	if (!dev) | ||||||
|  | +		return false; | ||||||
|  | + | ||||||
|  | +	put_device(dev); | ||||||
|  | +	return true; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int parse_qcom_smem_partitions(struct mtd_info *master, | ||||||
|  | +				      const struct mtd_partition **pparts, | ||||||
|  | +				      struct mtd_part_parser_data *data) | ||||||
|  | +{ | ||||||
|  | +	struct smem_partition_table *smem_parts; | ||||||
|  | +	u64 *smem_flash_type, *smem_blksz; | ||||||
|  | +	struct mtd_partition *mtd_parts; | ||||||
|  | +	struct device_node *of_node = master->dev.of_node; | ||||||
|  | +	int i, ret; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * SMEM will only store the partition table of the boot device. | ||||||
|  | +	 * If this is not the boot device, do not return any partition. | ||||||
|  | +	 */ | ||||||
|  | +	ret = qcom_smem_get_flash_type(&smem_flash_type); | ||||||
|  | +	if (ret < 0) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	if ((*smem_flash_type == SMEM_FLASH_NAND && !mtd_type_is_nand(master)) | ||||||
|  | +	    || (*smem_flash_type == SMEM_FLASH_SPI && !is_spi_device(of_node))) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Just for sanity purpose, make sure the block size in SMEM matches the | ||||||
|  | +	 * block size of the MTD device | ||||||
|  | +	 */ | ||||||
|  | +	ret = qcom_smem_get_flash_blksz(&smem_blksz); | ||||||
|  | +	if (ret < 0) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	if (*smem_blksz != master->erasesize) { | ||||||
|  | +		pr_err("SMEM block size differs from MTD block size\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Get partition pointer from SMEM */ | ||||||
|  | +	ret = qcom_smem_get_flash_partitions(&smem_parts); | ||||||
|  | +	if (ret < 0) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	if (memcmp(SMEM_PTABLE_MAGIC, smem_parts->magic, | ||||||
|  | +		   sizeof(SMEM_PTABLE_MAGIC))) { | ||||||
|  | +		pr_err("SMEM partition magic invalid\n"); | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Allocate and populate the mtd structures */ | ||||||
|  | +	mtd_parts = kcalloc(le32_to_cpu(smem_parts->len), sizeof(*mtd_parts), | ||||||
|  | +			    GFP_KERNEL); | ||||||
|  | +	if (!mtd_parts) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < smem_parts->len; i++) { | ||||||
|  | +		struct smem_partition *s_part = &smem_parts->parts[i]; | ||||||
|  | +		struct mtd_partition *m_part = &mtd_parts[i]; | ||||||
|  | + | ||||||
|  | +		m_part->name = s_part->name; | ||||||
|  | +		m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz); | ||||||
|  | +		m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz); | ||||||
|  | + | ||||||
|  | +		/* | ||||||
|  | +		 * The last SMEM partition may have its size marked as | ||||||
|  | +		 * something like 0xffffffff, which means "until the end of the | ||||||
|  | +		 * flash device". In this case, truncate it. | ||||||
|  | +		 */ | ||||||
|  | +		if (m_part->offset + m_part->size > master->size) | ||||||
|  | +			m_part->size = master->size - m_part->offset; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	*pparts = mtd_parts; | ||||||
|  | + | ||||||
|  | +	return smem_parts->len; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct of_device_id qcom_smem_of_match_table[] = { | ||||||
|  | +	{ .compatible = "qcom,smem" }, | ||||||
|  | +	{}, | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, qcom_smem_of_match_table); | ||||||
|  | + | ||||||
|  | +static struct mtd_part_parser qcom_smem_parser = { | ||||||
|  | +	.owner = THIS_MODULE, | ||||||
|  | +	.parse_fn = parse_qcom_smem_partitions, | ||||||
|  | +	.name = "qcom-smem", | ||||||
|  | +	.of_match_table = qcom_smem_of_match_table, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int __init qcom_smem_parser_init(void) | ||||||
|  | +{ | ||||||
|  | +	register_mtd_parser(&qcom_smem_parser); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void __exit qcom_smem_parser_exit(void) | ||||||
|  | +{ | ||||||
|  | +	deregister_mtd_parser(&qcom_smem_parser); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +module_init(qcom_smem_parser_init); | ||||||
|  | +module_exit(qcom_smem_parser_exit); | ||||||
|  | + | ||||||
|  | +MODULE_LICENSE("GPL"); | ||||||
|  | +MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>"); | ||||||
|  | +MODULE_DESCRIPTION("Parsing code for SMEM based partition tables"); | ||||||
|  | --- a/drivers/mtd/Makefile | ||||||
|  | +++ b/drivers/mtd/Makefile | ||||||
|  | @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o | ||||||
|  |  obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o | ||||||
|  |  obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o | ||||||
|  |  obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o | ||||||
|  | +obj-$(CONFIG_MTD_QCOM_SMEM_PARTS) += qcom_smem_part.o | ||||||
|  |  obj-y				+= parsers/ | ||||||
|  |   | ||||||
|  |  # 'Users' - code which presents functionality to userspace. | ||||||
| @@ -0,0 +1,616 @@ | |||||||
|  | From b9004f4fd23e4c614d71c972f3a9311665480e29 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Andy Gross <agross@codeaurora.org> | ||||||
|  | Date: Thu, 9 Mar 2017 08:19:18 +0100 | ||||||
|  | Subject: [PATCH 32/69] phy: add qcom dwc3 phy | ||||||
|  |  | ||||||
|  | Signed-off-by: Andy Gross <agross@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/phy/Kconfig         |  12 + | ||||||
|  |  drivers/phy/Makefile        |   1 + | ||||||
|  |  drivers/phy/phy-qcom-dwc3.c | 575 ++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 588 insertions(+) | ||||||
|  |  create mode 100644 drivers/phy/phy-qcom-dwc3.c | ||||||
|  |  | ||||||
|  | --- a/drivers/phy/qualcomm/Kconfig | ||||||
|  | +++ b/drivers/phy/qualcomm/Kconfig | ||||||
|  | @@ -56,3 +56,15 @@ config PHY_QCOM_USB_HSIC | ||||||
|  |  	select GENERIC_PHY | ||||||
|  |  	help | ||||||
|  |  	  Support for the USB HSIC ULPI compliant PHY on QCOM chipsets. | ||||||
|  | + | ||||||
|  | +config PHY_QCOM_DWC3 | ||||||
|  | +	tristate "QCOM DWC3 USB PHY support" | ||||||
|  | +	depends on ARCH_QCOM | ||||||
|  | +	depends on HAS_IOMEM | ||||||
|  | +	depends on OF | ||||||
|  | +	select GENERIC_PHY | ||||||
|  | +	help | ||||||
|  | +	  This option enables support for the Synopsis PHYs present inside the | ||||||
|  | +	  Qualcomm USB3.0 DWC3 controller.  This driver supports both HS and SS | ||||||
|  | +	  PHY controllers. | ||||||
|  | + | ||||||
|  | --- a/drivers/phy/qualcomm/Makefile | ||||||
|  | +++ b/drivers/phy/qualcomm/Makefile | ||||||
|  | @@ -8,3 +8,4 @@ obj-$(CONFIG_PHY_QCOM_UFS)		+= phy-qcom- | ||||||
|  |  obj-$(CONFIG_PHY_QCOM_UFS)		+= phy-qcom-ufs-qmp-20nm.o | ||||||
|  |  obj-$(CONFIG_PHY_QCOM_USB_HS) 		+= phy-qcom-usb-hs.o | ||||||
|  |  obj-$(CONFIG_PHY_QCOM_USB_HSIC) 	+= phy-qcom-usb-hsic.o | ||||||
|  | +obj-$(CONFIG_PHY_QCOM_DWC3)		+= phy-qcom-dwc3.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/phy/qualcomm/phy-qcom-dwc3.c | ||||||
|  | @@ -0,0 +1,575 @@ | ||||||
|  | +/* Copyright (c) 2014-2015, Code Aurora Forum. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | +* 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/err.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/phy/phy.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + *  USB QSCRATCH Hardware registers | ||||||
|  | + */ | ||||||
|  | +#define QSCRATCH_GENERAL_CFG		(0x08) | ||||||
|  | +#define HSUSB_PHY_CTRL_REG		(0x10) | ||||||
|  | + | ||||||
|  | +/* PHY_CTRL_REG */ | ||||||
|  | +#define HSUSB_CTRL_DMSEHV_CLAMP			BIT(24) | ||||||
|  | +#define HSUSB_CTRL_USB2_SUSPEND			BIT(23) | ||||||
|  | +#define HSUSB_CTRL_UTMI_CLK_EN			BIT(21) | ||||||
|  | +#define HSUSB_CTRL_UTMI_OTG_VBUS_VALID		BIT(20) | ||||||
|  | +#define HSUSB_CTRL_USE_CLKCORE			BIT(18) | ||||||
|  | +#define HSUSB_CTRL_DPSEHV_CLAMP			BIT(17) | ||||||
|  | +#define HSUSB_CTRL_COMMONONN			BIT(11) | ||||||
|  | +#define HSUSB_CTRL_ID_HV_CLAMP			BIT(9) | ||||||
|  | +#define HSUSB_CTRL_OTGSESSVLD_CLAMP		BIT(8) | ||||||
|  | +#define HSUSB_CTRL_CLAMP_EN			BIT(7) | ||||||
|  | +#define HSUSB_CTRL_RETENABLEN			BIT(1) | ||||||
|  | +#define HSUSB_CTRL_POR				BIT(0) | ||||||
|  | + | ||||||
|  | +/* QSCRATCH_GENERAL_CFG */ | ||||||
|  | +#define HSUSB_GCFG_XHCI_REV		BIT(2) | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + *  USB QSCRATCH Hardware registers | ||||||
|  | + */ | ||||||
|  | +#define SSUSB_PHY_CTRL_REG		(0x00) | ||||||
|  | +#define SSUSB_PHY_PARAM_CTRL_1		(0x04) | ||||||
|  | +#define SSUSB_PHY_PARAM_CTRL_2		(0x08) | ||||||
|  | +#define CR_PROTOCOL_DATA_IN_REG		(0x0c) | ||||||
|  | +#define CR_PROTOCOL_DATA_OUT_REG	(0x10) | ||||||
|  | +#define CR_PROTOCOL_CAP_ADDR_REG	(0x14) | ||||||
|  | +#define CR_PROTOCOL_CAP_DATA_REG	(0x18) | ||||||
|  | +#define CR_PROTOCOL_READ_REG		(0x1c) | ||||||
|  | +#define CR_PROTOCOL_WRITE_REG		(0x20) | ||||||
|  | + | ||||||
|  | +/* PHY_CTRL_REG */ | ||||||
|  | +#define SSUSB_CTRL_REF_USE_PAD		BIT(28) | ||||||
|  | +#define SSUSB_CTRL_TEST_POWERDOWN	BIT(27) | ||||||
|  | +#define SSUSB_CTRL_LANE0_PWR_PRESENT	BIT(24) | ||||||
|  | +#define SSUSB_CTRL_SS_PHY_EN		BIT(8) | ||||||
|  | +#define SSUSB_CTRL_SS_PHY_RESET		BIT(7) | ||||||
|  | + | ||||||
|  | +/* SSPHY control registers */ | ||||||
|  | +#define SSPHY_CTRL_RX_OVRD_IN_HI(lane)	(0x1006 + 0x100 * lane) | ||||||
|  | +#define SSPHY_CTRL_TX_OVRD_DRV_LO(lane)	(0x1002 + 0x100 * lane) | ||||||
|  | + | ||||||
|  | +/* SSPHY SoC version specific values */ | ||||||
|  | +#define SSPHY_RX_EQ_VALUE		4	/* Override value for rx_eq */ | ||||||
|  | +#define SSPHY_TX_DEEMPH_3_5DB		23	/* Override value for transmit | ||||||
|  | +						   preemphasis */ | ||||||
|  | +#define SSPHY_MPLL_VALUE		0	/* Override value for mpll */ | ||||||
|  | + | ||||||
|  | +/* QSCRATCH PHY_PARAM_CTRL1 fields */ | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_FULL_SWING_MASK	0x07f00000u | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK	0x000fc000u | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK	0x00003f00u | ||||||
|  | +#define PHY_PARAM_CTRL1_LOS_BIAS_MASK		0x000000f8u | ||||||
|  | + | ||||||
|  | +#define PHY_PARAM_CTRL1_MASK				\ | ||||||
|  | +		(PHY_PARAM_CTRL1_TX_FULL_SWING_MASK |	\ | ||||||
|  | +		 PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK |	\ | ||||||
|  | +		 PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK |	\ | ||||||
|  | +		 PHY_PARAM_CTRL1_LOS_BIAS_MASK) | ||||||
|  | + | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_FULL_SWING(x)	\ | ||||||
|  | +		(((x) << 20) & PHY_PARAM_CTRL1_TX_FULL_SWING_MASK) | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB(x)	\ | ||||||
|  | +		(((x) << 14) & PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK) | ||||||
|  | +#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(x)	\ | ||||||
|  | +		(((x) <<  8) & PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK) | ||||||
|  | +#define PHY_PARAM_CTRL1_LOS_BIAS(x)	\ | ||||||
|  | +		(((x) <<  3) & PHY_PARAM_CTRL1_LOS_BIAS_MASK) | ||||||
|  | + | ||||||
|  | +/* RX OVRD IN HI bits */ | ||||||
|  | +#define RX_OVRD_IN_HI_RX_RESET_OVRD		BIT(13) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_RX_RESET		BIT(12) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_EQ_OVRD		BIT(11) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_EQ_MASK		0x0700 | ||||||
|  | +#define RX_OVRD_IN_HI_RX_EQ_SHIFT		8 | ||||||
|  | +#define RX_OVRD_IN_HI_RX_EQ_EN_OVRD		BIT(7) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_EQ_EN			BIT(6) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_LOS_FILTER_OVRD	BIT(5) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_LOS_FILTER_MASK	0x0018 | ||||||
|  | +#define RX_OVRD_IN_HI_RX_RATE_OVRD		BIT(2) | ||||||
|  | +#define RX_OVRD_IN_HI_RX_RATE_MASK		0x0003 | ||||||
|  | + | ||||||
|  | +/* TX OVRD DRV LO register bits */ | ||||||
|  | +#define TX_OVRD_DRV_LO_AMPLITUDE_MASK	0x007F | ||||||
|  | +#define TX_OVRD_DRV_LO_PREEMPH_MASK	0x3F80 | ||||||
|  | +#define TX_OVRD_DRV_LO_PREEMPH_SHIFT	7 | ||||||
|  | +#define TX_OVRD_DRV_LO_EN		BIT(14) | ||||||
|  | + | ||||||
|  | +/* SS CAP register bits */ | ||||||
|  | +#define SS_CR_CAP_ADDR_REG		BIT(0) | ||||||
|  | +#define SS_CR_CAP_DATA_REG		BIT(0) | ||||||
|  | +#define SS_CR_READ_REG			BIT(0) | ||||||
|  | +#define SS_CR_WRITE_REG			BIT(0) | ||||||
|  | + | ||||||
|  | +struct qcom_dwc3_usb_phy { | ||||||
|  | +	void __iomem		*base; | ||||||
|  | +	struct device		*dev; | ||||||
|  | +	struct clk		*xo_clk; | ||||||
|  | +	struct clk		*ref_clk; | ||||||
|  | +	u32			rx_eq; | ||||||
|  | +	u32			tx_deamp_3_5db; | ||||||
|  | +	u32			mpll; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct qcom_dwc3_phy_drvdata { | ||||||
|  | +	struct phy_ops	ops; | ||||||
|  | +	u32		clk_rate; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * Write register and read back masked value to confirm it is written | ||||||
|  | + * | ||||||
|  | + * @base - QCOM DWC3 PHY base virtual address. | ||||||
|  | + * @offset - register offset. | ||||||
|  | + * @mask - register bitmask specifying what should be updated | ||||||
|  | + * @val - value to write. | ||||||
|  | + */ | ||||||
|  | +static inline void qcom_dwc3_phy_write_readback( | ||||||
|  | +	struct qcom_dwc3_usb_phy *phy_dwc3, u32 offset, | ||||||
|  | +	const u32 mask, u32 val) | ||||||
|  | +{ | ||||||
|  | +	u32 write_val, tmp = readl(phy_dwc3->base + offset); | ||||||
|  | + | ||||||
|  | +	tmp &= ~mask;		/* retain other bits */ | ||||||
|  | +	write_val = tmp | val; | ||||||
|  | + | ||||||
|  | +	writel(write_val, phy_dwc3->base + offset); | ||||||
|  | + | ||||||
|  | +	/* Read back to see if val was written */ | ||||||
|  | +	tmp = readl(phy_dwc3->base + offset); | ||||||
|  | +	tmp &= mask;		/* clear other bits */ | ||||||
|  | + | ||||||
|  | +	if (tmp != val) | ||||||
|  | +		dev_err(phy_dwc3->dev, "write: %x to QSCRATCH: %x FAILED\n", | ||||||
|  | +			val, offset); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int wait_for_latch(void __iomem *addr) | ||||||
|  | +{ | ||||||
|  | +	u32 retry = 10; | ||||||
|  | + | ||||||
|  | +	while (true) { | ||||||
|  | +		if (!readl(addr)) | ||||||
|  | +			break; | ||||||
|  | + | ||||||
|  | +		if (--retry == 0) | ||||||
|  | +			return -ETIMEDOUT; | ||||||
|  | + | ||||||
|  | +		usleep_range(10, 20); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * Write SSPHY register | ||||||
|  | + * | ||||||
|  | + * @base - QCOM DWC3 PHY base virtual address. | ||||||
|  | + * @addr - SSPHY address to write. | ||||||
|  | + * @val - value to write. | ||||||
|  | + */ | ||||||
|  | +static int qcom_dwc3_ss_write_phycreg(struct qcom_dwc3_usb_phy *phy_dwc3, | ||||||
|  | +					u32 addr, u32 val) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	writel(addr, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG); | ||||||
|  | +	writel(SS_CR_CAP_ADDR_REG, phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_wait; | ||||||
|  | + | ||||||
|  | +	writel(val, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG); | ||||||
|  | +	writel(SS_CR_CAP_DATA_REG, phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_wait; | ||||||
|  | + | ||||||
|  | +	writel(SS_CR_WRITE_REG, phy_dwc3->base + CR_PROTOCOL_WRITE_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_WRITE_REG); | ||||||
|  | + | ||||||
|  | +err_wait: | ||||||
|  | +	if (ret) | ||||||
|  | +		dev_err(phy_dwc3->dev, "timeout waiting for latch\n"); | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * Read SSPHY register. | ||||||
|  | + * | ||||||
|  | + * @base - QCOM DWC3 PHY base virtual address. | ||||||
|  | + * @addr - SSPHY address to read. | ||||||
|  | + */ | ||||||
|  | +static int qcom_dwc3_ss_read_phycreg(void __iomem *base, u32 addr, u32 *val) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	writel(addr, base + CR_PROTOCOL_DATA_IN_REG); | ||||||
|  | +	writel(SS_CR_CAP_ADDR_REG, base + CR_PROTOCOL_CAP_ADDR_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(base + CR_PROTOCOL_CAP_ADDR_REG); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_wait; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Due to hardware bug, first read of SSPHY register might be | ||||||
|  | +	 * incorrect. Hence as workaround, SW should perform SSPHY register | ||||||
|  | +	 * read twice, but use only second read and ignore first read. | ||||||
|  | +	 */ | ||||||
|  | +	writel(SS_CR_READ_REG, base + CR_PROTOCOL_READ_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(base + CR_PROTOCOL_READ_REG); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_wait; | ||||||
|  | + | ||||||
|  | +	/* throwaway read */ | ||||||
|  | +	readl(base + CR_PROTOCOL_DATA_OUT_REG); | ||||||
|  | + | ||||||
|  | +	writel(SS_CR_READ_REG, base + CR_PROTOCOL_READ_REG); | ||||||
|  | + | ||||||
|  | +	ret = wait_for_latch(base + CR_PROTOCOL_READ_REG); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_wait; | ||||||
|  | + | ||||||
|  | +	*val = readl(base + CR_PROTOCOL_DATA_OUT_REG); | ||||||
|  | + | ||||||
|  | +err_wait: | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_dwc3_hs_phy_init(struct phy *phy) | ||||||
|  | +{ | ||||||
|  | +	struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); | ||||||
|  | +	int ret; | ||||||
|  | +	u32 val; | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(phy_dwc3->xo_clk); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(phy_dwc3->ref_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		clk_disable_unprepare(phy_dwc3->xo_clk); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * HSPHY Initialization: Enable UTMI clock, select 19.2MHz fsel | ||||||
|  | +	 * enable clamping, and disable RETENTION (power-on default is ENABLED) | ||||||
|  | +	 */ | ||||||
|  | +	val = HSUSB_CTRL_DPSEHV_CLAMP | HSUSB_CTRL_DMSEHV_CLAMP | | ||||||
|  | +		HSUSB_CTRL_RETENABLEN  | HSUSB_CTRL_COMMONONN | | ||||||
|  | +		HSUSB_CTRL_OTGSESSVLD_CLAMP | HSUSB_CTRL_ID_HV_CLAMP | | ||||||
|  | +		HSUSB_CTRL_DPSEHV_CLAMP | HSUSB_CTRL_UTMI_OTG_VBUS_VALID | | ||||||
|  | +		HSUSB_CTRL_UTMI_CLK_EN | HSUSB_CTRL_CLAMP_EN | 0x70; | ||||||
|  | + | ||||||
|  | +	/* use core clock if external reference is not present */ | ||||||
|  | +	if (!phy_dwc3->xo_clk) | ||||||
|  | +		val |= HSUSB_CTRL_USE_CLKCORE; | ||||||
|  | + | ||||||
|  | +	writel(val, phy_dwc3->base + HSUSB_PHY_CTRL_REG); | ||||||
|  | +	usleep_range(2000, 2200); | ||||||
|  | + | ||||||
|  | +	/* Disable (bypass) VBUS and ID filters */ | ||||||
|  | +	writel(HSUSB_GCFG_XHCI_REV, phy_dwc3->base + QSCRATCH_GENERAL_CFG); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_dwc3_hs_phy_exit(struct phy *phy) | ||||||
|  | +{ | ||||||
|  | +	struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); | ||||||
|  | + | ||||||
|  | +	clk_disable_unprepare(phy_dwc3->ref_clk); | ||||||
|  | +	clk_disable_unprepare(phy_dwc3->xo_clk); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_dwc3_ss_phy_init(struct phy *phy) | ||||||
|  | +{ | ||||||
|  | +	struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); | ||||||
|  | +	int ret; | ||||||
|  | +	u32 data = 0; | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(phy_dwc3->xo_clk); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(phy_dwc3->ref_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		clk_disable_unprepare(phy_dwc3->xo_clk); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* reset phy */ | ||||||
|  | +	data = readl(phy_dwc3->base + SSUSB_PHY_CTRL_REG); | ||||||
|  | +	writel(data | SSUSB_CTRL_SS_PHY_RESET, | ||||||
|  | +		phy_dwc3->base + SSUSB_PHY_CTRL_REG); | ||||||
|  | +	usleep_range(2000, 2200); | ||||||
|  | +	writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); | ||||||
|  | + | ||||||
|  | +	/* clear REF_PAD if we don't have XO clk */ | ||||||
|  | +	if (!phy_dwc3->xo_clk) | ||||||
|  | +		data &= ~SSUSB_CTRL_REF_USE_PAD; | ||||||
|  | +	else | ||||||
|  | +		data |= SSUSB_CTRL_REF_USE_PAD; | ||||||
|  | + | ||||||
|  | +	writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); | ||||||
|  | + | ||||||
|  | +	/* wait for ref clk to become stable, this can take up to 30ms */ | ||||||
|  | +	msleep(30); | ||||||
|  | + | ||||||
|  | +	data |= SSUSB_CTRL_SS_PHY_EN | SSUSB_CTRL_LANE0_PWR_PRESENT; | ||||||
|  | +	writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates | ||||||
|  | +	 * in HS mode instead of SS mode. Workaround it by asserting | ||||||
|  | +	 * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode | ||||||
|  | +	 */ | ||||||
|  | +	ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x102D, &data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	data |= (1 << 7); | ||||||
|  | +	ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x102D, data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x1010, &data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	data &= ~0xff0; | ||||||
|  | +	data |= 0x20; | ||||||
|  | +	ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x1010, data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Fix RX Equalization setting as follows | ||||||
|  | +	 * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 | ||||||
|  | +	 * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 | ||||||
|  | +	 * LANE0.RX_OVRD_IN_HI.RX_EQ set based on SoC version | ||||||
|  | +	 * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 | ||||||
|  | +	 */ | ||||||
|  | +	ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, | ||||||
|  | +			SSPHY_CTRL_RX_OVRD_IN_HI(0), &data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	data &= ~RX_OVRD_IN_HI_RX_EQ_EN; | ||||||
|  | +	data |= RX_OVRD_IN_HI_RX_EQ_EN_OVRD; | ||||||
|  | +	data &= ~RX_OVRD_IN_HI_RX_EQ_MASK; | ||||||
|  | +	data |= phy_dwc3->rx_eq << RX_OVRD_IN_HI_RX_EQ_SHIFT; | ||||||
|  | +	data |= RX_OVRD_IN_HI_RX_EQ_OVRD; | ||||||
|  | +	ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, | ||||||
|  | +		SSPHY_CTRL_RX_OVRD_IN_HI(0), data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Set EQ and TX launch amplitudes as follows | ||||||
|  | +	 * LANE0.TX_OVRD_DRV_LO.PREEMPH set based on SoC version | ||||||
|  | +	 * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 110 | ||||||
|  | +	 * LANE0.TX_OVRD_DRV_LO.EN set to 1. | ||||||
|  | +	 */ | ||||||
|  | +	ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, | ||||||
|  | +		SSPHY_CTRL_TX_OVRD_DRV_LO(0), &data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	data &= ~TX_OVRD_DRV_LO_PREEMPH_MASK; | ||||||
|  | +	data |= phy_dwc3->tx_deamp_3_5db << TX_OVRD_DRV_LO_PREEMPH_SHIFT; | ||||||
|  | +	data &= ~TX_OVRD_DRV_LO_AMPLITUDE_MASK; | ||||||
|  | +	data |= 0x6E; | ||||||
|  | +	data |= TX_OVRD_DRV_LO_EN; | ||||||
|  | +	ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, | ||||||
|  | +		SSPHY_CTRL_TX_OVRD_DRV_LO(0), data); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_phy_trans; | ||||||
|  | + | ||||||
|  | +	qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x30, phy_dwc3->mpll); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows | ||||||
|  | +	 * TX_FULL_SWING [26:20] amplitude to 110 | ||||||
|  | +	 * TX_DEEMPH_6DB [19:14] to 32 | ||||||
|  | +	 * TX_DEEMPH_3_5DB [13:8] set based on SoC version | ||||||
|  | +	 * LOS_BIAS [7:3] to 9 | ||||||
|  | +	 */ | ||||||
|  | +	data = readl(phy_dwc3->base + SSUSB_PHY_PARAM_CTRL_1); | ||||||
|  | + | ||||||
|  | +	data &= ~PHY_PARAM_CTRL1_MASK; | ||||||
|  | + | ||||||
|  | +	data |= PHY_PARAM_CTRL1_TX_FULL_SWING(0x6e) | | ||||||
|  | +		PHY_PARAM_CTRL1_TX_DEEMPH_6DB(0x20) | | ||||||
|  | +		PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(phy_dwc3->tx_deamp_3_5db) | | ||||||
|  | +		PHY_PARAM_CTRL1_LOS_BIAS(0x9); | ||||||
|  | + | ||||||
|  | +	qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_PARAM_CTRL_1, | ||||||
|  | +				     PHY_PARAM_CTRL1_MASK, data); | ||||||
|  | + | ||||||
|  | +err_phy_trans: | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int qcom_dwc3_ss_phy_exit(struct phy *phy) | ||||||
|  | +{ | ||||||
|  | +	struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); | ||||||
|  | + | ||||||
|  | +	/* Sequence to put SSPHY in low power state: | ||||||
|  | +	 * 1. Clear REF_PHY_EN in PHY_CTRL_REG | ||||||
|  | +	 * 2. Clear REF_USE_PAD in PHY_CTRL_REG | ||||||
|  | +	 * 3. Set TEST_POWERED_DOWN in PHY_CTRL_REG to enable PHY retention | ||||||
|  | +	 */ | ||||||
|  | +	qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, | ||||||
|  | +		SSUSB_CTRL_SS_PHY_EN, 0x0); | ||||||
|  | +	qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, | ||||||
|  | +		SSUSB_CTRL_REF_USE_PAD, 0x0); | ||||||
|  | +	qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, | ||||||
|  | +		SSUSB_CTRL_TEST_POWERDOWN, 0x0); | ||||||
|  | + | ||||||
|  | +	clk_disable_unprepare(phy_dwc3->ref_clk); | ||||||
|  | +	clk_disable_unprepare(phy_dwc3->xo_clk); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct qcom_dwc3_phy_drvdata qcom_dwc3_hs_drvdata = { | ||||||
|  | +	.ops = { | ||||||
|  | +		.init		= qcom_dwc3_hs_phy_init, | ||||||
|  | +		.exit		= qcom_dwc3_hs_phy_exit, | ||||||
|  | +		.owner		= THIS_MODULE, | ||||||
|  | +	}, | ||||||
|  | +	.clk_rate = 60000000, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct qcom_dwc3_phy_drvdata qcom_dwc3_ss_drvdata = { | ||||||
|  | +	.ops = { | ||||||
|  | +		.init		= qcom_dwc3_ss_phy_init, | ||||||
|  | +		.exit		= qcom_dwc3_ss_phy_exit, | ||||||
|  | +		.owner		= THIS_MODULE, | ||||||
|  | +	}, | ||||||
|  | +	.clk_rate = 125000000, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct of_device_id qcom_dwc3_phy_table[] = { | ||||||
|  | +	{ .compatible = "qcom,dwc3-hs-usb-phy", .data = &qcom_dwc3_hs_drvdata }, | ||||||
|  | +	{ .compatible = "qcom,dwc3-ss-usb-phy", .data = &qcom_dwc3_ss_drvdata }, | ||||||
|  | +	{ /* Sentinel */ } | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, qcom_dwc3_phy_table); | ||||||
|  | + | ||||||
|  | +static int qcom_dwc3_phy_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct qcom_dwc3_usb_phy	*phy_dwc3; | ||||||
|  | +	struct phy_provider		*phy_provider; | ||||||
|  | +	struct phy			*generic_phy; | ||||||
|  | +	struct resource			*res; | ||||||
|  | +	const struct of_device_id *match; | ||||||
|  | +	const struct qcom_dwc3_phy_drvdata *data; | ||||||
|  | +	struct device_node *np; | ||||||
|  | + | ||||||
|  | +	phy_dwc3 = devm_kzalloc(&pdev->dev, sizeof(*phy_dwc3), GFP_KERNEL); | ||||||
|  | +	if (!phy_dwc3) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	match = of_match_node(qcom_dwc3_phy_table, pdev->dev.of_node); | ||||||
|  | +	data = match->data; | ||||||
|  | + | ||||||
|  | +	phy_dwc3->dev = &pdev->dev; | ||||||
|  | + | ||||||
|  | +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | +	phy_dwc3->base = devm_ioremap_resource(phy_dwc3->dev, res); | ||||||
|  | +	if (IS_ERR(phy_dwc3->base)) | ||||||
|  | +		return PTR_ERR(phy_dwc3->base); | ||||||
|  | + | ||||||
|  | +	phy_dwc3->ref_clk = devm_clk_get(phy_dwc3->dev, "ref"); | ||||||
|  | +	if (IS_ERR(phy_dwc3->ref_clk)) { | ||||||
|  | +		dev_dbg(phy_dwc3->dev, "cannot get reference clock\n"); | ||||||
|  | +		return PTR_ERR(phy_dwc3->ref_clk); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk_set_rate(phy_dwc3->ref_clk, data->clk_rate); | ||||||
|  | + | ||||||
|  | +	phy_dwc3->xo_clk = devm_clk_get(phy_dwc3->dev, "xo"); | ||||||
|  | +	if (IS_ERR(phy_dwc3->xo_clk)) { | ||||||
|  | +		dev_dbg(phy_dwc3->dev, "cannot get TCXO clock\n"); | ||||||
|  | +		phy_dwc3->xo_clk = NULL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Parse device node to probe HSIO settings */ | ||||||
|  | +	np = of_node_get(pdev->dev.of_node); | ||||||
|  | +	if (!of_compat_cmp(match->compatible, "qcom,dwc3-ss-usb-phy", | ||||||
|  | +			   strlen(match->compatible))) { | ||||||
|  | + | ||||||
|  | +		if (of_property_read_u32(np, "rx_eq", &phy_dwc3->rx_eq) || | ||||||
|  | +		    of_property_read_u32(np, "tx_deamp_3_5db", | ||||||
|  | +					 &phy_dwc3->tx_deamp_3_5db) || | ||||||
|  | +		    of_property_read_u32(np, "mpll", &phy_dwc3->mpll)) { | ||||||
|  | + | ||||||
|  | +			dev_err(phy_dwc3->dev, "cannot get HSIO settings from device node, using default values\n"); | ||||||
|  | + | ||||||
|  | +			/* Default HSIO settings */ | ||||||
|  | +			phy_dwc3->rx_eq = SSPHY_RX_EQ_VALUE; | ||||||
|  | +			phy_dwc3->tx_deamp_3_5db = SSPHY_TX_DEEMPH_3_5DB; | ||||||
|  | +			phy_dwc3->mpll = SSPHY_MPLL_VALUE; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	generic_phy = devm_phy_create(phy_dwc3->dev, pdev->dev.of_node, | ||||||
|  | +				      &data->ops); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(generic_phy)) | ||||||
|  | +		return PTR_ERR(generic_phy); | ||||||
|  | + | ||||||
|  | +	phy_set_drvdata(generic_phy, phy_dwc3); | ||||||
|  | +	platform_set_drvdata(pdev, phy_dwc3); | ||||||
|  | + | ||||||
|  | +	phy_provider = devm_of_phy_provider_register(phy_dwc3->dev, | ||||||
|  | +			of_phy_simple_xlate); | ||||||
|  | + | ||||||
|  | +	if (IS_ERR(phy_provider)) | ||||||
|  | +		return PTR_ERR(phy_provider); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver qcom_dwc3_phy_driver = { | ||||||
|  | +	.probe		= qcom_dwc3_phy_probe, | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name	= "qcom-dwc3-usb-phy", | ||||||
|  | +		.owner	= THIS_MODULE, | ||||||
|  | +		.of_match_table = qcom_dwc3_phy_table, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +module_platform_driver(qcom_dwc3_phy_driver); | ||||||
|  | + | ||||||
|  | +MODULE_ALIAS("platform:phy-qcom-dwc3"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | +MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>"); | ||||||
|  | +MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>"); | ||||||
|  | +MODULE_DESCRIPTION("DesignWare USB3 QCOM PHY driver"); | ||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | From 48051ece78136e4235a2415a52797db56f8a4478 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | Date: Tue, 21 Apr 2015 19:09:07 -0700 | ||||||
|  | Subject: [PATCH 33/69] ARM: qcom: automatically select PCI_DOMAINS if PCI is | ||||||
|  |  enabled | ||||||
|  |  | ||||||
|  | If multiple PCIe devices are present in the system, the kernel will | ||||||
|  | panic at boot time when trying to scan the PCI buses. This happens on | ||||||
|  | IPQ806x based platforms, which has 3 PCIe ports. | ||||||
|  |  | ||||||
|  | Enabling this option allows the kernel to assign the pci-domains | ||||||
|  | according to the device-tree content. This allows multiple PCIe | ||||||
|  | controllers to coexist in the system. | ||||||
|  |  | ||||||
|  | Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  arch/arm/mach-qcom/Kconfig | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  |  | ||||||
|  | --- a/arch/arm/mach-qcom/Kconfig | ||||||
|  | +++ b/arch/arm/mach-qcom/Kconfig | ||||||
|  | @@ -6,6 +6,7 @@ menuconfig ARCH_QCOM | ||||||
|  |  	select ARM_AMBA | ||||||
|  |  	select PINCTRL | ||||||
|  |  	select QCOM_SCM if SMP | ||||||
|  | +	select PCI_DOMAINS if PCI | ||||||
|  |  	help | ||||||
|  |  	  Support for Qualcomm's devicetree based systems. | ||||||
|  |   | ||||||
| @@ -0,0 +1,147 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:19 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,01/12] ARM: Add Krait L2 register accessor functions | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102101 | ||||||
|  | Message-Id: <1512726150-7204-2-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org, Mark Rutland <mark.rutland@arm.com>, | ||||||
|  |  Russell King <linux@arm.linux.org.uk>, | ||||||
|  |  Courtney Cavin <courtney.cavin@sonymobile.com> | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:19 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | Krait CPUs have a handful of L2 cache controller registers that | ||||||
|  | live behind a cp15 based indirection register. First you program | ||||||
|  | the indirection register (l2cpselr) to point the L2 'window' | ||||||
|  | register (l2cpdr) at what you want to read/write.  Then you | ||||||
|  | read/write the 'window' register to do what you want. The | ||||||
|  | l2cpselr register is not banked per-cpu so we must lock around | ||||||
|  | accesses to it to prevent other CPUs from re-pointing l2cpdr | ||||||
|  | underneath us. | ||||||
|  |  | ||||||
|  | Cc: Mark Rutland <mark.rutland@arm.com> | ||||||
|  | Cc: Russell King <linux@arm.linux.org.uk> | ||||||
|  | Cc: Courtney Cavin <courtney.cavin@sonymobile.com> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  arch/arm/common/Kconfig                   |  3 ++ | ||||||
|  |  arch/arm/common/Makefile                  |  1 + | ||||||
|  |  arch/arm/common/krait-l2-accessors.c      | 58 +++++++++++++++++++++++++++++++ | ||||||
|  |  arch/arm/include/asm/krait-l2-accessors.h | 20 +++++++++++ | ||||||
|  |  4 files changed, 82 insertions(+) | ||||||
|  |  create mode 100644 arch/arm/common/krait-l2-accessors.c | ||||||
|  |  create mode 100644 arch/arm/include/asm/krait-l2-accessors.h | ||||||
|  |  | ||||||
|  | --- a/arch/arm/common/Kconfig | ||||||
|  | +++ b/arch/arm/common/Kconfig | ||||||
|  | @@ -7,6 +7,9 @@ config DMABOUNCE | ||||||
|  |  	bool | ||||||
|  |  	select ZONE_DMA | ||||||
|  |   | ||||||
|  | +config KRAIT_L2_ACCESSORS | ||||||
|  | +	bool | ||||||
|  | + | ||||||
|  |  config SHARP_LOCOMO | ||||||
|  |  	bool | ||||||
|  |   | ||||||
|  | --- a/arch/arm/common/Makefile | ||||||
|  | +++ b/arch/arm/common/Makefile | ||||||
|  | @@ -7,6 +7,7 @@ obj-y				+= firmware.o | ||||||
|  |   | ||||||
|  |  obj-$(CONFIG_SA1111)		+= sa1111.o | ||||||
|  |  obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o | ||||||
|  | +obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o | ||||||
|  |  obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o | ||||||
|  |  obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o | ||||||
|  |  obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/arm/common/krait-l2-accessors.c | ||||||
|  | @@ -0,0 +1,58 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/spinlock.h> | ||||||
|  | +#include <linux/export.h> | ||||||
|  | + | ||||||
|  | +#include <asm/barrier.h> | ||||||
|  | +#include <asm/krait-l2-accessors.h> | ||||||
|  | + | ||||||
|  | +static DEFINE_RAW_SPINLOCK(krait_l2_lock); | ||||||
|  | + | ||||||
|  | +void krait_set_l2_indirect_reg(u32 addr, u32 val) | ||||||
|  | +{ | ||||||
|  | +	unsigned long flags; | ||||||
|  | + | ||||||
|  | +	raw_spin_lock_irqsave(&krait_l2_lock, flags); | ||||||
|  | +	/* | ||||||
|  | +	 * Select the L2 window by poking l2cpselr, then write to the window | ||||||
|  | +	 * via l2cpdr. | ||||||
|  | +	 */ | ||||||
|  | +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); | ||||||
|  | +	isb(); | ||||||
|  | +	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val)); | ||||||
|  | +	isb(); | ||||||
|  | + | ||||||
|  | +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(krait_set_l2_indirect_reg); | ||||||
|  | + | ||||||
|  | +u32 krait_get_l2_indirect_reg(u32 addr) | ||||||
|  | +{ | ||||||
|  | +	u32 val; | ||||||
|  | +	unsigned long flags; | ||||||
|  | + | ||||||
|  | +	raw_spin_lock_irqsave(&krait_l2_lock, flags); | ||||||
|  | +	/* | ||||||
|  | +	 * Select the L2 window by poking l2cpselr, then read from the window | ||||||
|  | +	 * via l2cpdr. | ||||||
|  | +	 */ | ||||||
|  | +	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); | ||||||
|  | +	isb(); | ||||||
|  | +	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val)); | ||||||
|  | + | ||||||
|  | +	raw_spin_unlock_irqrestore(&krait_l2_lock, flags); | ||||||
|  | + | ||||||
|  | +	return val; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(krait_get_l2_indirect_reg); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/arm/include/asm/krait-l2-accessors.h | ||||||
|  | @@ -0,0 +1,20 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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 __ASMARM_KRAIT_L2_ACCESSORS_H | ||||||
|  | +#define __ASMARM_KRAIT_L2_ACCESSORS_H | ||||||
|  | + | ||||||
|  | +extern void krait_set_l2_indirect_reg(u32 addr, u32 val); | ||||||
|  | +extern u32 krait_get_l2_indirect_reg(u32 addr); | ||||||
|  | + | ||||||
|  | +#endif | ||||||
| @@ -0,0 +1,195 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:20 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,02/12] clk: mux: Split out register accessors for reuse | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102103 | ||||||
|  | Message-Id: <1512726150-7204-3-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:20 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | We want to reuse the logic in clk-mux.c for other clock drivers | ||||||
|  | that don't use readl as register accessors. Fortunately, there | ||||||
|  | really isn't much to the mux code besides the table indirection | ||||||
|  | and quirk flags if you assume any bit shifting and masking has | ||||||
|  | been done already. Pull that logic out into reusable functions | ||||||
|  | that operate on an optional table and some flags so that other | ||||||
|  | drivers can use the same logic. | ||||||
|  |  | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/clk-mux.c        | 75 +++++++++++++++++++++++++++----------------- | ||||||
|  |  include/linux/clk-provider.h |  9 ++++-- | ||||||
|  |  2 files changed, 54 insertions(+), 30 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/clk-mux.c | ||||||
|  | +++ b/drivers/clk/clk-mux.c | ||||||
|  | @@ -26,35 +26,24 @@ | ||||||
|  |   * parent - parent is adjustable through clk_set_parent | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  | -static u8 clk_mux_get_parent(struct clk_hw *hw) | ||||||
|  | +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val, | ||||||
|  | +				unsigned int *table, unsigned long flags) | ||||||
|  |  { | ||||||
|  | -	struct clk_mux *mux = to_clk_mux(hw); | ||||||
|  |  	int num_parents = clk_hw_get_num_parents(hw); | ||||||
|  | -	u32 val; | ||||||
|  | - | ||||||
|  | -	/* | ||||||
|  | -	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric | ||||||
|  | -	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 | ||||||
|  | -	 * to 0x7 (index starts at one) | ||||||
|  | -	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so | ||||||
|  | -	 * val = 0x4 really means "bit 2, index starts at bit 0" | ||||||
|  | -	 */ | ||||||
|  | -	val = clk_readl(mux->reg) >> mux->shift; | ||||||
|  | -	val &= mux->mask; | ||||||
|  |   | ||||||
|  | -	if (mux->table) { | ||||||
|  | +	if (table) { | ||||||
|  |  		int i; | ||||||
|  |   | ||||||
|  |  		for (i = 0; i < num_parents; i++) | ||||||
|  | -			if (mux->table[i] == val) | ||||||
|  | +			if (table[i] == val) | ||||||
|  |  				return i; | ||||||
|  |  		return -EINVAL; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	if (val && (mux->flags & CLK_MUX_INDEX_BIT)) | ||||||
|  | +	if (val && (flags & CLK_MUX_INDEX_BIT)) | ||||||
|  |  		val = ffs(val) - 1; | ||||||
|  |   | ||||||
|  | -	if (val && (mux->flags & CLK_MUX_INDEX_ONE)) | ||||||
|  | +	if (val && (flags & CLK_MUX_INDEX_ONE)) | ||||||
|  |  		val--; | ||||||
|  |   | ||||||
|  |  	if (val >= num_parents) | ||||||
|  | @@ -62,23 +51,53 @@ static u8 clk_mux_get_parent(struct clk_ | ||||||
|  |   | ||||||
|  |  	return val; | ||||||
|  |  } | ||||||
|  | +EXPORT_SYMBOL_GPL(clk_mux_get_parent); | ||||||
|  |   | ||||||
|  | -static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | ||||||
|  | +static u8 _clk_mux_get_parent(struct clk_hw *hw) | ||||||
|  |  { | ||||||
|  |  	struct clk_mux *mux = to_clk_mux(hw); | ||||||
|  |  	u32 val; | ||||||
|  | -	unsigned long flags = 0; | ||||||
|  |   | ||||||
|  | -	if (mux->table) { | ||||||
|  | -		index = mux->table[index]; | ||||||
|  | +	/* | ||||||
|  | +	 * FIXME need a mux-specific flag to determine if val is bitwise or | ||||||
|  | +	 * numeric e.g. sys_clkin_ck's clksel field is 3 bits wide, | ||||||
|  | +	 * but ranges from 0x1 to 0x7 (index starts at one) | ||||||
|  | +	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so | ||||||
|  | +	 * val = 0x4 really means "bit 2, index starts at bit 0" | ||||||
|  | +	 */ | ||||||
|  | +	val = clk_readl(mux->reg) >> mux->shift; | ||||||
|  | +	val &= mux->mask; | ||||||
|  | + | ||||||
|  | +	return clk_mux_get_parent(hw, val, mux->table, mux->flags); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +unsigned int clk_mux_reindex(u8 index, unsigned int *table, | ||||||
|  | +			     unsigned long flags) | ||||||
|  | +{ | ||||||
|  | +	unsigned int val = index; | ||||||
|  | + | ||||||
|  | +	if (table) { | ||||||
|  | +		val = table[val]; | ||||||
|  |  	} else { | ||||||
|  | -		if (mux->flags & CLK_MUX_INDEX_BIT) | ||||||
|  | -			index = 1 << index; | ||||||
|  | +		if (flags & CLK_MUX_INDEX_BIT) | ||||||
|  | +			val = 1 << index; | ||||||
|  |   | ||||||
|  | -		if (mux->flags & CLK_MUX_INDEX_ONE) | ||||||
|  | -			index++; | ||||||
|  | +		if (flags & CLK_MUX_INDEX_ONE) | ||||||
|  | +			val++; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	return val; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL_GPL(clk_mux_reindex); | ||||||
|  | + | ||||||
|  | +static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | ||||||
|  | +{ | ||||||
|  | +	struct clk_mux *mux = to_clk_mux(hw); | ||||||
|  | +	u32 val; | ||||||
|  | +	unsigned long flags = 0; | ||||||
|  | + | ||||||
|  | +	index = clk_mux_reindex(index, mux->table, mux->flags); | ||||||
|  | + | ||||||
|  |  	if (mux->lock) | ||||||
|  |  		spin_lock_irqsave(mux->lock, flags); | ||||||
|  |  	else | ||||||
|  | @@ -110,14 +129,14 @@ static int clk_mux_determine_rate(struct | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  const struct clk_ops clk_mux_ops = { | ||||||
|  | -	.get_parent = clk_mux_get_parent, | ||||||
|  | +	.get_parent = _clk_mux_get_parent, | ||||||
|  |  	.set_parent = clk_mux_set_parent, | ||||||
|  |  	.determine_rate = clk_mux_determine_rate, | ||||||
|  |  }; | ||||||
|  |  EXPORT_SYMBOL_GPL(clk_mux_ops); | ||||||
|  |   | ||||||
|  |  const struct clk_ops clk_mux_ro_ops = { | ||||||
|  | -	.get_parent = clk_mux_get_parent, | ||||||
|  | +	.get_parent = _clk_mux_get_parent, | ||||||
|  |  }; | ||||||
|  |  EXPORT_SYMBOL_GPL(clk_mux_ro_ops); | ||||||
|  |   | ||||||
|  | @@ -125,7 +144,7 @@ struct clk_hw *clk_hw_register_mux_table | ||||||
|  |  		const char * const *parent_names, u8 num_parents, | ||||||
|  |  		unsigned long flags, | ||||||
|  |  		void __iomem *reg, u8 shift, u32 mask, | ||||||
|  | -		u8 clk_mux_flags, u32 *table, spinlock_t *lock) | ||||||
|  | +		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock) | ||||||
|  |  { | ||||||
|  |  	struct clk_mux *mux; | ||||||
|  |  	struct clk_hw *hw; | ||||||
|  | --- a/include/linux/clk-provider.h | ||||||
|  | +++ b/include/linux/clk-provider.h | ||||||
|  | @@ -468,7 +468,7 @@ void clk_hw_unregister_divider(struct cl | ||||||
|  |  struct clk_mux { | ||||||
|  |  	struct clk_hw	hw; | ||||||
|  |  	void __iomem	*reg; | ||||||
|  | -	u32		*table; | ||||||
|  | +	unsigned int	*table; | ||||||
|  |  	u32		mask; | ||||||
|  |  	u8		shift; | ||||||
|  |  	u8		flags; | ||||||
|  | @@ -486,6 +486,11 @@ struct clk_mux { | ||||||
|  |  extern const struct clk_ops clk_mux_ops; | ||||||
|  |  extern const struct clk_ops clk_mux_ro_ops; | ||||||
|  |   | ||||||
|  | +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val, | ||||||
|  | +				unsigned int *table, unsigned long flags); | ||||||
|  | +unsigned int clk_mux_reindex(u8 index, unsigned int *table, | ||||||
|  | +			     unsigned long flags); | ||||||
|  | + | ||||||
|  |  struct clk *clk_register_mux(struct device *dev, const char *name, | ||||||
|  |  		const char * const *parent_names, u8 num_parents, | ||||||
|  |  		unsigned long flags, | ||||||
|  | @@ -506,7 +511,7 @@ struct clk_hw *clk_hw_register_mux_table | ||||||
|  |  		const char * const *parent_names, u8 num_parents, | ||||||
|  |  		unsigned long flags, | ||||||
|  |  		void __iomem *reg, u8 shift, u32 mask, | ||||||
|  | -		u8 clk_mux_flags, u32 *table, spinlock_t *lock); | ||||||
|  | +		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock); | ||||||
|  |   | ||||||
|  |  void clk_unregister_mux(struct clk *clk); | ||||||
|  |  void clk_hw_unregister_mux(struct clk_hw *hw); | ||||||
| @@ -0,0 +1,352 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:21 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,03/12] clk: qcom: Add support for High-Frequency PLLs (HFPLLs) | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102083 | ||||||
|  | Message-Id: <1512726150-7204-4-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:21 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | HFPLLs are the main frequency source for Krait CPU clocks. Add | ||||||
|  | support for changing the rate of these PLLs. | ||||||
|  |  | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/Makefile    |   1 + | ||||||
|  |  drivers/clk/qcom/clk-hfpll.c | 253 +++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  drivers/clk/qcom/clk-hfpll.h |  54 +++++++++ | ||||||
|  |  3 files changed, 308 insertions(+) | ||||||
|  |  create mode 100644 drivers/clk/qcom/clk-hfpll.c | ||||||
|  |  create mode 100644 drivers/clk/qcom/clk-hfpll.h | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/Makefile | ||||||
|  | +++ b/drivers/clk/qcom/Makefile | ||||||
|  | @@ -10,6 +10,7 @@ clk-qcom-y += clk-rcg2.o | ||||||
|  |  clk-qcom-y += clk-branch.o | ||||||
|  |  clk-qcom-y += clk-regmap-divider.o | ||||||
|  |  clk-qcom-y += clk-regmap-mux.o | ||||||
|  | +clk-qcom-y += clk-hfpll.o | ||||||
|  |  clk-qcom-y += reset.o | ||||||
|  |  clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o | ||||||
|  |   | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/clk-hfpll.c | ||||||
|  | @@ -0,0 +1,253 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/export.h> | ||||||
|  | +#include <linux/regmap.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | + | ||||||
|  | +#include "clk-regmap.h" | ||||||
|  | +#include "clk-hfpll.h" | ||||||
|  | + | ||||||
|  | +#define PLL_OUTCTRL	BIT(0) | ||||||
|  | +#define PLL_BYPASSNL	BIT(1) | ||||||
|  | +#define PLL_RESET_N	BIT(2) | ||||||
|  | + | ||||||
|  | +/* Initialize a HFPLL at a given rate and enable it. */ | ||||||
|  | +static void __clk_hfpll_init_once(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | + | ||||||
|  | +	if (likely(h->init_done)) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	/* Configure PLL parameters for integer mode. */ | ||||||
|  | +	if (hd->config_val) | ||||||
|  | +		regmap_write(regmap, hd->config_reg, hd->config_val); | ||||||
|  | +	regmap_write(regmap, hd->m_reg, 0); | ||||||
|  | +	regmap_write(regmap, hd->n_reg, 1); | ||||||
|  | + | ||||||
|  | +	if (hd->user_reg) { | ||||||
|  | +		u32 regval = hd->user_val; | ||||||
|  | +		unsigned long rate; | ||||||
|  | + | ||||||
|  | +		rate = clk_hw_get_rate(hw); | ||||||
|  | + | ||||||
|  | +		/* Pick the right VCO. */ | ||||||
|  | +		if (hd->user_vco_mask && rate > hd->low_vco_max_rate) | ||||||
|  | +			regval |= hd->user_vco_mask; | ||||||
|  | +		regmap_write(regmap, hd->user_reg, regval); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (hd->droop_reg) | ||||||
|  | +		regmap_write(regmap, hd->droop_reg, hd->droop_val); | ||||||
|  | + | ||||||
|  | +	h->init_done = true; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void __clk_hfpll_enable(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	u32 val; | ||||||
|  | + | ||||||
|  | +	__clk_hfpll_init_once(hw); | ||||||
|  | + | ||||||
|  | +	/* Disable PLL bypass mode. */ | ||||||
|  | +	regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL); | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * H/W requires a 5us delay between disabling the bypass and | ||||||
|  | +	 * de-asserting the reset. Delay 10us just to be safe. | ||||||
|  | +	 */ | ||||||
|  | +	udelay(10); | ||||||
|  | + | ||||||
|  | +	/* De-assert active-low PLL reset. */ | ||||||
|  | +	regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N); | ||||||
|  | + | ||||||
|  | +	/* Wait for PLL to lock. */ | ||||||
|  | +	if (hd->status_reg) { | ||||||
|  | +		do { | ||||||
|  | +			regmap_read(regmap, hd->status_reg, &val); | ||||||
|  | +		} while (!(val & BIT(hd->lock_bit))); | ||||||
|  | +	} else { | ||||||
|  | +		udelay(60); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Enable PLL output. */ | ||||||
|  | +	regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* Enable an already-configured HFPLL. */ | ||||||
|  | +static int clk_hfpll_enable(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	u32 mode; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&h->lock, flags); | ||||||
|  | +	regmap_read(regmap, hd->mode_reg, &mode); | ||||||
|  | +	if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL))) | ||||||
|  | +		__clk_hfpll_enable(hw); | ||||||
|  | +	spin_unlock_irqrestore(&h->lock, flags); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void __clk_hfpll_disable(struct clk_hfpll *h) | ||||||
|  | +{ | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Disable the PLL output, disable test mode, enable the bypass mode, | ||||||
|  | +	 * and assert the reset. | ||||||
|  | +	 */ | ||||||
|  | +	regmap_update_bits(regmap, hd->mode_reg, | ||||||
|  | +			   PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void clk_hfpll_disable(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	unsigned long flags; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&h->lock, flags); | ||||||
|  | +	__clk_hfpll_disable(h); | ||||||
|  | +	spin_unlock_irqrestore(&h->lock, flags); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate, | ||||||
|  | +				 unsigned long *parent_rate) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	unsigned long rrate; | ||||||
|  | + | ||||||
|  | +	rate = clamp(rate, hd->min_rate, hd->max_rate); | ||||||
|  | + | ||||||
|  | +	rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate; | ||||||
|  | +	if (rrate > hd->max_rate) | ||||||
|  | +		rrate -= *parent_rate; | ||||||
|  | + | ||||||
|  | +	return rrate; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * For optimization reasons, assumes no downstream clocks are actively using | ||||||
|  | + * it. | ||||||
|  | + */ | ||||||
|  | +static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate, | ||||||
|  | +			      unsigned long parent_rate) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	u32 l_val, val; | ||||||
|  | +	bool enabled; | ||||||
|  | + | ||||||
|  | +	l_val = rate / parent_rate; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&h->lock, flags); | ||||||
|  | + | ||||||
|  | +	enabled = __clk_is_enabled(hw->clk); | ||||||
|  | +	if (enabled) | ||||||
|  | +		__clk_hfpll_disable(h); | ||||||
|  | + | ||||||
|  | +	/* Pick the right VCO. */ | ||||||
|  | +	if (hd->user_reg && hd->user_vco_mask) { | ||||||
|  | +		regmap_read(regmap, hd->user_reg, &val); | ||||||
|  | +		if (rate <= hd->low_vco_max_rate) | ||||||
|  | +			val &= ~hd->user_vco_mask; | ||||||
|  | +		else | ||||||
|  | +			val |= hd->user_vco_mask; | ||||||
|  | +		regmap_write(regmap, hd->user_reg, val); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	regmap_write(regmap, hd->l_reg, l_val); | ||||||
|  | + | ||||||
|  | +	if (enabled) | ||||||
|  | +		__clk_hfpll_enable(hw); | ||||||
|  | + | ||||||
|  | +	spin_unlock_irqrestore(&h->lock, flags); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw, | ||||||
|  | +					   unsigned long parent_rate) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	u32 l_val; | ||||||
|  | + | ||||||
|  | +	regmap_read(regmap, hd->l_reg, &l_val); | ||||||
|  | + | ||||||
|  | +	return l_val * parent_rate; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void clk_hfpll_init(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	u32 mode, status; | ||||||
|  | + | ||||||
|  | +	regmap_read(regmap, hd->mode_reg, &mode); | ||||||
|  | +	if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) { | ||||||
|  | +		__clk_hfpll_init_once(hw); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (hd->status_reg) { | ||||||
|  | +		regmap_read(regmap, hd->status_reg, &status); | ||||||
|  | +		if (!(status & BIT(hd->lock_bit))) { | ||||||
|  | +			WARN(1, "HFPLL %s is ON, but not locked!\n", | ||||||
|  | +			     __clk_get_name(hw->clk)); | ||||||
|  | +			clk_hfpll_disable(hw); | ||||||
|  | +			__clk_hfpll_init_once(hw); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int hfpll_is_enabled(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct clk_hfpll *h = to_clk_hfpll(hw); | ||||||
|  | +	struct hfpll_data const *hd = h->d; | ||||||
|  | +	struct regmap *regmap = h->clkr.regmap; | ||||||
|  | +	u32 mode; | ||||||
|  | + | ||||||
|  | +	regmap_read(regmap, hd->mode_reg, &mode); | ||||||
|  | +	mode &= 0x7; | ||||||
|  | +	return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct clk_ops clk_ops_hfpll = { | ||||||
|  | +	.enable = clk_hfpll_enable, | ||||||
|  | +	.disable = clk_hfpll_disable, | ||||||
|  | +	.is_enabled = hfpll_is_enabled, | ||||||
|  | +	.round_rate = clk_hfpll_round_rate, | ||||||
|  | +	.set_rate = clk_hfpll_set_rate, | ||||||
|  | +	.recalc_rate = clk_hfpll_recalc_rate, | ||||||
|  | +	.init = clk_hfpll_init, | ||||||
|  | +}; | ||||||
|  | +EXPORT_SYMBOL_GPL(clk_ops_hfpll); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/clk-hfpll.h | ||||||
|  | @@ -0,0 +1,54 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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 __QCOM_CLK_HFPLL_H__ | ||||||
|  | +#define __QCOM_CLK_HFPLL_H__ | ||||||
|  | + | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | +#include "clk-regmap.h" | ||||||
|  | + | ||||||
|  | +struct hfpll_data { | ||||||
|  | +	u32 mode_reg; | ||||||
|  | +	u32 l_reg; | ||||||
|  | +	u32 m_reg; | ||||||
|  | +	u32 n_reg; | ||||||
|  | +	u32 user_reg; | ||||||
|  | +	u32 droop_reg; | ||||||
|  | +	u32 config_reg; | ||||||
|  | +	u32 status_reg; | ||||||
|  | +	u8  lock_bit; | ||||||
|  | + | ||||||
|  | +	u32 droop_val; | ||||||
|  | +	u32 config_val; | ||||||
|  | +	u32 user_val; | ||||||
|  | +	u32 user_vco_mask; | ||||||
|  | +	unsigned long low_vco_max_rate; | ||||||
|  | + | ||||||
|  | +	unsigned long min_rate; | ||||||
|  | +	unsigned long max_rate; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +struct clk_hfpll { | ||||||
|  | +	struct hfpll_data const *d; | ||||||
|  | +	int init_done; | ||||||
|  | + | ||||||
|  | +	struct clk_regmap clkr; | ||||||
|  | +	spinlock_t lock; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +#define to_clk_hfpll(_hw) \ | ||||||
|  | +	container_of(to_clk_regmap(_hw), struct clk_hfpll, clkr) | ||||||
|  | + | ||||||
|  | +extern const struct clk_ops clk_ops_hfpll; | ||||||
|  | + | ||||||
|  | +#endif | ||||||
| @@ -0,0 +1,206 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:22 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,04/12] clk: qcom: Add HFPLL driver | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102079 | ||||||
|  | Message-Id: <1512726150-7204-5-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:22 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | On some devices (MSM8974 for example), the HFPLLs are | ||||||
|  | instantiated within the Krait processor subsystem as separate | ||||||
|  | register regions. Add a driver for these PLLs so that we can | ||||||
|  | provide HFPLL clocks for use by the system. | ||||||
|  |  | ||||||
|  | Cc: <devicetree@vger.kernel.org> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/clock/qcom,hfpll.txt       |  40 ++++++++ | ||||||
|  |  drivers/clk/qcom/Kconfig                           |   8 ++ | ||||||
|  |  drivers/clk/qcom/Makefile                          |   1 + | ||||||
|  |  drivers/clk/qcom/hfpll.c                           | 106 +++++++++++++++++++++ | ||||||
|  |  4 files changed, 155 insertions(+) | ||||||
|  |  create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt | ||||||
|  |  create mode 100644 drivers/clk/qcom/hfpll.c | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt | ||||||
|  | @@ -0,0 +1,40 @@ | ||||||
|  | +High-Frequency PLL (HFPLL) | ||||||
|  | + | ||||||
|  | +PROPERTIES | ||||||
|  | + | ||||||
|  | +- compatible: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: must be "qcom,hfpll" | ||||||
|  | + | ||||||
|  | +- reg: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <prop-encoded-array> | ||||||
|  | +	Definition: address and size of HPLL registers. An optional second | ||||||
|  | +		    element specifies the address and size of the alias | ||||||
|  | +		    register region. | ||||||
|  | + | ||||||
|  | +- clock-output-names: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: Name of the PLL. Typically hfpllX where X is a CPU number | ||||||
|  | +		    starting at 0. Otherwise hfpll_Y where Y is more specific | ||||||
|  | +		    such as "l2". | ||||||
|  | + | ||||||
|  | +Example: | ||||||
|  | + | ||||||
|  | +1) An HFPLL for the L2 cache. | ||||||
|  | + | ||||||
|  | +	clock-controller@f9016000 { | ||||||
|  | +		compatible = "qcom,hfpll"; | ||||||
|  | +		reg = <0xf9016000 0x30>; | ||||||
|  | +		clock-output-names = "hfpll_l2"; | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +2) An HFPLL for CPU0. This HFPLL has the alias register region. | ||||||
|  | + | ||||||
|  | +	clock-controller@f908a000 { | ||||||
|  | +		compatible = "qcom,hfpll"; | ||||||
|  | +		reg = <0xf908a000 0x30>, <0xf900a000 0x30>; | ||||||
|  | +		clock-output-names = "hfpll0"; | ||||||
|  | +	}; | ||||||
|  | --- a/drivers/clk/qcom/Kconfig | ||||||
|  | +++ b/drivers/clk/qcom/Kconfig | ||||||
|  | @@ -196,3 +196,11 @@ config MSM_MMCC_8996 | ||||||
|  |  	  Support for the multimedia clock controller on msm8996 devices. | ||||||
|  |  	  Say Y if you want to support multimedia devices such as display, | ||||||
|  |  	  graphics, video encode/decode, camera, etc. | ||||||
|  | + | ||||||
|  | +config QCOM_HFPLL | ||||||
|  | +	tristate "High-Frequency PLL (HFPLL) Clock Controller" | ||||||
|  | +	depends on COMMON_CLK_QCOM | ||||||
|  | +	help | ||||||
|  | +	  Support for the high-frequency PLLs present on Qualcomm devices. | ||||||
|  | +	  Say Y if you want to support CPU frequency scaling on devices | ||||||
|  | +	  such as MSM8974, APQ8084, etc. | ||||||
|  | --- a/drivers/clk/qcom/Makefile | ||||||
|  | +++ b/drivers/clk/qcom/Makefile | ||||||
|  | @@ -35,3 +35,4 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8 | ||||||
|  |  obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o | ||||||
|  |  obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o | ||||||
|  |  obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o | ||||||
|  | +obj-$(CONFIG_QCOM_HFPLL) += hfpll.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/hfpll.c | ||||||
|  | @@ -0,0 +1,106 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | +#include <linux/regmap.h> | ||||||
|  | + | ||||||
|  | +#include "clk-regmap.h" | ||||||
|  | +#include "clk-hfpll.h" | ||||||
|  | + | ||||||
|  | +static const struct hfpll_data hdata = { | ||||||
|  | +	.mode_reg = 0x00, | ||||||
|  | +	.l_reg = 0x04, | ||||||
|  | +	.m_reg = 0x08, | ||||||
|  | +	.n_reg = 0x0c, | ||||||
|  | +	.user_reg = 0x10, | ||||||
|  | +	.config_reg = 0x14, | ||||||
|  | +	.config_val = 0x430405d, | ||||||
|  | +	.status_reg = 0x1c, | ||||||
|  | +	.lock_bit = 16, | ||||||
|  | + | ||||||
|  | +	.user_val = 0x8, | ||||||
|  | +	.user_vco_mask = 0x100000, | ||||||
|  | +	.low_vco_max_rate = 1248000000, | ||||||
|  | +	.min_rate = 537600000UL, | ||||||
|  | +	.max_rate = 2900000000UL, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct of_device_id qcom_hfpll_match_table[] = { | ||||||
|  | +	{ .compatible = "qcom,hfpll" }, | ||||||
|  | +	{ } | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); | ||||||
|  | + | ||||||
|  | +static const struct regmap_config hfpll_regmap_config = { | ||||||
|  | +	.reg_bits	= 32, | ||||||
|  | +	.reg_stride	= 4, | ||||||
|  | +	.val_bits	= 32, | ||||||
|  | +	.max_register	= 0x30, | ||||||
|  | +	.fast_io	= true, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int qcom_hfpll_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct resource *res; | ||||||
|  | +	struct device *dev = &pdev->dev; | ||||||
|  | +	void __iomem *base; | ||||||
|  | +	struct regmap *regmap; | ||||||
|  | +	struct clk_hfpll *h; | ||||||
|  | +	struct clk_init_data init = { | ||||||
|  | +		.parent_names = (const char *[]){ "xo" }, | ||||||
|  | +		.num_parents = 1, | ||||||
|  | +		.ops = &clk_ops_hfpll, | ||||||
|  | +	}; | ||||||
|  | + | ||||||
|  | +	h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); | ||||||
|  | +	if (!h) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | +	base = devm_ioremap_resource(dev, res); | ||||||
|  | +	if (IS_ERR(base)) | ||||||
|  | +		return PTR_ERR(base); | ||||||
|  | + | ||||||
|  | +	regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config); | ||||||
|  | +	if (IS_ERR(regmap)) | ||||||
|  | +		return PTR_ERR(regmap); | ||||||
|  | + | ||||||
|  | +	if (of_property_read_string_index(dev->of_node, "clock-output-names", | ||||||
|  | +					  0, &init.name)) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	h->d = &hdata; | ||||||
|  | +	h->clkr.hw.init = &init; | ||||||
|  | +	spin_lock_init(&h->lock); | ||||||
|  | + | ||||||
|  | +	return devm_clk_register_regmap(&pdev->dev, &h->clkr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver qcom_hfpll_driver = { | ||||||
|  | +	.probe		= qcom_hfpll_probe, | ||||||
|  | +	.driver		= { | ||||||
|  | +		.name	= "qcom-hfpll", | ||||||
|  | +		.of_match_table = qcom_hfpll_match_table, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | +module_platform_driver(qcom_hfpll_driver); | ||||||
|  | + | ||||||
|  | +MODULE_DESCRIPTION("QCOM HFPLL Clock Driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | +MODULE_ALIAS("platform:qcom-hfpll"); | ||||||
| @@ -0,0 +1,129 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:24 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,06/12] clk: qcom: Add IPQ806X's HFPLLs | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102047 | ||||||
|  | Message-Id: <1512726150-7204-7-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:24 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | Describe the HFPLLs present on IPQ806X devices. | ||||||
|  |  | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/gcc-ipq806x.c | 82 ++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 82 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | +++ b/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | @@ -30,6 +30,7 @@ | ||||||
|  |  #include "clk-pll.h" | ||||||
|  |  #include "clk-rcg.h" | ||||||
|  |  #include "clk-branch.h" | ||||||
|  | +#include "clk-hfpll.h" | ||||||
|  |  #include "reset.h" | ||||||
|  |   | ||||||
|  |  static struct clk_pll pll0 = { | ||||||
|  | @@ -113,6 +114,84 @@ static struct clk_regmap pll8_vote = { | ||||||
|  |  	}, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static struct hfpll_data hfpll0_data = { | ||||||
|  | +	.mode_reg = 0x3200, | ||||||
|  | +	.l_reg = 0x3208, | ||||||
|  | +	.m_reg = 0x320c, | ||||||
|  | +	.n_reg = 0x3210, | ||||||
|  | +	.config_reg = 0x3204, | ||||||
|  | +	.status_reg = 0x321c, | ||||||
|  | +	.config_val = 0x7845c665, | ||||||
|  | +	.droop_reg = 0x3214, | ||||||
|  | +	.droop_val = 0x0108c000, | ||||||
|  | +	.min_rate = 600000000UL, | ||||||
|  | +	.max_rate = 1800000000UL, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct clk_hfpll hfpll0 = { | ||||||
|  | +	.d = &hfpll0_data, | ||||||
|  | +	.clkr.hw.init = &(struct clk_init_data){ | ||||||
|  | +		.parent_names = (const char *[]){ "pxo" }, | ||||||
|  | +		.num_parents = 1, | ||||||
|  | +		.name = "hfpll0", | ||||||
|  | +		.ops = &clk_ops_hfpll, | ||||||
|  | +		.flags = CLK_IGNORE_UNUSED, | ||||||
|  | +	}, | ||||||
|  | +	.lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct hfpll_data hfpll1_data = { | ||||||
|  | +	.mode_reg = 0x3240, | ||||||
|  | +	.l_reg = 0x3248, | ||||||
|  | +	.m_reg = 0x324c, | ||||||
|  | +	.n_reg = 0x3250, | ||||||
|  | +	.config_reg = 0x3244, | ||||||
|  | +	.status_reg = 0x325c, | ||||||
|  | +	.config_val = 0x7845c665, | ||||||
|  | +	.droop_reg = 0x3314, | ||||||
|  | +	.droop_val = 0x0108c000, | ||||||
|  | +	.min_rate = 600000000UL, | ||||||
|  | +	.max_rate = 1800000000UL, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct clk_hfpll hfpll1 = { | ||||||
|  | +	.d = &hfpll1_data, | ||||||
|  | +	.clkr.hw.init = &(struct clk_init_data){ | ||||||
|  | +		.parent_names = (const char *[]){ "pxo" }, | ||||||
|  | +		.num_parents = 1, | ||||||
|  | +		.name = "hfpll1", | ||||||
|  | +		.ops = &clk_ops_hfpll, | ||||||
|  | +		.flags = CLK_IGNORE_UNUSED, | ||||||
|  | +	}, | ||||||
|  | +	.lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct hfpll_data hfpll_l2_data = { | ||||||
|  | +	.mode_reg = 0x3300, | ||||||
|  | +	.l_reg = 0x3308, | ||||||
|  | +	.m_reg = 0x330c, | ||||||
|  | +	.n_reg = 0x3310, | ||||||
|  | +	.config_reg = 0x3304, | ||||||
|  | +	.status_reg = 0x331c, | ||||||
|  | +	.config_val = 0x7845c665, | ||||||
|  | +	.droop_reg = 0x3314, | ||||||
|  | +	.droop_val = 0x0108c000, | ||||||
|  | +	.min_rate = 600000000UL, | ||||||
|  | +	.max_rate = 1800000000UL, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static struct clk_hfpll hfpll_l2 = { | ||||||
|  | +	.d = &hfpll_l2_data, | ||||||
|  | +	.clkr.hw.init = &(struct clk_init_data){ | ||||||
|  | +		.parent_names = (const char *[]){ "pxo" }, | ||||||
|  | +		.num_parents = 1, | ||||||
|  | +		.name = "hfpll_l2", | ||||||
|  | +		.ops = &clk_ops_hfpll, | ||||||
|  | +		.flags = CLK_IGNORE_UNUSED, | ||||||
|  | +	}, | ||||||
|  | +	.lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  static struct clk_pll pll14 = { | ||||||
|  |  	.l_reg = 0x31c4, | ||||||
|  |  	.m_reg = 0x31c8, | ||||||
|  | @@ -2801,6 +2880,9 @@ static struct clk_regmap *gcc_ipq806x_cl | ||||||
|  |  	[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, | ||||||
|  |  	[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, | ||||||
|  |  	[NSSTCM_CLK] = &nss_tcm_clk.clkr, | ||||||
|  | +	[PLL9] = &hfpll0.clkr, | ||||||
|  | +	[PLL10] = &hfpll1.clkr, | ||||||
|  | +	[PLL12] = &hfpll_l2.clkr, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const struct qcom_reset_map gcc_ipq806x_resets[] = { | ||||||
| @@ -0,0 +1,241 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:25 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,07/12] clk: qcom: Add support for Krait clocks | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102051 | ||||||
|  | Message-Id: <1512726150-7204-8-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:25 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | The Krait clocks are made up of a series of muxes and a divider | ||||||
|  | that choose between a fixed rate clock and dedicated HFPLLs for | ||||||
|  | each CPU. Instead of using mmio accesses to remux parents, the | ||||||
|  | Krait implementation exposes the remux control via cp15 | ||||||
|  | registers. Support these clocks. | ||||||
|  |  | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/Kconfig     |   4 ++ | ||||||
|  |  drivers/clk/qcom/Makefile    |   1 + | ||||||
|  |  drivers/clk/qcom/clk-krait.c | 134 +++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  drivers/clk/qcom/clk-krait.h |  48 ++++++++++++++++ | ||||||
|  |  4 files changed, 187 insertions(+) | ||||||
|  |  create mode 100644 drivers/clk/qcom/clk-krait.c | ||||||
|  |  create mode 100644 drivers/clk/qcom/clk-krait.h | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/Kconfig | ||||||
|  | +++ b/drivers/clk/qcom/Kconfig | ||||||
|  | @@ -204,3 +204,7 @@ config QCOM_HFPLL | ||||||
|  |  	  Support for the high-frequency PLLs present on Qualcomm devices. | ||||||
|  |  	  Say Y if you want to support CPU frequency scaling on devices | ||||||
|  |  	  such as MSM8974, APQ8084, etc. | ||||||
|  | + | ||||||
|  | +config KRAIT_CLOCKS | ||||||
|  | +	bool | ||||||
|  | +	select KRAIT_L2_ACCESSORS | ||||||
|  | --- a/drivers/clk/qcom/Makefile | ||||||
|  | +++ b/drivers/clk/qcom/Makefile | ||||||
|  | @@ -10,6 +10,7 @@ clk-qcom-y += clk-rcg2.o | ||||||
|  |  clk-qcom-y += clk-branch.o | ||||||
|  |  clk-qcom-y += clk-regmap-divider.o | ||||||
|  |  clk-qcom-y += clk-regmap-mux.o | ||||||
|  | +clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o | ||||||
|  |  clk-qcom-y += clk-hfpll.o | ||||||
|  |  clk-qcom-y += reset.o | ||||||
|  |  clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/clk-krait.c | ||||||
|  | @@ -0,0 +1,134 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | +#include <linux/spinlock.h> | ||||||
|  | + | ||||||
|  | +#include <asm/krait-l2-accessors.h> | ||||||
|  | + | ||||||
|  | +#include "clk-krait.h" | ||||||
|  | + | ||||||
|  | +/* Secondary and primary muxes share the same cp15 register */ | ||||||
|  | +static DEFINE_SPINLOCK(krait_clock_reg_lock); | ||||||
|  | + | ||||||
|  | +#define LPL_SHIFT	8 | ||||||
|  | +static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel) | ||||||
|  | +{ | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	u32 regval; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&krait_clock_reg_lock, flags); | ||||||
|  | +	regval = krait_get_l2_indirect_reg(mux->offset); | ||||||
|  | +	regval &= ~(mux->mask << mux->shift); | ||||||
|  | +	regval |= (sel & mux->mask) << mux->shift; | ||||||
|  | +	if (mux->lpl) { | ||||||
|  | +		regval &= ~(mux->mask << (mux->shift + LPL_SHIFT)); | ||||||
|  | +		regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); | ||||||
|  | +	} | ||||||
|  | +	krait_set_l2_indirect_reg(mux->offset, regval); | ||||||
|  | +	spin_unlock_irqrestore(&krait_clock_reg_lock, flags); | ||||||
|  | + | ||||||
|  | +	/* Wait for switch to complete. */ | ||||||
|  | +	mb(); | ||||||
|  | +	udelay(1); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int krait_mux_set_parent(struct clk_hw *hw, u8 index) | ||||||
|  | +{ | ||||||
|  | +	struct krait_mux_clk *mux = to_krait_mux_clk(hw); | ||||||
|  | +	u32 sel; | ||||||
|  | + | ||||||
|  | +	sel = clk_mux_reindex(index, mux->parent_map, 0); | ||||||
|  | +	mux->en_mask = sel; | ||||||
|  | +	/* Don't touch mux if CPU is off as it won't work */ | ||||||
|  | +	if (__clk_is_enabled(hw->clk)) | ||||||
|  | +		__krait_mux_set_sel(mux, sel); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static u8 krait_mux_get_parent(struct clk_hw *hw) | ||||||
|  | +{ | ||||||
|  | +	struct krait_mux_clk *mux = to_krait_mux_clk(hw); | ||||||
|  | +	u32 sel; | ||||||
|  | + | ||||||
|  | +	sel = krait_get_l2_indirect_reg(mux->offset); | ||||||
|  | +	sel >>= mux->shift; | ||||||
|  | +	sel &= mux->mask; | ||||||
|  | +	mux->en_mask = sel; | ||||||
|  | + | ||||||
|  | +	return clk_mux_get_parent(hw, sel, mux->parent_map, 0); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct clk_ops krait_mux_clk_ops = { | ||||||
|  | +	.set_parent = krait_mux_set_parent, | ||||||
|  | +	.get_parent = krait_mux_get_parent, | ||||||
|  | +	.determine_rate = __clk_mux_determine_rate_closest, | ||||||
|  | +}; | ||||||
|  | +EXPORT_SYMBOL_GPL(krait_mux_clk_ops); | ||||||
|  | + | ||||||
|  | +/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */ | ||||||
|  | +static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate, | ||||||
|  | +				  unsigned long *parent_rate) | ||||||
|  | +{ | ||||||
|  | +	*parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2); | ||||||
|  | +	return DIV_ROUND_UP(*parent_rate, 2); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, | ||||||
|  | +			       unsigned long parent_rate) | ||||||
|  | +{ | ||||||
|  | +	struct krait_div2_clk *d = to_krait_div2_clk(hw); | ||||||
|  | +	unsigned long flags; | ||||||
|  | +	u32 val; | ||||||
|  | +	u32 mask = BIT(d->width) - 1; | ||||||
|  | + | ||||||
|  | +	if (d->lpl) | ||||||
|  | +		mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift; | ||||||
|  | + | ||||||
|  | +	spin_lock_irqsave(&krait_clock_reg_lock, flags); | ||||||
|  | +	val = krait_get_l2_indirect_reg(d->offset); | ||||||
|  | +	val &= ~mask; | ||||||
|  | +	krait_set_l2_indirect_reg(d->offset, val); | ||||||
|  | +	spin_unlock_irqrestore(&krait_clock_reg_lock, flags); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static unsigned long | ||||||
|  | +krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | ||||||
|  | +{ | ||||||
|  | +	struct krait_div2_clk *d = to_krait_div2_clk(hw); | ||||||
|  | +	u32 mask = BIT(d->width) - 1; | ||||||
|  | +	u32 div; | ||||||
|  | + | ||||||
|  | +	div = krait_get_l2_indirect_reg(d->offset); | ||||||
|  | +	div >>= d->shift; | ||||||
|  | +	div &= mask; | ||||||
|  | +	div = (div + 1) * 2; | ||||||
|  | + | ||||||
|  | +	return DIV_ROUND_UP(parent_rate, div); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct clk_ops krait_div2_clk_ops = { | ||||||
|  | +	.round_rate = krait_div2_round_rate, | ||||||
|  | +	.set_rate = krait_div2_set_rate, | ||||||
|  | +	.recalc_rate = krait_div2_recalc_rate, | ||||||
|  | +}; | ||||||
|  | +EXPORT_SYMBOL_GPL(krait_div2_clk_ops); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/clk-krait.h | ||||||
|  | @@ -0,0 +1,48 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2013, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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 __QCOM_CLK_KRAIT_H | ||||||
|  | +#define __QCOM_CLK_KRAIT_H | ||||||
|  | + | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | + | ||||||
|  | +struct krait_mux_clk { | ||||||
|  | +	unsigned int	*parent_map; | ||||||
|  | +	u32		offset; | ||||||
|  | +	u32		mask; | ||||||
|  | +	u32		shift; | ||||||
|  | +	u32		en_mask; | ||||||
|  | +	bool		lpl; | ||||||
|  | + | ||||||
|  | +	struct clk_hw	hw; | ||||||
|  | +	struct notifier_block   clk_nb; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw) | ||||||
|  | + | ||||||
|  | +extern const struct clk_ops krait_mux_clk_ops; | ||||||
|  | + | ||||||
|  | +struct krait_div2_clk { | ||||||
|  | +	u32		offset; | ||||||
|  | +	u8		width; | ||||||
|  | +	u32		shift; | ||||||
|  | +	bool		lpl; | ||||||
|  | + | ||||||
|  | +	struct clk_hw	hw; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw) | ||||||
|  | + | ||||||
|  | +extern const struct clk_ops krait_div2_clk_ops; | ||||||
|  | + | ||||||
|  | +#endif | ||||||
| @@ -0,0 +1,209 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:26 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,08/12] clk: qcom: Add KPSS ACC/GCC driver | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102023 | ||||||
|  | Message-Id: <1512726150-7204-9-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:26 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | The ACC and GCC regions present in KPSSv1 contain registers to | ||||||
|  | control clocks and power to each Krait CPU and L2. For CPUfreq | ||||||
|  | purposes probe these devices and expose a mux clock that chooses | ||||||
|  | between PXO and PLL8. | ||||||
|  |  | ||||||
|  | Cc: <devicetree@vger.kernel.org> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  7 ++ | ||||||
|  |  .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  | 28 +++++++ | ||||||
|  |  drivers/clk/qcom/Kconfig                           |  8 ++ | ||||||
|  |  drivers/clk/qcom/Makefile                          |  1 + | ||||||
|  |  drivers/clk/qcom/kpss-xcc.c                        | 96 ++++++++++++++++++++++ | ||||||
|  |  5 files changed, 140 insertions(+) | ||||||
|  |  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt | ||||||
|  |  create mode 100644 drivers/clk/qcom/kpss-xcc.c | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt | ||||||
|  | @@ -21,10 +21,17 @@ PROPERTIES | ||||||
|  |  		    the register region. An optional second element specifies | ||||||
|  |  		    the base address and size of the alias register region. | ||||||
|  |   | ||||||
|  | +- clock-output-names: | ||||||
|  | +	Usage: optional | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: Name of the output clock. Typically acpuX_aux where X is a | ||||||
|  | +		    CPU number starting at 0. | ||||||
|  | + | ||||||
|  |  Example: | ||||||
|  |   | ||||||
|  |  	clock-controller@2088000 { | ||||||
|  |  		compatible = "qcom,kpss-acc-v2"; | ||||||
|  |  		reg = <0x02088000 0x1000>, | ||||||
|  |  		      <0x02008000 0x1000>; | ||||||
|  | +		clock-output-names = "acpu0_aux"; | ||||||
|  |  	}; | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt | ||||||
|  | @@ -0,0 +1,28 @@ | ||||||
|  | +Krait Processor Sub-system (KPSS) Global Clock Controller (GCC) | ||||||
|  | + | ||||||
|  | +PROPERTIES | ||||||
|  | + | ||||||
|  | +- compatible: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: should be one of: | ||||||
|  | +			"qcom,kpss-gcc" | ||||||
|  | + | ||||||
|  | +- reg: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <prop-encoded-array> | ||||||
|  | +	Definition: base address and size of the register region | ||||||
|  | + | ||||||
|  | +- clock-output-names: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: Name of the output clock. Typically acpu_l2_aux indicating | ||||||
|  | +		    an L2 cache auxiliary clock. | ||||||
|  | + | ||||||
|  | +Example: | ||||||
|  | + | ||||||
|  | +	l2cc: clock-controller@2011000 { | ||||||
|  | +		compatible = "qcom,kpss-gcc"; | ||||||
|  | +		reg = <0x2011000 0x1000>; | ||||||
|  | +		clock-output-names = "acpu_l2_aux"; | ||||||
|  | +	}; | ||||||
|  | --- a/drivers/clk/qcom/Kconfig | ||||||
|  | +++ b/drivers/clk/qcom/Kconfig | ||||||
|  | @@ -205,6 +205,14 @@ config QCOM_HFPLL | ||||||
|  |  	  Say Y if you want to support CPU frequency scaling on devices | ||||||
|  |  	  such as MSM8974, APQ8084, etc. | ||||||
|  |   | ||||||
|  | +config KPSS_XCC | ||||||
|  | +	tristate "KPSS Clock Controller" | ||||||
|  | +	depends on COMMON_CLK_QCOM | ||||||
|  | +	help | ||||||
|  | +	  Support for the Krait ACC and GCC clock controllers. Say Y | ||||||
|  | +	  if you want to support CPU frequency scaling on devices such | ||||||
|  | +	  as MSM8960, APQ8064, etc. | ||||||
|  | + | ||||||
|  |  config KRAIT_CLOCKS | ||||||
|  |  	bool | ||||||
|  |  	select KRAIT_L2_ACCESSORS | ||||||
|  | --- a/drivers/clk/qcom/Makefile | ||||||
|  | +++ b/drivers/clk/qcom/Makefile | ||||||
|  | @@ -36,4 +36,5 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8 | ||||||
|  |  obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o | ||||||
|  |  obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o | ||||||
|  |  obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o | ||||||
|  | +obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o | ||||||
|  |  obj-$(CONFIG_QCOM_HFPLL) += hfpll.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/kpss-xcc.c | ||||||
|  | @@ -0,0 +1,96 @@ | ||||||
|  | +/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/of_device.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | + | ||||||
|  | +static const char *aux_parents[] = { | ||||||
|  | +	"pll8_vote", | ||||||
|  | +	"pxo", | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static unsigned int aux_parent_map[] = { | ||||||
|  | +	3, | ||||||
|  | +	0, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct of_device_id kpss_xcc_match_table[] = { | ||||||
|  | +	{ .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL }, | ||||||
|  | +	{ .compatible = "qcom,kpss-gcc" }, | ||||||
|  | +	{} | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, kpss_xcc_match_table); | ||||||
|  | + | ||||||
|  | +static int kpss_xcc_driver_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	const struct of_device_id *id; | ||||||
|  | +	struct clk *clk; | ||||||
|  | +	struct resource *res; | ||||||
|  | +	void __iomem *base; | ||||||
|  | +	const char *name; | ||||||
|  | + | ||||||
|  | +	id = of_match_device(kpss_xcc_match_table, &pdev->dev); | ||||||
|  | +	if (!id) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | +	base = devm_ioremap_resource(&pdev->dev, res); | ||||||
|  | +	if (IS_ERR(base)) | ||||||
|  | +		return PTR_ERR(base); | ||||||
|  | + | ||||||
|  | +	if (id->data) { | ||||||
|  | +		if (of_property_read_string_index(pdev->dev.of_node, | ||||||
|  | +						  "clock-output-names", | ||||||
|  | +						  0, &name)) | ||||||
|  | +			return -ENODEV; | ||||||
|  | +		base += 0x14; | ||||||
|  | +	} else { | ||||||
|  | +		name = "acpu_l2_aux"; | ||||||
|  | +		base += 0x28; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk = clk_register_mux_table(&pdev->dev, name, aux_parents, | ||||||
|  | +				     ARRAY_SIZE(aux_parents), 0, base, 0, 0x3, | ||||||
|  | +				     0, aux_parent_map, NULL); | ||||||
|  | + | ||||||
|  | +	platform_set_drvdata(pdev, clk); | ||||||
|  | + | ||||||
|  | +	return PTR_ERR_OR_ZERO(clk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int kpss_xcc_driver_remove(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	clk_unregister_mux(platform_get_drvdata(pdev)); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver kpss_xcc_driver = { | ||||||
|  | +	.probe = kpss_xcc_driver_probe, | ||||||
|  | +	.remove = kpss_xcc_driver_remove, | ||||||
|  | +	.driver = { | ||||||
|  | +		.name = "kpss-xcc", | ||||||
|  | +		.of_match_table = kpss_xcc_match_table, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | +module_platform_driver(kpss_xcc_driver); | ||||||
|  | + | ||||||
|  | +MODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | +MODULE_ALIAS("platform:kpss-xcc"); | ||||||
| @@ -0,0 +1,436 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:27 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,09/12] clk: qcom: Add Krait clock controller driver | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102061 | ||||||
|  | Message-Id: <1512726150-7204-10-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:27 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | The Krait CPU clocks are made up of a primary mux and secondary | ||||||
|  | mux for each CPU and the L2, controlled via cp15 accessors. For | ||||||
|  | Kraits within KPSSv1 each secondary mux accepts a different aux | ||||||
|  | source, but on KPSSv2 each secondary mux accepts the same aux | ||||||
|  | source. | ||||||
|  |  | ||||||
|  | Cc: <devicetree@vger.kernel.org> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/clock/qcom,krait-cc.txt    |  22 ++ | ||||||
|  |  drivers/clk/qcom/Kconfig                           |   8 + | ||||||
|  |  drivers/clk/qcom/Makefile                          |   1 + | ||||||
|  |  drivers/clk/qcom/krait-cc.c                        | 350 +++++++++++++++++++++ | ||||||
|  |  4 files changed, 381 insertions(+) | ||||||
|  |  create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt | ||||||
|  |  create mode 100644 drivers/clk/qcom/krait-cc.c | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt | ||||||
|  | @@ -0,0 +1,22 @@ | ||||||
|  | +Krait Clock Controller | ||||||
|  | + | ||||||
|  | +PROPERTIES | ||||||
|  | + | ||||||
|  | +- compatible: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <string> | ||||||
|  | +	Definition: must be one of: | ||||||
|  | +			"qcom,krait-cc-v1" | ||||||
|  | +			"qcom,krait-cc-v2" | ||||||
|  | + | ||||||
|  | +- #clock-cells: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <u32> | ||||||
|  | +	Definition: must be 1 | ||||||
|  | + | ||||||
|  | +Example: | ||||||
|  | + | ||||||
|  | +	kraitcc: clock-controller { | ||||||
|  | +		compatible = "qcom,krait-cc-v1"; | ||||||
|  | +		#clock-cells = <1>; | ||||||
|  | +	}; | ||||||
|  | --- a/drivers/clk/qcom/Kconfig | ||||||
|  | +++ b/drivers/clk/qcom/Kconfig | ||||||
|  | @@ -213,6 +213,14 @@ config KPSS_XCC | ||||||
|  |  	  if you want to support CPU frequency scaling on devices such | ||||||
|  |  	  as MSM8960, APQ8064, etc. | ||||||
|  |   | ||||||
|  | +config KRAITCC | ||||||
|  | +	tristate "Krait Clock Controller" | ||||||
|  | +	depends on COMMON_CLK_QCOM && ARM | ||||||
|  | +	select KRAIT_CLOCKS | ||||||
|  | +	help | ||||||
|  | +	  Support for the Krait CPU clocks on Qualcomm devices. | ||||||
|  | +	  Say Y if you want to support CPU frequency scaling. | ||||||
|  | + | ||||||
|  |  config KRAIT_CLOCKS | ||||||
|  |  	bool | ||||||
|  |  	select KRAIT_L2_ACCESSORS | ||||||
|  | --- a/drivers/clk/qcom/Makefile | ||||||
|  | +++ b/drivers/clk/qcom/Makefile | ||||||
|  | @@ -38,3 +38,4 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o | ||||||
|  |  obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o | ||||||
|  |  obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o | ||||||
|  |  obj-$(CONFIG_QCOM_HFPLL) += hfpll.o | ||||||
|  | +obj-$(CONFIG_KRAITCC) += krait-cc.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/clk/qcom/krait-cc.c | ||||||
|  | @@ -0,0 +1,350 @@ | ||||||
|  | +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/kernel.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/of_device.h> | ||||||
|  | +#include <linux/clk.h> | ||||||
|  | +#include <linux/clk-provider.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | + | ||||||
|  | +#include "clk-krait.h" | ||||||
|  | + | ||||||
|  | +static unsigned int sec_mux_map[] = { | ||||||
|  | +	2, | ||||||
|  | +	0, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static unsigned int pri_mux_map[] = { | ||||||
|  | +	1, | ||||||
|  | +	2, | ||||||
|  | +	0, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) | ||||||
|  | +{ | ||||||
|  | +	struct krait_div2_clk *div; | ||||||
|  | +	struct clk_init_data init = { | ||||||
|  | +		.num_parents = 1, | ||||||
|  | +		.ops = &krait_div2_clk_ops, | ||||||
|  | +		.flags = CLK_SET_RATE_PARENT, | ||||||
|  | +	}; | ||||||
|  | +	const char *p_names[1]; | ||||||
|  | +	struct clk *clk; | ||||||
|  | + | ||||||
|  | +	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); | ||||||
|  | +	if (!div) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	div->width = 2; | ||||||
|  | +	div->shift = 6; | ||||||
|  | +	div->lpl = id >= 0; | ||||||
|  | +	div->offset = offset; | ||||||
|  | +	div->hw.init = &init; | ||||||
|  | + | ||||||
|  | +	init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s); | ||||||
|  | +	if (!init.name) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	init.parent_names = p_names; | ||||||
|  | +	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); | ||||||
|  | +	if (!p_names[0]) { | ||||||
|  | +		kfree(init.name); | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk = devm_clk_register(dev, &div->hw); | ||||||
|  | +	kfree(p_names[0]); | ||||||
|  | +	kfree(init.name); | ||||||
|  | + | ||||||
|  | +	return PTR_ERR_OR_ZERO(clk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +krait_add_sec_mux(struct device *dev, int id, const char *s, | ||||||
|  | +		  unsigned int offset, bool unique_aux) | ||||||
|  | +{ | ||||||
|  | +	struct krait_mux_clk *mux; | ||||||
|  | +	static const char *sec_mux_list[] = { | ||||||
|  | +		"acpu_aux", | ||||||
|  | +		"qsb", | ||||||
|  | +	}; | ||||||
|  | +	struct clk_init_data init = { | ||||||
|  | +		.parent_names = sec_mux_list, | ||||||
|  | +		.num_parents = ARRAY_SIZE(sec_mux_list), | ||||||
|  | +		.ops = &krait_mux_clk_ops, | ||||||
|  | +		.flags = CLK_SET_RATE_PARENT, | ||||||
|  | +	}; | ||||||
|  | +	struct clk *clk; | ||||||
|  | + | ||||||
|  | +	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); | ||||||
|  | +	if (!mux) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	mux->offset = offset; | ||||||
|  | +	mux->lpl = id >= 0; | ||||||
|  | +	mux->mask = 0x3; | ||||||
|  | +	mux->shift = 2; | ||||||
|  | +	mux->parent_map = sec_mux_map; | ||||||
|  | +	mux->hw.init = &init; | ||||||
|  | + | ||||||
|  | +	init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); | ||||||
|  | +	if (!init.name) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	if (unique_aux) { | ||||||
|  | +		sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s); | ||||||
|  | +		if (!sec_mux_list[0]) { | ||||||
|  | +			clk = ERR_PTR(-ENOMEM); | ||||||
|  | +			goto err_aux; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk = devm_clk_register(dev, &mux->hw); | ||||||
|  | + | ||||||
|  | +	if (unique_aux) | ||||||
|  | +		kfree(sec_mux_list[0]); | ||||||
|  | +err_aux: | ||||||
|  | +	kfree(init.name); | ||||||
|  | +	return PTR_ERR_OR_ZERO(clk); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct clk * | ||||||
|  | +krait_add_pri_mux(struct device *dev, int id, const char *s, | ||||||
|  | +		  unsigned int offset) | ||||||
|  | +{ | ||||||
|  | +	struct krait_mux_clk *mux; | ||||||
|  | +	const char *p_names[3]; | ||||||
|  | +	struct clk_init_data init = { | ||||||
|  | +		.parent_names = p_names, | ||||||
|  | +		.num_parents = ARRAY_SIZE(p_names), | ||||||
|  | +		.ops = &krait_mux_clk_ops, | ||||||
|  | +		.flags = CLK_SET_RATE_PARENT, | ||||||
|  | +	}; | ||||||
|  | +	struct clk *clk; | ||||||
|  | + | ||||||
|  | +	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); | ||||||
|  | +	if (!mux) | ||||||
|  | +		return ERR_PTR(-ENOMEM); | ||||||
|  | + | ||||||
|  | +	mux->mask = 0x3; | ||||||
|  | +	mux->shift = 0; | ||||||
|  | +	mux->offset = offset; | ||||||
|  | +	mux->lpl = id >= 0; | ||||||
|  | +	mux->parent_map = pri_mux_map; | ||||||
|  | +	mux->hw.init = &init; | ||||||
|  | + | ||||||
|  | +	init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); | ||||||
|  | +	if (!init.name) | ||||||
|  | +		return ERR_PTR(-ENOMEM); | ||||||
|  | + | ||||||
|  | +	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); | ||||||
|  | +	if (!p_names[0]) { | ||||||
|  | +		clk = ERR_PTR(-ENOMEM); | ||||||
|  | +		goto err_p0; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s); | ||||||
|  | +	if (!p_names[1]) { | ||||||
|  | +		clk = ERR_PTR(-ENOMEM); | ||||||
|  | +		goto err_p1; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); | ||||||
|  | +	if (!p_names[2]) { | ||||||
|  | +		clk = ERR_PTR(-ENOMEM); | ||||||
|  | +		goto err_p2; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk = devm_clk_register(dev, &mux->hw); | ||||||
|  | + | ||||||
|  | +	kfree(p_names[2]); | ||||||
|  | +err_p2: | ||||||
|  | +	kfree(p_names[1]); | ||||||
|  | +err_p1: | ||||||
|  | +	kfree(p_names[0]); | ||||||
|  | +err_p0: | ||||||
|  | +	kfree(init.name); | ||||||
|  | +	return clk; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/* id < 0 for L2, otherwise id == physical CPU number */ | ||||||
|  | +static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	unsigned int offset; | ||||||
|  | +	void *p = NULL; | ||||||
|  | +	const char *s; | ||||||
|  | +	struct clk *clk; | ||||||
|  | + | ||||||
|  | +	if (id >= 0) { | ||||||
|  | +		offset = 0x4501 + (0x1000 * id); | ||||||
|  | +		s = p = kasprintf(GFP_KERNEL, "%d", id); | ||||||
|  | +		if (!s) | ||||||
|  | +			return ERR_PTR(-ENOMEM); | ||||||
|  | +	} else { | ||||||
|  | +		offset = 0x500; | ||||||
|  | +		s = "_l2"; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = krait_add_div(dev, id, s, offset); | ||||||
|  | +	if (ret) { | ||||||
|  | +		clk = ERR_PTR(ret); | ||||||
|  | +		goto err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = krait_add_sec_mux(dev, id, s, offset, unique_aux); | ||||||
|  | +	if (ret) { | ||||||
|  | +		clk = ERR_PTR(ret); | ||||||
|  | +		goto err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	clk = krait_add_pri_mux(dev, id, s, offset); | ||||||
|  | +err: | ||||||
|  | +	kfree(p); | ||||||
|  | +	return clk; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data) | ||||||
|  | +{ | ||||||
|  | +	unsigned int idx = clkspec->args[0]; | ||||||
|  | +	struct clk **clks = data; | ||||||
|  | + | ||||||
|  | +	if (idx >= 5) { | ||||||
|  | +		pr_err("%s: invalid clock index %d\n", __func__, idx); | ||||||
|  | +		return ERR_PTR(-EINVAL); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return clks[idx] ? : ERR_PTR(-ENODEV); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct of_device_id krait_cc_match_table[] = { | ||||||
|  | +	{ .compatible = "qcom,krait-cc-v1", (void *)1UL }, | ||||||
|  | +	{ .compatible = "qcom,krait-cc-v2" }, | ||||||
|  | +	{} | ||||||
|  | +}; | ||||||
|  | +MODULE_DEVICE_TABLE(of, krait_cc_match_table); | ||||||
|  | + | ||||||
|  | +static int krait_cc_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device *dev = &pdev->dev; | ||||||
|  | +	const struct of_device_id *id; | ||||||
|  | +	unsigned long cur_rate, aux_rate; | ||||||
|  | +	int cpu; | ||||||
|  | +	struct clk *clk; | ||||||
|  | +	struct clk **clks; | ||||||
|  | +	struct clk *l2_pri_mux_clk; | ||||||
|  | + | ||||||
|  | +	id = of_match_device(krait_cc_match_table, dev); | ||||||
|  | +	if (!id) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	/* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ | ||||||
|  | +	clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); | ||||||
|  | +	if (IS_ERR(clk)) | ||||||
|  | +		return PTR_ERR(clk); | ||||||
|  | + | ||||||
|  | +	if (!id->data) { | ||||||
|  | +		clk = clk_register_fixed_factor(dev, "acpu_aux", | ||||||
|  | +						"gpll0_vote", 0, 1, 2); | ||||||
|  | +		if (IS_ERR(clk)) | ||||||
|  | +			return PTR_ERR(clk); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Krait configurations have at most 4 CPUs and one L2 */ | ||||||
|  | +	clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL); | ||||||
|  | +	if (!clks) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	for_each_possible_cpu(cpu) { | ||||||
|  | +		clk = krait_add_clks(dev, cpu, id->data); | ||||||
|  | +		if (IS_ERR(clk)) | ||||||
|  | +			return PTR_ERR(clk); | ||||||
|  | +		clks[cpu] = clk; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	l2_pri_mux_clk = krait_add_clks(dev, -1, id->data); | ||||||
|  | +	if (IS_ERR(l2_pri_mux_clk)) | ||||||
|  | +		return PTR_ERR(l2_pri_mux_clk); | ||||||
|  | +	clks[4] = l2_pri_mux_clk; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * We don't want the CPU or L2 clocks to be turned off at late init | ||||||
|  | +	 * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the | ||||||
|  | +	 * refcount of these clocks. Any cpufreq/hotplug manager can assume | ||||||
|  | +	 * that the clocks have already been prepared and enabled by the time | ||||||
|  | +	 * they take over. | ||||||
|  | +	 */ | ||||||
|  | +	for_each_online_cpu(cpu) { | ||||||
|  | +		clk_prepare_enable(l2_pri_mux_clk); | ||||||
|  | +		WARN(clk_prepare_enable(clks[cpu]), | ||||||
|  | +		     "Unable to turn on CPU%d clock", cpu); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * Force reinit of HFPLLs and muxes to overwrite any potential | ||||||
|  | +	 * incorrect configuration of HFPLLs and muxes by the bootloader. | ||||||
|  | +	 * While at it, also make sure the cores are running at known rates | ||||||
|  | +	 * and print the current rate. | ||||||
|  | +	 * | ||||||
|  | +	 * The clocks are set to aux clock rate first to make sure the | ||||||
|  | +	 * secondary mux is not sourcing off of QSB. The rate is then set to | ||||||
|  | +	 * two different rates to force a HFPLL reinit under all | ||||||
|  | +	 * circumstances. | ||||||
|  | +	 */ | ||||||
|  | +	cur_rate = clk_get_rate(l2_pri_mux_clk); | ||||||
|  | +	aux_rate = 384000000; | ||||||
|  | +	if (cur_rate == 1) { | ||||||
|  | +		pr_info("L2 @ QSB rate. Forcing new rate.\n"); | ||||||
|  | +		cur_rate = aux_rate; | ||||||
|  | +	} | ||||||
|  | +	clk_set_rate(l2_pri_mux_clk, aux_rate); | ||||||
|  | +	clk_set_rate(l2_pri_mux_clk, 2); | ||||||
|  | +	clk_set_rate(l2_pri_mux_clk, cur_rate); | ||||||
|  | +	pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000); | ||||||
|  | +	for_each_possible_cpu(cpu) { | ||||||
|  | +		clk = clks[cpu]; | ||||||
|  | +		cur_rate = clk_get_rate(clk); | ||||||
|  | +		if (cur_rate == 1) { | ||||||
|  | +			pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu); | ||||||
|  | +			cur_rate = aux_rate; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  | +		clk_set_rate(clk, aux_rate); | ||||||
|  | +		clk_set_rate(clk, 2); | ||||||
|  | +		clk_set_rate(clk, cur_rate); | ||||||
|  | +		pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	of_clk_add_provider(dev->of_node, krait_of_get, clks); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver krait_cc_driver = { | ||||||
|  | +	.probe = krait_cc_probe, | ||||||
|  | +	.driver = { | ||||||
|  | +		.name = "krait-cc", | ||||||
|  | +		.of_match_table = krait_cc_match_table, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | +module_platform_driver(krait_cc_driver); | ||||||
|  | + | ||||||
|  | +MODULE_DESCRIPTION("Krait CPU Clock Driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | +MODULE_ALIAS("platform:krait-cc"); | ||||||
| @@ -0,0 +1,160 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:28 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,10/12] clk: qcom: Add safe switch hook for krait mux clocks | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102057 | ||||||
|  | Message-Id: <1512726150-7204-11-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:28 +0530 | ||||||
|  |  | ||||||
|  | When the Hfplls are reprogrammed during the rate change, | ||||||
|  | the primary muxes which are sourced from the same hfpll | ||||||
|  | for higher frequencies, needs to be switched to the 'safe | ||||||
|  | secondary mux' as the parent for that small window. This | ||||||
|  | is done by registering a clk notifier for the muxes and | ||||||
|  | switching to the safe parent in the PRE_RATE_CHANGE notifier | ||||||
|  | and back to the original parent in the POST_RATE_CHANGE notifier. | ||||||
|  |  | ||||||
|  | Signed-off-by: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/clk-krait.c |  2 ++ | ||||||
|  |  drivers/clk/qcom/clk-krait.h |  3 +++ | ||||||
|  |  drivers/clk/qcom/krait-cc.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 61 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/clk-krait.c | ||||||
|  | +++ b/drivers/clk/qcom/clk-krait.c | ||||||
|  | @@ -60,6 +60,8 @@ static int krait_mux_set_parent(struct c | ||||||
|  |  	if (__clk_is_enabled(hw->clk)) | ||||||
|  |  		__krait_mux_set_sel(mux, sel); | ||||||
|  |   | ||||||
|  | +	mux->reparent = true; | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- a/drivers/clk/qcom/clk-krait.h | ||||||
|  | +++ b/drivers/clk/qcom/clk-krait.h | ||||||
|  | @@ -23,6 +23,9 @@ struct krait_mux_clk { | ||||||
|  |  	u32		shift; | ||||||
|  |  	u32		en_mask; | ||||||
|  |  	bool		lpl; | ||||||
|  | +	u8		safe_sel; | ||||||
|  | +	u8		old_index; | ||||||
|  | +	bool		reparent; | ||||||
|  |   | ||||||
|  |  	struct clk_hw	hw; | ||||||
|  |  	struct notifier_block   clk_nb; | ||||||
|  | --- a/drivers/clk/qcom/krait-cc.c | ||||||
|  | +++ b/drivers/clk/qcom/krait-cc.c | ||||||
|  | @@ -35,6 +35,49 @@ static unsigned int pri_mux_map[] = { | ||||||
|  |  	0, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/* | ||||||
|  | + * Notifier function for switching the muxes to safe parent | ||||||
|  | + * while the hfpll is getting reprogrammed. | ||||||
|  | + */ | ||||||
|  | +static int krait_notifier_cb(struct notifier_block *nb, | ||||||
|  | +			     unsigned long event, | ||||||
|  | +			     void *data) | ||||||
|  | +{ | ||||||
|  | +	int ret = 0; | ||||||
|  | +	struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk, | ||||||
|  | +						 clk_nb); | ||||||
|  | +	/* Switch to safe parent */ | ||||||
|  | +	if (event == PRE_RATE_CHANGE) { | ||||||
|  | +		mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw); | ||||||
|  | +		ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel); | ||||||
|  | +		mux->reparent = false; | ||||||
|  | +	/* | ||||||
|  | +	 * By the time POST_RATE_CHANGE notifier is called, | ||||||
|  | +	 * clk framework itself would have changed the parent for the new rate. | ||||||
|  | +	 * Only otherwise, put back to the old parent. | ||||||
|  | +	 */ | ||||||
|  | +	} else if (event == POST_RATE_CHANGE) { | ||||||
|  | +		if (!mux->reparent) | ||||||
|  | +			ret = krait_mux_clk_ops.set_parent(&mux->hw, | ||||||
|  | +							   mux->old_index); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return notifier_from_errno(ret); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int krait_notifier_register(struct device *dev, struct clk *clk, | ||||||
|  | +				   struct krait_mux_clk *mux) | ||||||
|  | +{ | ||||||
|  | +	int ret = 0; | ||||||
|  | + | ||||||
|  | +	mux->clk_nb.notifier_call = krait_notifier_cb; | ||||||
|  | +	ret = clk_notifier_register(clk, &mux->clk_nb); | ||||||
|  | +	if (ret) | ||||||
|  | +		dev_err(dev, "failed to register clock notifier: %d\n", ret); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int | ||||||
|  |  krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) | ||||||
|  |  { | ||||||
|  | @@ -79,6 +122,7 @@ static int | ||||||
|  |  krait_add_sec_mux(struct device *dev, int id, const char *s, | ||||||
|  |  		  unsigned int offset, bool unique_aux) | ||||||
|  |  { | ||||||
|  | +	int ret; | ||||||
|  |  	struct krait_mux_clk *mux; | ||||||
|  |  	static const char *sec_mux_list[] = { | ||||||
|  |  		"acpu_aux", | ||||||
|  | @@ -102,6 +146,7 @@ krait_add_sec_mux(struct device *dev, in | ||||||
|  |  	mux->shift = 2; | ||||||
|  |  	mux->parent_map = sec_mux_map; | ||||||
|  |  	mux->hw.init = &init; | ||||||
|  | +	mux->safe_sel = 0; | ||||||
|  |   | ||||||
|  |  	init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); | ||||||
|  |  	if (!init.name) | ||||||
|  | @@ -117,6 +162,11 @@ krait_add_sec_mux(struct device *dev, in | ||||||
|  |   | ||||||
|  |  	clk = devm_clk_register(dev, &mux->hw); | ||||||
|  |   | ||||||
|  | +	ret = krait_notifier_register(dev, clk, mux); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto unique_aux; | ||||||
|  | + | ||||||
|  | +unique_aux: | ||||||
|  |  	if (unique_aux) | ||||||
|  |  		kfree(sec_mux_list[0]); | ||||||
|  |  err_aux: | ||||||
|  | @@ -128,6 +178,7 @@ static struct clk * | ||||||
|  |  krait_add_pri_mux(struct device *dev, int id, const char *s, | ||||||
|  |  		  unsigned int offset) | ||||||
|  |  { | ||||||
|  | +	int ret; | ||||||
|  |  	struct krait_mux_clk *mux; | ||||||
|  |  	const char *p_names[3]; | ||||||
|  |  	struct clk_init_data init = { | ||||||
|  | @@ -148,6 +199,7 @@ krait_add_pri_mux(struct device *dev, in | ||||||
|  |  	mux->lpl = id >= 0; | ||||||
|  |  	mux->parent_map = pri_mux_map; | ||||||
|  |  	mux->hw.init = &init; | ||||||
|  | +	mux->safe_sel = 2; | ||||||
|  |   | ||||||
|  |  	init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); | ||||||
|  |  	if (!init.name) | ||||||
|  | @@ -173,6 +225,10 @@ krait_add_pri_mux(struct device *dev, in | ||||||
|  |   | ||||||
|  |  	clk = devm_clk_register(dev, &mux->hw); | ||||||
|  |   | ||||||
|  | +	ret = krait_notifier_register(dev, clk, mux); | ||||||
|  | +	if (ret) | ||||||
|  | +		goto err_p3; | ||||||
|  | +err_p3: | ||||||
|  |  	kfree(p_names[2]); | ||||||
|  |  err_p2: | ||||||
|  |  	kfree(p_names[1]); | ||||||
| @@ -0,0 +1,307 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:29 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,11/12] cpufreq: Add module to register cpufreq on Krait CPUs | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102075 | ||||||
|  | Message-Id: <1512726150-7204-12-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:29 +0530 | ||||||
|  |  | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  |  | ||||||
|  | Register a cpufreq-generic device whenever we detect that a | ||||||
|  | "qcom,krait" compatible CPU is present in DT. | ||||||
|  |  | ||||||
|  | Cc: <devicetree@vger.kernel.org> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/arm/msm/qcom,pvs.txt       |  38 ++++ | ||||||
|  |  drivers/cpufreq/Kconfig.arm                        |   9 + | ||||||
|  |  drivers/cpufreq/Makefile                           |   1 + | ||||||
|  |  drivers/cpufreq/qcom-cpufreq.c                     | 204 +++++++++++++++++++++ | ||||||
|  |  4 files changed, 252 insertions(+) | ||||||
|  |  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt | ||||||
|  |  create mode 100644 drivers/cpufreq/qcom-cpufreq.c | ||||||
|  |  | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt | ||||||
|  | @@ -0,0 +1,38 @@ | ||||||
|  | +Qualcomm Process Voltage Scaling Tables | ||||||
|  | + | ||||||
|  | +The node name is required to be "qcom,pvs". There shall only be one | ||||||
|  | +such node present in the root of the tree. | ||||||
|  | + | ||||||
|  | +PROPERTIES | ||||||
|  | + | ||||||
|  | +- qcom,pvs-format-a or qcom,pvs-format-b: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <empty> | ||||||
|  | +	Definition: Indicates the format of qcom,speedX-pvsY-bin-vZ properties. | ||||||
|  | +		    If qcom,pvs-format-a is used the table is two columns | ||||||
|  | +		    (frequency and voltage in that order). If qcom,pvs-format-b 		    is used the table is three columns (frequency, voltage, | ||||||
|  | +		    and current in that order). | ||||||
|  | + | ||||||
|  | +- qcom,speedX-pvsY-bin-vZ: | ||||||
|  | +	Usage: required | ||||||
|  | +	Value type: <prop-encoded-array> | ||||||
|  | +	Definition: The PVS table corresponding to the speed bin X, pvs bin Y, | ||||||
|  | +		    and version Z. | ||||||
|  | +Example: | ||||||
|  | + | ||||||
|  | +	qcom,pvs { | ||||||
|  | +		qcom,pvs-format-a; | ||||||
|  | +		qcom,speed0-pvs0-bin-v0 = | ||||||
|  | +			<  384000000  950000 >, | ||||||
|  | +			<  486000000  975000 >, | ||||||
|  | +			<  594000000 1000000 >, | ||||||
|  | +			<  702000000 1025000 >, | ||||||
|  | +			<  810000000 1075000 >, | ||||||
|  | +			<  918000000 1100000 >, | ||||||
|  | +			< 1026000000 1125000 >, | ||||||
|  | +			< 1134000000 1175000 >, | ||||||
|  | +			< 1242000000 1200000 >, | ||||||
|  | +			< 1350000000 1225000 >, | ||||||
|  | +			< 1458000000 1237500 >, | ||||||
|  | +			< 1512000000 1250000 >; | ||||||
|  | +	}; | ||||||
|  | --- a/drivers/cpufreq/Kconfig.arm | ||||||
|  | +++ b/drivers/cpufreq/Kconfig.arm | ||||||
|  | @@ -100,6 +100,15 @@ config ARM_OMAP2PLUS_CPUFREQ | ||||||
|  |  	depends on ARCH_OMAP2PLUS | ||||||
|  |  	default ARCH_OMAP2PLUS | ||||||
|  |   | ||||||
|  | +config ARM_QCOM_CPUFREQ | ||||||
|  | +	tristate "Qualcomm based" | ||||||
|  | +	depends on ARCH_QCOM | ||||||
|  | +	select PM_OPP | ||||||
|  | +	help | ||||||
|  | +	  This adds the CPUFreq driver for Qualcomm SoC based boards. | ||||||
|  | + | ||||||
|  | +	  If in doubt, say N. | ||||||
|  | + | ||||||
|  |  config ARM_S3C_CPUFREQ | ||||||
|  |  	bool | ||||||
|  |  	help | ||||||
|  | --- a/drivers/cpufreq/Makefile | ||||||
|  | +++ b/drivers/cpufreq/Makefile | ||||||
|  | @@ -62,6 +62,7 @@ obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ)	+= me | ||||||
|  |  obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o | ||||||
|  |  obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o | ||||||
|  |  obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o | ||||||
|  | +obj-$(CONFIG_ARM_QCOM_CPUFREQ)		+= qcom-cpufreq.o | ||||||
|  |  obj-$(CONFIG_ARM_S3C24XX_CPUFREQ)	+= s3c24xx-cpufreq.o | ||||||
|  |  obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o | ||||||
|  |  obj-$(CONFIG_ARM_S3C2410_CPUFREQ)	+= s3c2410-cpufreq.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/cpufreq/qcom-cpufreq.c | ||||||
|  | @@ -0,0 +1,204 @@ | ||||||
|  | +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/cpu.h> | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/init.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/kernel.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/pm_opp.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | +#include "cpufreq-dt.h" | ||||||
|  | + | ||||||
|  | +static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver) | ||||||
|  | +{ | ||||||
|  | +	void __iomem *base; | ||||||
|  | +	u32 pte_efuse; | ||||||
|  | + | ||||||
|  | +	*speed = *pvs = *pvs_ver = 0; | ||||||
|  | + | ||||||
|  | +	base = ioremap(0x007000c0, 4); | ||||||
|  | +	if (!base) { | ||||||
|  | +		pr_warn("Unable to read efuse data. Defaulting to 0!\n"); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	pte_efuse = readl_relaxed(base); | ||||||
|  | +	iounmap(base); | ||||||
|  | + | ||||||
|  | +	*speed = pte_efuse & 0xf; | ||||||
|  | +	if (*speed == 0xf) | ||||||
|  | +		*speed = (pte_efuse >> 4) & 0xf; | ||||||
|  | + | ||||||
|  | +	if (*speed == 0xf) { | ||||||
|  | +		*speed = 0; | ||||||
|  | +		pr_warn("Speed bin: Defaulting to %d\n", *speed); | ||||||
|  | +	} else { | ||||||
|  | +		pr_info("Speed bin: %d\n", *speed); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	*pvs = (pte_efuse >> 10) & 0x7; | ||||||
|  | +	if (*pvs == 0x7) | ||||||
|  | +		*pvs = (pte_efuse >> 13) & 0x7; | ||||||
|  | + | ||||||
|  | +	if (*pvs == 0x7) { | ||||||
|  | +		*pvs = 0; | ||||||
|  | +		pr_warn("PVS bin: Defaulting to %d\n", *pvs); | ||||||
|  | +	} else { | ||||||
|  | +		pr_info("PVS bin: %d\n", *pvs); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void __init get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver) | ||||||
|  | +{ | ||||||
|  | +	u32 pte_efuse, redundant_sel; | ||||||
|  | +	void __iomem *base; | ||||||
|  | + | ||||||
|  | +	*speed = 0; | ||||||
|  | +	*pvs = 0; | ||||||
|  | +	*pvs_ver = 0; | ||||||
|  | + | ||||||
|  | +	base = ioremap(0xfc4b80b0, 8); | ||||||
|  | +	if (!base) { | ||||||
|  | +		pr_warn("Unable to read efuse data. Defaulting to 0!\n"); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	pte_efuse = readl_relaxed(base); | ||||||
|  | +	redundant_sel = (pte_efuse >> 24) & 0x7; | ||||||
|  | +	*speed = pte_efuse & 0x7; | ||||||
|  | +	/* 4 bits of PVS are in efuse register bits 31, 8-6. */ | ||||||
|  | +	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7); | ||||||
|  | +	*pvs_ver = (pte_efuse >> 4) & 0x3; | ||||||
|  | + | ||||||
|  | +	switch (redundant_sel) { | ||||||
|  | +	case 1: | ||||||
|  | +		*speed = (pte_efuse >> 27) & 0xf; | ||||||
|  | +		break; | ||||||
|  | +	case 2: | ||||||
|  | +		*pvs = (pte_efuse >> 27) & 0xf; | ||||||
|  | +		break; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Check SPEED_BIN_BLOW_STATUS */ | ||||||
|  | +	if (pte_efuse & BIT(3)) { | ||||||
|  | +		pr_info("Speed bin: %d\n", *speed); | ||||||
|  | +	} else { | ||||||
|  | +		pr_warn("Speed bin not set. Defaulting to 0!\n"); | ||||||
|  | +		*speed = 0; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Check PVS_BLOW_STATUS */ | ||||||
|  | +	pte_efuse = readl_relaxed(base + 0x4) & BIT(21); | ||||||
|  | +	if (pte_efuse) { | ||||||
|  | +		pr_info("PVS bin: %d\n", *pvs); | ||||||
|  | +	} else { | ||||||
|  | +		pr_warn("PVS bin not set. Defaulting to 0!\n"); | ||||||
|  | +		*pvs = 0; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	pr_info("PVS version: %d\n", *pvs_ver); | ||||||
|  | +	iounmap(base); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init qcom_cpufreq_populate_opps(void) | ||||||
|  | +{ | ||||||
|  | +	int len, rows, cols, i, k, speed, pvs, pvs_ver; | ||||||
|  | +	char table_name[] = "qcom,speedXX-pvsXX-bin-vXX"; | ||||||
|  | +	struct device_node *np; | ||||||
|  | +	struct device *dev; | ||||||
|  | +	int cpu = 0; | ||||||
|  | + | ||||||
|  | +	np = of_find_node_by_name(NULL, "qcom,pvs"); | ||||||
|  | +	if (!np) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	if (of_property_read_bool(np, "qcom,pvs-format-a")) { | ||||||
|  | +		get_krait_bin_format_a(&speed, &pvs, &pvs_ver); | ||||||
|  | +		cols = 2; | ||||||
|  | +	} else if (of_property_read_bool(np, "qcom,pvs-format-b")) { | ||||||
|  | +		get_krait_bin_format_b(&speed, &pvs, &pvs_ver); | ||||||
|  | +		cols = 3; | ||||||
|  | +	} else { | ||||||
|  | +		return -ENODEV; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	snprintf(table_name, sizeof(table_name), | ||||||
|  | +		 "qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver); | ||||||
|  | + | ||||||
|  | +	if (!of_find_property(np, table_name, &len)) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	len /= sizeof(u32); | ||||||
|  | +	if (len % cols || len == 0) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	rows = len / cols; | ||||||
|  | + | ||||||
|  | +	for (i = 0, k = 0; i < rows; i++) { | ||||||
|  | +		u32 freq, volt; | ||||||
|  | + | ||||||
|  | +		of_property_read_u32_index(np, table_name, k++, &freq); | ||||||
|  | +		of_property_read_u32_index(np, table_name, k++, &volt); | ||||||
|  | +		while (k % cols) | ||||||
|  | +			k++; /* Skip uA entries if present */ | ||||||
|  | +		for (cpu = 0; cpu < num_possible_cpus(); cpu++) { | ||||||
|  | +			dev = get_cpu_device(cpu); | ||||||
|  | +			if (!dev) | ||||||
|  | +				return -ENODEV; | ||||||
|  | +			if (dev_pm_opp_add(dev, freq, volt)) | ||||||
|  | +				pr_warn("failed to add OPP %u\n", freq); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __init qcom_cpufreq_driver_init(void) | ||||||
|  | +{ | ||||||
|  | +	struct cpufreq_dt_platform_data pdata = { .independent_clocks = true }; | ||||||
|  | +	struct platform_device_info devinfo = { | ||||||
|  | +		.name = "cpufreq-dt", | ||||||
|  | +		.data = &pdata, | ||||||
|  | +		.size_data = sizeof(pdata), | ||||||
|  | +	}; | ||||||
|  | +	struct device *cpu_dev; | ||||||
|  | +	struct device_node *np; | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	cpu_dev = get_cpu_device(0); | ||||||
|  | +	if (!cpu_dev) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	np = of_node_get(cpu_dev->of_node); | ||||||
|  | +	if (!np) | ||||||
|  | +		return -ENOENT; | ||||||
|  | + | ||||||
|  | +	if (!of_device_is_compatible(np, "qcom,krait")) { | ||||||
|  | +		of_node_put(np); | ||||||
|  | +		return -ENODEV; | ||||||
|  | +	} | ||||||
|  | +	of_node_put(np); | ||||||
|  | + | ||||||
|  | +	ret = qcom_cpufreq_populate_opps(); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return PTR_ERR_OR_ZERO(platform_device_register_full(&devinfo)); | ||||||
|  | +} | ||||||
|  | +module_init(qcom_cpufreq_driver_init); | ||||||
|  | + | ||||||
|  | +MODULE_DESCRIPTION("Qualcomm CPUfreq driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
| @@ -0,0 +1,66 @@ | |||||||
|  | From patchwork Fri Dec  8 09:42:30 2017 | ||||||
|  | Content-Type: text/plain; charset="utf-8" | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Transfer-Encoding: 7bit | ||||||
|  | Subject: [v4,12/12] cpufreq: dt: Reintroduce independent_clocks platform data | ||||||
|  | From: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | X-Patchwork-Id: 10102073 | ||||||
|  | Message-Id: <1512726150-7204-13-git-send-email-sricharan@codeaurora.org> | ||||||
|  | To: mturquette@baylibre.com, sboyd@codeaurora.org, | ||||||
|  |  devicetree@vger.kernel.org, linux-pm@vger.kernel.org, | ||||||
|  |  linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, | ||||||
|  |  viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org | ||||||
|  | Cc: sricharan@codeaurora.org | ||||||
|  | Date: Fri,  8 Dec 2017 15:12:30 +0530 | ||||||
|  |  | ||||||
|  | The Platform data was removed earlier by, | ||||||
|  | 'commit eb96924acddc ("cpufreq: dt: Kill platform-data")' | ||||||
|  | since there were no users at that time. | ||||||
|  | Now this is required when the each of the cpu clocks | ||||||
|  | can be scaled independently, which is the case | ||||||
|  | for krait cores. So reintroduce it. | ||||||
|  |  | ||||||
|  | Signed-off-by: Sricharan R <sricharan@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/cpufreq/cpufreq-dt.c | 7 ++++++- | ||||||
|  |  drivers/cpufreq/cpufreq-dt.h | 6 ++++++ | ||||||
|  |  2 files changed, 12 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | +++ b/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | @@ -231,7 +231,10 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (fallback) { | ||||||
|  | -		cpumask_setall(policy->cpus); | ||||||
|  | +		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data(); | ||||||
|  | + | ||||||
|  | +		if (!pd || !pd->independent_clocks) | ||||||
|  | +			cpumask_setall(policy->cpus); | ||||||
|  |   | ||||||
|  |  		/* | ||||||
|  |  		 * OPP tables are initialized only for policy->cpu, do it for | ||||||
|  | @@ -376,6 +379,8 @@ static int dt_cpufreq_probe(struct platf | ||||||
|  |  	if (data && data->have_governor_per_policy) | ||||||
|  |  		dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY; | ||||||
|  |   | ||||||
|  | +	dt_cpufreq_driver.driver_data = data; | ||||||
|  | + | ||||||
|  |  	ret = cpufreq_register_driver(&dt_cpufreq_driver); | ||||||
|  |  	if (ret) | ||||||
|  |  		dev_err(&pdev->dev, "failed register driver: %d\n", ret); | ||||||
|  | --- a/drivers/cpufreq/cpufreq-dt.h | ||||||
|  | +++ b/drivers/cpufreq/cpufreq-dt.h | ||||||
|  | @@ -13,6 +13,12 @@ | ||||||
|  |  #include <linux/types.h> | ||||||
|  |   | ||||||
|  |  struct cpufreq_dt_platform_data { | ||||||
|  | +	/* | ||||||
|  | +	 * True when each CPU has its own clock to control its | ||||||
|  | +	 * frequency, false when all CPUs are controlled by a single | ||||||
|  | +	 * clock. | ||||||
|  | +	 */ | ||||||
|  | +	bool independent_clocks; | ||||||
|  |  	bool have_governor_per_policy; | ||||||
|  |  }; | ||||||
|  |   | ||||||
| @@ -0,0 +1,72 @@ | |||||||
|  | From c7c6a0f50f9ac3620c611ce06ba1f9fafea0444e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Archit Taneja <architt@codeaurora.org> | ||||||
|  | Date: Mon, 3 Aug 2015 10:38:14 +0530 | ||||||
|  | Subject: [PATCH 47/69] mtd: nand: Create a BBT flag to access bad block | ||||||
|  |  markers in raw mode | ||||||
|  |  | ||||||
|  | Some controllers can access the factory bad block marker from OOB only | ||||||
|  | when they read it in raw mode. When ECC is enabled, these controllers | ||||||
|  | discard reading/writing bad block markers, preventing access to them | ||||||
|  | altogether. | ||||||
|  |  | ||||||
|  | The bbt driver assumes MTD_OPS_PLACE_OOB when scanning for bad blocks. | ||||||
|  | This results in the nand driver's ecc->read_oob() op to be called, which | ||||||
|  | works with ECC enabled. | ||||||
|  |  | ||||||
|  | Create a new BBT option flag that tells nand_bbt to force the mode to | ||||||
|  | MTD_OPS_RAW. This would result in the correct op being called for the | ||||||
|  | underlying nand controller driver. | ||||||
|  |  | ||||||
|  | Reviewed-by: Andy Gross <agross@codeaurora.org> | ||||||
|  | Signed-off-by: Archit Taneja <architt@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/nand/nand_base.c | 6 +++++- | ||||||
|  |  drivers/mtd/nand/nand_bbt.c  | 6 +++++- | ||||||
|  |  include/linux/mtd/bbm.h      | 6 ++++++ | ||||||
|  |  3 files changed, 16 insertions(+), 2 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/nand/nand_base.c | ||||||
|  | +++ b/drivers/mtd/nand/nand_base.c | ||||||
|  | @@ -481,7 +481,11 @@ static int nand_default_block_markbad(st | ||||||
|  |  	} else { | ||||||
|  |  		ops.len = ops.ooblen = 1; | ||||||
|  |  	} | ||||||
|  | -	ops.mode = MTD_OPS_PLACE_OOB; | ||||||
|  | + | ||||||
|  | +	if (unlikely(chip->bbt_options & NAND_BBT_ACCESS_BBM_RAW)) | ||||||
|  | +		ops.mode = MTD_OPS_RAW; | ||||||
|  | +	else | ||||||
|  | +		ops.mode = MTD_OPS_PLACE_OOB; | ||||||
|  |   | ||||||
|  |  	/* Write to first/last page(s) if necessary */ | ||||||
|  |  	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | ||||||
|  | --- a/drivers/mtd/nand/nand_bbt.c | ||||||
|  | +++ b/drivers/mtd/nand/nand_bbt.c | ||||||
|  | @@ -420,7 +420,11 @@ static int scan_block_fast(struct mtd_in | ||||||
|  |  	ops.oobbuf = buf; | ||||||
|  |  	ops.ooboffs = 0; | ||||||
|  |  	ops.datbuf = NULL; | ||||||
|  | -	ops.mode = MTD_OPS_PLACE_OOB; | ||||||
|  | + | ||||||
|  | +	if (unlikely(bd->options & NAND_BBT_ACCESS_BBM_RAW)) | ||||||
|  | +		ops.mode = MTD_OPS_RAW; | ||||||
|  | +	else | ||||||
|  | +		ops.mode = MTD_OPS_PLACE_OOB; | ||||||
|  |   | ||||||
|  |  	for (j = 0; j < numpages; j++) { | ||||||
|  |  		/* | ||||||
|  | --- a/include/linux/mtd/bbm.h | ||||||
|  | +++ b/include/linux/mtd/bbm.h | ||||||
|  | @@ -116,6 +116,12 @@ struct nand_bbt_descr { | ||||||
|  |  #define NAND_BBT_NO_OOB_BBM	0x00080000 | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | + * Force MTD_OPS_RAW mode when trying to access bad block markes from OOB. To | ||||||
|  | + * be used by controllers which can access BBM only when ECC is disabled, i.e, | ||||||
|  | + * when in RAW access mode | ||||||
|  | + */ | ||||||
|  | +#define NAND_BBT_ACCESS_BBM_RAW        0x00100000 | ||||||
|  | +/* | ||||||
|  |   * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr | ||||||
|  |   * was allocated dynamicaly and must be freed in nand_release(). Has no meaning | ||||||
|  |   * in nand_chip.bbt_options. | ||||||
| @@ -0,0 +1,26 @@ | |||||||
|  | From 5c294df1715d673f94f3b0a6e1ea3a426ca35e6e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | Date: Thu, 28 Apr 2016 16:20:12 +0300 | ||||||
|  | Subject: [PATCH 48/69] PM / OPP: HACK: Allow to set regulator without opp_list | ||||||
|  |  | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/base/power/opp/core.c | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/base/power/opp/core.c | ||||||
|  | +++ b/drivers/base/power/opp/core.c | ||||||
|  | @@ -1280,11 +1280,13 @@ struct opp_table *dev_pm_opp_set_regulat | ||||||
|  |  	if (!opp_table) | ||||||
|  |  		return ERR_PTR(-ENOMEM); | ||||||
|  |   | ||||||
|  | +#if 0 | ||||||
|  |  	/* This should be called before OPPs are initialized */ | ||||||
|  |  	if (WARN_ON(!list_empty(&opp_table->opp_list))) { | ||||||
|  |  		ret = -EBUSY; | ||||||
|  |  		goto err; | ||||||
|  |  	} | ||||||
|  | +#endif | ||||||
|  |   | ||||||
|  |  	/* Already have regulators set */ | ||||||
|  |  	if (opp_table->regulators) { | ||||||
| @@ -0,0 +1,147 @@ | |||||||
|  | From c949f08cf20fe82971fbdb4015daa38210da492e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | Date: Fri, 18 Sep 2015 17:52:06 -0700 | ||||||
|  | Subject: [PATCH 49/69] PM / OPP: Support adjusting OPP voltages at runtime | ||||||
|  |  | ||||||
|  | On some SoCs the Adaptive Voltage Scaling (AVS) technique is | ||||||
|  | employed to optimize the operating voltage of a device. At a | ||||||
|  | given frequency, the hardware monitors dynamic factors and either | ||||||
|  | makes a suggestion for how much to adjust a voltage for the | ||||||
|  | current frequency, or it automatically adjusts the voltage | ||||||
|  | without software intervention. Add an API to the OPP library for | ||||||
|  | the former case, so that AVS type devices can update the voltages | ||||||
|  | for an OPP when the hardware determines the voltage should | ||||||
|  | change. The assumption is that drivers like CPUfreq or devfreq | ||||||
|  | will register for the OPP notifiers and adjust the voltage | ||||||
|  | according to suggestions that AVS makes. | ||||||
|  |  | ||||||
|  | Cc: Nishanth Menon <nm@ti.com> | ||||||
|  | Acked-by: Viresh Kumar <viresh.kumar@linaro.org> | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | Acked-by: Viresh Kumar <viresh.kumar@linaro.org> | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/base/power/opp/core.c | 77 +++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  include/linux/pm_opp.h        | 11 +++++++ | ||||||
|  |  2 files changed, 88 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/base/power/opp/core.c | ||||||
|  | +++ b/drivers/base/power/opp/core.c | ||||||
|  | @@ -1608,6 +1608,83 @@ put_table: | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | + * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP | ||||||
|  | + * @dev:		device for which we do this operation | ||||||
|  | + * @freq:		OPP frequency to adjust voltage of | ||||||
|  | + * @u_volt:		new OPP voltage | ||||||
|  | + * | ||||||
|  | + * Change the voltage of an OPP with an RCU operation. | ||||||
|  | + * | ||||||
|  | + * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the | ||||||
|  | + * copy operation, returns 0 if no modifcation was done OR modification was | ||||||
|  | + * successful. | ||||||
|  | + * | ||||||
|  | + * Locking: The internal device_opp and opp structures are RCU protected. | ||||||
|  | + * Hence this function internally uses RCU updater strategy with mutex locks to | ||||||
|  | + * keep the integrity of the internal data structures. Callers should ensure | ||||||
|  | + * that this function is *NOT* called under RCU protection or in contexts where | ||||||
|  | + * mutex locking or synchronize_rcu() blocking calls cannot be used. | ||||||
|  | + */ | ||||||
|  | +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | ||||||
|  | +			      unsigned long u_volt) | ||||||
|  | +{ | ||||||
|  | +	struct opp_table *opp_table; | ||||||
|  | +	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); | ||||||
|  | +	int r = 0; | ||||||
|  | + | ||||||
|  | +	/* keep the node allocated */ | ||||||
|  | +	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL); | ||||||
|  | +	if (!new_opp) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	mutex_lock(&opp_table_lock); | ||||||
|  | + | ||||||
|  | +	/* Find the opp_table */ | ||||||
|  | +	opp_table = _find_opp_table(dev); | ||||||
|  | +	if (IS_ERR(opp_table)) { | ||||||
|  | +		r = PTR_ERR(opp_table); | ||||||
|  | +		dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); | ||||||
|  | +		goto unlock; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Do we have the frequency? */ | ||||||
|  | +	list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { | ||||||
|  | +		if (tmp_opp->rate == freq) { | ||||||
|  | +			opp = tmp_opp; | ||||||
|  | +			break; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	if (IS_ERR(opp)) { | ||||||
|  | +		r = PTR_ERR(opp); | ||||||
|  | +		goto unlock; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Is update really needed? */ | ||||||
|  | +	if (opp->supplies[0].u_volt == u_volt) | ||||||
|  | +		goto unlock; | ||||||
|  | +	/* copy the old data over */ | ||||||
|  | +	*new_opp = *opp; | ||||||
|  | + | ||||||
|  | +	/* plug in new node */ | ||||||
|  | +	new_opp->supplies[0].u_volt = u_volt; | ||||||
|  | + | ||||||
|  | +	list_replace(&opp->node, &new_opp->node); | ||||||
|  | +	mutex_unlock(&opp_table_lock); | ||||||
|  | +	kfree(opp); | ||||||
|  | + | ||||||
|  | +	/* Notify the change of the OPP */ | ||||||
|  | +	blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, | ||||||
|  | +				 new_opp); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +unlock: | ||||||
|  | +	mutex_unlock(&opp_table_lock); | ||||||
|  | +	kfree(new_opp); | ||||||
|  | +	return r; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  |   * dev_pm_opp_enable() - Enable a specific OPP | ||||||
|  |   * @dev:	device for which we do this operation | ||||||
|  |   * @freq:	OPP frequency to enable | ||||||
|  | --- a/include/linux/pm_opp.h | ||||||
|  | +++ b/include/linux/pm_opp.h | ||||||
|  | @@ -25,6 +25,7 @@ struct opp_table; | ||||||
|  |   | ||||||
|  |  enum dev_pm_opp_event { | ||||||
|  |  	OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, | ||||||
|  | +	OPP_EVENT_ADJUST_VOLTAGE, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | @@ -108,6 +109,9 @@ int dev_pm_opp_add(struct device *dev, u | ||||||
|  |  		   unsigned long u_volt); | ||||||
|  |  void dev_pm_opp_remove(struct device *dev, unsigned long freq); | ||||||
|  |   | ||||||
|  | +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | ||||||
|  | +			      unsigned long u_volt); | ||||||
|  | + | ||||||
|  |  int dev_pm_opp_enable(struct device *dev, unsigned long freq); | ||||||
|  |   | ||||||
|  |  int dev_pm_opp_disable(struct device *dev, unsigned long freq); | ||||||
|  | @@ -208,6 +212,13 @@ static inline void dev_pm_opp_remove(str | ||||||
|  |  { | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static inline int | ||||||
|  | +dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, | ||||||
|  | +			  unsigned long u_volt) | ||||||
|  | +{ | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) | ||||||
|  |  { | ||||||
|  |  	return 0; | ||||||
| @@ -0,0 +1,52 @@ | |||||||
|  | From d06ca5e7a3cf726f5be5ffd96e93ccd798b8c09a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | Date: Thu, 12 May 2016 14:41:33 +0300 | ||||||
|  | Subject: [PATCH 51/69] PM / OPP: Add a helper to get an opp regulator for | ||||||
|  |  device | ||||||
|  |  | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/base/power/opp/core.c | 21 +++++++++++++++++++++ | ||||||
|  |  include/linux/pm_opp.h        |  1 + | ||||||
|  |  2 files changed, 22 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/base/power/opp/core.c | ||||||
|  | +++ b/drivers/base/power/opp/core.c | ||||||
|  | @@ -126,6 +126,27 @@ unsigned long dev_pm_opp_get_freq(struct | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); | ||||||
|  |   | ||||||
|  | +struct regulator *dev_pm_opp_get_regulator(struct device *dev) | ||||||
|  | +{ | ||||||
|  | +	struct opp_table *opp_table; | ||||||
|  | +	struct regulator *reg; | ||||||
|  | + | ||||||
|  | +	rcu_read_lock(); | ||||||
|  | + | ||||||
|  | +	opp_table = _find_opp_table(dev); | ||||||
|  | +	if (IS_ERR(opp_table)) { | ||||||
|  | +		rcu_read_unlock(); | ||||||
|  | +		return ERR_CAST(opp_table); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	reg = opp_table->regulators[0]; | ||||||
|  | + | ||||||
|  | +	rcu_read_unlock(); | ||||||
|  | + | ||||||
|  | +	return reg; | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL_GPL(dev_pm_opp_get_regulator); | ||||||
|  | + | ||||||
|  |  /** | ||||||
|  |   * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not | ||||||
|  |   * @opp: opp for which turbo mode is being verified | ||||||
|  | --- a/include/linux/pm_opp.h | ||||||
|  | +++ b/include/linux/pm_opp.h | ||||||
|  | @@ -85,6 +85,7 @@ void dev_pm_opp_put_opp_table(struct opp | ||||||
|  |  unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); | ||||||
|  |   | ||||||
|  |  unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp); | ||||||
|  | +struct regulator *dev_pm_opp_get_regulator(struct device *dev); | ||||||
|  |   | ||||||
|  |  bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp); | ||||||
|  |   | ||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | From 4533c285c2aedce6d4434d7b877066de3b1ecb33 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | Date: Thu, 25 Aug 2016 18:43:35 +0300 | ||||||
|  | Subject: [PATCH 52/69] PM / OPP: Update the voltage tolerance when adjusting | ||||||
|  |  the OPP | ||||||
|  |  | ||||||
|  | When the voltage is adjusted, the voltage tolerance is not updated. | ||||||
|  | This can lead to situations where the voltage min value is greater | ||||||
|  | than the voltage max value. The final result is triggering a BUG() | ||||||
|  | in the regulator core. | ||||||
|  | Fix this by updating the voltage tolerance values too. | ||||||
|  |  | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/base/power/opp/core.c | 5 +++++ | ||||||
|  |  1 file changed, 5 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/base/power/opp/core.c | ||||||
|  | +++ b/drivers/base/power/opp/core.c | ||||||
|  | @@ -1652,6 +1652,7 @@ int dev_pm_opp_adjust_voltage(struct dev | ||||||
|  |  	struct opp_table *opp_table; | ||||||
|  |  	struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); | ||||||
|  |  	int r = 0; | ||||||
|  | +	unsigned long tol; | ||||||
|  |   | ||||||
|  |  	/* keep the node allocated */ | ||||||
|  |  	new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL); | ||||||
|  | @@ -1688,6 +1689,10 @@ int dev_pm_opp_adjust_voltage(struct dev | ||||||
|  |   | ||||||
|  |  	/* plug in new node */ | ||||||
|  |  	new_opp->supplies[0].u_volt = u_volt; | ||||||
|  | +	tol = u_volt * opp_table->voltage_tolerance_v1 / 100; | ||||||
|  | +	new_opp->supplies[0].u_volt = u_volt; | ||||||
|  | +	new_opp->supplies[0].u_volt_min = u_volt - tol; | ||||||
|  | +	new_opp->supplies[0].u_volt_max = u_volt + tol; | ||||||
|  |   | ||||||
|  |  	list_replace(&opp->node, &new_opp->node); | ||||||
|  |  	mutex_unlock(&opp_table_lock); | ||||||
| @@ -0,0 +1,55 @@ | |||||||
|  | From ef10381ca4d01848ebedb4afb2c78feb8052f103 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Adrian Panella <ianchi74@outlook.com> | ||||||
|  | Date: Thu, 9 Mar 2017 08:26:54 +0100 | ||||||
|  | Subject: [PATCH 53/69] regulator: add smb208 support | ||||||
|  |  | ||||||
|  | Signed-off-by: Adrian Panella <ianchi74@outlook.com> | ||||||
|  | --- | ||||||
|  |  Documentation/devicetree/bindings/mfd/qcom-rpm.txt | 4 ++++ | ||||||
|  |  drivers/regulator/qcom_rpm-regulator.c             | 9 +++++++++ | ||||||
|  |  2 files changed, 13 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt | ||||||
|  | @@ -61,6 +61,7 @@ Regulator nodes are identified by their | ||||||
|  |  		    "qcom,rpm-pm8901-regulators" | ||||||
|  |  		    "qcom,rpm-pm8921-regulators" | ||||||
|  |  		    "qcom,rpm-pm8018-regulators" | ||||||
|  | +		    "qcom,rpm-smb208-regulators" | ||||||
|  |   | ||||||
|  |  - vdd_l0_l1_lvs-supply: | ||||||
|  |  - vdd_l2_l11_l12-supply: | ||||||
|  | @@ -171,6 +172,9 @@ pm8018: | ||||||
|  |  	s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, | ||||||
|  |  	l12, l14, lvs1 | ||||||
|  |   | ||||||
|  | +smb208: | ||||||
|  | +	s1a, s1b, s2a, s2b | ||||||
|  | + | ||||||
|  |  The content of each sub-node is defined by the standard binding for regulators - | ||||||
|  |  see regulator.txt - with additional custom properties described below: | ||||||
|  |   | ||||||
|  | --- a/drivers/regulator/qcom_rpm-regulator.c | ||||||
|  | +++ b/drivers/regulator/qcom_rpm-regulator.c | ||||||
|  | @@ -933,12 +933,21 @@ static const struct rpm_regulator_data r | ||||||
|  |  	{ } | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static const struct rpm_regulator_data rpm_smb208_regulators[] = { | ||||||
|  | +	{ "s1a",  QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" }, | ||||||
|  | +	{ "s1b",  QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" }, | ||||||
|  | +	{ "s2a",  QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" }, | ||||||
|  | +	{ "s2b",  QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" }, | ||||||
|  | +	{ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  static const struct of_device_id rpm_of_match[] = { | ||||||
|  |  	{ .compatible = "qcom,rpm-pm8018-regulators", | ||||||
|  |  		.data = &rpm_pm8018_regulators }, | ||||||
|  |  	{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, | ||||||
|  |  	{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, | ||||||
|  |  	{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, | ||||||
|  | +	{ .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators }, | ||||||
|  |  	{ } | ||||||
|  |  }; | ||||||
|  |  MODULE_DEVICE_TABLE(of, rpm_of_match); | ||||||
| @@ -0,0 +1,128 @@ | |||||||
|  | From 10577f74c35bd395951d1b2382c8d821089b5745 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | Date: Fri, 18 Sep 2015 17:52:08 -0700 | ||||||
|  | Subject: [PATCH 54/69] cpufreq-dt: Handle OPP voltage adjust events | ||||||
|  |  | ||||||
|  | On some SoCs the Adaptive Voltage Scaling (AVS) technique is | ||||||
|  | employed to optimize the operating voltage of a device. At a | ||||||
|  | given frequency, the hardware monitors dynamic factors and either | ||||||
|  | makes a suggestion for how much to adjust a voltage for the | ||||||
|  | current frequency, or it automatically adjusts the voltage | ||||||
|  | without software intervention. | ||||||
|  |  | ||||||
|  | In the former case, an AVS driver will call | ||||||
|  | dev_pm_opp_modify_voltage() and update the voltage for the | ||||||
|  | particular OPP the CPUs are using. Add an OPP notifier to | ||||||
|  | cpufreq-dt so that we can adjust the voltage of the CPU when AVS | ||||||
|  | updates the OPP. | ||||||
|  |  | ||||||
|  | Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | Acked-by: Viresh Kumar <viresh.kumar@linaro.org> | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/cpufreq/cpufreq-dt.c | 68 ++++++++++++++++++++++++++++++++++++++++++-- | ||||||
|  |  1 file changed, 65 insertions(+), 3 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | +++ b/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | @@ -32,6 +32,9 @@ struct private_data { | ||||||
|  |  	struct device *cpu_dev; | ||||||
|  |  	struct thermal_cooling_device *cdev; | ||||||
|  |  	const char *reg_name; | ||||||
|  | +	struct notifier_block opp_nb; | ||||||
|  | +	struct mutex lock; | ||||||
|  | +	unsigned long opp_freq; | ||||||
|  |  	bool have_static_opps; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | @@ -44,9 +47,16 @@ static struct freq_attr *cpufreq_dt_attr | ||||||
|  |  static int set_target(struct cpufreq_policy *policy, unsigned int index) | ||||||
|  |  { | ||||||
|  |  	struct private_data *priv = policy->driver_data; | ||||||
|  | +	int ret; | ||||||
|  | +	unsigned long target_freq = policy->freq_table[index].frequency * 1000; | ||||||
|  | + | ||||||
|  | +	mutex_lock(&priv->lock); | ||||||
|  | +	ret = dev_pm_opp_set_rate(priv->cpu_dev, target_freq); | ||||||
|  | +	if (!ret) | ||||||
|  | +		priv->opp_freq = target_freq; | ||||||
|  | +	mutex_unlock(&priv->lock); | ||||||
|  |   | ||||||
|  | -	return dev_pm_opp_set_rate(priv->cpu_dev, | ||||||
|  | -				   policy->freq_table[index].frequency * 1000); | ||||||
|  | +	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | @@ -87,6 +97,39 @@ node_put: | ||||||
|  |  	return name; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int opp_notifier(struct notifier_block *nb, unsigned long event, | ||||||
|  | +			void *data) | ||||||
|  | +{ | ||||||
|  | +	struct dev_pm_opp *opp = data; | ||||||
|  | +	struct private_data *priv = container_of(nb, struct private_data, | ||||||
|  | +						 opp_nb); | ||||||
|  | +	struct device *cpu_dev = priv->cpu_dev; | ||||||
|  | +	struct regulator *cpu_reg; | ||||||
|  | +	unsigned long volt, freq; | ||||||
|  | +	int ret = 0; | ||||||
|  | + | ||||||
|  | +	if (event == OPP_EVENT_ADJUST_VOLTAGE) { | ||||||
|  | +		cpu_reg = dev_pm_opp_get_regulator(cpu_dev); | ||||||
|  | +		if (IS_ERR(cpu_reg)) { | ||||||
|  | +			ret = PTR_ERR(cpu_reg); | ||||||
|  | +			goto out; | ||||||
|  | +		} | ||||||
|  | +		volt = dev_pm_opp_get_voltage(opp); | ||||||
|  | +		freq = dev_pm_opp_get_freq(opp); | ||||||
|  | + | ||||||
|  | +		mutex_lock(&priv->lock); | ||||||
|  | +		if (freq == priv->opp_freq) { | ||||||
|  | +			ret = regulator_set_voltage_triplet(cpu_reg, volt, volt, volt); | ||||||
|  | +		} | ||||||
|  | +		mutex_unlock(&priv->lock); | ||||||
|  | +		if (ret) | ||||||
|  | +			dev_err(cpu_dev, "failed to scale voltage: %d\n", ret); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +out: | ||||||
|  | +	return notifier_from_errno(ret); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int resources_available(void) | ||||||
|  |  { | ||||||
|  |  	struct device *cpu_dev; | ||||||
|  | @@ -153,6 +196,7 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |  	bool fallback = false; | ||||||
|  |  	const char *name; | ||||||
|  |  	int ret; | ||||||
|  | +	struct srcu_notifier_head *opp_srcu_head; | ||||||
|  |   | ||||||
|  |  	cpu_dev = get_cpu_device(policy->cpu); | ||||||
|  |  	if (!cpu_dev) { | ||||||
|  | @@ -246,10 +290,13 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |  				__func__, ret); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	mutex_init(&priv->lock); | ||||||
|  | +	dev_pm_opp_register_notifier(cpu_dev, &priv->opp_nb); | ||||||
|  | + | ||||||
|  |  	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); | ||||||
|  | -		goto out_free_opp; | ||||||
|  | +		goto out_unregister_nb; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	priv->cpu_dev = cpu_dev; | ||||||
|  | @@ -285,6 +332,8 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |   | ||||||
|  |  out_free_cpufreq_table: | ||||||
|  |  	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); | ||||||
|  | +out_unregister_nb: | ||||||
|  | +	dev_pm_opp_unregister_notifier(cpu_dev, &priv->opp_nb); | ||||||
|  |  out_free_opp: | ||||||
|  |  	if (priv->have_static_opps) | ||||||
|  |  		dev_pm_opp_of_cpumask_remove_table(policy->cpus); | ||||||
| @@ -0,0 +1,90 @@ | |||||||
|  | From 0759cdff49f1cf361bf503c13f7bcb33da43ab95 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | Date: Tue, 8 Sep 2015 11:24:41 +0300 | ||||||
|  | Subject: [PATCH 55/69] cpufreq-dt: Add L2 frequency scaling support | ||||||
|  |  | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/cpufreq/cpufreq-dt.c | 41 ++++++++++++++++++++++++++++++++++++++++- | ||||||
|  |  include/linux/cpufreq.h      |  2 ++ | ||||||
|  |  2 files changed, 42 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | +++ b/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | @@ -49,11 +49,41 @@ static int set_target(struct cpufreq_pol | ||||||
|  |  	struct private_data *priv = policy->driver_data; | ||||||
|  |  	int ret; | ||||||
|  |  	unsigned long target_freq = policy->freq_table[index].frequency * 1000; | ||||||
|  | +	struct clk *l2_clk = policy->l2_clk; | ||||||
|  | +	unsigned int l2_freq; | ||||||
|  | +	unsigned long new_l2_freq = 0; | ||||||
|  |   | ||||||
|  |  	mutex_lock(&priv->lock); | ||||||
|  |  	ret = dev_pm_opp_set_rate(priv->cpu_dev, target_freq); | ||||||
|  | -	if (!ret) | ||||||
|  | + | ||||||
|  | +	if (!ret) { | ||||||
|  | +		if (!IS_ERR(l2_clk) && policy->l2_rate[0] && policy->l2_rate[1] && | ||||||
|  | +				policy->l2_rate[2]) { | ||||||
|  | +			static unsigned long krait_l2[CONFIG_NR_CPUS] = { }; | ||||||
|  | +			int cpu, ret = 0; | ||||||
|  | + | ||||||
|  | +			if (target_freq >= policy->l2_rate[2]) | ||||||
|  | +				new_l2_freq = policy->l2_rate[2]; | ||||||
|  | +			else if (target_freq >= policy->l2_rate[1]) | ||||||
|  | +				new_l2_freq = policy->l2_rate[1]; | ||||||
|  | +			else | ||||||
|  | +				new_l2_freq = policy->l2_rate[0]; | ||||||
|  | + | ||||||
|  | +			krait_l2[policy->cpu] = new_l2_freq; | ||||||
|  | +			for_each_present_cpu(cpu) | ||||||
|  | +				new_l2_freq = max(new_l2_freq, krait_l2[cpu]); | ||||||
|  | + | ||||||
|  | +			l2_freq = clk_get_rate(l2_clk); | ||||||
|  | + | ||||||
|  | +			if (l2_freq != new_l2_freq) { | ||||||
|  | +				/* scale l2 with the core */ | ||||||
|  | +				ret = clk_set_rate(l2_clk, new_l2_freq); | ||||||
|  | +			} | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		priv->opp_freq = target_freq; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	mutex_unlock(&priv->lock); | ||||||
|  |   | ||||||
|  |  	return ret; | ||||||
|  | @@ -197,6 +227,8 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |  	const char *name; | ||||||
|  |  	int ret; | ||||||
|  |  	struct srcu_notifier_head *opp_srcu_head; | ||||||
|  | +	struct device_node *l2_np; | ||||||
|  | +	struct clk *l2_clk = NULL; | ||||||
|  |   | ||||||
|  |  	cpu_dev = get_cpu_device(policy->cpu); | ||||||
|  |  	if (!cpu_dev) { | ||||||
|  | @@ -305,6 +337,13 @@ static int cpufreq_init(struct cpufreq_p | ||||||
|  |   | ||||||
|  |  	policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000; | ||||||
|  |   | ||||||
|  | +	l2_clk = clk_get(cpu_dev, "l2"); | ||||||
|  | +	if (!IS_ERR(l2_clk)) | ||||||
|  | +		policy->l2_clk = l2_clk; | ||||||
|  | +	l2_np = of_find_node_by_name(NULL, "qcom,l2"); | ||||||
|  | +	if (l2_np) | ||||||
|  | +		of_property_read_u32_array(l2_np, "qcom,l2-rates", policy->l2_rate, 3); | ||||||
|  | + | ||||||
|  |  	ret = cpufreq_table_validate_and_show(policy, freq_table); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__, | ||||||
|  | --- a/include/linux/cpufreq.h | ||||||
|  | +++ b/include/linux/cpufreq.h | ||||||
|  | @@ -73,6 +73,8 @@ struct cpufreq_policy { | ||||||
|  |  	unsigned int		cpu;    /* cpu managing this policy, must be online */ | ||||||
|  |   | ||||||
|  |  	struct clk		*clk; | ||||||
|  | +	struct clk		*l2_clk; /* L2 clock */ | ||||||
|  | +	unsigned int		l2_rate[3]; /* L2 bus clock rate thresholds */ | ||||||
|  |  	struct cpufreq_cpuinfo	cpuinfo;/* see above */ | ||||||
|  |   | ||||||
|  |  	unsigned int		min;    /* in kHz */ | ||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | From 001a8dcb56ced58c518aaa10a4f0ba5e878705b6 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | Date: Tue, 17 May 2016 16:15:43 +0300 | ||||||
|  | Subject: [PATCH 56/69] cpufreq-dt: Add missing rcu locks | ||||||
|  |  | ||||||
|  | Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/cpufreq/cpufreq-dt.c | 2 ++ | ||||||
|  |  1 file changed, 2 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | +++ b/drivers/cpufreq/cpufreq-dt.c | ||||||
|  | @@ -144,8 +144,10 @@ static int opp_notifier(struct notifier_ | ||||||
|  |  			ret = PTR_ERR(cpu_reg); | ||||||
|  |  			goto out; | ||||||
|  |  		} | ||||||
|  | +		rcu_read_lock(); | ||||||
|  |  		volt = dev_pm_opp_get_voltage(opp); | ||||||
|  |  		freq = dev_pm_opp_get_freq(opp); | ||||||
|  | +		rcu_read_unlock(); | ||||||
|  |   | ||||||
|  |  		mutex_lock(&priv->lock); | ||||||
|  |  		if (freq == priv->opp_freq) { | ||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | From 04ca10340f1b4d92e849724d322a7ca225d11539 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Lina Iyer <lina.iyer@linaro.org> | ||||||
|  | Date: Wed, 25 Mar 2015 14:25:29 -0600 | ||||||
|  | Subject: [PATCH 59/69] ARM: cpuidle: Add cpuidle support for QCOM cpus | ||||||
|  |  | ||||||
|  | Define ARM_QCOM_CPUIDLE config item to enable cpuidle support. | ||||||
|  |  | ||||||
|  | Cc: Stephen Boyd <sboyd@codeaurora.org> | ||||||
|  | Cc: Arnd Bergmann <arnd@arndb.de> | ||||||
|  | Cc: Kevin Hilman <khilman@linaro.org> | ||||||
|  | Cc: Daniel Lezcano <daniel.lezcano@linaro.org> | ||||||
|  | Signed-off-by: Lina Iyer <lina.iyer@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/cpuidle/Kconfig.arm | 7 +++++++ | ||||||
|  |  1 file changed, 7 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/cpuidle/Kconfig.arm | ||||||
|  | +++ b/drivers/cpuidle/Kconfig.arm | ||||||
|  | @@ -75,3 +75,10 @@ config ARM_MVEBU_V7_CPUIDLE | ||||||
|  |  	depends on ARCH_MVEBU && !ARM64 | ||||||
|  |  	help | ||||||
|  |  	  Select this to enable cpuidle on Armada 370, 38x and XP processors. | ||||||
|  | + | ||||||
|  | +config ARM_QCOM_CPUIDLE | ||||||
|  | +	bool "CPU Idle Driver for QCOM processors" | ||||||
|  | +	depends on ARCH_QCOM | ||||||
|  | +	select ARM_CPUIDLE | ||||||
|  | +	help | ||||||
|  | +	  Select this to enable cpuidle on QCOM processors. | ||||||
| @@ -0,0 +1,62 @@ | |||||||
|  | From fa71139b55e114aa8c3c4823ff8ee7d49ee810d4 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | Date: Wed, 29 Apr 2015 15:21:46 -0700 | ||||||
|  | Subject: [PATCH 60/69] HACK: arch: arm: force ZRELADDR on arch-qcom | ||||||
|  |  | ||||||
|  | ARCH_QCOM is using the ARCH_MULTIPLATFORM option, as now recommended | ||||||
|  | on most ARM architectures. This automatically calculate ZRELADDR by | ||||||
|  | masking PHYS_OFFSET with 0xf8000000. | ||||||
|  |  | ||||||
|  | However, on IPQ806x, the first ~20MB of RAM is reserved for the hardware | ||||||
|  | network accelerators, and the bootloader removes this section from the | ||||||
|  | layout passed from the ATAGS (when used). | ||||||
|  |  | ||||||
|  | For newer bootloader, when DT is used, this is not a problem, we just | ||||||
|  | reserve this memory in the device tree. But if the bootloader doesn't | ||||||
|  | have DT support, then ATAGS have to be used. In this case, the ARM | ||||||
|  | decompressor will position the kernel in this low mem, which will not be | ||||||
|  | in the RAM section mapped by the bootloader, which means the kernel will | ||||||
|  | freeze in the middle of the boot process trying to map the memory. | ||||||
|  |  | ||||||
|  | As a work around, this patch allows disabling AUTO_ZRELADDR when | ||||||
|  | ARCH_QCOM is selected. It makes the zImage usage possible on bootloaders | ||||||
|  | which don't support device-tree, which is the case on certain early | ||||||
|  | IPQ806x based designs. | ||||||
|  |  | ||||||
|  | Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  arch/arm/Kconfig                 | 2 +- | ||||||
|  |  arch/arm/Makefile                | 2 ++ | ||||||
|  |  arch/arm/mach-qcom/Makefile.boot | 1 + | ||||||
|  |  3 files changed, 4 insertions(+), 1 deletion(-) | ||||||
|  |  create mode 100644 arch/arm/mach-qcom/Makefile.boot | ||||||
|  |  | ||||||
|  | --- a/arch/arm/Kconfig | ||||||
|  | +++ b/arch/arm/Kconfig | ||||||
|  | @@ -341,7 +341,7 @@ config ARCH_MULTIPLATFORM | ||||||
|  |  	depends on MMU | ||||||
|  |  	select ARM_HAS_SG_CHAIN | ||||||
|  |  	select ARM_PATCH_PHYS_VIRT | ||||||
|  | -	select AUTO_ZRELADDR | ||||||
|  | +	select AUTO_ZRELADDR if !ARCH_QCOM | ||||||
|  |  	select TIMER_OF | ||||||
|  |  	select COMMON_CLK | ||||||
|  |  	select GENERIC_CLOCKEVENTS | ||||||
|  | --- a/arch/arm/Makefile | ||||||
|  | +++ b/arch/arm/Makefile | ||||||
|  | @@ -255,9 +255,11 @@ MACHINE  := arch/arm/mach-$(word 1,$(mac | ||||||
|  |  else | ||||||
|  |  MACHINE  := | ||||||
|  |  endif | ||||||
|  | +ifeq ($(CONFIG_ARCH_QCOM),) | ||||||
|  |  ifeq ($(CONFIG_ARCH_MULTIPLATFORM),y) | ||||||
|  |  MACHINE  := | ||||||
|  |  endif | ||||||
|  | +endif | ||||||
|  |   | ||||||
|  |  machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) | ||||||
|  |  platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y))) | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/arch/arm/mach-qcom/Makefile.boot | ||||||
|  | @@ -0,0 +1 @@ | ||||||
|  | +zreladdr-y+= 0x42208000 | ||||||
| @@ -0,0 +1,23 @@ | |||||||
|  | From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 9 Mar 2017 09:31:44 +0100 | ||||||
|  | Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  drivers/mtd/qcom_smem_part.c | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/mtd/qcom_smem_part.c | ||||||
|  | +++ b/drivers/mtd/qcom_smem_part.c | ||||||
|  | @@ -189,6 +189,10 @@ static int parse_qcom_smem_partitions(st | ||||||
|  |  		m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz); | ||||||
|  |  		m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz); | ||||||
|  |   | ||||||
|  | +		/* "rootfs" conflicts with OpenWrt auto mounting */ | ||||||
|  | +		if (mtd_type_is_nand(master) && !strcmp(m_part->name, "rootfs")) | ||||||
|  | +			m_part->name = "ubi"; | ||||||
|  | + | ||||||
|  |  		/* | ||||||
|  |  		 * The last SMEM partition may have its size marked as | ||||||
|  |  		 * something like 0xffffffff, which means "until the end of the | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | From a16fcf911a020e46439a3bb3e702463fc3159831 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | Date: Wed, 18 Nov 2015 12:38:56 +0530 | ||||||
|  | Subject: [PATCH 62/69] ipq806x: gcc: Added the enable regs and mask for PRNG | ||||||
|  |  | ||||||
|  | kernel got hanged while reading from /dev/hwrng at the | ||||||
|  | time of PRNG clock enable | ||||||
|  |  | ||||||
|  | Change-Id: I89856c7e19e6639508e6a2774304583a3ec91172 | ||||||
|  | Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/clk/qcom/gcc-ipq806x.c | 2 ++ | ||||||
|  |  1 file changed, 2 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | +++ b/drivers/clk/qcom/gcc-ipq806x.c | ||||||
|  | @@ -1233,6 +1233,8 @@ static struct clk_rcg prng_src = { | ||||||
|  |  		.parent_map = gcc_pxo_pll8_map, | ||||||
|  |  	}, | ||||||
|  |  	.clkr = { | ||||||
|  | +		.enable_reg = 0x2e80, | ||||||
|  | +		.enable_mask = BIT(11), | ||||||
|  |  		.hw.init = &(struct clk_init_data){ | ||||||
|  |  			.name = "prng_src", | ||||||
|  |  			.parent_names = gcc_pxo_pll8, | ||||||
| @@ -0,0 +1,627 @@ | |||||||
|  | From 3302e1e1a3cfa4e67fda2a61d6f0c42205d40932 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Rajith Cherian <rajith@codeaurora.org> | ||||||
|  | Date: Tue, 14 Feb 2017 18:30:43 +0530 | ||||||
|  | Subject: [PATCH] ipq8064: tsens: Base tsens driver for IPQ8064 | ||||||
|  |  | ||||||
|  | Add TSENS driver template to support IPQ8064. | ||||||
|  | This is a base file copied from tsens-8960.c | ||||||
|  |  | ||||||
|  | Change-Id: I47c573fdfa2d898243c6a6ba952d1632f91391f7 | ||||||
|  | Signed-off-by: Rajith Cherian <rajith@codeaurora.org> | ||||||
|  |  | ||||||
|  | ipq8064: tsens: TSENS driver support for IPQ8064 | ||||||
|  |  | ||||||
|  | Support for IPQ8064 tsens driver. The driver works | ||||||
|  | with the thermal framework. The driver overrides the | ||||||
|  | following fucntionalities: | ||||||
|  |  | ||||||
|  | 1. Get current temperature. | ||||||
|  | 2. Get/Set trip temperatures. | ||||||
|  | 3. Enabled/Disable trip points. | ||||||
|  | 4. ISR for threshold generated interrupt. | ||||||
|  | 5. Notify userspace when trip points are hit. | ||||||
|  |  | ||||||
|  | Change-Id: I8bc7204fd627d10875ab13fc1de8cb6c2ed7a918 | ||||||
|  | Signed-off-by: Rajith Cherian <rajith@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/thermal/qcom-tsens.txt     |   1 + | ||||||
|  |  drivers/thermal/qcom/Makefile                      |   3 +- | ||||||
|  |  drivers/thermal/qcom/tsens-ipq8064.c               | 551 +++++++++++++++++++++ | ||||||
|  |  drivers/thermal/qcom/tsens.c                       |   3 + | ||||||
|  |  drivers/thermal/qcom/tsens.h                       |   2 +- | ||||||
|  |  5 files changed, 558 insertions(+), 2 deletions(-) | ||||||
|  |  create mode 100644 drivers/thermal/qcom/tsens-ipq8064.c | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt | ||||||
|  | @@ -5,6 +5,7 @@ Required properties: | ||||||
|  |   - "qcom,msm8916-tsens" : For 8916 Family of SoCs | ||||||
|  |   - "qcom,msm8974-tsens" : For 8974 Family of SoCs | ||||||
|  |   - "qcom,msm8996-tsens" : For 8996 Family of SoCs | ||||||
|  | + - "qcom,ipq8064-tsens" : For IPQ8064 | ||||||
|  |   | ||||||
|  |  - reg: Address range of the thermal registers | ||||||
|  |  - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description. | ||||||
|  | --- a/drivers/thermal/qcom/Makefile | ||||||
|  | +++ b/drivers/thermal/qcom/Makefile | ||||||
|  | @@ -1,2 +1,3 @@ | ||||||
|  |  obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o | ||||||
|  | -qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o | ||||||
|  | +qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o \ | ||||||
|  | +				tsens-ipq8064.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/thermal/qcom/tsens-ipq8064.c | ||||||
|  | @@ -0,0 +1,551 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2015, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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/platform_device.h> | ||||||
|  | +#include <linux/delay.h> | ||||||
|  | +#include <linux/bitops.h> | ||||||
|  | +#include <linux/regmap.h> | ||||||
|  | +#include <linux/thermal.h> | ||||||
|  | +#include <linux/nvmem-consumer.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/interrupt.h> | ||||||
|  | +#include "tsens.h" | ||||||
|  | + | ||||||
|  | +#define CAL_MDEGC		30000 | ||||||
|  | + | ||||||
|  | +#define CONFIG_ADDR		0x3640 | ||||||
|  | +/* CONFIG_ADDR bitmasks */ | ||||||
|  | +#define CONFIG			0x9b | ||||||
|  | +#define CONFIG_MASK		0xf | ||||||
|  | +#define CONFIG_SHIFT		0 | ||||||
|  | + | ||||||
|  | +#define STATUS_CNTL_8064	0x3660 | ||||||
|  | +#define CNTL_ADDR		0x3620 | ||||||
|  | +/* CNTL_ADDR bitmasks */ | ||||||
|  | +#define EN			BIT(0) | ||||||
|  | +#define SW_RST			BIT(1) | ||||||
|  | +#define SENSOR0_EN		BIT(3) | ||||||
|  | +#define SLP_CLK_ENA		BIT(26) | ||||||
|  | +#define MEASURE_PERIOD		1 | ||||||
|  | +#define SENSOR0_SHIFT		3 | ||||||
|  | + | ||||||
|  | +/* INT_STATUS_ADDR bitmasks */ | ||||||
|  | +#define MIN_STATUS_MASK		BIT(0) | ||||||
|  | +#define LOWER_STATUS_CLR	BIT(1) | ||||||
|  | +#define UPPER_STATUS_CLR	BIT(2) | ||||||
|  | +#define MAX_STATUS_MASK		BIT(3) | ||||||
|  | + | ||||||
|  | +#define THRESHOLD_ADDR		0x3624 | ||||||
|  | +/* THRESHOLD_ADDR bitmasks */ | ||||||
|  | +#define THRESHOLD_MAX_CODE		0x20000 | ||||||
|  | +#define THRESHOLD_MIN_CODE		0 | ||||||
|  | +#define THRESHOLD_MAX_LIMIT_SHIFT	24 | ||||||
|  | +#define THRESHOLD_MIN_LIMIT_SHIFT	16 | ||||||
|  | +#define THRESHOLD_UPPER_LIMIT_SHIFT	8 | ||||||
|  | +#define THRESHOLD_LOWER_LIMIT_SHIFT	0 | ||||||
|  | +#define THRESHOLD_MAX_LIMIT_MASK	(THRESHOLD_MAX_CODE << \ | ||||||
|  | +						THRESHOLD_MAX_LIMIT_SHIFT) | ||||||
|  | +#define THRESHOLD_MIN_LIMIT_MASK	(THRESHOLD_MAX_CODE << \ | ||||||
|  | +						THRESHOLD_MIN_LIMIT_SHIFT) | ||||||
|  | +#define THRESHOLD_UPPER_LIMIT_MASK	(THRESHOLD_MAX_CODE << \ | ||||||
|  | +						THRESHOLD_UPPER_LIMIT_SHIFT) | ||||||
|  | +#define THRESHOLD_LOWER_LIMIT_MASK	(THRESHOLD_MAX_CODE << \ | ||||||
|  | +						THRESHOLD_LOWER_LIMIT_SHIFT) | ||||||
|  | + | ||||||
|  | +/* Initial temperature threshold values */ | ||||||
|  | +#define LOWER_LIMIT_TH		0x9d /* 95C */ | ||||||
|  | +#define UPPER_LIMIT_TH		0xa6 /* 105C */ | ||||||
|  | +#define MIN_LIMIT_TH		0x0 | ||||||
|  | +#define MAX_LIMIT_TH		0xff | ||||||
|  | + | ||||||
|  | +#define S0_STATUS_ADDR		0x3628 | ||||||
|  | +#define STATUS_ADDR_OFFSET	2 | ||||||
|  | +#define SENSOR_STATUS_SIZE	4 | ||||||
|  | +#define INT_STATUS_ADDR		0x363c | ||||||
|  | +#define TRDY_MASK		BIT(7) | ||||||
|  | +#define TIMEOUT_US		100 | ||||||
|  | + | ||||||
|  | +#define TSENS_EN		BIT(0) | ||||||
|  | +#define TSENS_SW_RST		BIT(1) | ||||||
|  | +#define TSENS_ADC_CLK_SEL	BIT(2) | ||||||
|  | +#define SENSOR0_EN		BIT(3) | ||||||
|  | +#define SENSOR1_EN		BIT(4) | ||||||
|  | +#define SENSOR2_EN		BIT(5) | ||||||
|  | +#define SENSOR3_EN		BIT(6) | ||||||
|  | +#define SENSOR4_EN		BIT(7) | ||||||
|  | +#define SENSORS_EN		(SENSOR0_EN | SENSOR1_EN | \ | ||||||
|  | +				SENSOR2_EN | SENSOR3_EN | SENSOR4_EN) | ||||||
|  | +#define TSENS_8064_SENSOR5_EN				BIT(8) | ||||||
|  | +#define TSENS_8064_SENSOR6_EN				BIT(9) | ||||||
|  | +#define TSENS_8064_SENSOR7_EN				BIT(10) | ||||||
|  | +#define TSENS_8064_SENSOR8_EN				BIT(11) | ||||||
|  | +#define TSENS_8064_SENSOR9_EN				BIT(12) | ||||||
|  | +#define TSENS_8064_SENSOR10_EN				BIT(13) | ||||||
|  | +#define TSENS_8064_SENSORS_EN				(SENSORS_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR5_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR6_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR7_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR8_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR9_EN | \ | ||||||
|  | +						TSENS_8064_SENSOR10_EN) | ||||||
|  | + | ||||||
|  | +#define TSENS_8064_SEQ_SENSORS	5 | ||||||
|  | +#define TSENS_8064_S4_S5_OFFSET	40 | ||||||
|  | +#define TSENS_FACTOR		1 | ||||||
|  | + | ||||||
|  | +/* Trips: from very hot to very cold */ | ||||||
|  | +enum tsens_trip_type { | ||||||
|  | +	TSENS_TRIP_STAGE3 = 0, | ||||||
|  | +	TSENS_TRIP_STAGE2, | ||||||
|  | +	TSENS_TRIP_STAGE1, | ||||||
|  | +	TSENS_TRIP_STAGE0, | ||||||
|  | +	TSENS_TRIP_NUM, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +u32 tsens_8064_slope[] = { | ||||||
|  | +			1176, 1176, 1154, 1176, | ||||||
|  | +			1111, 1132, 1132, 1199, | ||||||
|  | +			1132, 1199, 1132 | ||||||
|  | +			}; | ||||||
|  | + | ||||||
|  | +/* Temperature on y axis and ADC-code on x-axis */ | ||||||
|  | +static inline int code_to_degC(u32 adc_code, const struct tsens_sensor *s) | ||||||
|  | +{ | ||||||
|  | +	int degcbeforefactor, degc; | ||||||
|  | + | ||||||
|  | +	degcbeforefactor = (adc_code * s->slope) + s->offset; | ||||||
|  | + | ||||||
|  | +	if (degcbeforefactor == 0) | ||||||
|  | +		degc = degcbeforefactor; | ||||||
|  | +	else if (degcbeforefactor > 0) | ||||||
|  | +		degc = (degcbeforefactor + TSENS_FACTOR/2) | ||||||
|  | +			/ TSENS_FACTOR; | ||||||
|  | +	else | ||||||
|  | +		degc = (degcbeforefactor - TSENS_FACTOR/2) | ||||||
|  | +			/ TSENS_FACTOR; | ||||||
|  | + | ||||||
|  | +	return degc; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int degC_to_code(int degC, const struct tsens_sensor *s) | ||||||
|  | +{ | ||||||
|  | +	int code = ((degC * TSENS_FACTOR - s->offset) + (s->slope/2)) | ||||||
|  | +			/ s->slope; | ||||||
|  | + | ||||||
|  | +	if (code > THRESHOLD_MAX_CODE) | ||||||
|  | +		code = THRESHOLD_MAX_CODE; | ||||||
|  | +	else if (code < THRESHOLD_MIN_CODE) | ||||||
|  | +		code = THRESHOLD_MIN_CODE; | ||||||
|  | +	return code; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int suspend_ipq8064(struct tsens_device *tmdev) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	unsigned int mask; | ||||||
|  | +	struct regmap *map = tmdev->map; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	mask = SLP_CLK_ENA | EN; | ||||||
|  | + | ||||||
|  | +	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int resume_ipq8064(struct tsens_device *tmdev) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	struct regmap *map = tmdev->map; | ||||||
|  | + | ||||||
|  | +	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void notify_uspace_tsens_fn(struct work_struct *work) | ||||||
|  | +{ | ||||||
|  | +	struct tsens_sensor *s = container_of(work, struct tsens_sensor, | ||||||
|  | +								notify_work); | ||||||
|  | + | ||||||
|  | +	sysfs_notify(&s->tzd->device.kobj, NULL, "type"); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void tsens_scheduler_fn(struct work_struct *work) | ||||||
|  | +{ | ||||||
|  | +	struct tsens_device *tmdev = container_of(work, struct tsens_device, | ||||||
|  | +					tsens_work); | ||||||
|  | +	unsigned int threshold, threshold_low, code, reg, sensor, mask; | ||||||
|  | +	unsigned int sensor_addr; | ||||||
|  | +	bool upper_th_x, lower_th_x; | ||||||
|  | +	int adc_code, ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, STATUS_CNTL_8064, ®); | ||||||
|  | +	if (ret) | ||||||
|  | +		return; | ||||||
|  | +	reg = reg | LOWER_STATUS_CLR | UPPER_STATUS_CLR; | ||||||
|  | +	ret = regmap_write(tmdev->map, STATUS_CNTL_8064, reg); | ||||||
|  | +	if (ret) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	mask = ~(LOWER_STATUS_CLR | UPPER_STATUS_CLR); | ||||||
|  | +	ret = regmap_read(tmdev->map, THRESHOLD_ADDR, &threshold); | ||||||
|  | +	if (ret) | ||||||
|  | +		return; | ||||||
|  | +	threshold_low = (threshold & THRESHOLD_LOWER_LIMIT_MASK) | ||||||
|  | +				>> THRESHOLD_LOWER_LIMIT_SHIFT; | ||||||
|  | +	threshold = (threshold & THRESHOLD_UPPER_LIMIT_MASK) | ||||||
|  | +				>> THRESHOLD_UPPER_LIMIT_SHIFT; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, STATUS_CNTL_8064, ®); | ||||||
|  | +	if (ret) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, CNTL_ADDR, &sensor); | ||||||
|  | +	if (ret) | ||||||
|  | +		return; | ||||||
|  | +	sensor &= (uint32_t) TSENS_8064_SENSORS_EN; | ||||||
|  | +	sensor >>= SENSOR0_SHIFT; | ||||||
|  | + | ||||||
|  | +	/* Constraint: There is only 1 interrupt control register for all | ||||||
|  | +	 * 11 temperature sensor. So monitoring more than 1 sensor based | ||||||
|  | +	 * on interrupts will yield inconsistent result. To overcome this | ||||||
|  | +	 * issue we will monitor only sensor 0 which is the master sensor. | ||||||
|  | +	 */ | ||||||
|  | + | ||||||
|  | +	/* Skip if the sensor is disabled */ | ||||||
|  | +	if (sensor & 1) { | ||||||
|  | +		ret = regmap_read(tmdev->map, tmdev->sensor[0].status, &code); | ||||||
|  | +		if (ret) | ||||||
|  | +			return; | ||||||
|  | +		upper_th_x = code >= threshold; | ||||||
|  | +		lower_th_x = code <= threshold_low; | ||||||
|  | +		if (upper_th_x) | ||||||
|  | +			mask |= UPPER_STATUS_CLR; | ||||||
|  | +		if (lower_th_x) | ||||||
|  | +			mask |= LOWER_STATUS_CLR; | ||||||
|  | +		if (upper_th_x || lower_th_x) { | ||||||
|  | +			/* Notify user space */ | ||||||
|  | +			schedule_work(&tmdev->sensor[0].notify_work); | ||||||
|  | +			regmap_read(tmdev->map, sensor_addr, &adc_code); | ||||||
|  | +			pr_debug("Trigger (%d degrees) for sensor %d\n", | ||||||
|  | +				code_to_degC(adc_code, &tmdev->sensor[0]), 0); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	regmap_write(tmdev->map, STATUS_CNTL_8064, reg & mask); | ||||||
|  | + | ||||||
|  | +	/* force memory to sync */ | ||||||
|  | +	mb(); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static irqreturn_t tsens_isr(int irq, void *data) | ||||||
|  | +{ | ||||||
|  | +	struct tsens_device *tmdev = data; | ||||||
|  | + | ||||||
|  | +	schedule_work(&tmdev->tsens_work); | ||||||
|  | +	return IRQ_HANDLED; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void hw_init(struct tsens_device *tmdev) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0; | ||||||
|  | +	unsigned int reg_status_cntl = 0; | ||||||
|  | + | ||||||
|  | +	regmap_read(tmdev->map, CNTL_ADDR, ®_cntl); | ||||||
|  | +	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl | TSENS_SW_RST); | ||||||
|  | + | ||||||
|  | +	reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18) | ||||||
|  | +		| (((1 << tmdev->num_sensors) - 1) << SENSOR0_SHIFT); | ||||||
|  | +	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); | ||||||
|  | +	regmap_read(tmdev->map, STATUS_CNTL_8064, ®_status_cntl); | ||||||
|  | +	reg_status_cntl |= LOWER_STATUS_CLR | UPPER_STATUS_CLR | ||||||
|  | +			| MIN_STATUS_MASK | MAX_STATUS_MASK; | ||||||
|  | +	regmap_write(tmdev->map, STATUS_CNTL_8064, reg_status_cntl); | ||||||
|  | +	reg_cntl |= TSENS_EN; | ||||||
|  | +	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); | ||||||
|  | + | ||||||
|  | +	regmap_read(tmdev->map, CONFIG_ADDR, ®_cfg); | ||||||
|  | +	reg_cfg = (reg_cfg & ~CONFIG_MASK) | (CONFIG << CONFIG_SHIFT); | ||||||
|  | +	regmap_write(tmdev->map, CONFIG_ADDR, reg_cfg); | ||||||
|  | + | ||||||
|  | +	reg_thr |= (LOWER_LIMIT_TH << THRESHOLD_LOWER_LIMIT_SHIFT) | ||||||
|  | +		| (UPPER_LIMIT_TH << THRESHOLD_UPPER_LIMIT_SHIFT) | ||||||
|  | +		| (MIN_LIMIT_TH << THRESHOLD_MIN_LIMIT_SHIFT) | ||||||
|  | +		| (MAX_LIMIT_TH << THRESHOLD_MAX_LIMIT_SHIFT); | ||||||
|  | + | ||||||
|  | +	regmap_write(tmdev->map, THRESHOLD_ADDR, reg_thr); | ||||||
|  | + | ||||||
|  | +	ret = devm_request_irq(tmdev->dev, tmdev->tsens_irq, tsens_isr, | ||||||
|  | +			IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev); | ||||||
|  | +	if (ret < 0) { | ||||||
|  | +		pr_err("%s: request_irq FAIL: %d\n", __func__, ret); | ||||||
|  | +		return; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int init_ipq8064(struct tsens_device *tmdev) | ||||||
|  | +{ | ||||||
|  | +	int ret, i; | ||||||
|  | +	u32 reg_cntl, offset = 0; | ||||||
|  | + | ||||||
|  | +	init_common(tmdev); | ||||||
|  | +	if (!tmdev->map) | ||||||
|  | +		return -ENODEV; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * The status registers for each sensor are discontiguous | ||||||
|  | +	 * because some SoCs have 5 sensors while others have more | ||||||
|  | +	 * but the control registers stay in the same place, i.e | ||||||
|  | +	 * directly after the first 5 status registers. | ||||||
|  | +	 */ | ||||||
|  | +	for (i = 0; i < tmdev->num_sensors; i++) { | ||||||
|  | +		if (i >= TSENS_8064_SEQ_SENSORS) | ||||||
|  | +			offset = TSENS_8064_S4_S5_OFFSET; | ||||||
|  | + | ||||||
|  | +		tmdev->sensor[i].status = S0_STATUS_ADDR + offset | ||||||
|  | +					+ (i << STATUS_ADDR_OFFSET); | ||||||
|  | +		tmdev->sensor[i].slope = tsens_8064_slope[i]; | ||||||
|  | +		INIT_WORK(&tmdev->sensor[i].notify_work, | ||||||
|  | +						notify_uspace_tsens_fn); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	reg_cntl = SW_RST; | ||||||
|  | +	ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18); | ||||||
|  | +	reg_cntl &= ~SW_RST; | ||||||
|  | +	ret = regmap_update_bits(tmdev->map, CONFIG_ADDR, | ||||||
|  | +					 CONFIG_MASK, CONFIG); | ||||||
|  | + | ||||||
|  | +	reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT; | ||||||
|  | +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	reg_cntl |= EN; | ||||||
|  | +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int calibrate_ipq8064(struct tsens_device *tmdev) | ||||||
|  | +{ | ||||||
|  | +	int i; | ||||||
|  | +	char *data, *data_backup; | ||||||
|  | + | ||||||
|  | +	ssize_t num_read = tmdev->num_sensors; | ||||||
|  | +	struct tsens_sensor *s = tmdev->sensor; | ||||||
|  | + | ||||||
|  | +	data = qfprom_read(tmdev->dev, "calib"); | ||||||
|  | +	if (IS_ERR(data)) { | ||||||
|  | +		pr_err("Calibration not found.\n"); | ||||||
|  | +		return PTR_ERR(data); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	data_backup = qfprom_read(tmdev->dev, "calib_backup"); | ||||||
|  | +	if (IS_ERR(data_backup)) { | ||||||
|  | +		pr_err("Backup calibration not found.\n"); | ||||||
|  | +		return PTR_ERR(data_backup); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < num_read; i++) { | ||||||
|  | +		s[i].calib_data = readb_relaxed(data + i); | ||||||
|  | +		s[i].calib_data_backup = readb_relaxed(data_backup + i); | ||||||
|  | + | ||||||
|  | +		if (s[i].calib_data_backup) | ||||||
|  | +			s[i].calib_data = s[i].calib_data_backup; | ||||||
|  | +		if (!s[i].calib_data) { | ||||||
|  | +			pr_err("QFPROM TSENS calibration data not present\n"); | ||||||
|  | +			return -ENODEV; | ||||||
|  | +		} | ||||||
|  | +		s[i].slope = tsens_8064_slope[i]; | ||||||
|  | +		s[i].offset = CAL_MDEGC - (s[i].calib_data * s[i].slope); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	hw_init(tmdev); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int get_temp_ipq8064(struct tsens_device *tmdev, int id, int *temp) | ||||||
|  | +{ | ||||||
|  | +	int ret; | ||||||
|  | +	u32 code, trdy; | ||||||
|  | +	const struct tsens_sensor *s = &tmdev->sensor[id]; | ||||||
|  | +	unsigned long timeout; | ||||||
|  | + | ||||||
|  | +	timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); | ||||||
|  | +	do { | ||||||
|  | +		ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy); | ||||||
|  | +		if (ret) | ||||||
|  | +			return ret; | ||||||
|  | +		if (!(trdy & TRDY_MASK)) | ||||||
|  | +			continue; | ||||||
|  | +		ret = regmap_read(tmdev->map, s->status, &code); | ||||||
|  | +		if (ret) | ||||||
|  | +			return ret; | ||||||
|  | +		*temp = code_to_degC(code, s); | ||||||
|  | +		return 0; | ||||||
|  | +	} while (time_before(jiffies, timeout)); | ||||||
|  | + | ||||||
|  | +	return -ETIMEDOUT; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int set_trip_temp_ipq8064(void *data, int trip, int temp) | ||||||
|  | +{ | ||||||
|  | +	unsigned int reg_th, reg_cntl; | ||||||
|  | +	int ret, code, code_chk, hi_code, lo_code; | ||||||
|  | +	const struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  | + | ||||||
|  | +	code_chk = code = degC_to_code(temp, s); | ||||||
|  | + | ||||||
|  | +	if (code < THRESHOLD_MIN_CODE || code > THRESHOLD_MAX_CODE) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, STATUS_CNTL_8064, ®_cntl); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, THRESHOLD_ADDR, ®_th); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	hi_code = (reg_th & THRESHOLD_UPPER_LIMIT_MASK) | ||||||
|  | +			>> THRESHOLD_UPPER_LIMIT_SHIFT; | ||||||
|  | +	lo_code = (reg_th & THRESHOLD_LOWER_LIMIT_MASK) | ||||||
|  | +			>> THRESHOLD_LOWER_LIMIT_SHIFT; | ||||||
|  | + | ||||||
|  | +	switch (trip) { | ||||||
|  | +	case TSENS_TRIP_STAGE3: | ||||||
|  | +		code <<= THRESHOLD_MAX_LIMIT_SHIFT; | ||||||
|  | +		reg_th &= ~THRESHOLD_MAX_LIMIT_MASK; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE2: | ||||||
|  | +		if (code_chk <= lo_code) | ||||||
|  | +			return -EINVAL; | ||||||
|  | +		code <<= THRESHOLD_UPPER_LIMIT_SHIFT; | ||||||
|  | +		reg_th &= ~THRESHOLD_UPPER_LIMIT_MASK; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE1: | ||||||
|  | +		if (code_chk >= hi_code) | ||||||
|  | +			return -EINVAL; | ||||||
|  | +		code <<= THRESHOLD_LOWER_LIMIT_SHIFT; | ||||||
|  | +		reg_th &= ~THRESHOLD_LOWER_LIMIT_MASK; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE0: | ||||||
|  | +		code <<= THRESHOLD_MIN_LIMIT_SHIFT; | ||||||
|  | +		reg_th &= ~THRESHOLD_MIN_LIMIT_MASK; | ||||||
|  | +		break; | ||||||
|  | +	default: | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = regmap_write(tmdev->map, THRESHOLD_ADDR, reg_th | code); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int set_trip_activate_ipq8064(void *data, int trip, | ||||||
|  | +					enum thermal_trip_activation_mode mode) | ||||||
|  | +{ | ||||||
|  | +	unsigned int reg_cntl, mask, val; | ||||||
|  | +	const struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	if (!tmdev || trip < 0) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	ret = regmap_read(tmdev->map, STATUS_CNTL_8064, ®_cntl); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	switch (trip) { | ||||||
|  | +	case TSENS_TRIP_STAGE3: | ||||||
|  | +		mask = MAX_STATUS_MASK; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE2: | ||||||
|  | +		mask = UPPER_STATUS_CLR; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE1: | ||||||
|  | +		mask = LOWER_STATUS_CLR; | ||||||
|  | +		break; | ||||||
|  | +	case TSENS_TRIP_STAGE0: | ||||||
|  | +		mask = MIN_STATUS_MASK; | ||||||
|  | +		break; | ||||||
|  | +	default: | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) | ||||||
|  | +		val = reg_cntl | mask; | ||||||
|  | +	else | ||||||
|  | +		val = reg_cntl & ~mask; | ||||||
|  | + | ||||||
|  | +	ret = regmap_write(tmdev->map, STATUS_CNTL_8064, val); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	/* force memory to sync */ | ||||||
|  | +	mb(); | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct tsens_ops ops_ipq8064 = { | ||||||
|  | +	.init		= init_ipq8064, | ||||||
|  | +	.calibrate	= calibrate_ipq8064, | ||||||
|  | +	.get_temp	= get_temp_ipq8064, | ||||||
|  | +	.suspend	= suspend_ipq8064, | ||||||
|  | +	.resume		= resume_ipq8064, | ||||||
|  | +	.set_trip_temp	= set_trip_temp_ipq8064, | ||||||
|  | +	.set_trip_activate = set_trip_activate_ipq8064, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +const struct tsens_data data_ipq8064 = { | ||||||
|  | +	.num_sensors	= 11, | ||||||
|  | +	.ops		= &ops_ipq8064, | ||||||
|  | +}; | ||||||
|  | --- a/drivers/thermal/qcom/tsens.c | ||||||
|  | +++ b/drivers/thermal/qcom/tsens.c | ||||||
|  | @@ -72,6 +72,9 @@ static const struct of_device_id tsens_t | ||||||
|  |  	}, { | ||||||
|  |  		.compatible = "qcom,msm8996-tsens", | ||||||
|  |  		.data = &data_8996, | ||||||
|  | +	}, { | ||||||
|  | +		.compatible = "qcom,ipq8064-tsens", | ||||||
|  | +		.data = &data_ipq8064, | ||||||
|  |  	}, | ||||||
|  |  	{} | ||||||
|  |  }; | ||||||
|  | --- a/drivers/thermal/qcom/tsens.h | ||||||
|  | +++ b/drivers/thermal/qcom/tsens.h | ||||||
|  | @@ -89,6 +89,6 @@ void compute_intercept_slope(struct tsen | ||||||
|  |  int init_common(struct tsens_device *); | ||||||
|  |  int get_temp_common(struct tsens_device *, int, int *); | ||||||
|  |   | ||||||
|  | -extern const struct tsens_data data_8916, data_8974, data_8960, data_8996; | ||||||
|  | +extern const struct tsens_data data_8916, data_8974, data_8960, data_8996, data_ipq8064; | ||||||
|  |   | ||||||
|  |  #endif /* __QCOM_TSENS_H__ */ | ||||||
| @@ -0,0 +1,453 @@ | |||||||
|  | From 4e87400732c77765afae2ea89ed43837457aa604 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Rajith Cherian <rajith@codeaurora.org> | ||||||
|  | Date: Wed, 1 Feb 2017 19:00:26 +0530 | ||||||
|  | Subject: [PATCH] ipq8064: tsens: Support for configurable interrupts | ||||||
|  |  | ||||||
|  | Provide support for adding configurable high and | ||||||
|  | configurable low trip temperatures. An interrupts is | ||||||
|  | also triggerred when these trip points are hit. The | ||||||
|  | interrupts can be activated or deactivated from sysfs. | ||||||
|  | This functionality is made available only if | ||||||
|  | CONFIG_THERMAL_WRITABLE_TRIPS is defined. | ||||||
|  |  | ||||||
|  | Change-Id: Ib73f3f9459de4fffce7bb985a0312a88291f4934 | ||||||
|  | Signed-off-by: Rajith Cherian <rajith@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/thermal/qcom-tsens.txt     |  4 ++ | ||||||
|  |  drivers/thermal/of-thermal.c                       | 63 ++++++++++++++++++---- | ||||||
|  |  drivers/thermal/qcom/tsens.c                       | 43 ++++++++++++--- | ||||||
|  |  drivers/thermal/qcom/tsens.h                       | 11 ++++ | ||||||
|  |  drivers/thermal/thermal_core.c                     | 44 ++++++++++++++- | ||||||
|  |  include/linux/thermal.h                            | 14 +++++ | ||||||
|  |  6 files changed, 162 insertions(+), 17 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt | ||||||
|  | @@ -12,11 +12,15 @@ Required properties: | ||||||
|  |  - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify | ||||||
|  |  nvmem cells | ||||||
|  |   | ||||||
|  | +Optional properties: | ||||||
|  | +- interrupts: Interrupt which gets triggered when threshold is hit | ||||||
|  | + | ||||||
|  |  Example: | ||||||
|  |  tsens: thermal-sensor@900000 { | ||||||
|  |  		compatible = "qcom,msm8916-tsens"; | ||||||
|  |  		reg = <0x4a8000 0x2000>; | ||||||
|  |  		nvmem-cells = <&tsens_caldata>, <&tsens_calsel>; | ||||||
|  |  		nvmem-cell-names = "caldata", "calsel"; | ||||||
|  | +		interrupts = <0 178 0>; | ||||||
|  |  		#thermal-sensor-cells = <1>; | ||||||
|  |  	}; | ||||||
|  | --- a/drivers/thermal/of-thermal.c | ||||||
|  | +++ b/drivers/thermal/of-thermal.c | ||||||
|  | @@ -95,7 +95,7 @@ static int of_thermal_get_temp(struct th | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (!data->ops->get_temp) | ||||||
|  | +	if (!data->ops->get_temp || (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EINVAL; | ||||||
|  |   | ||||||
|  |  	return data->ops->get_temp(data->sensor_data, temp); | ||||||
|  | @@ -106,7 +106,8 @@ static int of_thermal_set_trips(struct t | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (!data->ops || !data->ops->set_trips) | ||||||
|  | +	if (!data->ops || !data->ops->set_trips | ||||||
|  | +			|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EINVAL; | ||||||
|  |   | ||||||
|  |  	return data->ops->set_trips(data->sensor_data, low, high); | ||||||
|  | @@ -192,6 +193,9 @@ static int of_thermal_set_emul_temp(stru | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | +	if (data->mode == THERMAL_DEVICE_DISABLED) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  |  	return data->ops->set_emul_temp(data->sensor_data, temp); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -200,7 +204,7 @@ static int of_thermal_get_trend(struct t | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (!data->ops->get_trend) | ||||||
|  | +	if (!data->ops->get_trend || (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EINVAL; | ||||||
|  |   | ||||||
|  |  	return data->ops->get_trend(data->sensor_data, trip, trend); | ||||||
|  | @@ -289,7 +293,9 @@ static int of_thermal_set_mode(struct th | ||||||
|  |  	mutex_unlock(&tz->lock); | ||||||
|  |   | ||||||
|  |  	data->mode = mode; | ||||||
|  | -	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); | ||||||
|  | + | ||||||
|  | +	if (mode == THERMAL_DEVICE_ENABLED) | ||||||
|  | +		thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); | ||||||
|  |   | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  | @@ -299,7 +305,8 @@ static int of_thermal_get_trip_type(stru | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (trip >= data->ntrips || trip < 0) | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EDOM; | ||||||
|  |   | ||||||
|  |  	*type = data->trips[trip].type; | ||||||
|  | @@ -307,12 +314,39 @@ static int of_thermal_get_trip_type(stru | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int of_thermal_activate_trip_type(struct thermal_zone_device *tz, | ||||||
|  | +			int trip, enum thermal_trip_activation_mode mode) | ||||||
|  | +{ | ||||||
|  | +	struct __thermal_zone *data = tz->devdata; | ||||||
|  | + | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  | +		return -EDOM; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * The configurable_hi and configurable_lo trip points can be | ||||||
|  | +	 * activated and deactivated. | ||||||
|  | +	 */ | ||||||
|  | + | ||||||
|  | +	if (data->ops->set_trip_activate) { | ||||||
|  | +		int ret; | ||||||
|  | + | ||||||
|  | +		ret = data->ops->set_trip_activate(data->sensor_data, | ||||||
|  | +								trip, mode); | ||||||
|  | +		if (ret) | ||||||
|  | +			return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, | ||||||
|  |  				    int *temp) | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (trip >= data->ntrips || trip < 0) | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EDOM; | ||||||
|  |   | ||||||
|  |  	*temp = data->trips[trip].temperature; | ||||||
|  | @@ -325,7 +359,8 @@ static int of_thermal_set_trip_temp(stru | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (trip >= data->ntrips || trip < 0) | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EDOM; | ||||||
|  |   | ||||||
|  |  	if (data->ops->set_trip_temp) { | ||||||
|  | @@ -347,7 +382,8 @@ static int of_thermal_get_trip_hyst(stru | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (trip >= data->ntrips || trip < 0) | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EDOM; | ||||||
|  |   | ||||||
|  |  	*hyst = data->trips[trip].hysteresis; | ||||||
|  | @@ -360,7 +396,8 @@ static int of_thermal_set_trip_hyst(stru | ||||||
|  |  { | ||||||
|  |  	struct __thermal_zone *data = tz->devdata; | ||||||
|  |   | ||||||
|  | -	if (trip >= data->ntrips || trip < 0) | ||||||
|  | +	if (trip >= data->ntrips || trip < 0 | ||||||
|  | +				|| (data->mode == THERMAL_DEVICE_DISABLED)) | ||||||
|  |  		return -EDOM; | ||||||
|  |   | ||||||
|  |  	/* thermal framework should take care of data->mask & (1 << trip) */ | ||||||
|  | @@ -435,6 +472,9 @@ thermal_zone_of_add_sensor(struct device | ||||||
|  |  	if (ops->set_emul_temp) | ||||||
|  |  		tzd->ops->set_emul_temp = of_thermal_set_emul_temp; | ||||||
|  |   | ||||||
|  | +	if (ops->set_trip_activate) | ||||||
|  | +		tzd->ops->set_trip_activate = of_thermal_activate_trip_type; | ||||||
|  | + | ||||||
|  |  	mutex_unlock(&tzd->lock); | ||||||
|  |   | ||||||
|  |  	return tzd; | ||||||
|  | @@ -729,7 +769,10 @@ static const char * const trip_types[] = | ||||||
|  |  	[THERMAL_TRIP_ACTIVE]	= "active", | ||||||
|  |  	[THERMAL_TRIP_PASSIVE]	= "passive", | ||||||
|  |  	[THERMAL_TRIP_HOT]	= "hot", | ||||||
|  | -	[THERMAL_TRIP_CRITICAL]	= "critical", | ||||||
|  | +	[THERMAL_TRIP_CRITICAL]	= "critical_high", | ||||||
|  | +	[THERMAL_TRIP_CONFIGURABLE_HI] = "configurable_hi", | ||||||
|  | +	[THERMAL_TRIP_CONFIGURABLE_LOW] = "configurable_lo", | ||||||
|  | +	[THERMAL_TRIP_CRITICAL_LOW] = "critical_low", | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | --- a/drivers/thermal/qcom/tsens.c | ||||||
|  | +++ b/drivers/thermal/qcom/tsens.c | ||||||
|  | @@ -31,7 +31,7 @@ static int tsens_get_temp(void *data, in | ||||||
|  |   | ||||||
|  |  static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) | ||||||
|  |  { | ||||||
|  | -	const struct tsens_sensor *s = p; | ||||||
|  | +	struct tsens_sensor *s = p; | ||||||
|  |  	struct tsens_device *tmdev = s->tmdev; | ||||||
|  |   | ||||||
|  |  	if (tmdev->ops->get_trend) | ||||||
|  | @@ -40,9 +40,10 @@ static int tsens_get_trend(void *p, int | ||||||
|  |  	return -ENOTSUPP; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int  __maybe_unused tsens_suspend(struct device *dev) | ||||||
|  | +static int  __maybe_unused tsens_suspend(void *data) | ||||||
|  |  { | ||||||
|  | -	struct tsens_device *tmdev = dev_get_drvdata(dev); | ||||||
|  | +	struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  |   | ||||||
|  |  	if (tmdev->ops && tmdev->ops->suspend) | ||||||
|  |  		return tmdev->ops->suspend(tmdev); | ||||||
|  | @@ -50,9 +51,10 @@ static int  __maybe_unused tsens_suspend | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int __maybe_unused tsens_resume(struct device *dev) | ||||||
|  | +static int __maybe_unused tsens_resume(void *data) | ||||||
|  |  { | ||||||
|  | -	struct tsens_device *tmdev = dev_get_drvdata(dev); | ||||||
|  | +	struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  |   | ||||||
|  |  	if (tmdev->ops && tmdev->ops->resume) | ||||||
|  |  		return tmdev->ops->resume(tmdev); | ||||||
|  | @@ -60,6 +62,30 @@ static int __maybe_unused tsens_resume(s | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int  __maybe_unused tsens_set_trip_temp(void *data, int trip, int temp) | ||||||
|  | +{ | ||||||
|  | +	struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  | + | ||||||
|  | +	if (tmdev->ops && tmdev->ops->set_trip_temp) | ||||||
|  | +		return tmdev->ops->set_trip_temp(s, trip, temp); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int __maybe_unused tsens_activate_trip_type(void *data, int trip, | ||||||
|  | +					enum thermal_trip_activation_mode mode) | ||||||
|  | +{ | ||||||
|  | +	struct tsens_sensor *s = data; | ||||||
|  | +	struct tsens_device *tmdev = s->tmdev; | ||||||
|  | + | ||||||
|  | +	if (tmdev->ops && tmdev->ops->set_trip_activate) | ||||||
|  | +		return tmdev->ops->set_trip_activate(s, trip, mode); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | + | ||||||
|  |  static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume); | ||||||
|  |   | ||||||
|  |  static const struct of_device_id tsens_table[] = { | ||||||
|  | @@ -83,6 +109,8 @@ MODULE_DEVICE_TABLE(of, tsens_table); | ||||||
|  |  static const struct thermal_zone_of_device_ops tsens_of_ops = { | ||||||
|  |  	.get_temp = tsens_get_temp, | ||||||
|  |  	.get_trend = tsens_get_trend, | ||||||
|  | +	.set_trip_temp = tsens_set_trip_temp, | ||||||
|  | +	.set_trip_activate = tsens_activate_trip_type, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int tsens_register(struct tsens_device *tmdev) | ||||||
|  | @@ -131,7 +159,7 @@ static int tsens_probe(struct platform_d | ||||||
|  |  	if (id) | ||||||
|  |  		data = id->data; | ||||||
|  |  	else | ||||||
|  | -		data = &data_8960; | ||||||
|  | +		return -EINVAL; | ||||||
|  |   | ||||||
|  |  	if (data->num_sensors <= 0) { | ||||||
|  |  		dev_err(dev, "invalid number of sensors\n"); | ||||||
|  | @@ -146,6 +174,9 @@ static int tsens_probe(struct platform_d | ||||||
|  |  	tmdev->dev = dev; | ||||||
|  |  	tmdev->num_sensors = data->num_sensors; | ||||||
|  |  	tmdev->ops = data->ops; | ||||||
|  | + | ||||||
|  | +	tmdev->tsens_irq = platform_get_irq(pdev, 0); | ||||||
|  | + | ||||||
|  |  	for (i = 0;  i < tmdev->num_sensors; i++) { | ||||||
|  |  		if (data->hw_ids) | ||||||
|  |  			tmdev->sensor[i].hw_id = data->hw_ids[i]; | ||||||
|  | --- a/drivers/thermal/qcom/tsens.h | ||||||
|  | +++ b/drivers/thermal/qcom/tsens.h | ||||||
|  | @@ -24,9 +24,12 @@ struct tsens_device; | ||||||
|  |  struct tsens_sensor { | ||||||
|  |  	struct tsens_device		*tmdev; | ||||||
|  |  	struct thermal_zone_device	*tzd; | ||||||
|  | +	struct work_struct		notify_work; | ||||||
|  |  	int				offset; | ||||||
|  |  	int				id; | ||||||
|  |  	int				hw_id; | ||||||
|  | +	int				calib_data; | ||||||
|  | +	int				calib_data_backup; | ||||||
|  |  	int				slope; | ||||||
|  |  	u32				status; | ||||||
|  |  }; | ||||||
|  | @@ -41,6 +44,9 @@ struct tsens_sensor { | ||||||
|  |   * @suspend: Function to suspend the tsens device | ||||||
|  |   * @resume: Function to resume the tsens device | ||||||
|  |   * @get_trend: Function to get the thermal/temp trend | ||||||
|  | + * @set_trip_temp: Function to set trip temp | ||||||
|  | + * @get_trip_temp: Function to get trip temp | ||||||
|  | + * @set_trip_activate: Function to activate trip points | ||||||
|  |   */ | ||||||
|  |  struct tsens_ops { | ||||||
|  |  	/* mandatory callbacks */ | ||||||
|  | @@ -53,6 +59,9 @@ struct tsens_ops { | ||||||
|  |  	int (*suspend)(struct tsens_device *); | ||||||
|  |  	int (*resume)(struct tsens_device *); | ||||||
|  |  	int (*get_trend)(struct tsens_device *, int, enum thermal_trend *); | ||||||
|  | +	int (*set_trip_temp)(void *, int, int); | ||||||
|  | +	int (*set_trip_activate)(void *, int, | ||||||
|  | +					enum thermal_trip_activation_mode); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | @@ -76,11 +85,13 @@ struct tsens_context { | ||||||
|  |  struct tsens_device { | ||||||
|  |  	struct device			*dev; | ||||||
|  |  	u32				num_sensors; | ||||||
|  | +	u32				tsens_irq; | ||||||
|  |  	struct regmap			*map; | ||||||
|  |  	struct regmap_field		*status_field; | ||||||
|  |  	struct tsens_context		ctx; | ||||||
|  |  	bool				trdy; | ||||||
|  |  	const struct tsens_ops		*ops; | ||||||
|  | +	struct work_struct		tsens_work; | ||||||
|  |  	struct tsens_sensor		sensor[0]; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | --- a/drivers/thermal/thermal_sysfs.c | ||||||
|  | +++ b/drivers/thermal/thermal_sysfs.c | ||||||
|  | @@ -115,12 +115,48 @@ trip_point_type_show(struct device *dev, | ||||||
|  |  		return sprintf(buf, "passive\n"); | ||||||
|  |  	case THERMAL_TRIP_ACTIVE: | ||||||
|  |  		return sprintf(buf, "active\n"); | ||||||
|  | +	case THERMAL_TRIP_CONFIGURABLE_HI: | ||||||
|  | +		return sprintf(buf, "configurable_hi\n"); | ||||||
|  | +	case THERMAL_TRIP_CONFIGURABLE_LOW: | ||||||
|  | +		return sprintf(buf, "configurable_low\n"); | ||||||
|  | +	case THERMAL_TRIP_CRITICAL_LOW: | ||||||
|  | +		return sprintf(buf, "critical_low\n"); | ||||||
|  |  	default: | ||||||
|  |  		return sprintf(buf, "unknown\n"); | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static ssize_t | ||||||
|  | +trip_point_type_activate(struct device *dev, struct device_attribute *attr, | ||||||
|  | +						const char *buf, size_t count) | ||||||
|  | +{ | ||||||
|  | +	struct thermal_zone_device *tz = to_thermal_zone(dev); | ||||||
|  | +	int trip, ret; | ||||||
|  | +	char *enabled = "enabled"; | ||||||
|  | +	char *disabled = "disabled"; | ||||||
|  | + | ||||||
|  | +	if (!tz->ops->set_trip_activate) | ||||||
|  | +		return -EPERM; | ||||||
|  | + | ||||||
|  | +	if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	if (!strncmp(buf, enabled, strlen(enabled))) | ||||||
|  | +		ret = tz->ops->set_trip_activate(tz, trip, | ||||||
|  | +				THERMAL_TRIP_ACTIVATION_ENABLED); | ||||||
|  | +	else if (!strncmp(buf, disabled, strlen(disabled))) | ||||||
|  | +		ret = tz->ops->set_trip_activate(tz, trip, | ||||||
|  | +				THERMAL_TRIP_ACTIVATION_DISABLED); | ||||||
|  | +	else | ||||||
|  | +		ret = -EINVAL; | ||||||
|  | + | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  | + | ||||||
|  | +	return count; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static ssize_t | ||||||
|  |  trip_point_temp_store(struct device *dev, struct device_attribute *attr, | ||||||
|  |  		      const char *buf, size_t count) | ||||||
|  |  { | ||||||
|  | @@ -562,6 +598,12 @@ static int create_trip_attrs(struct ther | ||||||
|  |  		tz->trip_type_attrs[indx].attr.show = trip_point_type_show; | ||||||
|  |  		attrs[indx] = &tz->trip_type_attrs[indx].attr.attr; | ||||||
|  |   | ||||||
|  | +		if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS)) { | ||||||
|  | +			tz->trip_type_attrs[indx].attr.store | ||||||
|  | +						= trip_point_type_activate; | ||||||
|  | +			tz->trip_type_attrs[indx].attr.attr.mode |= S_IWUSR; | ||||||
|  | +		} | ||||||
|  | + | ||||||
|  |  		/* create trip temp attribute */ | ||||||
|  |  		snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, | ||||||
|  |  			 "trip_point_%d_temp", indx); | ||||||
|  | --- a/include/linux/thermal.h | ||||||
|  | +++ b/include/linux/thermal.h | ||||||
|  | @@ -78,11 +78,19 @@ enum thermal_device_mode { | ||||||
|  |  	THERMAL_DEVICE_ENABLED, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +enum thermal_trip_activation_mode { | ||||||
|  | +	THERMAL_TRIP_ACTIVATION_DISABLED = 0, | ||||||
|  | +	THERMAL_TRIP_ACTIVATION_ENABLED, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  enum thermal_trip_type { | ||||||
|  |  	THERMAL_TRIP_ACTIVE = 0, | ||||||
|  |  	THERMAL_TRIP_PASSIVE, | ||||||
|  |  	THERMAL_TRIP_HOT, | ||||||
|  |  	THERMAL_TRIP_CRITICAL, | ||||||
|  | +	THERMAL_TRIP_CONFIGURABLE_HI, | ||||||
|  | +	THERMAL_TRIP_CONFIGURABLE_LOW, | ||||||
|  | +	THERMAL_TRIP_CRITICAL_LOW, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  enum thermal_trend { | ||||||
|  | @@ -120,6 +128,8 @@ struct thermal_zone_device_ops { | ||||||
|  |  		enum thermal_trip_type *); | ||||||
|  |  	int (*get_trip_temp) (struct thermal_zone_device *, int, int *); | ||||||
|  |  	int (*set_trip_temp) (struct thermal_zone_device *, int, int); | ||||||
|  | +	int (*set_trip_activate) (struct thermal_zone_device *, int, | ||||||
|  | +					enum thermal_trip_activation_mode); | ||||||
|  |  	int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); | ||||||
|  |  	int (*set_trip_hyst) (struct thermal_zone_device *, int, int); | ||||||
|  |  	int (*get_crit_temp) (struct thermal_zone_device *, int *); | ||||||
|  | @@ -363,6 +373,8 @@ struct thermal_genl_event { | ||||||
|  |   *		   temperature. | ||||||
|  |   * @set_trip_temp: a pointer to a function that sets the trip temperature on | ||||||
|  |   *		   hardware. | ||||||
|  | + * @activate_trip_type: a pointer to a function to enable/disable trip | ||||||
|  | + *		temperature interrupts | ||||||
|  |   */ | ||||||
|  |  struct thermal_zone_of_device_ops { | ||||||
|  |  	int (*get_temp)(void *, int *); | ||||||
|  | @@ -370,6 +382,8 @@ struct thermal_zone_of_device_ops { | ||||||
|  |  	int (*set_trips)(void *, int, int); | ||||||
|  |  	int (*set_emul_temp)(void *, int); | ||||||
|  |  	int (*set_trip_temp)(void *, int, int); | ||||||
|  | +	int (*set_trip_activate)(void *, int, | ||||||
|  | +				enum thermal_trip_activation_mode); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
| @@ -0,0 +1,93 @@ | |||||||
|  | From d30840e2b1cf79d90392e6051b0c0b6006d29d8b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 9 Mar 2017 09:32:40 +0100 | ||||||
|  | Subject: [PATCH 64/69] clk: clk-rpm fixes | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  .../devicetree/bindings/clock/qcom,rpmcc.txt       |  1 + | ||||||
|  |  drivers/clk/qcom/clk-rpm.c                         | 35 ++++++++++++++++++++++ | ||||||
|  |  include/dt-bindings/clock/qcom,rpmcc.h             |  4 +++ | ||||||
|  |  3 files changed, 40 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | ||||||
|  | +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | ||||||
|  | @@ -13,6 +13,7 @@ Required properties : | ||||||
|  |  			"qcom,rpmcc-msm8916", "qcom,rpmcc" | ||||||
|  |  			"qcom,rpmcc-msm8974", "qcom,rpmcc" | ||||||
|  |  			"qcom,rpmcc-apq8064", "qcom,rpmcc" | ||||||
|  | +			"qcom,rpmcc-ipq806x", "qcom,rpmcc" | ||||||
|  |   | ||||||
|  |  - #clock-cells : shall contain 1 | ||||||
|  |   | ||||||
|  | --- a/drivers/clk/qcom/clk-rpm.c | ||||||
|  | +++ b/drivers/clk/qcom/clk-rpm.c | ||||||
|  | @@ -359,6 +359,16 @@ DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a | ||||||
|  |  DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK); | ||||||
|  |  DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK); | ||||||
|  |   | ||||||
|  | +/* ipq806x */ | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, nss_fabric_0_clk, nss_fabric_0_a_clk, QCOM_RPM_NSS_FABRIC_0_CLK); | ||||||
|  | +DEFINE_CLK_RPM(ipq806x, nss_fabric_1_clk, nss_fabric_1_a_clk, QCOM_RPM_NSS_FABRIC_1_CLK); | ||||||
|  | + | ||||||
|  |  static struct clk_rpm *apq8064_clks[] = { | ||||||
|  |  	[RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk, | ||||||
|  |  	[RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk, | ||||||
|  | @@ -380,13 +390,38 @@ static struct clk_rpm *apq8064_clks[] = | ||||||
|  |  	[RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static struct clk_rpm *ipq806x_clks[] = { | ||||||
|  | +	[RPM_APPS_FABRIC_CLK] = &ipq806x_afab_clk, | ||||||
|  | +	[RPM_APPS_FABRIC_A_CLK] = &ipq806x_afab_a_clk, | ||||||
|  | +	[RPM_CFPB_CLK] = &ipq806x_cfpb_clk, | ||||||
|  | +	[RPM_CFPB_A_CLK] = &ipq806x_cfpb_a_clk, | ||||||
|  | +	[RPM_DAYTONA_FABRIC_CLK] = &ipq806x_daytona_clk, | ||||||
|  | +	[RPM_DAYTONA_FABRIC_A_CLK] = &ipq806x_daytona_a_clk, | ||||||
|  | +	[RPM_EBI1_CLK] = &ipq806x_ebi1_clk, | ||||||
|  | +	[RPM_EBI1_A_CLK] = &ipq806x_ebi1_a_clk, | ||||||
|  | +	[RPM_SYS_FABRIC_CLK] = &ipq806x_sfab_clk, | ||||||
|  | +	[RPM_SYS_FABRIC_A_CLK] = &ipq806x_sfab_a_clk, | ||||||
|  | +	[RPM_SFPB_CLK] = &ipq806x_sfpb_clk, | ||||||
|  | +	[RPM_SFPB_A_CLK] = &ipq806x_sfpb_a_clk, | ||||||
|  | +	[RPM_NSS_FABRIC_0_CLK] = &ipq806x_nss_fabric_0_clk, | ||||||
|  | +	[RPM_NSS_FABRIC_0_A_CLK] = &ipq806x_nss_fabric_0_a_clk, | ||||||
|  | +	[RPM_NSS_FABRIC_1_CLK] = &ipq806x_nss_fabric_1_clk, | ||||||
|  | +	[RPM_NSS_FABRIC_1_A_CLK] = &ipq806x_nss_fabric_1_a_clk, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  static const struct rpm_clk_desc rpm_clk_apq8064 = { | ||||||
|  |  	.clks = apq8064_clks, | ||||||
|  |  	.num_clks = ARRAY_SIZE(apq8064_clks), | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static const struct rpm_clk_desc rpm_clk_ipq806x = { | ||||||
|  | +	.clks = ipq806x_clks, | ||||||
|  | +	.num_clks = ARRAY_SIZE(ipq806x_clks), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  static const struct of_device_id rpm_clk_match_table[] = { | ||||||
|  |  	{ .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 }, | ||||||
|  | +	{ .compatible = "qcom,rpmcc-ipq806x", .data = &rpm_clk_ipq806x }, | ||||||
|  |  	{ } | ||||||
|  |  }; | ||||||
|  |  MODULE_DEVICE_TABLE(of, rpm_clk_match_table); | ||||||
|  | --- a/include/dt-bindings/clock/qcom,rpmcc.h | ||||||
|  | +++ b/include/dt-bindings/clock/qcom,rpmcc.h | ||||||
|  | @@ -37,6 +37,10 @@ | ||||||
|  |  #define RPM_SYS_FABRIC_A_CLK			19 | ||||||
|  |  #define RPM_SFPB_CLK				20 | ||||||
|  |  #define RPM_SFPB_A_CLK				21 | ||||||
|  | +#define RPM_NSS_FABRIC_0_CLK				22 | ||||||
|  | +#define RPM_NSS_FABRIC_0_A_CLK				23 | ||||||
|  | +#define RPM_NSS_FABRIC_1_CLK				24 | ||||||
|  | +#define RPM_NSS_FABRIC_1_A_CLK				25 | ||||||
|  |   | ||||||
|  |  /* SMD RPM clocks */ | ||||||
|  |  #define RPM_SMD_XO_CLK_SRC				0 | ||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | From 4d8e29642661397a339ac3485f212c6360445421 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 9 Mar 2017 09:33:32 +0100 | ||||||
|  | Subject: [PATCH 65/69] arm: override compiler flags | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  arch/arm/Makefile | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/arch/arm/Makefile | ||||||
|  | +++ b/arch/arm/Makefile | ||||||
|  | @@ -67,7 +67,7 @@ KBUILD_CFLAGS	+= $(call cc-option,-fno-i | ||||||
|  |  # macro, but instead defines a whole series of macros which makes | ||||||
|  |  # testing for a specific architecture or later rather impossible. | ||||||
|  |  arch-$(CONFIG_CPU_32v7M)	=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m | ||||||
|  | -arch-$(CONFIG_CPU_32v7)		=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) | ||||||
|  | +arch-$(CONFIG_CPU_32v7)		=-D__LINUX_ARM_ARCH__=7 -mcpu=cortex-a15 | ||||||
|  |  arch-$(CONFIG_CPU_32v6)		=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) | ||||||
|  |  # Only override the compiler option if ARMv6. The ARMv6K extensions are | ||||||
|  |  # always available in ARMv7 | ||||||
| @@ -0,0 +1,189 @@ | |||||||
|  | From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Adrian Panella <ianchi74@outlook.com> | ||||||
|  | Date: Thu, 9 Mar 2017 09:37:17 +0100 | ||||||
|  | Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments | ||||||
|  |  | ||||||
|  | The command-line arguments provided by the boot loader will be | ||||||
|  | appended to a new device tree property: bootloader-args. | ||||||
|  | If there is a property "append-rootblock" in DT under /chosen | ||||||
|  | and a root= option in bootloaders command line it will be parsed | ||||||
|  | and added to DT bootargs with the form: <append-rootblock>XX. | ||||||
|  | Only command line ATAG will be processed, the rest of the ATAGs | ||||||
|  | sent by bootloader will be ignored. | ||||||
|  | This is usefull in dual boot systems, to get the current root partition | ||||||
|  | without afecting the rest of the system. | ||||||
|  |  | ||||||
|  | Signed-off-by: Adrian Panella <ianchi74@outlook.com> | ||||||
|  | --- | ||||||
|  |  arch/arm/Kconfig                        | 11 +++++ | ||||||
|  |  arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++- | ||||||
|  |  init/main.c                             | 16 ++++++++ | ||||||
|  |  3 files changed, 98 insertions(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/arch/arm/Kconfig | ||||||
|  | +++ b/arch/arm/Kconfig | ||||||
|  | @@ -1939,6 +1939,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN | ||||||
|  |  	  The command-line arguments provided by the boot loader will be | ||||||
|  |  	  appended to the the device tree bootargs property. | ||||||
|  |   | ||||||
|  | +config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE | ||||||
|  | +	bool "Append rootblock parsing bootloader's kernel arguments" | ||||||
|  | +	help | ||||||
|  | +	  The command-line arguments provided by the boot loader will be | ||||||
|  | +	  appended to a new device tree property: bootloader-args. | ||||||
|  | +	  If there is a property "append-rootblock" in DT under /chosen | ||||||
|  | +	  and a root= option in bootloaders command line it will be parsed | ||||||
|  | +	  and added to DT bootargs with the form: <append-rootblock>XX. | ||||||
|  | +	  Only command line ATAG will be processed, the rest of the ATAGs | ||||||
|  | +	  sent by bootloader will be ignored. | ||||||
|  | + | ||||||
|  |  endchoice | ||||||
|  |   | ||||||
|  |  config CMDLINE | ||||||
|  | --- a/arch/arm/boot/compressed/atags_to_fdt.c | ||||||
|  | +++ b/arch/arm/boot/compressed/atags_to_fdt.c | ||||||
|  | @@ -4,6 +4,8 @@ | ||||||
|  |   | ||||||
|  |  #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) | ||||||
|  |  #define do_extend_cmdline 1 | ||||||
|  | +#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) | ||||||
|  | +#define do_extend_cmdline 1 | ||||||
|  |  #else | ||||||
|  |  #define do_extend_cmdline 0 | ||||||
|  |  #endif | ||||||
|  | @@ -67,6 +69,59 @@ static uint32_t get_cell_size(const void | ||||||
|  |  	return cell_size; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) | ||||||
|  | + | ||||||
|  | +static char *append_rootblock(char *dest, const char *str, int len, void *fdt) | ||||||
|  | +{ | ||||||
|  | +	char *ptr, *end; | ||||||
|  | +	char *root="root="; | ||||||
|  | +	int i, l; | ||||||
|  | +	const char *rootblock; | ||||||
|  | + | ||||||
|  | +	//ARM doesn't have __HAVE_ARCH_STRSTR, so search manually | ||||||
|  | +	ptr = str - 1; | ||||||
|  | + | ||||||
|  | +	do { | ||||||
|  | +		//first find an 'r' at the begining or after a space | ||||||
|  | +		do { | ||||||
|  | +			ptr++; | ||||||
|  | +			ptr = strchr(ptr, 'r'); | ||||||
|  | +			if(!ptr) return dest; | ||||||
|  | + | ||||||
|  | +		} while (ptr != str && *(ptr-1) != ' '); | ||||||
|  | + | ||||||
|  | +		//then check for the rest | ||||||
|  | +		for(i = 1; i <= 4; i++) | ||||||
|  | +			if(*(ptr+i) != *(root+i)) break; | ||||||
|  | + | ||||||
|  | +	} while (i != 5); | ||||||
|  | + | ||||||
|  | +	end = strchr(ptr, ' '); | ||||||
|  | +	end = end ? (end - 1) : (strchr(ptr, 0) - 1); | ||||||
|  | + | ||||||
|  | +	//find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX ) | ||||||
|  | +	for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); | ||||||
|  | +	ptr = end + 1; | ||||||
|  | + | ||||||
|  | +	/* if append-rootblock property is set use it to append to command line */ | ||||||
|  | +	rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); | ||||||
|  | +	if(rootblock != NULL) { | ||||||
|  | +		if(*dest != ' ') { | ||||||
|  | +			*dest = ' '; | ||||||
|  | +			dest++; | ||||||
|  | +			len++; | ||||||
|  | +		} | ||||||
|  | +		if (len + l + i <= COMMAND_LINE_SIZE) { | ||||||
|  | +			memcpy(dest, rootblock, l); | ||||||
|  | +			dest += l - 1; | ||||||
|  | +			memcpy(dest, ptr, i); | ||||||
|  | +			dest += i; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +	return dest; | ||||||
|  | +} | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) | ||||||
|  |  { | ||||||
|  |  	char cmdline[COMMAND_LINE_SIZE]; | ||||||
|  | @@ -86,12 +141,21 @@ static void merge_fdt_bootargs(void *fdt | ||||||
|  |   | ||||||
|  |  	/* and append the ATAG_CMDLINE */ | ||||||
|  |  	if (fdt_cmdline) { | ||||||
|  | + | ||||||
|  | +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) | ||||||
|  | +		//save original bootloader args | ||||||
|  | +		//and append ubi.mtd with root partition number to current cmdline | ||||||
|  | +		setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); | ||||||
|  | +		ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); | ||||||
|  | + | ||||||
|  | +#else | ||||||
|  |  		len = strlen(fdt_cmdline); | ||||||
|  |  		if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { | ||||||
|  |  			*ptr++ = ' '; | ||||||
|  |  			memcpy(ptr, fdt_cmdline, len); | ||||||
|  |  			ptr += len; | ||||||
|  |  		} | ||||||
|  | +#endif | ||||||
|  |  	} | ||||||
|  |  	*ptr = '\0'; | ||||||
|  |   | ||||||
|  | @@ -148,7 +212,9 @@ int atags_to_fdt(void *atag_list, void * | ||||||
|  |  			else | ||||||
|  |  				setprop_string(fdt, "/chosen", "bootargs", | ||||||
|  |  					       atag->u.cmdline.cmdline); | ||||||
|  | -		} else if (atag->hdr.tag == ATAG_MEM) { | ||||||
|  | +		} | ||||||
|  | +#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE | ||||||
|  | +		else if (atag->hdr.tag == ATAG_MEM) { | ||||||
|  |  			if (memcount >= sizeof(mem_reg_property)/4) | ||||||
|  |  				continue; | ||||||
|  |  			if (!atag->u.mem.size) | ||||||
|  | @@ -187,6 +253,10 @@ int atags_to_fdt(void *atag_list, void * | ||||||
|  |  		setprop(fdt, "/memory", "reg", mem_reg_property, | ||||||
|  |  			4 * memcount * memsize); | ||||||
|  |  	} | ||||||
|  | +#else | ||||||
|  | + | ||||||
|  | +	} | ||||||
|  | +#endif | ||||||
|  |   | ||||||
|  |  	return fdt_pack(fdt); | ||||||
|  |  } | ||||||
|  | --- a/init/main.c | ||||||
|  | +++ b/init/main.c | ||||||
|  | @@ -95,6 +95,10 @@ | ||||||
|  |  #include <asm/sections.h> | ||||||
|  |  #include <asm/cacheflush.h> | ||||||
|  |   | ||||||
|  | +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  static int kernel_init(void *); | ||||||
|  |   | ||||||
|  |  extern void init_IRQ(void); | ||||||
|  | @@ -574,6 +578,18 @@ asmlinkage __visible void __init start_k | ||||||
|  |  	page_alloc_init(); | ||||||
|  |   | ||||||
|  |  	pr_notice("Kernel command line: %s\n", boot_command_line); | ||||||
|  | + | ||||||
|  | +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) | ||||||
|  | +	//Show bootloader's original command line for reference | ||||||
|  | +	if(of_chosen) { | ||||||
|  | +		const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); | ||||||
|  | +		if(prop) | ||||||
|  | +			pr_notice("Bootloader command line (ignored): %s\n", prop); | ||||||
|  | +		else | ||||||
|  | +			pr_notice("Bootloader command line not present\n"); | ||||||
|  | +	} | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  	/* parameters may set static keys */ | ||||||
|  |  	jump_label_init(); | ||||||
|  |  	parse_early_param(); | ||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | From 8f68331e14dff9a101f2d0e1d6bec84a031f27ee Mon Sep 17 00:00:00 2001 | ||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Thu, 9 Mar 2017 11:03:18 +0100 | ||||||
|  | Subject: [PATCH 69/69] arm: boot: add dts files | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | --- | ||||||
|  |  arch/arm/boot/dts/Makefile | 8 ++++++++ | ||||||
|  |  1 file changed, 8 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/arch/arm/boot/dts/Makefile | ||||||
|  | +++ b/arch/arm/boot/dts/Makefile | ||||||
|  | @@ -699,6 +699,18 @@ dtb-$(CONFIG_ARCH_QCOM) += \ | ||||||
|  |  	qcom-apq8084-mtp.dtb \ | ||||||
|  |  	qcom-ipq4019-ap.dk01.1-c1.dtb \ | ||||||
|  |  	qcom-ipq8064-ap148.dtb \ | ||||||
|  | +	qcom-ipq8064-c2600.dtb \ | ||||||
|  | +	qcom-ipq8064-d7800.dtb \ | ||||||
|  | +	qcom-ipq8064-db149.dtb \ | ||||||
|  | +	qcom-ipq8064-ap161.dtb \ | ||||||
|  | +	qcom-ipq8064-ea8500.dtb \ | ||||||
|  | +	qcom-ipq8064-r7500.dtb \ | ||||||
|  | +	qcom-ipq8064-r7500v2.dtb \ | ||||||
|  | +	qcom-ipq8064-wg2600hp.dtb \ | ||||||
|  | +	qcom-ipq8064-wpq864.dtb \ | ||||||
|  | +	qcom-ipq8064-wxr-2533dhp.dtb \ | ||||||
|  | +	qcom-ipq8065-nbg6817.dtb \ | ||||||
|  | +	qcom-ipq8065-r7800.dtb \ | ||||||
|  |  	qcom-msm8660-surf.dtb \ | ||||||
|  |  	qcom-msm8960-cdp.dtb \ | ||||||
|  |  	qcom-msm8974-lge-nexus5-hammerhead.dtb \ | ||||||
| @@ -0,0 +1,16 @@ | |||||||
|  | Check for SCM availability before attempting to use SPM | ||||||
|  |  | ||||||
|  | Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||||
|  |  | ||||||
|  | --- a/drivers/soc/qcom/spm.c | ||||||
|  | +++ b/drivers/soc/qcom/spm.c | ||||||
|  | @@ -219,6 +219,9 @@ static int __init qcom_cpuidle_init(stru | ||||||
|  |  	cpumask_t mask; | ||||||
|  |  	bool use_scm_power_down = false; | ||||||
|  |   | ||||||
|  | +	if (!qcom_scm_is_available()) | ||||||
|  | +		return -EPROBE_DEFER; | ||||||
|  | + | ||||||
|  |  	for (i = 0; ; i++) { | ||||||
|  |  		state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); | ||||||
|  |  		if (!state_node) | ||||||
| @@ -0,0 +1,95 @@ | |||||||
|  | From 86655aa14304ca88a8ce8847276147dbc1a83238 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | Date: Tue, 19 Jul 2016 18:44:49 +0530 | ||||||
|  | Subject: PCI: qcom: Fixed IPQ806x specific clocks | ||||||
|  |  | ||||||
|  | Change-Id: I488e1bc707d6a22b37a338f41935e3922009ba5e | ||||||
|  | Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 38 +++++++++++++++++++++++++++++++++----- | ||||||
|  |  1 file changed, 33 insertions(+), 5 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -91,6 +91,8 @@ struct qcom_pcie_resources_2_1_0 { | ||||||
|  |  	struct clk *iface_clk; | ||||||
|  |  	struct clk *core_clk; | ||||||
|  |  	struct clk *phy_clk; | ||||||
|  | +	struct clk *aux_clk; | ||||||
|  | +	struct clk *ref_clk; | ||||||
|  |  	struct reset_control *pci_reset; | ||||||
|  |  	struct reset_control *axi_reset; | ||||||
|  |  	struct reset_control *ahb_reset; | ||||||
|  | @@ -249,6 +251,14 @@ static int qcom_pcie_get_resources_2_1_0 | ||||||
|  |  	if (IS_ERR(res->phy_clk)) | ||||||
|  |  		return PTR_ERR(res->phy_clk); | ||||||
|  |   | ||||||
|  | +	res->aux_clk = devm_clk_get(dev, "aux"); | ||||||
|  | +	if (IS_ERR(res->aux_clk)) | ||||||
|  | +		return PTR_ERR(res->aux_clk); | ||||||
|  | + | ||||||
|  | +	res->ref_clk = devm_clk_get(dev, "ref"); | ||||||
|  | +	if (IS_ERR(res->ref_clk)) | ||||||
|  | +		return PTR_ERR(res->ref_clk); | ||||||
|  | + | ||||||
|  |  	res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); | ||||||
|  |  	if (IS_ERR(res->pci_reset)) | ||||||
|  |  		return PTR_ERR(res->pci_reset); | ||||||
|  | @@ -281,6 +291,8 @@ static void qcom_pcie_deinit_2_1_0(struc | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
|  |  	clk_disable_unprepare(res->core_clk); | ||||||
|  |  	clk_disable_unprepare(res->phy_clk); | ||||||
|  | +	clk_disable_unprepare(res->aux_clk); | ||||||
|  | +	clk_disable_unprepare(res->ref_clk); | ||||||
|  |  	regulator_disable(res->vdda); | ||||||
|  |  	regulator_disable(res->vdda_phy); | ||||||
|  |  	regulator_disable(res->vdda_refclk); | ||||||
|  | @@ -324,16 +336,28 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  		goto err_assert_ahb; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	ret = clk_prepare_enable(res->core_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(dev, "cannot prepare/enable core clock\n"); | ||||||
|  | +		goto err_clk_core; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	ret = clk_prepare_enable(res->phy_clk); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(dev, "cannot prepare/enable phy clock\n"); | ||||||
|  |  		goto err_clk_phy; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ret = clk_prepare_enable(res->core_clk); | ||||||
|  | +	ret = clk_prepare_enable(res->aux_clk); | ||||||
|  |  	if (ret) { | ||||||
|  | -		dev_err(dev, "cannot prepare/enable core clock\n"); | ||||||
|  | -		goto err_clk_core; | ||||||
|  | +		dev_err(dev, "cannot prepare/enable aux clock\n"); | ||||||
|  | +		goto err_clk_aux; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ret = clk_prepare_enable(res->ref_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(dev, "cannot prepare/enable ref clock\n"); | ||||||
|  | +		goto err_clk_ref; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = reset_control_deassert(res->ahb_reset); | ||||||
|  | @@ -389,10 +413,14 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  |  err_deassert_ahb: | ||||||
|  | -	clk_disable_unprepare(res->core_clk); | ||||||
|  | -err_clk_core: | ||||||
|  | +	clk_disable_unprepare(res->ref_clk); | ||||||
|  | +err_clk_ref: | ||||||
|  | +	clk_disable_unprepare(res->aux_clk); | ||||||
|  | +err_clk_aux: | ||||||
|  |  	clk_disable_unprepare(res->phy_clk); | ||||||
|  |  err_clk_phy: | ||||||
|  | +	clk_disable_unprepare(res->core_clk); | ||||||
|  | +err_clk_core: | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
|  |  err_assert_ahb: | ||||||
|  |  	regulator_disable(res->vdda_phy); | ||||||
| @@ -0,0 +1,85 @@ | |||||||
|  | From 490d103232287eb51c92c49a4ef8865fd0a9d59e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | Date: Tue, 19 Jul 2016 18:58:18 +0530 | ||||||
|  | Subject: PCI: qcom: Fixed IPQ806x PCIE reset changes | ||||||
|  |  | ||||||
|  | Change-Id: Ia6590e960b9754b1e8b7a51f318788cd63e9e321 | ||||||
|  | Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 24 +++++++++++++++++++----- | ||||||
|  |  1 file changed, 19 insertions(+), 5 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -98,6 +98,7 @@ struct qcom_pcie_resources_2_1_0 { | ||||||
|  |  	struct reset_control *ahb_reset; | ||||||
|  |  	struct reset_control *por_reset; | ||||||
|  |  	struct reset_control *phy_reset; | ||||||
|  | +	struct reset_control *ext_reset; | ||||||
|  |  	struct regulator *vdda; | ||||||
|  |  	struct regulator *vdda_phy; | ||||||
|  |  	struct regulator *vdda_refclk; | ||||||
|  | @@ -275,6 +276,10 @@ static int qcom_pcie_get_resources_2_1_0 | ||||||
|  |  	if (IS_ERR(res->por_reset)) | ||||||
|  |  		return PTR_ERR(res->por_reset); | ||||||
|  |   | ||||||
|  | +	res->ext_reset = devm_reset_control_get(dev, "ext"); | ||||||
|  | +	if (IS_ERR(res->ext_reset)) | ||||||
|  | +		return PTR_ERR(res->ext_reset); | ||||||
|  | + | ||||||
|  |  	res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); | ||||||
|  |  	return PTR_ERR_OR_ZERO(res->phy_reset); | ||||||
|  |  } | ||||||
|  | @@ -288,6 +293,7 @@ static void qcom_pcie_deinit_2_1_0(struc | ||||||
|  |  	reset_control_assert(res->ahb_reset); | ||||||
|  |  	reset_control_assert(res->por_reset); | ||||||
|  |  	reset_control_assert(res->pci_reset); | ||||||
|  | +	reset_control_assert(res->ext_reset); | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
|  |  	clk_disable_unprepare(res->core_clk); | ||||||
|  |  	clk_disable_unprepare(res->phy_clk); | ||||||
|  | @@ -306,6 +312,12 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  	u32 val; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | +	ret = reset_control_assert(res->ahb_reset); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(dev, "cannot assert ahb reset\n"); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	ret = regulator_enable(res->vdda); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(dev, "cannot enable vdda regulator\n"); | ||||||
|  | @@ -324,16 +336,16 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  		goto err_vdda_phy; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ret = reset_control_assert(res->ahb_reset); | ||||||
|  | +	ret = reset_control_deassert(res->ext_reset); | ||||||
|  |  	if (ret) { | ||||||
|  | -		dev_err(dev, "cannot assert ahb reset\n"); | ||||||
|  | -		goto err_assert_ahb; | ||||||
|  | +		dev_err(dev, "cannot assert ext reset\n"); | ||||||
|  | +		goto err_reset_ext; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = clk_prepare_enable(res->iface_clk); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(dev, "cannot prepare/enable iface clock\n"); | ||||||
|  | -		goto err_assert_ahb; | ||||||
|  | +		goto err_iface; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = clk_prepare_enable(res->core_clk); | ||||||
|  | @@ -422,7 +434,9 @@ err_clk_phy: | ||||||
|  |  	clk_disable_unprepare(res->core_clk); | ||||||
|  |  err_clk_core: | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
|  | -err_assert_ahb: | ||||||
|  | +err_iface: | ||||||
|  | +	reset_control_assert(res->ext_reset); | ||||||
|  | +err_reset_ext: | ||||||
|  |  	regulator_disable(res->vdda_phy); | ||||||
|  |  err_vdda_phy: | ||||||
|  |  	regulator_disable(res->vdda_refclk); | ||||||
| @@ -0,0 +1,126 @@ | |||||||
|  | From eddd13215d0f2b549ebc5f0e8796d5b1231f90a0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | Date: Tue, 19 Jul 2016 19:58:22 +0530 | ||||||
|  | Subject: PCI: qcom: Fixed IPQ806x PCIE init changes | ||||||
|  |  | ||||||
|  | Change-Id: Ic319b1aec27a47809284759f8fcb6a8815b7cf7e | ||||||
|  | Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 62 +++++++++++++++++++++++++++++++++++++------- | ||||||
|  |  1 file changed, 53 insertions(+), 9 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -52,7 +52,13 @@ | ||||||
|  |  #define PCIE_CAP_CPL_TIMEOUT_DISABLE		0x10 | ||||||
|  |   | ||||||
|  |  #define PCIE20_PARF_PHY_CTRL			0x40 | ||||||
|  | +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK	(0x1f << 16) | ||||||
|  | +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)		(x << 16) | ||||||
|  | + | ||||||
|  |  #define PCIE20_PARF_PHY_REFCLK			0x4C | ||||||
|  | +#define REF_SSP_EN				BIT(16) | ||||||
|  | +#define REF_USE_PAD				BIT(12) | ||||||
|  | + | ||||||
|  |  #define PCIE20_PARF_DBI_BASE_ADDR		0x168 | ||||||
|  |  #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16C | ||||||
|  |  #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174 | ||||||
|  | @@ -83,6 +89,18 @@ | ||||||
|  |  #define DBI_RO_WR_EN				1 | ||||||
|  |   | ||||||
|  |  #define PERST_DELAY_US				1000 | ||||||
|  | +/* PARF registers */ | ||||||
|  | +#define PCIE20_PARF_PCS_DEEMPH			0x34 | ||||||
|  | +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x)		(x << 16) | ||||||
|  | +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x)	(x << 8) | ||||||
|  | +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x)	(x << 0) | ||||||
|  | + | ||||||
|  | +#define PCIE20_PARF_PCS_SWING			0x38 | ||||||
|  | +#define PCS_SWING_TX_SWING_FULL(x)		(x << 8) | ||||||
|  | +#define PCS_SWING_TX_SWING_LOW(x)		(x << 0) | ||||||
|  | + | ||||||
|  | +#define PCIE20_PARF_CONFIG_BITS			0x50 | ||||||
|  | +#define PHY_RX0_EQ(x)				(x << 24) | ||||||
|  |   | ||||||
|  |  #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE	0x358 | ||||||
|  |  #define SLV_ADDR_SPACE_SZ			0x10000000 | ||||||
|  | @@ -102,6 +120,7 @@ struct qcom_pcie_resources_2_1_0 { | ||||||
|  |  	struct regulator *vdda; | ||||||
|  |  	struct regulator *vdda_phy; | ||||||
|  |  	struct regulator *vdda_refclk; | ||||||
|  | +	uint8_t phy_tx0_term_offset; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct qcom_pcie_resources_1_0_0 { | ||||||
|  | @@ -179,6 +198,16 @@ struct qcom_pcie { | ||||||
|  |   | ||||||
|  |  #define to_qcom_pcie(x)		dev_get_drvdata((x)->dev) | ||||||
|  |   | ||||||
|  | +static inline void | ||||||
|  | +writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask) | ||||||
|  | +{ | ||||||
|  | +	u32 val = readl(addr); | ||||||
|  | + | ||||||
|  | +	val &= ~clear_mask; | ||||||
|  | +	val |= set_mask; | ||||||
|  | +	writel(val, addr); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void qcom_ep_reset_assert(struct qcom_pcie *pcie) | ||||||
|  |  { | ||||||
|  |  	gpiod_set_value_cansleep(pcie->reset, 1); | ||||||
|  | @@ -280,6 +309,10 @@ static int qcom_pcie_get_resources_2_1_0 | ||||||
|  |  	if (IS_ERR(res->ext_reset)) | ||||||
|  |  		return PTR_ERR(res->ext_reset); | ||||||
|  |   | ||||||
|  | +	if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset", | ||||||
|  | +				&res->phy_tx0_term_offset)) | ||||||
|  | +		res->phy_tx0_term_offset = 0; | ||||||
|  | + | ||||||
|  |  	res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); | ||||||
|  |  	return PTR_ERR_OR_ZERO(res->phy_reset); | ||||||
|  |  } | ||||||
|  | @@ -309,7 +342,6 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; | ||||||
|  |  	struct dw_pcie *pci = pcie->pci; | ||||||
|  |  	struct device *dev = pci->dev; | ||||||
|  | -	u32 val; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  |  	ret = reset_control_assert(res->ahb_reset); | ||||||
|  | @@ -378,15 +410,26 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  		goto err_deassert_ahb; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* enable PCIe clocks and resets */ | ||||||
|  | -	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); | ||||||
|  | -	val &= ~BIT(0); | ||||||
|  | -	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); | ||||||
|  | - | ||||||
|  | -	/* enable external reference clock */ | ||||||
|  | -	val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); | ||||||
|  | -	val |= BIT(16); | ||||||
|  | -	writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); | ||||||
|  | +	writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); | ||||||
|  | + | ||||||
|  | +	/* Set Tx termination offset */ | ||||||
|  | +	writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, | ||||||
|  | +		      PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, | ||||||
|  | +		      PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset)); | ||||||
|  | + | ||||||
|  | +	/* PARF programming */ | ||||||
|  | +	writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | | ||||||
|  | +	       PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | | ||||||
|  | +	       PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), | ||||||
|  | +	       pcie->parf + PCIE20_PARF_PCS_DEEMPH); | ||||||
|  | +	writel(PCS_SWING_TX_SWING_FULL(0x78) | | ||||||
|  | +	       PCS_SWING_TX_SWING_LOW(0x78), | ||||||
|  | +	       pcie->parf + PCIE20_PARF_PCS_SWING); | ||||||
|  | +	writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS); | ||||||
|  | + | ||||||
|  | +	/* Enable reference clock */ | ||||||
|  | +	writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, | ||||||
|  | +		      REF_USE_PAD, REF_SSP_EN); | ||||||
|  |   | ||||||
|  |  	ret = reset_control_deassert(res->phy_reset); | ||||||
|  |  	if (ret) { | ||||||
| @@ -0,0 +1,114 @@ | |||||||
|  | From d27c303e828d7e42f339a459d2abfe30c51698e9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | Date: Tue, 26 Jul 2016 12:28:31 +0530 | ||||||
|  | Subject: PCI: qcom: Programming the PCIE iATU for IPQ806x | ||||||
|  |  | ||||||
|  | Resolved PCIE EP detection errors caused due to missing iATU programming. | ||||||
|  |  | ||||||
|  | Change-Id: Ie95c0f8cb940abc0192a8a3c4e825ddba54b72fe | ||||||
|  | Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 77 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -83,6 +83,30 @@ | ||||||
|  |  #define PCIE20_CAP_LINK_1			(PCIE20_CAP + 0x14) | ||||||
|  |  #define PCIE_CAP_LINK1_VAL			0x2FD7F | ||||||
|  |   | ||||||
|  | +#define PCIE20_CAP_LINKCTRLSTATUS		(PCIE20_CAP + 0x10) | ||||||
|  | + | ||||||
|  | +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0		0x818 | ||||||
|  | +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1		0x81c | ||||||
|  | + | ||||||
|  | +#define PCIE20_PLR_IATU_VIEWPORT		0x900 | ||||||
|  | +#define PCIE20_PLR_IATU_REGION_OUTBOUND		(0x0 << 31) | ||||||
|  | +#define PCIE20_PLR_IATU_REGION_INDEX(x)		(x << 0) | ||||||
|  | + | ||||||
|  | +#define PCIE20_PLR_IATU_CTRL1			0x904 | ||||||
|  | +#define PCIE20_PLR_IATU_TYPE_CFG0		(0x4 << 0) | ||||||
|  | +#define PCIE20_PLR_IATU_TYPE_MEM		(0x0 << 0) | ||||||
|  | + | ||||||
|  | +#define PCIE20_PLR_IATU_CTRL2			0x908 | ||||||
|  | +#define PCIE20_PLR_IATU_ENABLE			BIT(31) | ||||||
|  | + | ||||||
|  | +#define PCIE20_PLR_IATU_LBAR			0x90C | ||||||
|  | +#define PCIE20_PLR_IATU_UBAR			0x910 | ||||||
|  | +#define PCIE20_PLR_IATU_LAR			0x914 | ||||||
|  | +#define PCIE20_PLR_IATU_LTAR			0x918 | ||||||
|  | +#define PCIE20_PLR_IATU_UTAR			0x91c | ||||||
|  | + | ||||||
|  | +#define MSM_PCIE_DEV_CFG_ADDR			0x01000000 | ||||||
|  | + | ||||||
|  |  #define PCIE20_PARF_Q2A_FLUSH			0x1AC | ||||||
|  |   | ||||||
|  |  #define PCIE20_MISC_CONTROL_1_REG		0x8BC | ||||||
|  | @@ -251,6 +275,57 @@ static void qcom_pcie_2_1_0_ltssm_enable | ||||||
|  |  	writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev) | ||||||
|  | +{ | ||||||
|  | +	struct pcie_port *pp = &pcie->pci->pp; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * program and enable address translation region 0 (device config | ||||||
|  | +	 * address space); region type config; | ||||||
|  | +	 * axi config address range to device config address range | ||||||
|  | +	 */ | ||||||
|  | +	writel(PCIE20_PLR_IATU_REGION_OUTBOUND | | ||||||
|  | +	       PCIE20_PLR_IATU_REGION_INDEX(0), | ||||||
|  | +	       pcie->pci->dbi_base + PCIE20_PLR_IATU_VIEWPORT); | ||||||
|  | + | ||||||
|  | +	writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->pci->dbi_base + PCIE20_PLR_IATU_CTRL1); | ||||||
|  | +	writel(PCIE20_PLR_IATU_ENABLE, pcie->pci->dbi_base + PCIE20_PLR_IATU_CTRL2); | ||||||
|  | +	writel(pp->cfg0_base, pcie->pci->dbi_base + PCIE20_PLR_IATU_LBAR); | ||||||
|  | +	writel((pp->cfg0_base >> 32), pcie->pci->dbi_base + PCIE20_PLR_IATU_UBAR); | ||||||
|  | +	writel((pp->cfg0_base + pp->cfg0_size - 1), | ||||||
|  | +	       pcie->pci->dbi_base + PCIE20_PLR_IATU_LAR); | ||||||
|  | +	writel(busdev, pcie->pci->dbi_base + PCIE20_PLR_IATU_LTAR); | ||||||
|  | +	writel(0, pcie->pci->dbi_base + PCIE20_PLR_IATU_UTAR); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie) | ||||||
|  | +{ | ||||||
|  | +	struct pcie_port *pp = &pcie->pci->pp; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * program and enable address translation region 2 (device resource | ||||||
|  | +	 * address space); region type memory; | ||||||
|  | +	 * axi device bar address range to device bar address range | ||||||
|  | +	 */ | ||||||
|  | +	writel(PCIE20_PLR_IATU_REGION_OUTBOUND | | ||||||
|  | +	       PCIE20_PLR_IATU_REGION_INDEX(2), | ||||||
|  | +	       pcie->pci->dbi_base + PCIE20_PLR_IATU_VIEWPORT); | ||||||
|  | + | ||||||
|  | +	writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->pci->dbi_base + PCIE20_PLR_IATU_CTRL1); | ||||||
|  | +	writel(PCIE20_PLR_IATU_ENABLE, pcie->pci->dbi_base + PCIE20_PLR_IATU_CTRL2); | ||||||
|  | +	writel(pp->mem_base, pcie->pci->dbi_base + PCIE20_PLR_IATU_LBAR); | ||||||
|  | +	writel((pp->mem_base >> 32), pcie->pci->dbi_base + PCIE20_PLR_IATU_UBAR); | ||||||
|  | +	writel(pp->mem_base + pp->mem_size - 1, | ||||||
|  | +	       pcie->pci->dbi_base + PCIE20_PLR_IATU_LAR); | ||||||
|  | +	writel(pp->mem_bus_addr, pcie->pci->dbi_base + PCIE20_PLR_IATU_LTAR); | ||||||
|  | +	writel(upper_32_bits(pp->mem_bus_addr), | ||||||
|  | +	       pcie->pci->dbi_base + PCIE20_PLR_IATU_UTAR); | ||||||
|  | + | ||||||
|  | +	/* 256B PCIE buffer setting */ | ||||||
|  | +	writel(0x1, pcie->pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); | ||||||
|  | +	writel(0x1, pcie->pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) | ||||||
|  |  { | ||||||
|  |  	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; | ||||||
|  | @@ -465,6 +540,9 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  	writel(CFG_BRIDGE_SB_INIT, | ||||||
|  |  	       pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); | ||||||
|  |   | ||||||
|  | +	qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); | ||||||
|  | +	qcom_pcie_prog_viewport_mem2_outbound(pcie); | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |   | ||||||
|  |  err_deassert_ahb: | ||||||
| @@ -0,0 +1,61 @@ | |||||||
|  | From 4910cfd150342ec7b038892262923c725a9c4001 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | Date: Wed, 7 Sep 2016 16:44:28 +0530 | ||||||
|  | Subject: PCI: qcom: Force GEN1 support | ||||||
|  |  | ||||||
|  | Change-Id: Ica54ddb737d7b851469deab1745f54bf431bd3f0 | ||||||
|  | Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 13 +++++++++++++ | ||||||
|  |  1 file changed, 13 insertions(+) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -129,6 +129,8 @@ | ||||||
|  |  #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE	0x358 | ||||||
|  |  #define SLV_ADDR_SPACE_SZ			0x10000000 | ||||||
|  |   | ||||||
|  | +#define PCIE20_LNK_CONTROL2_LINK_STATUS2        0xA0 | ||||||
|  | + | ||||||
|  |  struct qcom_pcie_resources_2_1_0 { | ||||||
|  |  	struct clk *iface_clk; | ||||||
|  |  	struct clk *core_clk; | ||||||
|  | @@ -218,6 +220,7 @@ struct qcom_pcie { | ||||||
|  |  	struct phy *phy; | ||||||
|  |  	struct gpio_desc *reset; | ||||||
|  |  	struct qcom_pcie_ops *ops; | ||||||
|  | +	uint32_t force_gen1; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  #define to_qcom_pcie(x)		dev_get_drvdata((x)->dev) | ||||||
|  | @@ -532,6 +535,11 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |   | ||||||
|  |  	/* wait for clock acquisition */ | ||||||
|  |  	usleep_range(1000, 1500); | ||||||
|  | +	if (pcie->force_gen1) { | ||||||
|  | +		writel_relaxed((readl_relaxed( | ||||||
|  | +			pcie->pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2) | 1), | ||||||
|  | +			pcie->pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  	/* Set the Max TLP size to 2K, instead of using default of 4K */ | ||||||
|  | @@ -1382,6 +1390,8 @@ static int qcom_pcie_probe(struct platfo | ||||||
|  |  	struct dw_pcie *pci; | ||||||
|  |  	struct qcom_pcie *pcie; | ||||||
|  |  	int ret; | ||||||
|  | +	uint32_t force_gen1 = 0; | ||||||
|  | +	struct device_node *np = pdev->dev.of_node; | ||||||
|  |   | ||||||
|  |  	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | ||||||
|  |  	if (!pcie) | ||||||
|  | @@ -1403,6 +1413,9 @@ static int qcom_pcie_probe(struct platfo | ||||||
|  |  	if (IS_ERR(pcie->reset)) | ||||||
|  |  		return PTR_ERR(pcie->reset); | ||||||
|  |   | ||||||
|  | +	of_property_read_u32(np, "force_gen1", &force_gen1); | ||||||
|  | +	pcie->force_gen1 = force_gen1; | ||||||
|  | + | ||||||
|  |  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); | ||||||
|  |  	pcie->parf = devm_ioremap_resource(dev, res); | ||||||
|  |  	if (IS_ERR(pcie->parf)) | ||||||
| @@ -0,0 +1,69 @@ | |||||||
|  | From edff8f777c6321ca89bb950a382f409c4a126e28 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Gokul Sriram Palanisamy <gpalan@codeaurora.org> | ||||||
|  | Date: Thu, 15 Dec 2016 17:38:18 +0530 | ||||||
|  | Subject: pcie: Set PCIE MRRS and MPS to 256B | ||||||
|  |  | ||||||
|  | Set Max Read Request Size and Max Payload Size to 256 bytes, | ||||||
|  | per chip team recommendation. | ||||||
|  |  | ||||||
|  | Change-Id: I097004be2ced1b3096ffc10c318aae0b2bb155e8 | ||||||
|  | Signed-off-by: Gokul Sriram Palanisamy <gpalan@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 37 +++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 37 insertions(+) | ||||||
|  |  | ||||||
|  | (limited to 'drivers/pci/host/pcie-qcom.c') | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -131,6 +131,14 @@ | ||||||
|  |   | ||||||
|  |  #define PCIE20_LNK_CONTROL2_LINK_STATUS2        0xA0 | ||||||
|  |   | ||||||
|  | +#define __set(v, a, b)	(((v) << (b)) & GENMASK(a, b)) | ||||||
|  | +#define __mask(a, b)	(((1 << ((a) + 1)) - 1) & ~((1 << (b)) - 1)) | ||||||
|  | +#define PCIE20_DEV_CAS			0x78 | ||||||
|  | +#define PCIE20_MRRS_MASK		__mask(14, 12) | ||||||
|  | +#define PCIE20_MRRS(x)			__set(x, 14, 12) | ||||||
|  | +#define PCIE20_MPS_MASK			__mask(7, 5) | ||||||
|  | +#define PCIE20_MPS(x)			__set(x, 7, 5) | ||||||
|  | + | ||||||
|  |  struct qcom_pcie_resources_2_1_0 { | ||||||
|  |  	struct clk *iface_clk; | ||||||
|  |  	struct clk *core_clk; | ||||||
|  | @@ -1472,6 +1480,35 @@ static int qcom_pcie_probe(struct platfo | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void qcom_pcie_fixup_final(struct pci_dev *dev) | ||||||
|  | +{ | ||||||
|  | +	int cap, err; | ||||||
|  | +	u16 ctl, reg_val; | ||||||
|  | + | ||||||
|  | +	cap = pci_pcie_cap(dev); | ||||||
|  | +	if (!cap) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); | ||||||
|  | + | ||||||
|  | +	if (err) | ||||||
|  | +		return; | ||||||
|  | + | ||||||
|  | +	reg_val = ctl; | ||||||
|  | + | ||||||
|  | +	if (((reg_val & PCIE20_MRRS_MASK) >> 12) > 1) | ||||||
|  | +		reg_val = (reg_val & ~(PCIE20_MRRS_MASK)) | PCIE20_MRRS(0x1); | ||||||
|  | + | ||||||
|  | +	if (((ctl & PCIE20_MPS_MASK) >> 5) > 1) | ||||||
|  | +		reg_val = (reg_val & ~(PCIE20_MPS_MASK)) | PCIE20_MPS(0x1); | ||||||
|  | + | ||||||
|  | +	err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, reg_val); | ||||||
|  | + | ||||||
|  | +	if (err) | ||||||
|  | +		pr_err("pcie config write failed %d\n", err); | ||||||
|  | +} | ||||||
|  | +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, qcom_pcie_fixup_final); | ||||||
|  | + | ||||||
|  |  static const struct of_device_id qcom_pcie_match[] = { | ||||||
|  |  	{ .compatible = "qcom,pcie-apq8084", .data = &ops_1_0_0 }, | ||||||
|  |  	{ .compatible = "qcom,pcie-ipq8064", .data = &ops_2_1_0 }, | ||||||
| @@ -0,0 +1,91 @@ | |||||||
|  | From b74bab6186131eea09459eedf5d737645a3559c9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | Date: Thu, 22 Dec 2016 11:18:45 +0530 | ||||||
|  | Subject: pcie: qcom: Fixed pcie_phy_clk branch issue | ||||||
|  |  | ||||||
|  | Following backtraces are observed in PCIe deinit operation. | ||||||
|  |  | ||||||
|  |  Hardware name: Qualcomm (Flattened Device Tree) | ||||||
|  |  (unwind_backtrace) from [] (show_stack+0x10/0x14) | ||||||
|  |  (show_stack) from [] (dump_stack+0x84/0x98) | ||||||
|  |  (dump_stack) from [] (warn_slowpath_common+0x9c/0xb8) | ||||||
|  |  (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) | ||||||
|  |  (warn_slowpath_fmt) from [] (clk_branch_wait+0x114/0x120) | ||||||
|  |  (clk_branch_wait) from [] (clk_core_disable+0xd0/0x1f4) | ||||||
|  |  (clk_core_disable) from [] (clk_disable+0x24/0x30) | ||||||
|  |  (clk_disable) from [] (qcom_pcie_deinit_v0+0x6c/0xb8) | ||||||
|  |  (qcom_pcie_deinit_v0) from [] (qcom_pcie_host_init+0xe0/0xe8) | ||||||
|  |  (qcom_pcie_host_init) from [] (dw_pcie_host_init+0x3b0/0x538) | ||||||
|  |  (dw_pcie_host_init) from [] (qcom_pcie_probe+0x20c/0x2e4) | ||||||
|  |  | ||||||
|  | pcie_phy_clk is generated for PCIe controller itself and the | ||||||
|  | GCC controls its branch operation. This error is coming since | ||||||
|  | the assert operations turn off the parent clock before branch | ||||||
|  | clock. Now this patch moves clk_disable_unprepare before assert | ||||||
|  | operations. | ||||||
|  |  | ||||||
|  | Similarly, during probe function, the clock branch operation | ||||||
|  | should be done after dessert operation. Currently, it does not | ||||||
|  | generate any error since bootloader enables the pcie_phy_clk | ||||||
|  | but the same error is coming during probe, if bootloader | ||||||
|  | disables pcie_phy_clk. | ||||||
|  |  | ||||||
|  | Change-Id: Ib29c154d10eb64363d9cc982ce5fd8107af5627d | ||||||
|  | Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 16 +++++++--------- | ||||||
|  |  1 file changed, 7 insertions(+), 9 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -407,6 +407,7 @@ static void qcom_pcie_deinit_2_1_0(struc | ||||||
|  |  { | ||||||
|  |  	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; | ||||||
|  |   | ||||||
|  | +	clk_disable_unprepare(res->phy_clk); | ||||||
|  |  	reset_control_assert(res->pci_reset); | ||||||
|  |  	reset_control_assert(res->axi_reset); | ||||||
|  |  	reset_control_assert(res->ahb_reset); | ||||||
|  | @@ -415,7 +416,6 @@ static void qcom_pcie_deinit_2_1_0(struc | ||||||
|  |  	reset_control_assert(res->ext_reset); | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
|  |  	clk_disable_unprepare(res->core_clk); | ||||||
|  | -	clk_disable_unprepare(res->phy_clk); | ||||||
|  |  	clk_disable_unprepare(res->aux_clk); | ||||||
|  |  	clk_disable_unprepare(res->ref_clk); | ||||||
|  |  	regulator_disable(res->vdda); | ||||||
|  | @@ -472,12 +472,6 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  		goto err_clk_core; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	ret = clk_prepare_enable(res->phy_clk); | ||||||
|  | -	if (ret) { | ||||||
|  | -		dev_err(dev, "cannot prepare/enable phy clock\n"); | ||||||
|  | -		goto err_clk_phy; | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  |  	ret = clk_prepare_enable(res->aux_clk); | ||||||
|  |  	if (ret) { | ||||||
|  |  		dev_err(dev, "cannot prepare/enable aux clock\n"); | ||||||
|  | @@ -541,6 +535,12 @@ static int qcom_pcie_init_2_1_0(struct q | ||||||
|  |  		return ret; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	ret = clk_prepare_enable(res->phy_clk); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(dev, "cannot prepare/enable phy clock\n"); | ||||||
|  | +		goto err_deassert_ahb; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	/* wait for clock acquisition */ | ||||||
|  |  	usleep_range(1000, 1500); | ||||||
|  |  	if (pcie->force_gen1) { | ||||||
|  | @@ -566,8 +566,6 @@ err_deassert_ahb: | ||||||
|  |  err_clk_ref: | ||||||
|  |  	clk_disable_unprepare(res->aux_clk); | ||||||
|  |  err_clk_aux: | ||||||
|  | -	clk_disable_unprepare(res->phy_clk); | ||||||
|  | -err_clk_phy: | ||||||
|  |  	clk_disable_unprepare(res->core_clk); | ||||||
|  |  err_clk_core: | ||||||
|  |  	clk_disable_unprepare(res->iface_clk); | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | From 1a9c48123bd09f75562b6a2ee0f0a7b2d533cd45 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | Date: Thu, 22 Dec 2016 11:50:49 +0530 | ||||||
|  | Subject: pcie: qcom: change duplicate pci reset to phy reset | ||||||
|  |  | ||||||
|  | The deinit issues reset_control_assert for pci twice and | ||||||
|  | does not contain phy reset. | ||||||
|  |  | ||||||
|  | Change-Id: Iba849963c7e5f9a2a1063f0e2e89635df70b8a99 | ||||||
|  | Signed-off-by: Abhishek Sahu <absahu@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pci/host/pcie-qcom.c | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | +++ b/drivers/pci/dwc/pcie-qcom.c | ||||||
|  | @@ -408,7 +408,7 @@ static void qcom_pcie_deinit_2_1_0(struc | ||||||
|  |  	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; | ||||||
|  |   | ||||||
|  |  	clk_disable_unprepare(res->phy_clk); | ||||||
|  | -	reset_control_assert(res->pci_reset); | ||||||
|  | +	reset_control_assert(res->phy_reset); | ||||||
|  |  	reset_control_assert(res->axi_reset); | ||||||
|  |  	reset_control_assert(res->ahb_reset); | ||||||
|  |  	reset_control_assert(res->por_reset); | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | --- a/drivers/firmware/qcom_scm.c | ||||||
|  | +++ b/drivers/firmware/qcom_scm.c | ||||||
|  | @@ -422,6 +422,9 @@ static const struct of_device_id qcom_sc | ||||||
|  |  	{ .compatible = "qcom,scm-msm8996", | ||||||
|  |  	  .data = NULL, /* no clocks */ | ||||||
|  |  	}, | ||||||
|  | +	{ .compatible = "qcom,scm-ipq806x", | ||||||
|  | +	  .data = NULL, /* no clocks */ | ||||||
|  | +	}, | ||||||
|  |  	{ .compatible = "qcom,scm", | ||||||
|  |  	  .data = (void *)(SCM_HAS_CORE_CLK | ||||||
|  |  			   | SCM_HAS_IFACE_CLK | ||||||
| @@ -0,0 +1,183 @@ | |||||||
|  | From 2034addc7e193dc81d7ca60d8884832751b76758 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ajay Kishore <akisho@codeaurora.org> | ||||||
|  | Date: Tue, 24 Jan 2017 14:14:16 +0530 | ||||||
|  | Subject: pinctrl: qcom: use scm_call to route GPIO irq to Apps | ||||||
|  |  | ||||||
|  | For IPQ806x targets, TZ protects the registers that are used to | ||||||
|  | configure the routing of interrupts to a target processor. | ||||||
|  | To resolve this, this patch uses scm call to route GPIO interrupts | ||||||
|  | to application processor. Also the scm call interface is changed. | ||||||
|  |  | ||||||
|  | Change-Id: Ib6c06829d04bc8c20483c36e63da92e26cdef9ce | ||||||
|  | Signed-off-by: Ajay Kishore <akisho@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/firmware/qcom_scm-32.c     | 17 +++++++++++++++++ | ||||||
|  |  drivers/firmware/qcom_scm-64.c     |  9 +++++++++ | ||||||
|  |  drivers/firmware/qcom_scm.c        | 13 +++++++++++++ | ||||||
|  |  drivers/firmware/qcom_scm.h        |  8 ++++++++ | ||||||
|  |  drivers/pinctrl/qcom/pinctrl-msm.c | 34 ++++++++++++++++++++++++++++------ | ||||||
|  |  include/linux/qcom_scm.h           |  3 ++- | ||||||
|  |  6 files changed, 77 insertions(+), 7 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/firmware/qcom_scm-32.c | ||||||
|  | +++ b/drivers/firmware/qcom_scm-32.c | ||||||
|  | @@ -561,6 +561,24 @@ int __qcom_scm_pas_mss_reset(struct devi | ||||||
|  |  	return ret ? : le32_to_cpu(out); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1) | ||||||
|  | +{ | ||||||
|  | +	s32 ret; | ||||||
|  | + | ||||||
|  | +	ret = qcom_scm_call_atomic1(svc_id, cmd_id, arg1); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +int __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2) | ||||||
|  | +{ | ||||||
|  | +	s32 ret; | ||||||
|  | + | ||||||
|  | +	ret = qcom_scm_call_atomic2(svc_id, cmd_id, arg1, arg2); | ||||||
|  | + | ||||||
|  | + return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) | ||||||
|  |  { | ||||||
|  |  	struct { | ||||||
|  | --- a/drivers/firmware/qcom_scm-64.c | ||||||
|  | +++ b/drivers/firmware/qcom_scm-64.c | ||||||
|  | @@ -366,6 +366,16 @@ int __qcom_scm_pas_mss_reset(struct devi | ||||||
|  |  	return ret ? : res.a1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +int __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1) | ||||||
|  | +{ | ||||||
|  | +	return -ENOTSUPP; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +int __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2) | ||||||
|  | +{ | ||||||
|  | +	return -ENOTSUPP; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) | ||||||
|  |  { | ||||||
|  |  	struct qcom_scm_desc desc = {0}; | ||||||
|  | --- a/drivers/firmware/qcom_scm.c | ||||||
|  | +++ b/drivers/firmware/qcom_scm.c | ||||||
|  | @@ -470,3 +470,16 @@ static int __init qcom_scm_init(void) | ||||||
|  |  	return platform_driver_register(&qcom_scm_driver); | ||||||
|  |  } | ||||||
|  |  subsys_initcall(qcom_scm_init); | ||||||
|  | + | ||||||
|  | +int qcom_scm_pinmux_read(u32 arg1) | ||||||
|  | +{ | ||||||
|  | +	return __qcom_scm_pinmux_read(SCM_SVC_IO_ACCESS, SCM_IO_READ, arg1); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(qcom_scm_pinmux_read); | ||||||
|  | + | ||||||
|  | +int qcom_scm_pinmux_write(u32 arg1, u32 arg2) | ||||||
|  | +{ | ||||||
|  | +	return __qcom_scm_pinmux_write(SCM_SVC_IO_ACCESS, SCM_IO_WRITE, | ||||||
|  | +					arg1, arg2); | ||||||
|  | +} | ||||||
|  | +EXPORT_SYMBOL(qcom_scm_pinmux_write); | ||||||
|  | --- a/drivers/firmware/qcom_scm.h | ||||||
|  | +++ b/drivers/firmware/qcom_scm.h | ||||||
|  | @@ -58,6 +58,13 @@ extern int  __qcom_scm_pas_auth_and_rese | ||||||
|  |  extern int  __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral); | ||||||
|  |  extern int  __qcom_scm_pas_mss_reset(struct device *dev, bool reset); | ||||||
|  |   | ||||||
|  | +#define SCM_IO_READ	1 | ||||||
|  | +#define SCM_IO_WRITE	2 | ||||||
|  | +#define SCM_SVC_IO_ACCESS	0x5 | ||||||
|  | + | ||||||
|  | +s32 __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1); | ||||||
|  | +s32 __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2); | ||||||
|  | + | ||||||
|  |  /* common error codes */ | ||||||
|  |  #define QCOM_SCM_V2_EBUSY	-12 | ||||||
|  |  #define QCOM_SCM_ENOMEM		-5 | ||||||
|  | --- a/drivers/pinctrl/qcom/pinctrl-msm.c | ||||||
|  | +++ b/drivers/pinctrl/qcom/pinctrl-msm.c | ||||||
|  | @@ -30,7 +30,8 @@ | ||||||
|  |  #include <linux/reboot.h> | ||||||
|  |  #include <linux/pm.h> | ||||||
|  |  #include <linux/log2.h> | ||||||
|  | - | ||||||
|  | +#include <linux/qcom_scm.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  |  #include "../core.h" | ||||||
|  |  #include "../pinconf.h" | ||||||
|  |  #include "pinctrl-msm.h" | ||||||
|  | @@ -646,6 +647,9 @@ static void msm_gpio_irq_ack(struct irq_ | ||||||
|  |  	const struct msm_pingroup *g; | ||||||
|  |  	unsigned long flags; | ||||||
|  |  	u32 val; | ||||||
|  | +	u32 addr; | ||||||
|  | +	int ret; | ||||||
|  | +	const __be32 *reg; | ||||||
|  |   | ||||||
|  |  	g = &pctrl->soc->groups[d->hwirq]; | ||||||
|  |   | ||||||
|  | @@ -684,11 +688,30 @@ static int msm_gpio_irq_set_type(struct | ||||||
|  |  	else | ||||||
|  |  		clear_bit(d->hwirq, pctrl->dual_edge_irqs); | ||||||
|  |   | ||||||
|  | +	int ret = of_device_is_compatible(pctrl->dev->of_node, | ||||||
|  | +					"qcom,ipq8064-pinctrl"); | ||||||
|  |  	/* Route interrupts to application cpu */ | ||||||
|  | -	val = readl(pctrl->regs + g->intr_target_reg); | ||||||
|  | -	val &= ~(7 << g->intr_target_bit); | ||||||
|  | -	val |= g->intr_target_kpss_val << g->intr_target_bit; | ||||||
|  | -	writel(val, pctrl->regs + g->intr_target_reg); | ||||||
|  | +	if (!ret) { | ||||||
|  | +		val = readl(pctrl->regs + g->intr_target_reg); | ||||||
|  | +		val &= ~(7 << g->intr_target_bit); | ||||||
|  | +		val |= g->intr_target_kpss_val << g->intr_target_bit; | ||||||
|  | +		writel(val, pctrl->regs + g->intr_target_reg); | ||||||
|  | +	} else { | ||||||
|  | +		const __be32 *reg = of_get_property(pctrl->dev->of_node, "reg", NULL); | ||||||
|  | +		if (reg) { | ||||||
|  | +			u32 addr = be32_to_cpup(reg) + g->intr_target_reg; | ||||||
|  | +			val = qcom_scm_pinmux_read(addr); | ||||||
|  | +			__iormb(); | ||||||
|  | + | ||||||
|  | +			val &= ~(7 << g->intr_target_bit); | ||||||
|  | +			val |= g->intr_target_kpss_val << g->intr_target_bit; | ||||||
|  | + | ||||||
|  | +			__iowmb(); | ||||||
|  | +			ret = qcom_scm_pinmux_write(addr, val); | ||||||
|  | +			if (ret) | ||||||
|  | +				pr_err("\n Routing interrupts to Apps proc failed"); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  |   | ||||||
|  |  	/* Update configuration for gpio. | ||||||
|  |  	 * RAW_STATUS_EN is left on for all gpio irqs. Due to the | ||||||
|  | @@ -975,4 +998,3 @@ int msm_pinctrl_remove(struct platform_d | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |  EXPORT_SYMBOL(msm_pinctrl_remove); | ||||||
|  | - | ||||||
|  | --- a/include/linux/qcom_scm.h | ||||||
|  | +++ b/include/linux/qcom_scm.h | ||||||
|  | @@ -43,6 +43,8 @@ extern int qcom_scm_set_remote_state(u32 | ||||||
|  |  extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); | ||||||
|  |  extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); | ||||||
|  |  extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); | ||||||
|  | +extern s32 qcom_scm_pinmux_read(u32 arg1); | ||||||
|  | +extern s32 qcom_scm_pinmux_write(u32 arg1, u32 arg2); | ||||||
|  |  #else | ||||||
|  |  static inline | ||||||
|  |  int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) | ||||||
|  | @@ -73,5 +75,7 @@ qcom_scm_set_remote_state(u32 state,u32 | ||||||
|  |  static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; } | ||||||
|  |  static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } | ||||||
|  |  static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } | ||||||
|  | +extern s32 qcom_scm_pinmux_read(u32 arg1) { return -ENODEV; } | ||||||
|  | +extern s32 qcom_scm_pinmux_write(u32 arg1, u32 arg2) { return -ENODEV; } | ||||||
|  |  #endif | ||||||
|  |  #endif | ||||||
| @@ -0,0 +1,71 @@ | |||||||
|  | From a86bda9f8a7965f0cedd347a9c04800eb9f41ea3 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Vasudevan Murugesan <vmuruges@codeaurora.org> | ||||||
|  | Date: Tue, 21 Jul 2015 10:22:38 +0530 | ||||||
|  | Subject: ipq806x: usb: Control USB master reset | ||||||
|  |  | ||||||
|  | During removal of the glue layer(dwc3-of-simple), | ||||||
|  | USB master reset is set to active and during insertion | ||||||
|  | it is de-activated. | ||||||
|  |  | ||||||
|  | Change-Id: I537dc810f6cb2a46664ee674840145066432b957 | ||||||
|  | Signed-off-by: Vasudevan Murugesan <vmuruges@codeaurora.org> | ||||||
|  | (cherry picked from commit 4611e13580a216812f85f0801b95442d02eeb836) | ||||||
|  | --- | ||||||
|  |  drivers/usb/dwc3/dwc3-of-simple.c | 22 ++++++++++++++++++++++ | ||||||
|  |  1 file changed, 12 insertions(+) | ||||||
|  |  | ||||||
|  | (limited to 'drivers/usb/dwc3/dwc3-of-simple.c') | ||||||
|  |  | ||||||
|  | --- a/drivers/usb/dwc3/dwc3-of-simple.c | ||||||
|  | +++ b/drivers/usb/dwc3/dwc3-of-simple.c | ||||||
|  | @@ -25,6 +25,7 @@ | ||||||
|  |  #include <linux/platform_device.h> | ||||||
|  |  #include <linux/dma-mapping.h> | ||||||
|  |  #include <linux/clk.h> | ||||||
|  | +#include <linux/reset.h> | ||||||
|  |  #include <linux/of.h> | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  |  #include <linux/pm_runtime.h> | ||||||
|  | @@ -33,6 +34,8 @@ struct dwc3_of_simple { | ||||||
|  |  	struct device		*dev; | ||||||
|  |  	struct clk		**clks; | ||||||
|  |  	int			num_clocks; | ||||||
|  | +	struct reset_control	*mstr_rst_30_0; | ||||||
|  | +	struct reset_control	*mstr_rst_30_1; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count) | ||||||
|  | @@ -102,6 +105,20 @@ static int dwc3_of_simple_probe(struct p | ||||||
|  |  	if (ret) | ||||||
|  |  		return ret; | ||||||
|  |   | ||||||
|  | +	simple->mstr_rst_30_0 = devm_reset_control_get(dev, "usb30_0_mstr_rst"); | ||||||
|  | + | ||||||
|  | +	if (!IS_ERR(simple->mstr_rst_30_0)) | ||||||
|  | +		reset_control_deassert(simple->mstr_rst_30_0); | ||||||
|  | +	else | ||||||
|  | +		dev_dbg(simple->dev, "cannot get handle for USB PHY 0 master reset control\n"); | ||||||
|  | + | ||||||
|  | +	simple->mstr_rst_30_1 = devm_reset_control_get(dev, "usb30_1_mstr_rst"); | ||||||
|  | + | ||||||
|  | +	if (!IS_ERR(simple->mstr_rst_30_1)) | ||||||
|  | +		reset_control_deassert(simple->mstr_rst_30_1); | ||||||
|  | +	else | ||||||
|  | +		dev_dbg(simple->dev, "cannot get handle for USB PHY 1 master reset control\n"); | ||||||
|  | + | ||||||
|  |  	ret = of_platform_populate(np, NULL, NULL, dev); | ||||||
|  |  	if (ret) { | ||||||
|  |  		for (i = 0; i < simple->num_clocks; i++) { | ||||||
|  | @@ -130,6 +147,12 @@ static int dwc3_of_simple_remove(struct | ||||||
|  |  		clk_put(simple->clks[i]); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (!IS_ERR(simple->mstr_rst_30_0)) | ||||||
|  | +		reset_control_assert(simple->mstr_rst_30_0); | ||||||
|  | + | ||||||
|  | +	if (!IS_ERR(simple->mstr_rst_30_1)) | ||||||
|  | +		reset_control_assert(simple->mstr_rst_30_1); | ||||||
|  | + | ||||||
|  |  	of_platform_depopulate(dev); | ||||||
|  |   | ||||||
|  |  	pm_runtime_disable(dev); | ||||||
| @@ -0,0 +1,50 @@ | |||||||
|  | From a3488aa9bed37c56e405967d44e821c484b5d6b9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ram Chandra Jangir <rjangir@codeaurora.org> | ||||||
|  | Date: Fri, 28 Sep 2018 15:19:50 +0530 | ||||||
|  | Subject: [PATCH] ipq8064: pinctrl: Fixed missing RGMII pincontrol definitions | ||||||
|  |  | ||||||
|  | Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org> | ||||||
|  | --- | ||||||
|  |  drivers/pinctrl/qcom/pinctrl-ipq8064.c | 10 +++++----- | ||||||
|  |  1 file changed, 5 insertions(+), 5 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c | ||||||
|  | +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c | ||||||
|  | @@ -308,7 +308,7 @@ static const char * const gpio_groups[] | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char * const mdio_groups[] = { | ||||||
|  | -	"gpio0", "gpio1", "gpio10", "gpio11", | ||||||
|  | +	"gpio0", "gpio1", "gpio2", "gpio10", "gpio11", "gpio66", | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char * const mi2s_groups[] = { | ||||||
|  | @@ -412,8 +412,8 @@ static const char * const usb2_hsic_grou | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char * const rgmii2_groups[] = { | ||||||
|  | -	"gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | -	"gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", | ||||||
|  | +	"gpio2", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", | ||||||
|  | +	"gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", "gpio66", | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static const char * const sata_groups[] = { | ||||||
|  | @@ -548,7 +548,7 @@ static const struct msm_function ipq8064 | ||||||
|  |  static const struct msm_pingroup ipq8064_groups[] = { | ||||||
|  |  	PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  | -	PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  | +	PINGROUP(2, gsbi5_spi_cs3, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  | @@ -612,7 +612,7 @@ static const struct msm_pingroup ipq8064 | ||||||
|  |  	PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  | -	PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  | +	PINGROUP(66, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), | ||||||
|  |  	SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6), | ||||||
| @@ -0,0 +1,22 @@ | |||||||
|  | Subject: mtd: spi-nor: add mx25l25635f with SECT_4K | ||||||
|  |  | ||||||
|  | This patch fixes an issue with the creation of the | ||||||
|  | ubi volume on the AVM FRITZ!Box 4040. The mx25l25635f | ||||||
|  | and mx25l25635e support SECT_4K which will set the | ||||||
|  | erase size to 4K. This is used by ubi to calculate | ||||||
|  | VID header offsets. Without this, uboot and linux | ||||||
|  | disagrees about the layout and refuse to attach | ||||||
|  | the ubi volume created by the other. | ||||||
|  |  | ||||||
|  | --- | ||||||
|  | --- a/drivers/mtd/spi-nor/spi-nor.c | ||||||
|  | +++ b/drivers/mtd/spi-nor/spi-nor.c | ||||||
|  | @@ -1031,7 +1031,7 @@ static const struct flash_info spi_nor_i | ||||||
|  |  	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, | ||||||
|  |  	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, | ||||||
|  |  	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, | ||||||
|  | -	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||||||
|  | +	{ "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, SECT_4K) }, | ||||||
|  |  	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, | ||||||
|  |  	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, | ||||||
|  |  	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, | ||||||
							
								
								
									
										11026
									
								
								target/linux/ipq806x/patches-4.19/310-msm-adhoc-bus-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11026
									
								
								target/linux/ipq806x/patches-4.19/310-msm-adhoc-bus-support.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,177 @@ | |||||||
|  | From: Christian Lamparter <chunkeey@googlemail.com> | ||||||
|  | Subject: SoC: add qualcomm syscon | ||||||
|  | --- a/drivers/soc/qcom/Makefile | ||||||
|  | +++ b/drivers/soc/qcom/Makefile | ||||||
|  | @@ -9,3 +9,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_st | ||||||
|  |  obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o | ||||||
|  |  obj-$(CONFIG_QCOM_SMSM)	+= smsm.o | ||||||
|  |  obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o | ||||||
|  | +obj-$(CONFIG_QCOM_TCSR)	 += qcom_tcsr.o | ||||||
|  | --- a/drivers/soc/qcom/Kconfig | ||||||
|  | +++ b/drivers/soc/qcom/Kconfig | ||||||
|  | @@ -78,6 +78,13 @@ config QCOM_SMSM | ||||||
|  |  	  Say yes here to support the Qualcomm Shared Memory State Machine. | ||||||
|  |  	  The state machine is represented by bits in shared memory. | ||||||
|  |   | ||||||
|  | +config QCOM_TCSR | ||||||
|  | +	tristate "QCOM Top Control and Status Registers" | ||||||
|  | +	depends on ARCH_QCOM | ||||||
|  | +	help | ||||||
|  | +	  Say y here to enable TCSR support.  The TCSR provides control | ||||||
|  | +	  functions for various peripherals. | ||||||
|  | + | ||||||
|  |  config QCOM_WCNSS_CTRL | ||||||
|  |  	tristate "Qualcomm WCNSS control driver" | ||||||
|  |  	depends on ARCH_QCOM | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/soc/qcom/qcom_tcsr.c | ||||||
|  | @@ -0,0 +1,98 @@ | ||||||
|  | +/* | ||||||
|  | + * Copyright (c) 2014, The Linux foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License rev 2 and | ||||||
|  | + * only rev 2 as published by the free Software foundation. | ||||||
|  | + * | ||||||
|  | + * 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/err.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/of_platform.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | + | ||||||
|  | +#define TCSR_USB_PORT_SEL	0xb0 | ||||||
|  | +#define TCSR_USB_HSPHY_CONFIG	0xC | ||||||
|  | + | ||||||
|  | +#define TCSR_ESS_INTERFACE_SEL_OFFSET   0x0 | ||||||
|  | +#define TCSR_ESS_INTERFACE_SEL_MASK     0xf | ||||||
|  | + | ||||||
|  | +#define TCSR_WIFI0_GLB_CFG_OFFSET	0x0 | ||||||
|  | +#define TCSR_WIFI1_GLB_CFG_OFFSET	0x4 | ||||||
|  | +#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2	0x4 | ||||||
|  | + | ||||||
|  | +static int tcsr_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct resource *res; | ||||||
|  | +	const struct device_node *node = pdev->dev.of_node; | ||||||
|  | +	void __iomem *base; | ||||||
|  | +	u32 val; | ||||||
|  | + | ||||||
|  | +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | +	base = devm_ioremap_resource(&pdev->dev, res); | ||||||
|  | +	if (IS_ERR(base)) | ||||||
|  | +		return PTR_ERR(base); | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { | ||||||
|  | +		dev_err(&pdev->dev, "setting usb port select = %d\n", val); | ||||||
|  | +		writel(val, base + TCSR_USB_PORT_SEL); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) { | ||||||
|  | +		dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val); | ||||||
|  | +		writel(val, base + TCSR_USB_HSPHY_CONFIG); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) { | ||||||
|  | +		u32 tmp = 0; | ||||||
|  | +		dev_info(&pdev->dev, "setting ess interface select = %x\n", val); | ||||||
|  | +		tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET); | ||||||
|  | +		tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK); | ||||||
|  | +		tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK); | ||||||
|  | +		writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET); | ||||||
|  | +        } | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) { | ||||||
|  | +		dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val); | ||||||
|  | +		writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET); | ||||||
|  | +		writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) { | ||||||
|  | +		dev_info(&pdev->dev, | ||||||
|  | +			"setting wifi_noc_memtype_m0_m2 = %x\n", val); | ||||||
|  | +		writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct of_device_id tcsr_dt_match[] = { | ||||||
|  | +	{ .compatible = "qcom,tcsr", }, | ||||||
|  | +	{ }, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +MODULE_DEVICE_TABLE(of, tcsr_dt_match); | ||||||
|  | + | ||||||
|  | +static struct platform_driver tcsr_driver = { | ||||||
|  | +	.driver = { | ||||||
|  | +		.name		= "tcsr", | ||||||
|  | +		.owner		= THIS_MODULE, | ||||||
|  | +		.of_match_table	= tcsr_dt_match, | ||||||
|  | +	}, | ||||||
|  | +	.probe = tcsr_probe, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +module_platform_driver(tcsr_driver); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>"); | ||||||
|  | +MODULE_DESCRIPTION("QCOM TCSR driver"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/include/dt-bindings/soc/qcom,tcsr.h | ||||||
|  | @@ -0,0 +1,48 @@ | ||||||
|  | +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. | ||||||
|  | + * | ||||||
|  | + * This program is free software; you can redistribute it and/or modify | ||||||
|  | + * it under the terms of the GNU General Public License version 2 and | ||||||
|  | + * only version 2 as published by the Free Software Foundation. | ||||||
|  | + * | ||||||
|  | + * 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 __DT_BINDINGS_QCOM_TCSR_H | ||||||
|  | +#define __DT_BINDINGS_QCOM_TCSR_H | ||||||
|  | + | ||||||
|  | +#define TCSR_USB_SELECT_USB3_P0		0x1 | ||||||
|  | +#define TCSR_USB_SELECT_USB3_P1		0x2 | ||||||
|  | +#define TCSR_USB_SELECT_USB3_DUAL	0x3 | ||||||
|  | + | ||||||
|  | +/* IPQ40xx HS PHY Mode Select */ | ||||||
|  | +#define TCSR_USB_HSPHY_HOST_MODE	0x00E700E7 | ||||||
|  | +#define TCSR_USB_HSPHY_DEVICE_MODE	0x00C700E7 | ||||||
|  | + | ||||||
|  | +/* IPQ40xx ess interface mode select */ | ||||||
|  | +#define TCSR_ESS_PSGMII              0 | ||||||
|  | +#define TCSR_ESS_PSGMII_RGMII5       1 | ||||||
|  | +#define TCSR_ESS_PSGMII_RMII0        2 | ||||||
|  | +#define TCSR_ESS_PSGMII_RMII1        4 | ||||||
|  | +#define TCSR_ESS_PSGMII_RMII0_RMII1  6 | ||||||
|  | +#define TCSR_ESS_PSGMII_RGMII4       9 | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * IPQ40xx WiFi Global Config | ||||||
|  | + * Bit 30:AXID_EN | ||||||
|  | + * Enable AXI master bus Axid translating to confirm all txn submitted by order | ||||||
|  | + * Bit 24: Use locally generated socslv_wxi_bvalid | ||||||
|  | + * 1:  use locally generate socslv_wxi_bvalid for performance. | ||||||
|  | + * 0:  use SNOC socslv_wxi_bvalid. | ||||||
|  | + */ | ||||||
|  | +#define TCSR_WIFI_GLB_CFG		0x41000000 | ||||||
|  | + | ||||||
|  | +/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */ | ||||||
|  | +#define TCSR_WIFI_NOC_MEMTYPE_M0_M2	0x02222222 | ||||||
|  | + | ||||||
|  | +/* TCSR A/B REG */ | ||||||
|  | +#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL     0 | ||||||
|  | +#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL     1 | ||||||
|  | + | ||||||
|  | +#endif | ||||||
		Reference in New Issue
	
	Block a user