diff --git a/target/linux/rockchip/Makefile b/target/linux/rockchip/Makefile index c50dcc5c6..ed10bc0d2 100644 --- a/target/linux/rockchip/Makefile +++ b/target/linux/rockchip/Makefile @@ -8,7 +8,7 @@ FEATURES:=ext4 audio usb usbgadget display gpio fpu pci pcie rootfs-part boot-pa SUBTARGETS:=armv8 KERNEL_PATCHVER=5.15 -KERNEL_TESTING_PATCHVER=5.10 +KERNEL_TESTING_PATCHVER=5.18 define Target/Description Build firmware image for Rockchip SoC devices. @@ -18,7 +18,7 @@ include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += uboot-envtools partx-utils e2fsprogs mkf2fs kmod-gpio-button-hotplug \ automount autocore-arm autosamba fdisk cfdisk e2fsprogs ethtool haveged htop \ - luci-app-zerotier luci-app-ipsec-vpnd wpad-openssl kmod-mt76x2u usbutils + luci-app-zerotier luci-app-ipsec-vpnd usbutils KERNELNAME:=Image dtbs diff --git a/target/linux/rockchip/armv8/config-5.18 b/target/linux/rockchip/armv8/config-5.18 new file mode 100644 index 000000000..e0232eb9b --- /dev/null +++ b/target/linux/rockchip/armv8/config-5.18 @@ -0,0 +1,830 @@ +CONFIG_64BIT=y +CONFIG_AF_UNIX_OOB=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARC_EMAC_CORE=y +CONFIG_ARM64=y +CONFIG_ARM64_CNP=y +CONFIG_ARM64_ERRATUM_1024718=y +CONFIG_ARM64_ERRATUM_1530923=y +CONFIG_ARM64_ERRATUM_2051678=y +CONFIG_ARM64_ERRATUM_2077057=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_858921=y +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_MODULE_PLTS=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PAN=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_RAS_EXTN=y +CONFIG_ARM64_SVE=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=48 +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +# CONFIG_ARMV8_DEPRECATED is not set +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_FFA_SMCCC=y +CONFIG_ARM_FFA_TRANSPORT=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MHU=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_RK3399_DMC_DEVFREQ=y +CONFIG_ARM_SCMI_CPUFREQ=y +CONFIG_ARM_SCMI_HAVE_SHMEM=y +CONFIG_ARM_SCMI_HAVE_TRANSPORT=y +CONFIG_ARM_SCMI_POWER_DOMAIN=y +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=y +CONFIG_ARM_SCMI_TRANSPORT_SMC=y +# CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE is not set +CONFIG_ARM_SCPI_CPUFREQ=y +CONFIG_ARM_SCPI_POWER_DOMAIN=y +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_ARM_SMCCC_SOC_ID=y +CONFIG_ARM_SMMU=y +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +CONFIG_ARM_SMMU_V3=y +# CONFIG_ARM_SMMU_V3_SVA is not set +CONFIG_ATA=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BINARY_PRINTF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_BSG_COMMON=y +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_INTEGRITY_T10=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_PCIESSD_MTIP32XX=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BLOCK_COMPAT=y +CONFIG_BLOCK_LEGACY_AUTOLOAD=y +CONFIG_BRCMSTB_GISB_ARB=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CHARGER_GPIO=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLK_PX30=y +CONFIG_CLK_RK3308=y +CONFIG_CLK_RK3328=y +CONFIG_CLK_RK3368=y +CONFIG_CLK_RK3399=y +CONFIG_CLK_RK3568=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=5 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_RK808=y +CONFIG_COMMON_CLK_ROCKCHIP=y +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_SCMI is not set +CONFIG_COMMON_CLK_SCPI=y +CONFIG_COMPAT=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTIG_ALLOC=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_ISOLATION=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRASH_CORE=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRC64=y +CONFIG_CRC64_ROCKSOFT=y +CONFIG_CRC_T10DIF=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC64_ROCKSOFT=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_RNG2=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_NONE is not set +# CONFIG_DEFAULT_FQ_CODEL is not set +CONFIG_DEFAULT_NET_SCH="pfifo_fast" +CONFIG_DEFAULT_PFIFO_FAST=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_GOV_PASSIVE is not set +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DEVMEM=y +# CONFIG_DEVPORT is not set +# CONFIG_DM9051 is not set +CONFIG_DMADEVICES=y +CONFIG_DMA_CMA=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DNOTIFY=y +CONFIG_DRM=y +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +CONFIG_DRM_BRIDGE=y +# CONFIG_DRM_CHIPONE_ICN6211 is not set +CONFIG_DRM_DEBUG_MODESET_LOCK=y +CONFIG_DRM_DP_HELPER=y +CONFIG_DRM_DW_HDMI=y +CONFIG_DRM_DW_MIPI_DSI=y +CONFIG_DRM_GEM_CMA_HELPER=y +# CONFIG_DRM_ITE_IT6505 is not set +# CONFIG_DRM_ITE_IT66121 is not set +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_NOMODESET=y +CONFIG_DRM_PANEL=y +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set +# CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set +CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_PANEL_DSI_CM is not set +# CONFIG_DRM_PANEL_EDP is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set +# CONFIG_DRM_PANEL_JDI_R63452 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set +# CONFIG_DRM_PANEL_MIPI_DBI is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35560 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set +# CONFIG_DRM_PANEL_SHARP_LS060T1SX01 is not set +# CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set +# CONFIG_DRM_RCAR_MIPI_DSI is not set +# CONFIG_DRM_RCAR_USE_LVDS is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_DRM_SIMPLEDRM is not set +# CONFIG_DRM_SSD130X is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +CONFIG_DTC=y +CONFIG_DT_IDLE_GENPD=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_DWMAC_DWC_QOS_ETH=y +CONFIG_DWMAC_GENERIC=y +CONFIG_DWMAC_ROCKCHIP=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_EMAC_ROCKCHIP=y +CONFIG_ENERGY_MODEL=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_FB_CMDLINE=y +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +# CONFIG_FORTIFY_SOURCE is not set +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=2048 +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +# CONFIG_FUN_ETH is not set +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PHY_MIPI_DPHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=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_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_GPIO_CASCADE is not set +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_DWAPB=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_ROCKCHIP=y +# CONFIG_GPIO_SIM is not set +CONFIG_GRO_CELLS=y +# CONFIG_HARDENED_USERCOPY is not set +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HDMI=y +CONFIG_HID=y +CONFIG_HID_GENERIC=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_HOTPLUG_PCI_SHPC=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HWMON=y +CONFIG_HWSPINLOCK=y +CONFIG_HW_CONSOLE=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_RK3X=y +CONFIG_IGB=y +CONFIG_IGB_HWMON=y +CONFIG_IGC=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INDIRECT_PIO=y +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_RK805_PWRKEY=y +CONFIG_INPUT_SPARSEKMAP=y +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_IO_PGTABLE=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_IOMMU_SUPPORT=y +# CONFIG_IO_STRICT_DEVMEM is not set +CONFIG_IO_URING=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JUMP_LABEL=y +CONFIG_KALLSYMS=y +CONFIG_KCMP=y +CONFIG_KEXEC_CORE=y +CONFIG_KEXEC_FILE=y +# CONFIG_KEXEC_SIG is not set +CONFIG_KSM=y +# CONFIG_LAN966X_SWITCH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_SYSCON=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_LIBCRC32C=y +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOG_BUF_SHIFT=19 +CONFIG_LTO_NONE=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_BUS_MUX=y +CONFIG_MDIO_BUS_MUX_GPIO=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_GE_PHY=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MFD_CORE=y +# CONFIG_MFD_KHADAS_MCU is not set +# CONFIG_MFD_MAX77714 is not set +CONFIG_MFD_RK808=y +# CONFIG_MFD_SIMPLE_MFD_I2C is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_CQHCI=y +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_DW_PCI is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +CONFIG_MMC_SDHCI_OF_DWCMSHC=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MOTORCOMM_PHY=y +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_CYPRESS=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SMBUS=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +CONFIG_MQ_IOSCHED_DEADLINE=y +# CONFIG_MTD_CFI is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_NAND_ECC_MXIC is not set +# CONFIG_MTD_NAND_MTK_BMT is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +# CONFIG_NET_DSA_REALTEK is not set +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_DAVICOM=y +CONFIG_NET_VENDOR_FUNGIBLE=y +CONFIG_NLS=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NTFS_FS=y +CONFIG_NTFS_RW=y +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +# CONFIG_NVME_VERBOSE_ERRORS is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_OLD_SIGSUSPEND3=y +# CONFIG_OPEN_DICE is not set +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +# CONFIG_PAGE_POOL_STATS is not set +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_SPLIT_BTF=y +CONFIG_PAHOLE_VERSION=121 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_PERCPU=y +CONFIG_PATA_SIS=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCIE_ROCKCHIP=y +CONFIG_PCIE_ROCKCHIP_DW_HOST=y +CONFIG_PCIE_ROCKCHIP_HOST=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_STUB=y +CONFIG_PCS_XPCS=y +# CONFIG_PECI is not set +CONFIG_PGTABLE_LEVELS=4 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_CADENCE_DPHY_RX is not set +CONFIG_PHY_ROCKCHIP_DP=y +CONFIG_PHY_ROCKCHIP_DPHY_RX0=y +CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY=y +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y +CONFIG_PHY_ROCKCHIP_INNO_HDMI=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y +CONFIG_PHY_ROCKCHIP_PCIE=y +CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y +CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_PHY_ROCKCHIP_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RK805=y +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PL330_DMA=y +CONFIG_PLATFORM_MHU=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_SUPPLY_HWMON=y +CONFIG_PPS=y +CONFIG_PREEMPT=y +CONFIG_PREEMPTION=y +CONFIG_PREEMPT_BUILD=y +CONFIG_PREEMPT_COUNT=y +# CONFIG_PREEMPT_DYNAMIC is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_RCU=y +CONFIG_PRINTK_TIME=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_VMCORE=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_PWM_SYSFS=y +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_RAID_ATTRS=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_MODULE_REGION_FULL=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_RCU_TRACE=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_ARM_SCMI is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +# CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_SY7636A is not set +# CONFIG_REGULATOR_TPS6286X is not set +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_SCMI=y +CONFIG_RFS_ACCEL=y +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_CDN_DP is not set +CONFIG_ROCKCHIP_DW_HDMI=y +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +CONFIG_ROCKCHIP_EFUSE=y +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_INNO_HDMI=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_ROCKCHIP_IOMMU=y +# CONFIG_ROCKCHIP_LVDS is not set +CONFIG_ROCKCHIP_MBOX=y +# CONFIG_ROCKCHIP_OTP is not set +CONFIG_ROCKCHIP_PHY=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +# CONFIG_ROCKCHIP_RGB is not set +CONFIG_ROCKCHIP_RK3066_HDMI=y +CONFIG_ROCKCHIP_THERMAL=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ROCKCHIP_VOP=y +CONFIG_ROCKCHIP_VOP2=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RSEQ=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_RK808=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_NVMEM=y +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SATA_AHCI=y +CONFIG_SATA_HOST=y +CONFIG_SATA_PMP=y +CONFIG_SATA_SIS=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_SCSI_SAS_ATA is not set +CONFIG_SCSI_SAS_ATTRS=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SENSORS_ARM_SCMI is not set +CONFIG_SENSORS_ARM_SCPI=y +# CONFIG_SENSORS_SY7636A is not set +# CONFIG_SENSORS_TMP464 is not set +CONFIG_SERIAL_8250_ASPEED_VUART=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_EXAR=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FINTEK=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIO=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_PCIPS2=y +CONFIG_SERIO_RAW=y +CONFIG_SG_POOL=y +CONFIG_SLUB_DEBUG=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_ROCKCHIP=y +CONFIG_SPI_SPIDEV=y +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SRAM=y +CONFIG_SRCU=y +CONFIG_STACKDEPOT=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_PER_TASK=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_STACKTRACE=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y +# CONFIG_STMMAC_SELFTESTS is not set +CONFIG_STRICT_DEVMEM=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_SWAP is not set +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYNC_FILE=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSFS_SYSCALL=y +CONFIG_SYSVIPC_COMPAT=y +# CONFIG_TEXTSEARCH is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +# CONFIG_TINYDRM_ILI9163 is not set +CONFIG_TRACE_CLOCK=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set +CONFIG_TRANS_TABLE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_TYPEC=y +# CONFIG_TYPEC_DP_ALTMODE is not set +CONFIG_TYPEC_FUSB302=y +# CONFIG_TYPEC_HD3SS3220 is not set +# CONFIG_TYPEC_MUX_PI3USB30532 is not set +# CONFIG_TYPEC_RT1719 is not set +# CONFIG_TYPEC_STUSB160X is not set +# CONFIG_TYPEC_TCPCI is not set +CONFIG_TYPEC_TCPM=y +# CONFIG_TYPEC_TPS6598X is not set +# CONFIG_TYPEC_WUSB3801 is not set +# CONFIG_UACCE is not set +# CONFIG_UCLAMP_TASK is not set +# CONFIG_UEVENT_HELPER is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_HOST=y +CONFIG_USB_DWC3_OF_SIMPLE=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_HID=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_PHY=y +CONFIG_USB_ROLE_SWITCH=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USERIO=y +CONFIG_VIDEOMODE_HELPERS=y +# CONFIG_VIRTIO_MENU is not set +CONFIG_VMAP_STACK=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_WATCHDOG is not set +CONFIG_XARRAY_MULTI=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts new file mode 100644 index 000000000..7fd8d82a5 --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-doornet1.dts @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2020 David Bauer + */ + +/dts-v1/; + +#include +#include +#include "rk3328.dtsi" + +/ { + model = "EmbedFire DoorNet1"; + compatible = "embedfire,doornet1", "rockchip,rk3328"; + + aliases { + ethernet1 = &rtl8153; + mmc0 = &sdmmc; + }; + + aliases { + led-boot = &sys_led; + led-failsafe = &sys_led; + led-running = &sys_led; + led-upgrade = &sys_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + gmac_clk: gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&reset_button_pin>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + pinctrl-names = "default"; + + lan_led: led-0 { + gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:lan"; + }; + + sys_led: led-1 { + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:red:sys"; + default-state = "on"; + }; + + wan_led: led-2 { + gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:wan"; + }; + }; + + vcc_io_sdio: sdmmcio-regulator { + compatible = "regulator-gpio"; + enable-active-high; + gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&sdio_vcc_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_io_sdio"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <5000>; + regulator-type = "voltage"; + startup-delay-us = <2000>; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <&vcc_io_33>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdmmc0m1_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_sd"; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io_33>; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vdd_5v_lan: vdd-5v-lan { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&lan_vdd_pin>; + pinctrl-names = "default"; + regulator-name = "vdd_5v_lan"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "disabled"; +}; + +&gmac2io { + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; + clock_in_out = "input"; + phy-handle = <&rtl8211e>; + phy-mode = "rgmii"; + phy-supply = <&vcc_io_33>; + pinctrl-0 = <&rgmiim1_pins>; + pinctrl-names = "default"; + rx_delay = <0x18>; + snps,aal; + tx_delay = <0x24>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c1 { + status = "okay"; + + rk805: pmic@18 { + compatible = "rockchip,rk805"; + reg = <0x18>; + interrupt-parent = <&gpio1>; + interrupts = <24 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-0 = <&pmic_int_l>; + pinctrl-names = "default"; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vdd_5v>; + vcc2-supply = <&vdd_5v>; + vcc3-supply = <&vdd_5v>; + vcc4-supply = <&vdd_5v>; + vcc5-supply = <&vcc_io_33>; + vcc6-supply = <&vdd_5v>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io_33: DCDC_REG4 { + regulator-name = "vcc_io_33"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_18: LDO_REG1 { + regulator-name = "vcc_18"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_emmc: LDO_REG2 { + regulator-name = "vcc18_emmc"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_10: LDO_REG3 { + regulator-name = "vdd_10"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + }; + }; +}; + +&io_domains { + pmuio-supply = <&vcc_io_33>; + vccio1-supply = <&vcc_io_33>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io_sdio>; + vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io_33>; + vccio6-supply = <&vcc_io_33>; + status = "okay"; +}; + +&pinctrl { + button { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac2io { + eth_phy_reset_pin: eth-phy-reset-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + lan_led_pin: lan-led-pin { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lan { + lan_vdd_pin: lan-vdd-pin { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd { + sdio_vcc_pin: sdio-vcc-pin { + rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm2 { + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; + pinctrl-names = "default"; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vcc_io_sdio>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&u2phy { + status = "okay"; +}; + +&u2phy_host { + status = "okay"; +}; + +&u2phy_otg { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "host"; +}; + +&usbdrd3 { + dr_mode = "host"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* Second port is for USB 3.0 */ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; + realtek,led-data = <0x87>; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts new file mode 100644 index 000000000..ef7a5eda8 --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c.dts @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2020 David Bauer + */ + +/dts-v1/; + +#include +#include +#include "rk3328.dtsi" + +/ { + model = "FriendlyElec NanoPi R2C"; + compatible = "friendlyarm,nanopi-r2c", "rockchip,rk3328"; + + aliases { + ethernet1 = &rtl8153; + mmc0 = &sdmmc; + }; + + aliases { + led-boot = &sys_led; + led-failsafe = &sys_led; + led-running = &sys_led; + led-upgrade = &sys_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + gmac_clk: gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&reset_button_pin>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + pinctrl-names = "default"; + + lan_led: led-0 { + gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:lan"; + }; + + sys_led: led-1 { + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:red:sys"; + default-state = "on"; + }; + + wan_led: led-2 { + gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:wan"; + }; + }; + + vcc_io_sdio: sdmmcio-regulator { + compatible = "regulator-gpio"; + enable-active-high; + gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&sdio_vcc_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_io_sdio"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <5000>; + regulator-type = "voltage"; + startup-delay-us = <2000>; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <&vcc_io_33>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdmmc0m1_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_sd"; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io_33>; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vdd_5v_lan: vdd-5v-lan { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&lan_vdd_pin>; + pinctrl-names = "default"; + regulator-name = "vdd_5v_lan"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "disabled"; +}; + +&gmac2io { + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; + clock_in_out = "input"; + phy-handle = <&rtl8211e>; + phy-mode = "rgmii"; + phy-supply = <&vcc_io_33>; + pinctrl-0 = <&rgmiim1_pins>; + pinctrl-names = "default"; + rx_delay = <0x18>; + snps,aal; + tx_delay = <0x24>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c1 { + status = "okay"; + + rk805: pmic@18 { + compatible = "rockchip,rk805"; + reg = <0x18>; + interrupt-parent = <&gpio1>; + interrupts = <24 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-0 = <&pmic_int_l>; + pinctrl-names = "default"; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vdd_5v>; + vcc2-supply = <&vdd_5v>; + vcc3-supply = <&vdd_5v>; + vcc4-supply = <&vdd_5v>; + vcc5-supply = <&vcc_io_33>; + vcc6-supply = <&vdd_5v>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io_33: DCDC_REG4 { + regulator-name = "vcc_io_33"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_18: LDO_REG1 { + regulator-name = "vcc_18"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_emmc: LDO_REG2 { + regulator-name = "vcc18_emmc"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_10: LDO_REG3 { + regulator-name = "vdd_10"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + }; + }; +}; + +&io_domains { + pmuio-supply = <&vcc_io_33>; + vccio1-supply = <&vcc_io_33>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io_sdio>; + vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io_33>; + vccio6-supply = <&vcc_io_33>; + status = "okay"; +}; + +&pinctrl { + button { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac2io { + eth_phy_reset_pin: eth-phy-reset-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + lan_led_pin: lan-led-pin { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lan { + lan_vdd_pin: lan-vdd-pin { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd { + sdio_vcc_pin: sdio-vcc-pin { + rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm2 { + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; + pinctrl-names = "default"; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vcc_io_sdio>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&u2phy { + status = "okay"; +}; + +&u2phy_host { + status = "okay"; +}; + +&u2phy_otg { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "host"; +}; + +&usbdrd3 { + dr_mode = "host"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* Second port is for USB 3.0 */ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; + realtek,led-data = <0x87>; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts new file mode 100644 index 000000000..07c8dcc2b --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2020 David Bauer + */ + +/dts-v1/; + +#include +#include +#include "rk3328.dtsi" + +/ { + model = "Xunlong Orange Pi R1 Plus LTS"; + compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; + + aliases { + ethernet1 = &rtl8153; + mmc0 = &sdmmc; + }; + + aliases { + led-boot = &sys_led; + led-failsafe = &sys_led; + led-running = &sys_led; + led-upgrade = &sys_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + gmac_clk: gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&reset_button_pin>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + pinctrl-names = "default"; + + lan_led: led-0 { + gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:lan"; + }; + + sys_led: led-1 { + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:red:sys"; + default-state = "on"; + }; + + wan_led: led-2 { + gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:wan"; + }; + }; + + vcc_io_sdio: sdmmcio-regulator { + compatible = "regulator-gpio"; + enable-active-high; + gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&sdio_vcc_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_io_sdio"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <5000>; + regulator-type = "voltage"; + startup-delay-us = <2000>; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <&vcc_io_33>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdmmc0m1_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_sd"; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io_33>; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vdd_5v_lan: vdd-5v-lan { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&lan_vdd_pin>; + pinctrl-names = "default"; + regulator-name = "vdd_5v_lan"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "disabled"; +}; + +&gmac2io { + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; + clock_in_out = "input"; + phy-handle = <&rtl8211e>; + phy-mode = "rgmii"; + phy-supply = <&vcc_io_33>; + pinctrl-0 = <&rgmiim1_pins>; + pinctrl-names = "default"; + rx_delay = <0x18>; + snps,aal; + tx_delay = <0x24>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c1 { + status = "okay"; + + rk805: pmic@18 { + compatible = "rockchip,rk805"; + reg = <0x18>; + interrupt-parent = <&gpio1>; + interrupts = <24 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-0 = <&pmic_int_l>; + pinctrl-names = "default"; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vdd_5v>; + vcc2-supply = <&vdd_5v>; + vcc3-supply = <&vdd_5v>; + vcc4-supply = <&vdd_5v>; + vcc5-supply = <&vcc_io_33>; + vcc6-supply = <&vdd_5v>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io_33: DCDC_REG4 { + regulator-name = "vcc_io_33"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_18: LDO_REG1 { + regulator-name = "vcc_18"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_emmc: LDO_REG2 { + regulator-name = "vcc18_emmc"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_10: LDO_REG3 { + regulator-name = "vdd_10"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + }; + }; +}; + +&io_domains { + pmuio-supply = <&vcc_io_33>; + vccio1-supply = <&vcc_io_33>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io_sdio>; + vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io_33>; + vccio6-supply = <&vcc_io_33>; + status = "okay"; +}; + +&pinctrl { + button { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac2io { + eth_phy_reset_pin: eth-phy-reset-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + lan_led_pin: lan-led-pin { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lan { + lan_vdd_pin: lan-vdd-pin { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd { + sdio_vcc_pin: sdio-vcc-pin { + rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm2 { + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; + pinctrl-names = "default"; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vcc_io_sdio>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&u2phy { + status = "okay"; +}; + +&u2phy_host { + status = "okay"; +}; + +&u2phy_otg { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "host"; +}; + +&usbdrd3 { + dr_mode = "host"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* Second port is for USB 3.0 */ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; + realtek,led-data = <0x87>; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts new file mode 100644 index 000000000..6ee9be0cd --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2020 David Bauer + */ + +/dts-v1/; + +#include +#include +#include "rk3328.dtsi" + +/ { + model = "Xunlong Orange Pi R1 Plus"; + compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; + + aliases { + ethernet1 = &rtl8153; + mmc0 = &sdmmc; + }; + + aliases { + led-boot = &sys_led; + led-failsafe = &sys_led; + led-running = &sys_led; + led-upgrade = &sys_led; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + gmac_clk: gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_clkin"; + #clock-cells = <0>; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&reset_button_pin>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <50>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + pinctrl-names = "default"; + + lan_led: led-0 { + gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:lan"; + }; + + sys_led: led-1 { + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:red:sys"; + default-state = "on"; + }; + + wan_led: led-2 { + gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; + label = "nanopi-r2s:green:wan"; + }; + }; + + vcc_io_sdio: sdmmcio-regulator { + compatible = "regulator-gpio"; + enable-active-high; + gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&sdio_vcc_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_io_sdio"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-settling-time-us = <5000>; + regulator-type = "voltage"; + startup-delay-us = <2000>; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <&vcc_io_33>; + }; + + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdmmc0m1_pin>; + pinctrl-names = "default"; + regulator-name = "vcc_sd"; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_io_33>; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vdd_5v_lan: vdd-5v-lan { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&lan_vdd_pin>; + pinctrl-names = "default"; + regulator-name = "vdd_5v_lan"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + +&cpu1 { + cpu-supply = <&vdd_arm>; +}; + +&cpu2 { + cpu-supply = <&vdd_arm>; +}; + +&cpu3 { + cpu-supply = <&vdd_arm>; +}; + +&display_subsystem { + status = "disabled"; +}; + +&gmac2io { + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; + clock_in_out = "input"; + phy-handle = <&rtl8211e>; + phy-mode = "rgmii"; + phy-supply = <&vcc_io_33>; + pinctrl-0 = <&rgmiim1_pins>; + pinctrl-names = "default"; + rx_delay = <0x18>; + snps,aal; + tx_delay = <0x24>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + rtl8211e: ethernet-phy@1 { + reg = <1>; + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c1 { + status = "okay"; + + rk805: pmic@18 { + compatible = "rockchip,rk805"; + reg = <0x18>; + interrupt-parent = <&gpio1>; + interrupts = <24 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk805-clkout2"; + gpio-controller; + #gpio-cells = <2>; + pinctrl-0 = <&pmic_int_l>; + pinctrl-names = "default"; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vdd_5v>; + vcc2-supply = <&vdd_5v>; + vcc3-supply = <&vdd_5v>; + vcc4-supply = <&vdd_5v>; + vcc5-supply = <&vcc_io_33>; + vcc6-supply = <&vdd_5v>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io_33: DCDC_REG4 { + regulator-name = "vcc_io_33"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_18: LDO_REG1 { + regulator-name = "vcc_18"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_emmc: LDO_REG2 { + regulator-name = "vcc18_emmc"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_10: LDO_REG3 { + regulator-name = "vdd_10"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + }; + }; +}; + +&io_domains { + pmuio-supply = <&vcc_io_33>; + vccio1-supply = <&vcc_io_33>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io_sdio>; + vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io_33>; + vccio6-supply = <&vcc_io_33>; + status = "okay"; +}; + +&pinctrl { + button { + reset_button_pin: reset-button-pin { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gmac2io { + eth_phy_reset_pin: eth-phy-reset-pin { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + leds { + lan_led_pin: lan-led-pin { + rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lan { + lan_vdd_pin: lan-vdd-pin { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd { + sdio_vcc_pin: sdio-vcc-pin { + rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm2 { + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; + pinctrl-names = "default"; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vcc_io_sdio>; + status = "okay"; +}; + +&tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; + status = "okay"; +}; + +&u2phy { + status = "okay"; +}; + +&u2phy_host { + status = "okay"; +}; + +&u2phy_otg { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb20_otg { + status = "okay"; + dr_mode = "host"; +}; + +&usbdrd3 { + dr_mode = "host"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* Second port is for USB 3.0 */ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; + realtek,led-data = <0x87>; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-doornet2.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-doornet2.dts new file mode 100644 index 000000000..d5184595e --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-doornet2.dts @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * FriendlyElec NanoPC-T4 board device tree source + * + * Copyright (c) 2020 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * Copyright (c) 2018 Collabora Ltd. + * + * Copyright (c) 2020 Jensen Huang + * Copyright (c) 2020 Marty Jones + * Copyright (c) 2021 Tianling Shen + */ + +/dts-v1/; +#include "rk3399-nanopi4.dtsi" + +/ { + model = "EmbedFire DoorNet2"; + compatible = "embedfire,doornet2", "rockchip,rk3399"; + + /delete-node/ display-subsystem; + + gpio-leds { + pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; + + /delete-node/ led-0; + + lan_led: led-lan { + gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + label = "green:lan"; + }; + + sys_led: led-sys { + gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; + label = "red:power"; + default-state = "on"; + }; + + wan_led: led-wan { + gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_HIGH>; + label = "green:wan"; + }; + }; + + gpio-keys { + pinctrl-0 = <&reset_button_pin>; + + /delete-node/ power; + + reset { + debounce-interval = <50>; + gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>; + label = "reset"; + linux,code = ; + }; + }; + + vdd_5v: vdd-5v { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v"; + regulator-always-on; + regulator-boot-on; + }; +}; + +&emmc_phy { + status = "disabled"; +}; + +&i2c2 { + eeprom@51 { + compatible = "microchip,24c02", "atmel,24c02"; + reg = <0x51>; + pagesize = <16>; + read-only; /* This holds our MAC */ + }; +}; + +&i2c4 { + status = "disabled"; +}; + +&pcie0 { + max-link-speed = <1>; + num-lanes = <1>; + vpcie3v3-supply = <&vcc3v3_sys>; +}; + +&pinctrl { + gpio-leds { + /delete-node/ status-led-pin; + + lan_led_pin: lan-led-pin { + rockchip,pins = <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + sys_led_pin: sys-led-pin { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rockchip-key { + /delete-node/ power-key; + + reset_button_pin: reset-button-pin { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&sdhci { + status = "disabled"; +}; + +&sdio0 { + status = "disabled"; +}; + +&u2phy0_host { + phy-supply = <&vdd_5v>; +}; + +&u2phy1_host { + status = "disabled"; +}; + +&uart0 { + status = "disabled"; +}; + +&usbdrd_dwc3_0 { + dr_mode = "host"; +}; + +&vcc3v3_sys { + vin-supply = <&vcc5v0_sys>; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts new file mode 100644 index 000000000..12d1bfa08 --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Akash Gajjar + * Copyright (c) 2019 Pragnesh Patel + */ + +/* TODO + * Delete this file and migrate RockPi 4 to RockPi 4A after + * removing Kernel 5.4. + */ + + +/dts-v1/; +#include "rk3399-rock-pi-4.dtsi" + +/ { + model = "SHAREVDI GuangMiao G4C"; + compatible = "sharevdi,guangmiao-g4c", "rockchip,rk3399"; +}; diff --git a/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts new file mode 100644 index 000000000..f6e7710a0 --- /dev/null +++ b/target/linux/rockchip/files-5.18/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Akash Gajjar + * Copyright (c) 2019 Pragnesh Patel + */ + +/* TODO + * Delete this file and migrate RockPi 4 to RockPi 4A after + * removing Kernel 5.4. + */ + + +/dts-v1/; +#include "rk3399-rock-pi-4.dtsi" + +/ { + model = "Radxa ROCK Pi 4"; + compatible = "radxa,rockpi4", "rockchip,rk3399"; +}; diff --git a/target/linux/rockchip/files/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml b/target/linux/rockchip/files-5.4/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml similarity index 100% rename from target/linux/rockchip/files/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml rename to target/linux/rockchip/files-5.4/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb3.yaml diff --git a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi b/target/linux/rockchip/files-5.4/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi similarity index 100% rename from target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi rename to target/linux/rockchip/files-5.4/arch/arm64/boot/dts/rockchip/rk3328-dram-nanopi2-timing.dtsi diff --git a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts b/target/linux/rockchip/files-5.4/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts similarity index 100% rename from target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts rename to target/linux/rockchip/files-5.4/arch/arm64/boot/dts/rockchip/rk3399-guangmiao-g4c.dts diff --git a/target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c b/target/linux/rockchip/files-5.4/drivers/char/hw_random/rockchip-rng.c similarity index 100% rename from target/linux/rockchip/files/drivers/char/hw_random/rockchip-rng.c rename to target/linux/rockchip/files-5.4/drivers/char/hw_random/rockchip-rng.c diff --git a/target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c b/target/linux/rockchip/files-5.4/drivers/devfreq/rk3328_dmc.c similarity index 100% rename from target/linux/rockchip/files/drivers/devfreq/rk3328_dmc.c rename to target/linux/rockchip/files-5.4/drivers/devfreq/rk3328_dmc.c diff --git a/target/linux/rockchip/files/drivers/phy/rockchip/phy-rockchip-inno-usb3.c b/target/linux/rockchip/files-5.4/drivers/phy/rockchip/phy-rockchip-inno-usb3.c similarity index 100% rename from target/linux/rockchip/files/drivers/phy/rockchip/phy-rockchip-inno-usb3.c rename to target/linux/rockchip/files-5.4/drivers/phy/rockchip/phy-rockchip-inno-usb3.c diff --git a/target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h b/target/linux/rockchip/files-5.4/include/dt-bindings/clock/rockchip-ddr.h similarity index 100% rename from target/linux/rockchip/files/include/dt-bindings/clock/rockchip-ddr.h rename to target/linux/rockchip/files-5.4/include/dt-bindings/clock/rockchip-ddr.h diff --git a/target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h b/target/linux/rockchip/files-5.4/include/dt-bindings/memory/rk3328-dram.h similarity index 100% rename from target/linux/rockchip/files/include/dt-bindings/memory/rk3328-dram.h rename to target/linux/rockchip/files-5.4/include/dt-bindings/memory/rk3328-dram.h diff --git a/target/linux/rockchip/patches-5.18/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/target/linux/rockchip/patches-5.18/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch new file mode 100644 index 000000000..792028b29 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch @@ -0,0 +1,31 @@ +From af20b3384e8723077cc6484160b0cf4e9be321de Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 7 Jun 2021 15:45:37 +0800 +Subject: [PATCH] arm64: dts: rockchip: add EEPROM node for NanoPi R4S + +NanoPi R4S has a EEPROM attached to the 2nd I2C bus (U92), which +stores the MAC address. + +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -68,6 +68,15 @@ + status = "disabled"; + }; + ++&i2c2 { ++ eeprom@51 { ++ compatible = "microchip,24c02", "atmel,24c02"; ++ reg = <0x51>; ++ pagesize = <16>; ++ read-only; /* This holds our MAC */ ++ }; ++}; ++ + &i2c4 { + status = "disabled"; + }; diff --git a/target/linux/rockchip/patches-5.18/100-rockchip-use-system-LED-for-OpenWrt.patch b/target/linux/rockchip/patches-5.18/100-rockchip-use-system-LED-for-OpenWrt.patch new file mode 100644 index 000000000..5ec7952bf --- /dev/null +++ b/target/linux/rockchip/patches-5.18/100-rockchip-use-system-LED-for-OpenWrt.patch @@ -0,0 +1,31 @@ +From 6731d2c9039fbe1ecf21915eab3acee0a999508a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Fri, 10 Jul 2020 21:38:20 +0200 +Subject: [PATCH] rockchip: use system LED for OpenWrt + +Use the SYS LED on the casing for showing system status. + +This patch is kept separate from the NanoPi R2S support patch, as i plan +on submitting the device support upstream. + +Signed-off-by: David Bauer +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -18,6 +18,13 @@ + mmc0 = &sdmmc; + }; + ++ aliases { ++ led-boot = &sys_led; ++ led-failsafe = &sys_led; ++ led-running = &sys_led; ++ led-upgrade = &sys_led; ++ }; ++ + chosen { + stdout-path = "serial2:1500000n8"; + }; diff --git a/target/linux/rockchip/patches-5.18/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/target/linux/rockchip/patches-5.18/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch new file mode 100644 index 000000000..06e593a5a --- /dev/null +++ b/target/linux/rockchip/patches-5.18/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch @@ -0,0 +1,24 @@ +From 2795c8b31a686bdb8338f9404d18ef7a154f0d75 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 13:32:59 +0200 +Subject: [PATCH] arm64: rockchip: add OF node for USB eth on NanoPi R2S + +This adds the OF node for the USB3 ethernet adapter on the FriendlyARM +NanoPi R2S. Add the correct value for the RTL8153 LED configuration +register to match the blink behavior of the other port on the device. + +Signed-off-by: David Bauer +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -404,6 +404,7 @@ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; ++ realtek,led-data = <0x87>; + }; + }; + diff --git a/target/linux/rockchip/patches-5.18/111-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-N.patch b/target/linux/rockchip/patches-5.18/111-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-N.patch new file mode 100644 index 000000000..56d2ea02a --- /dev/null +++ b/target/linux/rockchip/patches-5.18/111-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-N.patch @@ -0,0 +1,397 @@ +From ac8fa7a4d6e548cd4d4719f12cefb664191a41c2 Mon Sep 17 00:00:00 2001 +From: Marty Jones +Date: Wed, 12 May 2021 13:04:20 -0400 +Subject: [PATCH] rockchip: rk3328: add support for FriendlyARM NanoPi NEO3 + +This patch adds support for FriendlyARM NanoPi NEO3 + +Soc: RockChip RK3328 +RAM: 1GB/2GB DDR4 +LAN: 10/100/1000M Ethernet with unique MAC +USB Host: 1x USB3.0 Type A and 2x USB2.0 on 2.54mm pin header +MicroSD: x 1 for system boot and storage +LED: Power LED x 1, System LED x 1 +Key: User Button x 1 +Fan: 2 Pin JST ZH 1.5mm Connector for 5V Fan +GPIO: 26 pin-header, include I2C, UART, SPI, I2S, GPIO +Power: 5V/1A, via Type-C or GPIO + +Signed-off-by: Marty Jones +--- + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../boot/dts/rockchip/rk3328-nanopi-neo3.dts | 359 ++++++++++++++++++ + 2 files changed, 360 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts + +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -9,6 +9,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3318-a9 + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go2.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-neo3.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock-pi-e.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts +@@ -0,0 +1,359 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 David Bauer ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3328.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPi NEO3"; ++ compatible = "friendlyarm,nanopi-neo3", "rockchip,rk3328"; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ gmac_clk: gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ pinctrl-0 = <&reset_button_pin>; ++ pinctrl-names = "default"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-0 = <&stat_led_pin>; ++ pinctrl-names = "default"; ++ ++ stat_led: led-1 { ++ gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ label = "nanopi-neo3:green:stat"; ++ }; ++ }; ++ ++ vcc_io_sdio: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ enable-active-high; ++ gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&sdio_vcc_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_io_sdio"; ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-settling-time-us = <5000>; ++ regulator-type = "voltage"; ++ startup-delay-us = <2000>; ++ states = <1800000 0x1>, ++ <3300000 0x0>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&sdmmc0m1_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_sd"; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vdd_5v: vdd-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_5v"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&display_subsystem { ++ status = "disabled"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; ++ clock_in_out = "input"; ++ phy-handle = <&rtl8211e>; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc_io_33>; ++ pinctrl-0 = <&rgmiim1_pins>; ++ pinctrl-names = "default"; ++ rx_delay = <0x18>; ++ snps,aal; ++ tx_delay = <0x24>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rtl8211e: ethernet-phy@1 { ++ reg = <1>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: pmic@18 { ++ compatible = "rockchip,rk805"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ pinctrl-0 = <&pmic_int_l>; ++ pinctrl-names = "default"; ++ rockchip,system-power-controller; ++ wakeup-source; ++ ++ vcc1-supply = <&vdd_5v>; ++ vcc2-supply = <&vdd_5v>; ++ vcc3-supply = <&vdd_5v>; ++ vcc4-supply = <&vdd_5v>; ++ vcc5-supply = <&vcc_io_33>; ++ vcc6-supply = <&vdd_5v>; ++ ++ regulators { ++ vdd_log: DCDC_REG1 { ++ regulator-name = "vdd_log"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: DCDC_REG2 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io_33: DCDC_REG4 { ++ regulator-name = "vcc_io_33"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: LDO_REG1 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: LDO_REG2 { ++ regulator-name = "vcc18_emmc"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ pmuio-supply = <&vcc_io_33>; ++ vccio1-supply = <&vcc_io_33>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io_sdio>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io_33>; ++ vccio6-supply = <&vcc_io_33>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ button { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ gmac2io { ++ eth_phy_reset_pin: eth-phy-reset-pin { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ leds { ++ stat_led_pin: stat-led-pin { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sd { ++ sdio_vcc_pin: sdio-vcc-pin { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ disable-wp; ++ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; ++ pinctrl-names = "default"; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vcc_io_sdio>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++}; ++ ++&u2phy_host { ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ dr_mode = "host"; ++ status = "okay"; ++}; diff --git a/target/linux/rockchip/patches-5.18/112-rockchip-Add-sata-nodes-to-rk356x.patch b/target/linux/rockchip/patches-5.18/112-rockchip-Add-sata-nodes-to-rk356x.patch new file mode 100644 index 000000000..7d2a55801 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/112-rockchip-Add-sata-nodes-to-rk356x.patch @@ -0,0 +1,78 @@ +From 16c0f95d9ed14f033b5f1bd37e96d257b60c198c Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 11 Mar 2022 22:03:57 +0100 +Subject: arm64: dts: rockchip: Add sata nodes to rk356x + +RK356x supports up to 3 sata controllers which were compatible with the +existing snps,dwc-ahci binding. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220311210357.222830-7-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 14 ++++++++++++++ + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 28 ++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +(limited to 'arch/arm64/boot/dts/rockchip') + +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -8,6 +8,20 @@ + / { + compatible = "rockchip,rk3568"; + ++ sata0: sata@fc000000 { ++ compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfc000000 0 0x1000>; ++ clocks = <&cru ACLK_SATA0>, <&cru CLK_SATA0_PMALIVE>, ++ <&cru CLK_SATA0_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ phys = <&combphy0 PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; ++ }; ++ + pipe_phy_grf0: syscon@fdc70000 { + compatible = "rockchip,rk3568-pipe-phy-grf", "syscon"; + reg = <0x0 0xfdc70000 0x0 0x1000>; +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -230,6 +230,34 @@ + }; + }; + ++ sata1: sata@fc400000 { ++ compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfc400000 0 0x1000>; ++ clocks = <&cru ACLK_SATA1>, <&cru CLK_SATA1_PMALIVE>, ++ <&cru CLK_SATA1_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ phys = <&combphy1 PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; ++ }; ++ ++ sata2: sata@fc800000 { ++ compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfc800000 0 0x1000>; ++ clocks = <&cru ACLK_SATA2>, <&cru CLK_SATA2_PMALIVE>, ++ <&cru CLK_SATA2_RXOOB>; ++ clock-names = "sata", "pmalive", "rxoob"; ++ interrupts = ; ++ phys = <&combphy2 PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&power RK3568_PD_PIPE>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@fd400000 { + compatible = "arm,gic-v3"; + reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ diff --git a/target/linux/rockchip/patches-5.18/113-rockchip-add-rk356x-dwc3-usb3-nodes.patch b/target/linux/rockchip/patches-5.18/113-rockchip-add-rk356x-dwc3-usb3-nodes.patch new file mode 100644 index 000000000..1972e99ed --- /dev/null +++ b/target/linux/rockchip/patches-5.18/113-rockchip-add-rk356x-dwc3-usb3-nodes.patch @@ -0,0 +1,120 @@ +From 9f4c480f24e2ce1d464ff9d5f8a249a485acdc7f Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 8 Apr 2022 11:12:35 -0400 +Subject: arm64: dts: rockchip: add rk356x dwc3 usb3 nodes + +Add the dwc3 device nodes to the rk356x device trees. +The rk3566 has one usb2 capable dwc3 otg controller and one usb3 capable +dwc3 host controller. +The rk3568 has one usb3 capable dwc3 otg controller and one usb3 capable +dwc3 host controller. + +Signed-off-by: Peter Geis +Tested-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220408151237.3165046-4-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566.dtsi | 11 ++++++++++ + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 9 ++++++++ + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 35 +++++++++++++++++++++++++++++++- + 3 files changed, 54 insertions(+), 1 deletion(-) + +(limited to 'arch/arm64/boot/dts/rockchip') + +--- a/arch/arm64/boot/dts/rockchip/rk3566.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3566.dtsi +@@ -6,6 +6,10 @@ + compatible = "rockchip,rk3566"; + }; + ++&pipegrf { ++ compatible = "rockchip,rk3566-pipe-grf", "syscon"; ++}; ++ + &power { + power-domain@RK3568_PD_PIPE { + reg = ; +@@ -18,3 +22,10 @@ + #power-domain-cells = <0>; + }; + }; ++ ++&usb_host0_xhci { ++ phys = <&usb2phy0_otg>; ++ phy-names = "usb2-phy"; ++ extcon = <&usb2phy0>; ++ maximum-speed = "high-speed"; ++}; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -113,6 +113,10 @@ + }; + }; + ++&pipegrf { ++ compatible = "rockchip,rk3568-pipe-grf", "syscon"; ++}; ++ + &power { + power-domain@RK3568_PD_PIPE { + reg = ; +@@ -128,3 +132,8 @@ + #power-domain-cells = <0>; + }; + }; ++ ++&usb_host0_xhci { ++ phys = <&usb2phy0_otg>, <&combphy0 PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++}; +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -258,6 +258,40 @@ + status = "disabled"; + }; + ++ usb_host0_xhci: usb@fcc00000 { ++ compatible = "rockchip,rk3568-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfcc00000 0x0 0x400000>; ++ interrupts = ; ++ clocks = <&cru CLK_USB3OTG0_REF>, <&cru CLK_USB3OTG0_SUSPEND>, ++ <&cru ACLK_USB3OTG0>; ++ clock-names = "ref_clk", "suspend_clk", ++ "bus_clk"; ++ dr_mode = "host"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG0>; ++ snps,dis_u2_susphy_quirk; ++ status = "disabled"; ++ }; ++ ++ usb_host1_xhci: usb@fd000000 { ++ compatible = "rockchip,rk3568-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfd000000 0x0 0x400000>; ++ interrupts = ; ++ clocks = <&cru CLK_USB3OTG1_REF>, <&cru CLK_USB3OTG1_SUSPEND>, ++ <&cru ACLK_USB3OTG1>; ++ clock-names = "ref_clk", "suspend_clk", ++ "bus_clk"; ++ dr_mode = "host"; ++ phys = <&usb2phy0_host>, <&combphy1 PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ resets = <&cru SRST_USB3OTG1>; ++ snps,dis_u2_susphy_quirk; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@fd400000 { + compatible = "arm,gic-v3"; + reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ +@@ -325,7 +359,6 @@ + }; + + pipegrf: syscon@fdc50000 { +- compatible = "rockchip,rk3568-pipe-grf", "syscon"; + reg = <0x0 0xfdc50000 0x0 0x1000>; + }; + diff --git a/target/linux/rockchip/patches-5.18/114-rockchip-enable-dwc3-on-quartz64-a.patch b/target/linux/rockchip/patches-5.18/114-rockchip-enable-dwc3-on-quartz64-a.patch new file mode 100644 index 000000000..ed55eebc9 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/114-rockchip-enable-dwc3-on-quartz64-a.patch @@ -0,0 +1,78 @@ +From e432309ff8bf2a148bbdd4946ca1580c6b5b610c Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 8 Apr 2022 11:12:36 -0400 +Subject: arm64: dts: rockchip: enable dwc3 on quartz64-a + +The quartz64 model a has support for both the dwc3 otg port and the dwc3 +host port. Add the otg power supply and dwc3 nodes to the device tree to +enable support for these. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220408151237.3165046-5-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 37 ++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +(limited to 'arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts') + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -151,6 +151,16 @@ + vin-supply = <&vcc5v0_usb>; + }; + ++ vcc5v0_usb20_otg: vcc5v0_usb20_otg { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vcc5v0_usb20_otg"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dcdc_boost>; ++ }; ++ + vcc3v3_sd: vcc3v3_sd { + compatible = "regulator-fixed"; + enable-active-low; +@@ -187,6 +197,10 @@ + }; + }; + ++&combphy1 { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <&vdd_cpu>; + }; +@@ -672,6 +686,29 @@ + status = "okay"; + }; + ++&usb_host0_xhci { ++ status = "okay"; ++}; ++ ++/* usb3 controller is muxed with sata1 */ ++&usb_host1_xhci { ++ status = "okay"; ++}; ++ ++&usb2phy0 { ++ status = "okay"; ++}; ++ ++&usb2phy0_host { ++ phy-supply = <&vcc5v0_usb20_host>; ++ status = "okay"; ++}; ++ ++&usb2phy0_otg { ++ phy-supply = <&vcc5v0_usb20_otg>; ++ status = "okay"; ++}; ++ + &usb2phy1 { + status = "okay"; + }; diff --git a/target/linux/rockchip/patches-5.18/115-soc-rockchip-set-dwc3-clock-for-rk3566.patch b/target/linux/rockchip/patches-5.18/115-soc-rockchip-set-dwc3-clock-for-rk3566.patch new file mode 100644 index 000000000..979daa417 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/115-soc-rockchip-set-dwc3-clock-for-rk3566.patch @@ -0,0 +1,49 @@ +From 8c3089f4a9e38f73baa68f0b3cbec667ff09c0dd Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 25 Feb 2022 09:16:51 -0500 +Subject: [PATCH] soc: rockchip: set dwc3 clock for rk3566 + +The rk3566 dwc3 otg port clock is unavailable at boot, as it defaults to +the combophy as the clock source. As combophy0 doesn't exist on rk3566, +we need to set the clock source to the usb2 phy instead. + +Add handling to the grf driver to handle this on boot. + +Signed-off-by: Peter Geis +--- + drivers/soc/rockchip/grf.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/soc/rockchip/grf.c ++++ b/drivers/soc/rockchip/grf.c +@@ -108,6 +108,20 @@ static const struct rockchip_grf_info rk + .num_values = ARRAY_SIZE(rk3399_defaults), + }; + ++#define RK3566_GRF_USB3OTG0_CON1 0x0104 ++ ++static const struct rockchip_grf_value rk3566_defaults[] __initconst = { ++ { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, ++ { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, ++ { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, ++}; ++ ++static const struct rockchip_grf_info rk3566_pipegrf __initconst = { ++ .values = rk3566_defaults, ++ .num_values = ARRAY_SIZE(rk3566_defaults), ++}; ++ ++ + static const struct of_device_id rockchip_grf_dt_match[] __initconst = { + { + .compatible = "rockchip,rk3036-grf", +@@ -130,6 +144,9 @@ static const struct of_device_id rockchi + }, { + .compatible = "rockchip,rk3399-grf", + .data = (void *)&rk3399_grf, ++ }, { ++ .compatible = "rockchip,rk3566-pipe-grf", ++ .data = (void *)&rk3566_pipegrf, + }, + { /* sentinel */ }, + }; diff --git a/target/linux/rockchip/patches-5.18/116-dt-bindings-PCI-Remove-fallback-from-Rockchip-DesignWare-binding.patch b/target/linux/rockchip/patches-5.18/116-dt-bindings-PCI-Remove-fallback-from-Rockchip-DesignWare-binding.patch new file mode 100644 index 000000000..2dcf9403e --- /dev/null +++ b/target/linux/rockchip/patches-5.18/116-dt-bindings-PCI-Remove-fallback-from-Rockchip-DesignWare-binding.patch @@ -0,0 +1,46 @@ +Subject: [PATCH] dt-bindings: PCI: Remove fallback from Rockchip DesignWare binding + +The snps,dw-pcie binds to a standalone driver. It is not fully +compatible with the Rockchip implementation and causes a hang if it +binds to the device. + +Remove this binding as a valid fallback. + +Signed-off-by: Peter Geis +Reviewed-by: Rob Herring +--- + .../devicetree/bindings/pci/rockchip-dw-pcie.yaml | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) +--- +--- a/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/rockchip-dw-pcie.yaml +@@ -19,20 +19,10 @@ description: |+ + allOf: + - $ref: /schemas/pci/pci-bus.yaml# + +-# We need a select here so we don't match all nodes with 'snps,dw-pcie' +-select: +- properties: +- compatible: +- contains: +- const: rockchip,rk3568-pcie +- required: +- - compatible +- + properties: + compatible: + items: + - const: rockchip,rk3568-pcie +- - const: snps,dw-pcie + + reg: + items: +@@ -110,7 +100,7 @@ examples: + #size-cells = <2>; + + pcie3x2: pcie@fe280000 { +- compatible = "rockchip,rk3568-pcie", "snps,dw-pcie"; ++ compatible = "rockchip,rk3568-pcie"; + reg = <0x3 0xc0800000 0x0 0x390000>, + <0x0 0xfe280000 0x0 0x10000>, + <0x3 0x80000000 0x0 0x100000>; diff --git a/target/linux/rockchip/patches-5.18/117-03arm64-dts-rockchip-Add-USB-nodes-for-BPI-R2-Pro.patch b/target/linux/rockchip/patches-5.18/117-03arm64-dts-rockchip-Add-USB-nodes-for-BPI-R2-Pro.patch new file mode 100644 index 000000000..61248a114 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/117-03arm64-dts-rockchip-Add-USB-nodes-for-BPI-R2-Pro.patch @@ -0,0 +1,127 @@ +From f29ffce32b4e1204b67f82fd80584ec4173cca54 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 9 Apr 2022 13:21:35 +0200 +Subject: [PATCH] arm64: dts: rockchip: Add USB nodes for BPI-R2-Pro + +Add usb2 nodes to Bananapi R2 Pro board + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220409112136.164481-2-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + .../boot/dts/rockchip/rk3568-bpi-r2-pro.dts | 93 +++++++++++++++++++ + 1 file changed, 93 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts +@@ -73,6 +73,50 @@ + regulator-max-microvolt = <5000000>; + vin-supply = <&dc_12v>; + }; ++ ++ vcc5v0_usb: vcc5v0_usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dc_12v>; ++ }; ++ ++ vcc5v0_usb_host: vcc5v0-usb-host { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_host_en>; ++ regulator-name = "vcc5v0_usb_host"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ ++ vcc5v0_usb_otg: vcc5v0-usb-otg { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_otg_en>; ++ regulator-name = "vcc5v0_usb_otg"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&combphy0 { ++ /* used for USB3 */ ++ status = "okay"; ++}; ++ ++&combphy1 { ++ /* used for USB3 */ ++ status = "okay"; + }; + + &gmac0 { +@@ -368,6 +412,16 @@ + <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; ++ ++ usb { ++ vcc5v0_usb_host_en: vcc5v0_usb_host_en { ++ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; + }; + + &pmu_io_domains { +@@ -485,3 +539,42 @@ + pinctrl-0 = <&uart9m1_xfer>; + status = "disabled"; + }; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host0_xhci { ++ extcon = <&usb2phy0>; ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_xhci { ++ status = "okay"; ++}; ++ ++&usb2phy0 { ++ status = "okay"; ++}; ++ ++&usb2phy0_host { ++ phy-supply = <&vcc5v0_usb_host>; ++ status = "okay"; ++}; ++ ++&usb2phy0_otg { ++ phy-supply = <&vcc5v0_usb_otg>; ++ status = "okay"; ++}; diff --git a/target/linux/rockchip/patches-5.18/117-04-arm64-dts-rockchip-Add-SATAsupport-to-BPI-R2-Pro.patch b/target/linux/rockchip/patches-5.18/117-04-arm64-dts-rockchip-Add-SATAsupport-to-BPI-R2-Pro.patch new file mode 100644 index 000000000..a4478a30f --- /dev/null +++ b/target/linux/rockchip/patches-5.18/117-04-arm64-dts-rockchip-Add-SATAsupport-to-BPI-R2-Pro.patch @@ -0,0 +1,39 @@ +From 551e645fed5dd2ed4c81c9e3d3b4827862f51dc6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 9 Apr 2022 13:21:36 +0200 +Subject: [PATCH] arm64: dts: rockchip: Add SATA support to BPI-R2-Pro + +Enable the Combphy and Sata nodes in Bananapi R2 Pro Board. + +Signed-off-by: Frank Wunderlich +Link: https://lore.kernel.org/r/20220409112136.164481-3-linux@fw-web.de +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts +@@ -119,6 +119,11 @@ + status = "okay"; + }; + ++&combphy2 { ++ /* used for SATA */ ++ status = "okay"; ++}; ++ + &gmac0 { + assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; + assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>; +@@ -484,6 +489,10 @@ + status = "okay"; + }; + ++&sata2 { ++ status = "okay"; ++}; ++ + &sdhci { + bus-width = <8>; + max-frequency = <200000000>; diff --git a/target/linux/rockchip/patches-5.18/117-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch b/target/linux/rockchip/patches-5.18/117-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch new file mode 100644 index 000000000..12138e89c --- /dev/null +++ b/target/linux/rockchip/patches-5.18/117-PCI-rockchip-dwc-Reset-core-at-driver-probe.patch @@ -0,0 +1,66 @@ +Subject: [PATCH] PCI: rockchip-dwc: Reset core at driver probe +The PCIe controller is in an unknown state at driver probe. This can +lead to undesireable effects when the driver attempts to configure the +controller. + +Prevent issues in the future by resetting the core during probe. + +Signed-off-by: Peter Geis +Tested-by: Nicolas Frattaroli +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 23 ++++++++----------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -152,6 +152,11 @@ static int rockchip_pcie_resource_get(st + if (IS_ERR(rockchip->rst_gpio)) + return PTR_ERR(rockchip->rst_gpio); + ++ rockchip->rst = devm_reset_control_array_get_exclusive(&pdev->dev); ++ if (IS_ERR(rockchip->rst)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(rockchip->rst), ++ "failed to get reset lines\n"); ++ + return 0; + } + +@@ -182,18 +187,6 @@ static void rockchip_pcie_phy_deinit(str + phy_power_off(rockchip->phy); + } + +-static int rockchip_pcie_reset_control_release(struct rockchip_pcie *rockchip) +-{ +- struct device *dev = rockchip->pci.dev; +- +- rockchip->rst = devm_reset_control_array_get_exclusive(dev); +- if (IS_ERR(rockchip->rst)) +- return dev_err_probe(dev, PTR_ERR(rockchip->rst), +- "failed to get reset lines\n"); +- +- return reset_control_deassert(rockchip->rst); +-} +- + static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = rockchip_pcie_link_up, + .start_link = rockchip_pcie_start_link, +@@ -222,6 +215,10 @@ static int rockchip_pcie_probe(struct pl + if (ret) + return ret; + ++ ret = reset_control_assert(rockchip->rst); ++ if (ret) ++ return ret; ++ + /* DON'T MOVE ME: must be enable before PHY init */ + rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); + if (IS_ERR(rockchip->vpcie3v3)) { +@@ -241,7 +238,7 @@ static int rockchip_pcie_probe(struct pl + if (ret) + goto disable_regulator; + +- ret = rockchip_pcie_reset_control_release(rockchip); ++ ret = reset_control_deassert(rockchip->rst); + if (ret) + goto deinit_phy; + diff --git a/target/linux/rockchip/patches-5.18/118-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch b/target/linux/rockchip/patches-5.18/118-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch new file mode 100644 index 000000000..b413ead7f --- /dev/null +++ b/target/linux/rockchip/patches-5.18/118-PCI-rockchip-dwc-Add-legacy-interrupt-support.patch @@ -0,0 +1,155 @@ +Subject: [PATCH] PCI: rockchip-dwc: Add legacy interrupt support +The legacy interrupts on the rk356x PCIe controller are handled by a +single muxed interrupt. Add IRQ domain support to the pcie-dw-rockchip +driver to support the virtual domain. + +Signed-off-by: Peter Geis +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 96 ++++++++++++++++++- + 1 file changed, 94 insertions(+), 2 deletions(-) +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -10,9 +10,12 @@ + + #include + #include ++#include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -26,6 +29,7 @@ + */ + #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) + #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) ++#define HIWORD_DISABLE_BIT(val) HIWORD_UPDATE(val, ~val) + + #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) + +@@ -36,10 +40,12 @@ + #define PCIE_LINKUP (PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP) + #define PCIE_L0S_ENTRY 0x11 + #define PCIE_CLIENT_GENERAL_CONTROL 0x0 ++#define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8 ++#define PCIE_CLIENT_INTR_MASK_LEGACY 0x1c + #define PCIE_CLIENT_GENERAL_DEBUG 0x104 +-#define PCIE_CLIENT_HOT_RESET_CTRL 0x180 ++#define PCIE_CLIENT_HOT_RESET_CTRL 0x180 + #define PCIE_CLIENT_LTSSM_STATUS 0x300 +-#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) ++#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) + #define PCIE_LTSSM_STATUS_MASK GENMASK(5, 0) + + struct rockchip_pcie { +@@ -51,6 +57,7 @@ struct rockchip_pcie { + struct reset_control *rst; + struct gpio_desc *rst_gpio; + struct regulator *vpcie3v3; ++ struct irq_domain *irq_domain; + }; + + static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, +@@ -65,6 +72,78 @@ static void rockchip_pcie_writel_apb(str + writel_relaxed(val, rockchip->apb_base + reg); + } + ++static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct rockchip_pcie *rockchip = irq_desc_get_handler_data(desc); ++ unsigned long reg, hwirq; ++ ++ chained_irq_enter(chip, desc); ++ ++ reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_LEGACY); ++ ++ for_each_set_bit(hwirq, ®, 4) ++ generic_handle_domain_irq(rockchip->irq_domain, hwirq); ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static void rockchip_intx_mask(struct irq_data *data) ++{ ++ rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), ++ HIWORD_UPDATE_BIT(BIT(data->hwirq)), ++ PCIE_CLIENT_INTR_MASK_LEGACY); ++}; ++ ++static void rockchip_intx_unmask(struct irq_data *data) ++{ ++ rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), ++ HIWORD_DISABLE_BIT(BIT(data->hwirq)), ++ PCIE_CLIENT_INTR_MASK_LEGACY); ++}; ++ ++static struct irq_chip rockchip_intx_irq_chip = { ++ .name = "INTx", ++ .irq_mask = rockchip_intx_mask, ++ .irq_unmask = rockchip_intx_unmask, ++ .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, ++}; ++ ++static int rockchip_pcie_intx_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_and_handler(irq, &rockchip_intx_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, domain->host_data); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops intx_domain_ops = { ++ .map = rockchip_pcie_intx_map, ++}; ++ ++static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip) ++{ ++ struct device *dev = rockchip->pci.dev; ++ struct device_node *intc; ++ ++ intc = of_get_child_by_name(dev->of_node, "legacy-interrupt-controller"); ++ if (!intc) { ++ dev_err(dev, "missing child interrupt-controller node\n"); ++ return -EINVAL; ++ } ++ ++ rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX, ++ &intx_domain_ops, rockchip); ++ of_node_put(intc); ++ if (!rockchip->irq_domain) { ++ dev_err(dev, "failed to get a INTx IRQ domain\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip) + { + rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM, +@@ -111,7 +190,20 @@ static int rockchip_pcie_host_init(struc + { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct rockchip_pcie *rockchip = to_rockchip_pcie(pci); ++ struct device *dev = rockchip->pci.dev; + u32 val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); ++ int irq, ret; ++ ++ irq = of_irq_get_byname(dev->of_node, "legacy"); ++ if (irq < 0) ++ return irq; ++ ++ ret = rockchip_pcie_init_irq_domain(rockchip); ++ if (ret < 0) ++ dev_err(dev, "failed to init irq domain\n"); ++ ++ irq_set_chained_handler_and_data(irq, rockchip_pcie_legacy_int_handler, ++ rockchip); + + /* LTSSM enable control mode */ + rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); diff --git a/target/linux/rockchip/patches-5.18/119-arm64-dts-rockchip-Add-rk3568-PCIe2x1-controller.patch b/target/linux/rockchip/patches-5.18/119-arm64-dts-rockchip-Add-rk3568-PCIe2x1-controller.patch new file mode 100644 index 000000000..3804db1d2 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/119-arm64-dts-rockchip-Add-rk3568-PCIe2x1-controller.patch @@ -0,0 +1,69 @@ +Subject: [PATCH] arm64: dts: rockchip: Add rk3568 PCIe2x1 controller +The PCIe2x1 controller is common between the rk3568 and rk3566. It is a +single lane PCIe2 compliant controller. + +Signed-off-by: Peter Geis +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++ + 1 file changed, 52 insertions(+) +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -750,6 +750,58 @@ + reg = <0x0 0xfe1a8100 0x0 0x20>; + }; + ++ pcie2x1: pcie@fe260000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0xf>; ++ clocks = <&cru ACLK_PCIE20_MST>, <&cru ACLK_PCIE20_SLV>, ++ <&cru ACLK_PCIE20_DBI>, <&cru PCLK_PCIE20>, ++ <&cru CLK_PCIE20_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msi", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc 0>, ++ <0 0 0 2 &pcie_intc 1>, ++ <0 0 0 3 &pcie_intc 2>, ++ <0 0 0 4 &pcie_intc 3>; ++ linux,pci-domain = <0>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <2>; ++ msi-map = <0x0 &gic 0x0 0x1000>; ++ num-lanes = <1>; ++ phys = <&combphy2 PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0000000 0x0 0x00400000>, ++ <0x0 0xfe260000 0x0 0x00010000>, ++ <0x3 0x00000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x01000000 0x3 0x01000000 0x0 0x00100000 ++ 0x02000000 0x0 0x02000000 0x3 0x01100000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE20_POWERUP>; ++ reset-names = "pipe"; ++ status = "disabled"; ++ ++ pcie_intc: legacy-interrupt-controller { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ ++ }; ++ + sdmmc0: mmc@fe2b0000 { + compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe2b0000 0x0 0x4000>; diff --git a/target/linux/rockchip/patches-5.18/120-arm64-dts-rockchip-Enable-PCIe-controller-on-quartz64-a.patch b/target/linux/rockchip/patches-5.18/120-arm64-dts-rockchip-Enable-PCIe-controller-on-quartz64-a.patch new file mode 100644 index 000000000..84f345c5d --- /dev/null +++ b/target/linux/rockchip/patches-5.18/120-arm64-dts-rockchip-Enable-PCIe-controller-on-quartz64-a.patch @@ -0,0 +1,75 @@ +Subject: [PATCH] arm64: dts: rockchip: Enable PCIe controller on quartz64-a +Add the nodes to enable the PCIe controller on the Quartz64 Model A +board. + +Signed-off-by: Peter Geis +--- + .../boot/dts/rockchip/rk3566-quartz64-a.dts | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + + + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -125,6 +125,18 @@ + vin-supply = <&vcc12v_dcin>; + }; + ++ vcc3v3_pcie_p: vcc3v3_pcie_p { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_enable_h>; ++ regulator-name = "vcc3v3_pcie_p"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3>; ++ }; ++ + vcc5v0_usb: vcc5v0_usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; +@@ -201,6 +213,10 @@ + status = "okay"; + }; + ++&combphy2 { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <&vdd_cpu>; + }; +@@ -509,6 +525,14 @@ + }; + }; + ++&pcie2x1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_reset_h>; ++ reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; ++ vpcie3v3-supply = <&vcc3v3_pcie_p>; ++ status = "okay"; ++}; ++ + &pinctrl { + bt { + bt_enable_h: bt-enable-h { +@@ -534,6 +558,16 @@ + }; + }; + ++ pcie { ++ pcie_enable_h: pcie-enable-h { ++ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ pcie_reset_h: pcie-reset-h { ++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; diff --git a/target/linux/rockchip/patches-5.18/121-arm64-dts-rockchip-add-rk356x-sfc-support.patch b/target/linux/rockchip/patches-5.18/121-arm64-dts-rockchip-add-rk356x-sfc-support.patch new file mode 100644 index 000000000..5f91000d8 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/121-arm64-dts-rockchip-add-rk356x-sfc-support.patch @@ -0,0 +1,35 @@ +From 13e0ee34f39c01948a7bbaab0b3c225d9b00a5bb Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Fri, 29 Apr 2022 07:52:49 -0400 +Subject: [PATCH] arm64: dts: rockchip: add rk356x sfc support + +Add the sfc node to the rk356x device tree. This enables spi flash +support for this soc. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220429115252.2360496-5-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -830,6 +830,17 @@ + status = "disabled"; + }; + ++ sfc: spi@fe300000 { ++ compatible = "rockchip,sfc"; ++ reg = <0x0 0xfe300000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; ++ clock-names = "clk_sfc", "hclk_sfc"; ++ pinctrl-0 = <&fspi_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ }; ++ + sdhci: mmc@fe310000 { + compatible = "rockchip,rk3568-dwcmshc"; + reg = <0x0 0xfe310000 0x0 0x10000>; diff --git a/target/linux/rockchip/patches-5.18/219-arm64-dts-rockchip-enable-otg-drd-operation-of-usb_h.patch b/target/linux/rockchip/patches-5.18/219-arm64-dts-rockchip-enable-otg-drd-operation-of-usb_h.patch new file mode 100644 index 000000000..85bb462e1 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/219-arm64-dts-rockchip-enable-otg-drd-operation-of-usb_h.patch @@ -0,0 +1,27 @@ +From 72bac38408c6fbbc8af77f62e6f528c4b1cb5d98 Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Mon, 25 Apr 2022 15:35:00 +0200 +Subject: [PATCH 19/50] arm64: dts: rockchip: enable otg/drd operation of + usb_host0_xhci in rk356x + +This USB 3.0 controller is capable of OTG/DRD operation. Enable it in the +device tree. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20220425133502.405512-1-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -266,7 +266,7 @@ + <&cru ACLK_USB3OTG0>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk"; +- dr_mode = "host"; ++ dr_mode = "otg"; + phy_type = "utmi_wide"; + power-domains = <&power RK3568_PD_PIPE>; + resets = <&cru SRST_USB3OTG0>; diff --git a/target/linux/rockchip/patches-5.18/220-arm64-dts-rockchip-add-clocks-to-rk356x-cru.patch b/target/linux/rockchip/patches-5.18/220-arm64-dts-rockchip-add-clocks-to-rk356x-cru.patch new file mode 100644 index 000000000..b88467501 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/220-arm64-dts-rockchip-add-clocks-to-rk356x-cru.patch @@ -0,0 +1,26 @@ +From fbdfb63842751de7d32202542c25410e0f42688f Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:13 -0400 +Subject: [PATCH 20/50] arm64: dts: rockchip: add clocks to rk356x cru + +The rk356x cru requires a 24m clock input to function. Add the clocks +properties to the cru to clear some dtbs_check warnings. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220511150117.113070-3-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -397,6 +397,8 @@ + cru: clock-controller@fdd20000 { + compatible = "rockchip,rk3568-cru"; + reg = <0x0 0xfdd20000 0x0 0x1000>; ++ clocks = <&xin24m>; ++ clock-names = "xin24m"; + #clock-cells = <1>; + #reset-cells = <1>; + assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>; diff --git a/target/linux/rockchip/patches-5.18/221-arm64-dts-rockchip-rename-Quartz64-A-bluetooth-gpios.patch b/target/linux/rockchip/patches-5.18/221-arm64-dts-rockchip-rename-Quartz64-A-bluetooth-gpios.patch new file mode 100644 index 000000000..fa33be105 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/221-arm64-dts-rockchip-rename-Quartz64-A-bluetooth-gpios.patch @@ -0,0 +1,29 @@ +From 319683942f42e6857535b9c5d0392dec193d72b4 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:14 -0400 +Subject: [PATCH 21/50] arm64: dts: rockchip: rename Quartz64-A bluetooth gpios + +The bluetooth binding for the Quartz64 Model A has incorrectly named +host-wakeup and device-wakeup gpios. Rename them to clear some dtbs_check +warnings. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220511150117.113070-4-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -686,8 +686,8 @@ + compatible = "brcm,bcm43438-bt"; + clocks = <&rk817 1>; + clock-names = "lpo"; +- device-wake-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; +- host-wake-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; ++ device-wakeup-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; ++ host-wakeup-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; + shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>; diff --git a/target/linux/rockchip/patches-5.18/222-arm64-dts-rockchip-add-Quartz64-A-fan-pinctrl.patch b/target/linux/rockchip/patches-5.18/222-arm64-dts-rockchip-add-Quartz64-A-fan-pinctrl.patch new file mode 100644 index 000000000..42c0dc209 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/222-arm64-dts-rockchip-add-Quartz64-A-fan-pinctrl.patch @@ -0,0 +1,39 @@ +From 29347ccca4124943160073419bcf581f74d8a722 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:15 -0400 +Subject: [PATCH 22/50] arm64: dts: rockchip: add Quartz64-A fan pinctrl + +The Quartz64 Model A fan is bound to a single gpio. Prevent pinctrl +issues in the future by binding the pinctrl assignment for the gpio. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220511150117.113070-5-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -32,6 +32,8 @@ + gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <0 0 + 4500 1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fan_en_h>; + #cooling-cells = <2>; + }; + +@@ -548,6 +550,12 @@ + }; + }; + ++ fan { ++ fan_en_h: fan-en-h { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + leds { + work_led_enable_h: work-led-enable-h { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/target/linux/rockchip/patches-5.18/223-arm64-dts-rockchip-enable-sdr-104-for-sdmmc-on-Quart.patch b/target/linux/rockchip/patches-5.18/223-arm64-dts-rockchip-enable-sdr-104-for-sdmmc-on-Quart.patch new file mode 100644 index 000000000..2e7d38817 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/223-arm64-dts-rockchip-enable-sdr-104-for-sdmmc-on-Quart.patch @@ -0,0 +1,32 @@ +From 8fd0ad58558f01b7b3bef42659dd94b6fa2c3aa7 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:16 -0400 +Subject: [PATCH 23/50] arm64: dts: rockchip: enable sdr-104 for sdmmc on + Quartz A + +Now that we have working io-domain support, we can enable higher date +rates on the sdmmc card. + +Before: +Timing buffered disk reads: 68 MB in 3.08 seconds = 22.07 MB/sec + +After: +Timing buffered disk reads: 188 MB in 3.02 seconds = 62.29 MB/sec + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220511150117.113070-6-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -630,6 +630,7 @@ + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; ++ sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; diff --git a/target/linux/rockchip/patches-5.18/224-arm64-dts-rockchip-enable-sfc-controller-on-Quartz64.patch b/target/linux/rockchip/patches-5.18/224-arm64-dts-rockchip-enable-sfc-controller-on-Quartz64.patch new file mode 100644 index 000000000..7795cc8fd --- /dev/null +++ b/target/linux/rockchip/patches-5.18/224-arm64-dts-rockchip-enable-sfc-controller-on-Quartz64.patch @@ -0,0 +1,41 @@ +From 9981e62d40223e6ec7887db0c283ab404c9e9619 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:17 -0400 +Subject: [PATCH 24/50] arm64: dts: rockchip: enable sfc controller on Quartz64 + Model A + +Add the sfc controller binding for the Quartz64 Model A. This is not +populated by default, so leave it disabled. + +Signed-off-by: Peter Geis +Link: https://lore.kernel.org/r/20220511150117.113070-7-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + .../boot/dts/rockchip/rk3566-quartz64-a.dts | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -651,6 +651,22 @@ + status = "okay"; + }; + ++&sfc { ++ pinctrl-0 = <&fspi_pins>; ++ pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ spi-rx-bus-width = <4>; ++ spi-tx-bus-width = <1>; ++ }; ++}; ++ + /* spdif is exposed on con40 pin 18 */ + &spdif { + status = "okay"; diff --git a/target/linux/rockchip/patches-5.18/225-drm-rockchip-Refactor-IOMMU-initialisation.patch b/target/linux/rockchip/patches-5.18/225-drm-rockchip-Refactor-IOMMU-initialisation.patch new file mode 100644 index 000000000..1bbf511df --- /dev/null +++ b/target/linux/rockchip/patches-5.18/225-drm-rockchip-Refactor-IOMMU-initialisation.patch @@ -0,0 +1,201 @@ +From 2ed40a293d246987d6009718cdcb5af73474822f Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Tue, 5 Apr 2022 15:32:50 +0100 +Subject: [PATCH 25/50] drm/rockchip: Refactor IOMMU initialisation + +Defer the IOMMU domain setup until after successfully binding +components, so we can figure out IOMMU support directly from the VOP +devices themselves, rather than manually inferring it from the DT (which +also fails to account for whether the IOMMU driver is actually loaded). +Although this is somewhat of a logical cleanup, the main motivation is +to prepare for a change in the iommu_domain_alloc() interface. + +Signed-off-by: Robin Murphy +--- + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 60 +++++++++------------ + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 ++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 + + 3 files changed, 31 insertions(+), 34 deletions(-) + +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +@@ -7,7 +7,6 @@ + */ + + #include +-#include + #include + #include + #include +@@ -34,7 +33,6 @@ + #define DRIVER_MAJOR 1 + #define DRIVER_MINOR 0 + +-static bool is_support_iommu = true; + static const struct drm_driver rockchip_drm_driver; + + /* +@@ -48,7 +46,7 @@ int rockchip_drm_dma_attach_device(struc + struct rockchip_drm_private *private = drm_dev->dev_private; + int ret; + +- if (!is_support_iommu) ++ if (!private->domain) + return 0; + + ret = iommu_attach_device(private->domain, dev); +@@ -64,12 +62,22 @@ void rockchip_drm_dma_detach_device(stru + struct device *dev) + { + struct rockchip_drm_private *private = drm_dev->dev_private; +- struct iommu_domain *domain = private->domain; + +- if (!is_support_iommu) ++ if (!private->domain) + return; + +- iommu_detach_device(domain, dev); ++ iommu_detach_device(private->domain, dev); ++} ++ ++void rockchip_drm_dma_init_device(struct drm_device *drm_dev, ++ struct device *dev) ++{ ++ struct rockchip_drm_private *private = drm_dev->dev_private; ++ ++ if (!device_iommu_mapped(dev)) ++ private->iommu_dev = ERR_PTR(-ENODEV); ++ else if (!private->iommu_dev) ++ private->iommu_dev = dev; + } + + static int rockchip_drm_init_iommu(struct drm_device *drm_dev) +@@ -78,10 +86,10 @@ static int rockchip_drm_init_iommu(struc + struct iommu_domain_geometry *geometry; + u64 start, end; + +- if (!is_support_iommu) ++ if (IS_ERR_OR_NULL(private->iommu_dev)) + return 0; + +- private->domain = iommu_domain_alloc(&platform_bus_type); ++ private->domain = iommu_domain_alloc(private->iommu_dev->bus); + if (!private->domain) + return -ENOMEM; + +@@ -101,7 +109,7 @@ static void rockchip_iommu_cleanup(struc + { + struct rockchip_drm_private *private = drm_dev->dev_private; + +- if (!is_support_iommu) ++ if (!private->domain) + return; + + drm_mm_takedown(&private->mm); +@@ -137,25 +145,25 @@ static int rockchip_drm_bind(struct devi + + drm_dev->dev_private = private; + +- ret = rockchip_drm_init_iommu(drm_dev); +- if (ret) +- goto err_free; +- + ret = drmm_mode_config_init(drm_dev); + if (ret) +- goto err_iommu_cleanup; ++ goto err_free; + + rockchip_drm_mode_config_init(drm_dev); + + /* Try to bind all sub drivers. */ + ret = component_bind_all(dev, drm_dev); + if (ret) +- goto err_iommu_cleanup; ++ goto err_free; + +- ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); ++ ret = rockchip_drm_init_iommu(drm_dev); + if (ret) + goto err_unbind_all; + ++ ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); ++ if (ret) ++ goto err_iommu_cleanup; ++ + drm_mode_config_reset(drm_dev); + + /* init kms poll for handling hpd */ +@@ -170,10 +178,10 @@ static int rockchip_drm_bind(struct devi + return 0; + err_kms_helper_poll_fini: + drm_kms_helper_poll_fini(drm_dev); +-err_unbind_all: +- component_unbind_all(dev, drm_dev); + err_iommu_cleanup: + rockchip_iommu_cleanup(drm_dev); ++err_unbind_all: ++ component_unbind_all(dev, drm_dev); + err_free: + drm_dev_put(drm_dev); + return ret; +@@ -342,8 +350,6 @@ static int rockchip_drm_platform_of_prob + return -ENODEV; + + for (i = 0;; i++) { +- struct device_node *iommu; +- + port = of_parse_phandle(np, "ports", i); + if (!port) + break; +@@ -353,21 +359,7 @@ static int rockchip_drm_platform_of_prob + continue; + } + +- iommu = of_parse_phandle(port->parent, "iommus", 0); +- if (!iommu || !of_device_is_available(iommu)) { +- DRM_DEV_DEBUG(dev, +- "no iommu attached for %pOF, using non-iommu buffers\n", +- port->parent); +- /* +- * if there is a crtc not support iommu, force set all +- * crtc use non-iommu buffer. +- */ +- is_support_iommu = false; +- } +- + found = true; +- +- of_node_put(iommu); + of_node_put(port); + } + +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -44,6 +44,7 @@ struct rockchip_crtc_state { + */ + struct rockchip_drm_private { + struct iommu_domain *domain; ++ struct device *iommu_dev; + struct mutex mm_lock; + struct drm_mm mm; + }; +@@ -52,6 +53,8 @@ int rockchip_drm_dma_attach_device(struc + struct device *dev); + void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, + struct device *dev); ++void rockchip_drm_dma_init_device(struct drm_device *drm_dev, ++ struct device *dev); + int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout); + + int rockchip_drm_endpoint_is_subdriver(struct device_node *ep); +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -2175,6 +2175,8 @@ static int vop_bind(struct device *dev, + } + } + ++ rockchip_drm_dma_init_device(drm_dev, dev); ++ + return 0; + + err_disable_pm_runtime: diff --git a/target/linux/rockchip/patches-5.18/226-clk-rk3568-Mark-hclk_vo-as-critical.patch b/target/linux/rockchip/patches-5.18/226-clk-rk3568-Mark-hclk_vo-as-critical.patch new file mode 100644 index 000000000..bf96d00fe --- /dev/null +++ b/target/linux/rockchip/patches-5.18/226-clk-rk3568-Mark-hclk_vo-as-critical.patch @@ -0,0 +1,63 @@ +From 2028e2bad127e43bee0bed0b2c7ce39745366b88 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:15 +0200 +Subject: [PATCH 26/50] clk: rk3568: Mark hclk_vo as critical + +Whenever pclk_vo is enabled hclk_vo must be enabled as well. This is +described in the Reference Manual as: + +| 2.8.6 NIU Clock gating reliance +| +| A part of niu clocks have a dependence on another niu clock in order to +| sharing the internal bus. When these clocks are in use, another niu +| clock must be opened, and cannot be gated. These clocks and the special +| clock on which they are relied are as following: +| +| Clocks which have dependency The clock which can not be gated +| ----------------------------------------------------------------- +| ... +| pclk_vo_niu, hclk_vo_s_niu hclk_vo_niu +| ... + +The clock framework doesn't offer a way to enable clock B whenever clock A is +enabled, at least not when B is not an ancestor of A. Workaround this by +marking hclk_vo as critical so it is never disabled. This is suboptimal in +terms of power consumption, but a stop gap solution until the clock framework +has a way to deal with this. + +We have this clock tree: + +| aclk_vo 2 2 0 300000000 0 0 50000 Y +| aclk_hdcp 0 0 0 300000000 0 0 50000 N +| pclk_vo 2 3 0 75000000 0 0 50000 Y +| pclk_edp_ctrl 0 0 0 75000000 0 0 50000 N +| pclk_dsitx_1 0 0 0 75000000 0 0 50000 N +| pclk_dsitx_0 1 2 0 75000000 0 0 50000 Y +| pclk_hdmi_host 1 2 0 75000000 0 0 50000 Y +| pclk_hdcp 0 0 0 75000000 0 0 50000 N +| hclk_vo 2 5 0 150000000 0 0 50000 Y +| hclk_hdcp 0 0 0 150000000 0 0 50000 N +| hclk_vop 0 2 0 150000000 0 0 50000 N + +Without this patch the edp, dsitx, hdmi and hdcp driver would enable their +clocks which then enables pclk_vo, but hclk_vo stays disabled and register +accesses just hang. hclk_vo is enabled by the VOP2 driver, so reproducibility +of this issue depends on the probe order. + +Signed-off-by: Sascha Hauer +Reviewed-by: Dmitry Osipenko +Reviewed-by: Robin Murphy +--- + drivers/clk/rockchip/clk-rk3568.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/clk/rockchip/clk-rk3568.c ++++ b/drivers/clk/rockchip/clk-rk3568.c +@@ -1591,6 +1591,7 @@ static const char *const rk3568_cru_crit + "hclk_php", + "pclk_php", + "hclk_usb", ++ "hclk_vo", + }; + + static const char *const rk3568_pmucru_critical_clocks[] __initconst = { diff --git a/target/linux/rockchip/patches-5.18/227-drm-rockchip-Embed-drm_encoder-into-rockchip_decoder.patch b/target/linux/rockchip/patches-5.18/227-drm-rockchip-Embed-drm_encoder-into-rockchip_decoder.patch new file mode 100644 index 000000000..753f1b8c0 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/227-drm-rockchip-Embed-drm_encoder-into-rockchip_decoder.patch @@ -0,0 +1,598 @@ +From de2c94373a27286225543c0bbe6d00950c568963 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:16 +0200 +Subject: [PATCH 27/50] drm/rockchip: Embed drm_encoder into rockchip_decoder + +The VOP2 driver needs rockchip specific information for a drm_encoder. + +This patch creates a struct rockchip_encoder with a struct drm_encoder +embedded in it. This is used throughout the rockchip driver instead of +struct drm_encoder directly. + +The information the VOP2 drivers needs is the of_graph endpoint node +of the encoder. To ease bisectability this is added here. + +While at it convert the different encoder-to-driverdata macros to +static inline functions in order to gain type safety and readability. + +Signed-off-by: Sascha Hauer +--- + .../gpu/drm/rockchip/analogix_dp-rockchip.c | 32 +++++++++++------ + drivers/gpu/drm/rockchip/cdn-dp-core.c | 18 ++++++---- + drivers/gpu/drm/rockchip/cdn-dp-core.h | 2 +- + .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 17 ++++++---- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 ++++-- + drivers/gpu/drm/rockchip/inno_hdmi.c | 32 +++++++++++------ + drivers/gpu/drm/rockchip/rk3066_hdmi.c | 34 ++++++++++++------- + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 10 ++++++ + drivers/gpu/drm/rockchip/rockchip_lvds.c | 26 ++++++++------ + 9 files changed, 122 insertions(+), 60 deletions(-) + +--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c ++++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +@@ -40,8 +40,6 @@ + + #define PSR_WAIT_LINE_FLAG_TIMEOUT_MS 100 + +-#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm) +- + /** + * struct rockchip_dp_chip_data - splite the grf setting of kind of chips + * @lcdsel_grf_reg: grf register offset of lcdc select +@@ -59,7 +57,7 @@ struct rockchip_dp_chip_data { + struct rockchip_dp_device { + struct drm_device *drm_dev; + struct device *dev; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + struct drm_display_mode mode; + + struct clk *pclk; +@@ -73,6 +71,18 @@ struct rockchip_dp_device { + struct analogix_dp_plat_data plat_data; + }; + ++static struct rockchip_dp_device *encoder_to_dp(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct rockchip_dp_device, encoder); ++} ++ ++static struct rockchip_dp_device *pdata_encoder_to_dp(struct analogix_dp_plat_data *plat_data) ++{ ++ return container_of(plat_data, struct rockchip_dp_device, plat_data); ++} ++ + static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) + { + reset_control_assert(dp->rst); +@@ -84,7 +94,7 @@ static int rockchip_dp_pre_init(struct r + + static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data) + { +- struct rockchip_dp_device *dp = to_dp(plat_data); ++ struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data); + int ret; + + ret = clk_prepare_enable(dp->pclk); +@@ -105,7 +115,7 @@ static int rockchip_dp_poweron_start(str + + static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) + { +- struct rockchip_dp_device *dp = to_dp(plat_data); ++ struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data); + + clk_disable_unprepare(dp->pclk); + +@@ -166,7 +176,7 @@ struct drm_crtc *rockchip_dp_drm_get_new + static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) + { +- struct rockchip_dp_device *dp = to_dp(encoder); ++ struct rockchip_dp_device *dp = encoder_to_dp(encoder); + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int ret; +@@ -208,7 +218,7 @@ static void rockchip_dp_drm_encoder_enab + static void rockchip_dp_drm_encoder_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) + { +- struct rockchip_dp_device *dp = to_dp(encoder); ++ struct rockchip_dp_device *dp = encoder_to_dp(encoder); + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state = NULL; + int ret; +@@ -297,7 +307,7 @@ static int rockchip_dp_of_probe(struct r + + static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp) + { +- struct drm_encoder *encoder = &dp->encoder; ++ struct drm_encoder *encoder = &dp->encoder.encoder; + struct drm_device *drm_dev = dp->drm_dev; + struct device *dev = dp->dev; + int ret; +@@ -333,7 +343,7 @@ static int rockchip_dp_bind(struct devic + return ret; + } + +- dp->plat_data.encoder = &dp->encoder; ++ dp->plat_data.encoder = &dp->encoder.encoder; + + ret = analogix_dp_bind(dp->adp, drm_dev); + if (ret) +@@ -341,7 +351,7 @@ static int rockchip_dp_bind(struct devic + + return 0; + err_cleanup_encoder: +- dp->encoder.funcs->destroy(&dp->encoder); ++ dp->encoder.encoder.funcs->destroy(&dp->encoder.encoder); + return ret; + } + +@@ -351,7 +361,7 @@ static void rockchip_dp_unbind(struct de + struct rockchip_dp_device *dp = dev_get_drvdata(dev); + + analogix_dp_unbind(dp->adp); +- dp->encoder.funcs->destroy(&dp->encoder); ++ dp->encoder.encoder.funcs->destroy(&dp->encoder.encoder); + } + + static const struct component_ops rockchip_dp_component_ops = { +--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c ++++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c +@@ -26,11 +26,17 @@ + #include "cdn-dp-reg.h" + #include "rockchip_drm_vop.h" + +-#define connector_to_dp(c) \ +- container_of(c, struct cdn_dp_device, connector) ++static inline struct cdn_dp_device *connector_to_dp(struct drm_connector *connector) ++{ ++ return container_of(connector, struct cdn_dp_device, connector); ++} + +-#define encoder_to_dp(c) \ +- container_of(c, struct cdn_dp_device, encoder) ++static inline struct cdn_dp_device *encoder_to_dp(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct cdn_dp_device, encoder); ++} + + #define GRF_SOC_CON9 0x6224 + #define DP_SEL_VOP_LIT BIT(12) +@@ -1050,7 +1056,7 @@ static int cdn_dp_bind(struct device *de + + INIT_WORK(&dp->event_work, cdn_dp_pd_event_work); + +- encoder = &dp->encoder; ++ encoder = &dp->encoder.encoder; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, + dev->of_node); +@@ -1115,7 +1121,7 @@ err_free_encoder: + static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) + { + struct cdn_dp_device *dp = dev_get_drvdata(dev); +- struct drm_encoder *encoder = &dp->encoder; ++ struct drm_encoder *encoder = &dp->encoder.encoder; + struct drm_connector *connector = &dp->connector; + + cancel_work_sync(&dp->event_work); +--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h ++++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h +@@ -66,7 +66,7 @@ struct cdn_dp_device { + struct device *dev; + struct drm_device *drm_dev; + struct drm_connector connector; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + struct drm_display_mode mode; + struct platform_device *audio_pdev; + struct work_struct event_work; +--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +@@ -181,8 +181,6 @@ + + #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) + +-#define to_dsi(nm) container_of(nm, struct dw_mipi_dsi_rockchip, nm) +- + enum { + DW_DSI_USAGE_IDLE, + DW_DSI_USAGE_DSI, +@@ -236,7 +234,7 @@ struct rockchip_dw_dsi_chip_data { + + struct dw_mipi_dsi_rockchip { + struct device *dev; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + void __iomem *base; + + struct regmap *grf_regmap; +@@ -271,6 +269,13 @@ struct dw_mipi_dsi_rockchip { + bool dsi_bound; + }; + ++static struct dw_mipi_dsi_rockchip *to_dsi(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct dw_mipi_dsi_rockchip, encoder); ++} ++ + struct dphy_pll_parameter_map { + unsigned int max_mbps; + u8 hsfreqrange; +@@ -770,7 +775,7 @@ static void dw_mipi_dsi_encoder_enable(s + int ret, mux; + + mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, +- &dsi->encoder); ++ &dsi->encoder.encoder); + if (mux < 0) + return; + +@@ -801,7 +806,7 @@ dw_mipi_dsi_encoder_helper_funcs = { + static int rockchip_dsi_drm_create_encoder(struct dw_mipi_dsi_rockchip *dsi, + struct drm_device *drm_dev) + { +- struct drm_encoder *encoder = &dsi->encoder; ++ struct drm_encoder *encoder = &dsi->encoder.encoder; + int ret; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, +@@ -959,7 +964,7 @@ static int dw_mipi_dsi_rockchip_bind(str + goto out_pll_clk; + } + +- ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder); ++ ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder.encoder); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret); + goto out_pll_clk; +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -67,7 +67,7 @@ struct rockchip_hdmi_chip_data { + struct rockchip_hdmi { + struct device *dev; + struct regmap *regmap; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; + struct clk *grf_clk; +@@ -75,7 +75,12 @@ struct rockchip_hdmi { + struct phy *phy; + }; + +-#define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) ++static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct rockchip_hdmi, encoder); ++} + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +@@ -511,7 +516,7 @@ static int dw_hdmi_rockchip_bind(struct + hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; + plat_data->phy_data = hdmi; +- encoder = &hdmi->encoder; ++ encoder = &hdmi->encoder.encoder; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); + /* +--- a/drivers/gpu/drm/rockchip/inno_hdmi.c ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c +@@ -26,8 +26,6 @@ + + #include "inno_hdmi.h" + +-#define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x) +- + struct hdmi_data_info { + int vic; + bool sink_is_hdmi; +@@ -56,7 +54,7 @@ struct inno_hdmi { + void __iomem *regs; + + struct drm_connector connector; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + + struct inno_hdmi_i2c *i2c; + struct i2c_adapter *ddc; +@@ -67,6 +65,18 @@ struct inno_hdmi { + struct drm_display_mode previous_mode; + }; + ++static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct inno_hdmi, encoder); ++} ++ ++static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector) ++{ ++ return container_of(connector, struct inno_hdmi, connector); ++} ++ + enum { + CSC_ITU601_16_235_TO_RGB_0_255_8BIT, + CSC_ITU601_0_255_TO_RGB_0_255_8BIT, +@@ -483,7 +493,7 @@ static void inno_hdmi_encoder_mode_set(s + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) + { +- struct inno_hdmi *hdmi = to_inno_hdmi(encoder); ++ struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); + + inno_hdmi_setup(hdmi, adj_mode); + +@@ -493,14 +503,14 @@ static void inno_hdmi_encoder_mode_set(s + + static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) + { +- struct inno_hdmi *hdmi = to_inno_hdmi(encoder); ++ struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); + + inno_hdmi_set_pwr_mode(hdmi, NORMAL); + } + + static void inno_hdmi_encoder_disable(struct drm_encoder *encoder) + { +- struct inno_hdmi *hdmi = to_inno_hdmi(encoder); ++ struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); + + inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR); + } +@@ -536,7 +546,7 @@ static struct drm_encoder_helper_funcs i + static enum drm_connector_status + inno_hdmi_connector_detect(struct drm_connector *connector, bool force) + { +- struct inno_hdmi *hdmi = to_inno_hdmi(connector); ++ struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); + + return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ? + connector_status_connected : connector_status_disconnected; +@@ -544,7 +554,7 @@ inno_hdmi_connector_detect(struct drm_co + + static int inno_hdmi_connector_get_modes(struct drm_connector *connector) + { +- struct inno_hdmi *hdmi = to_inno_hdmi(connector); ++ struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); + struct edid *edid; + int ret = 0; + +@@ -599,7 +609,7 @@ static struct drm_connector_helper_funcs + + static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) + { +- struct drm_encoder *encoder = &hdmi->encoder; ++ struct drm_encoder *encoder = &hdmi->encoder.encoder; + struct device *dev = hdmi->dev; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); +@@ -879,7 +889,7 @@ static int inno_hdmi_bind(struct device + return 0; + err_cleanup_hdmi: + hdmi->connector.funcs->destroy(&hdmi->connector); +- hdmi->encoder.funcs->destroy(&hdmi->encoder); ++ hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder); + err_put_adapter: + i2c_put_adapter(hdmi->ddc); + err_disable_clk: +@@ -893,7 +903,7 @@ static void inno_hdmi_unbind(struct devi + struct inno_hdmi *hdmi = dev_get_drvdata(dev); + + hdmi->connector.funcs->destroy(&hdmi->connector); +- hdmi->encoder.funcs->destroy(&hdmi->encoder); ++ hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder); + + i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->pclk); +--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c ++++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c +@@ -47,7 +47,7 @@ struct rk3066_hdmi { + void __iomem *regs; + + struct drm_connector connector; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + + struct rk3066_hdmi_i2c *i2c; + struct i2c_adapter *ddc; +@@ -58,7 +58,17 @@ struct rk3066_hdmi { + struct drm_display_mode previous_mode; + }; + +-#define to_rk3066_hdmi(x) container_of(x, struct rk3066_hdmi, x) ++static struct rk3066_hdmi *encoder_to_rk3066_hdmi(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct rk3066_hdmi, encoder); ++} ++ ++static struct rk3066_hdmi *connector_to_rk3066_hdmi(struct drm_connector *connector) ++{ ++ return container_of(connector, struct rk3066_hdmi, connector); ++} + + static inline u8 hdmi_readb(struct rk3066_hdmi *hdmi, u16 offset) + { +@@ -380,7 +390,7 @@ rk3066_hdmi_encoder_mode_set(struct drm_ + struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(encoder); ++ struct rk3066_hdmi *hdmi = encoder_to_rk3066_hdmi(encoder); + + /* Store the display mode for plugin/DPMS poweron events. */ + memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode)); +@@ -388,7 +398,7 @@ rk3066_hdmi_encoder_mode_set(struct drm_ + + static void rk3066_hdmi_encoder_enable(struct drm_encoder *encoder) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(encoder); ++ struct rk3066_hdmi *hdmi = encoder_to_rk3066_hdmi(encoder); + int mux, val; + + mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); +@@ -407,7 +417,7 @@ static void rk3066_hdmi_encoder_enable(s + + static void rk3066_hdmi_encoder_disable(struct drm_encoder *encoder) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(encoder); ++ struct rk3066_hdmi *hdmi = encoder_to_rk3066_hdmi(encoder); + + DRM_DEV_DEBUG(hdmi->dev, "hdmi encoder disable\n"); + +@@ -455,7 +465,7 @@ struct drm_encoder_helper_funcs rk3066_h + static enum drm_connector_status + rk3066_hdmi_connector_detect(struct drm_connector *connector, bool force) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(connector); ++ struct rk3066_hdmi *hdmi = connector_to_rk3066_hdmi(connector); + + return (hdmi_readb(hdmi, HDMI_HPG_MENS_STA) & HDMI_HPG_IN_STATUS_HIGH) ? + connector_status_connected : connector_status_disconnected; +@@ -463,7 +473,7 @@ rk3066_hdmi_connector_detect(struct drm_ + + static int rk3066_hdmi_connector_get_modes(struct drm_connector *connector) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(connector); ++ struct rk3066_hdmi *hdmi = connector_to_rk3066_hdmi(connector); + struct edid *edid; + int ret = 0; + +@@ -496,9 +506,9 @@ rk3066_hdmi_connector_mode_valid(struct + static struct drm_encoder * + rk3066_hdmi_connector_best_encoder(struct drm_connector *connector) + { +- struct rk3066_hdmi *hdmi = to_rk3066_hdmi(connector); ++ struct rk3066_hdmi *hdmi = connector_to_rk3066_hdmi(connector); + +- return &hdmi->encoder; ++ return &hdmi->encoder.encoder; + } + + static int +@@ -538,7 +548,7 @@ struct drm_connector_helper_funcs rk3066 + static int + rk3066_hdmi_register(struct drm_device *drm, struct rk3066_hdmi *hdmi) + { +- struct drm_encoder *encoder = &hdmi->encoder; ++ struct drm_encoder *encoder = &hdmi->encoder.encoder; + struct device *dev = hdmi->dev; + + encoder->possible_crtcs = +@@ -816,7 +826,7 @@ static int rk3066_hdmi_bind(struct devic + + err_cleanup_hdmi: + hdmi->connector.funcs->destroy(&hdmi->connector); +- hdmi->encoder.funcs->destroy(&hdmi->encoder); ++ hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder); + err_disable_i2c: + i2c_put_adapter(hdmi->ddc); + err_disable_hclk: +@@ -831,7 +841,7 @@ static void rk3066_hdmi_unbind(struct de + struct rk3066_hdmi *hdmi = dev_get_drvdata(dev); + + hdmi->connector.funcs->destroy(&hdmi->connector); +- hdmi->encoder.funcs->destroy(&hdmi->encoder); ++ hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder); + + i2c_put_adapter(hdmi->ddc); + clk_disable_unprepare(hdmi->hclk); +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -49,6 +49,10 @@ struct rockchip_drm_private { + struct drm_mm mm; + }; + ++struct rockchip_encoder { ++ struct drm_encoder encoder; ++}; ++ + int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, + struct device *dev); + void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, +@@ -66,4 +70,10 @@ extern struct platform_driver rockchip_d + extern struct platform_driver rockchip_lvds_driver; + extern struct platform_driver vop_platform_driver; + extern struct platform_driver rk3066_hdmi_driver; ++ ++static inline struct rockchip_encoder *to_rockchip_encoder(struct drm_encoder *encoder) ++{ ++ return container_of(encoder, struct rockchip_encoder, encoder); ++} ++ + #endif /* _ROCKCHIP_DRM_DRV_H_ */ +--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c ++++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c +@@ -36,12 +36,6 @@ + + struct rockchip_lvds; + +-#define connector_to_lvds(c) \ +- container_of(c, struct rockchip_lvds, connector) +- +-#define encoder_to_lvds(c) \ +- container_of(c, struct rockchip_lvds, encoder) +- + /** + * struct rockchip_lvds_soc_data - rockchip lvds Soc private data + * @probe: LVDS platform probe function +@@ -65,10 +59,22 @@ struct rockchip_lvds { + struct drm_panel *panel; + struct drm_bridge *bridge; + struct drm_connector connector; +- struct drm_encoder encoder; ++ struct rockchip_encoder encoder; + struct dev_pin_info *pins; + }; + ++static inline struct rockchip_lvds *connector_to_lvds(struct drm_connector *connector) ++{ ++ return container_of(connector, struct rockchip_lvds, connector); ++} ++ ++static inline struct rockchip_lvds *encoder_to_lvds(struct drm_encoder *encoder) ++{ ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ return container_of(rkencoder, struct rockchip_lvds, encoder); ++} ++ + static inline void rk3288_writel(struct rockchip_lvds *lvds, u32 offset, + u32 val) + { +@@ -599,7 +605,7 @@ static int rockchip_lvds_bind(struct dev + goto err_put_remote; + } + +- encoder = &lvds->encoder; ++ encoder = &lvds->encoder.encoder; + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, + dev->of_node); + +@@ -674,10 +680,10 @@ static void rockchip_lvds_unbind(struct + const struct drm_encoder_helper_funcs *encoder_funcs; + + encoder_funcs = lvds->soc_data->helper_funcs; +- encoder_funcs->disable(&lvds->encoder); ++ encoder_funcs->disable(&lvds->encoder.encoder); + pm_runtime_disable(dev); + drm_connector_cleanup(&lvds->connector); +- drm_encoder_cleanup(&lvds->encoder); ++ drm_encoder_cleanup(&lvds->encoder.encoder); + } + + static const struct component_ops rockchip_lvds_component_ops = { diff --git a/target/linux/rockchip/patches-5.18/228-drm-rockchip-Add-crtc_endpoint_id-to-rockchip_encode.patch b/target/linux/rockchip/patches-5.18/228-drm-rockchip-Add-crtc_endpoint_id-to-rockchip_encode.patch new file mode 100644 index 000000000..7dfce79e9 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/228-drm-rockchip-Add-crtc_endpoint_id-to-rockchip_encode.patch @@ -0,0 +1,85 @@ +From 09a20d5d90f1e6f260a2564b645bda913048f85b Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:17 +0200 +Subject: [PATCH 28/50] drm/rockchip: Add crtc_endpoint_id to rockchip_encoder + +The VOP2 has an interface mux which decides to which encoder(s) a CRTC +is routed to. The encoders and CRTCs are connected via of_graphs in the +device tree. When given an encoder the VOP2 driver needs to know to +which internal register setting this encoder matches. For this the VOP2 +binding offers different endpoints, one for each possible encoder. The +endpoint ids of these endpoints are used as a key from an encoders +device tree description to the internal register setting. + +This patch adds the key aka endpoint id to struct rockchip_encoder plus +a function to read the endpoint id starting from the encoders device +node. + +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 33 +++++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 4 ++- + 2 files changed, 36 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +@@ -245,6 +245,39 @@ static struct platform_driver *rockchip_ + static int num_rockchip_sub_drivers; + + /* ++ * Get the endpoint id of the remote endpoint of the given encoder. This ++ * information is used by the VOP2 driver to identify the encoder. ++ * ++ * @rkencoder: The encoder to get the remote endpoint id from ++ * @np: The encoder device node ++ * @port: The number of the port leading to the VOP2 ++ * @reg: The endpoint number leading to the VOP2 ++ */ ++int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rkencoder, ++ struct device_node *np, int port, int reg) ++{ ++ struct of_endpoint ep; ++ struct device_node *en, *ren; ++ int ret; ++ ++ en = of_graph_get_endpoint_by_regs(np, port, reg); ++ if (!en) ++ return -ENOENT; ++ ++ ren = of_graph_get_remote_endpoint(en); ++ if (!ren) ++ return -ENOENT; ++ ++ ret = of_graph_parse_endpoint(ren, &ep); ++ if (ret) ++ return ret; ++ ++ rkencoder->crtc_endpoint_id = ep.id; ++ ++ return 0; ++} ++ ++/* + * Check if a vop endpoint is leading to a rockchip subdriver or bridge. + * Should be called from the component bind stage of the drivers + * to ensure that all subdrivers are probed. +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -50,6 +50,7 @@ struct rockchip_drm_private { + }; + + struct rockchip_encoder { ++ int crtc_endpoint_id; + struct drm_encoder encoder; + }; + +@@ -60,7 +61,8 @@ void rockchip_drm_dma_detach_device(stru + void rockchip_drm_dma_init_device(struct drm_device *drm_dev, + struct device *dev); + int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout); +- ++int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rencoder, ++ struct device_node *np, int port, int reg); + int rockchip_drm_endpoint_is_subdriver(struct device_node *ep); + extern struct platform_driver cdn_dp_driver; + extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; diff --git a/target/linux/rockchip/patches-5.18/229-drm-rockchip-dw_hdmi-rename-vpll-clock-to-reference-.patch b/target/linux/rockchip/patches-5.18/229-drm-rockchip-dw_hdmi-rename-vpll-clock-to-reference-.patch new file mode 100644 index 000000000..e6bb3b8f0 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/229-drm-rockchip-dw_hdmi-rename-vpll-clock-to-reference-.patch @@ -0,0 +1,91 @@ +From ac6f3d88fd9f6fd241bf6cfacb850f6c644a97d7 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:18 +0200 +Subject: [PATCH 29/50] drm/rockchip: dw_hdmi: rename vpll clock to reference + clock + +"vpll" is a misnomer. A clock input to a device should be named after +the usage in the device, not after the clock that drives it. On the +rk3568 the same clock is driven by the HPLL. +To fix that, this patch renames the vpll clock to ref clock. The clock +name "vpll" is left for compatibility to old device trees. + +Signed-off-by: Sascha Hauer +Reviewed-by: Dmitry Osipenko +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 27 +++++++++++---------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -69,7 +69,7 @@ struct rockchip_hdmi { + struct regmap *regmap; + struct rockchip_encoder encoder; + const struct rockchip_hdmi_chip_data *chip_data; +- struct clk *vpll_clk; ++ struct clk *ref_clk; + struct clk *grf_clk; + struct dw_hdmi *hdmi; + struct phy *phy; +@@ -201,14 +201,15 @@ static int rockchip_hdmi_parse_dt(struct + return PTR_ERR(hdmi->regmap); + } + +- hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll"); +- if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) { +- hdmi->vpll_clk = NULL; +- } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { ++ hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "ref"); ++ if (!hdmi->ref_clk) ++ hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "vpll"); ++ ++ if (PTR_ERR(hdmi->ref_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; +- } else if (IS_ERR(hdmi->vpll_clk)) { +- DRM_DEV_ERROR(hdmi->dev, "failed to get vpll clock\n"); +- return PTR_ERR(hdmi->vpll_clk); ++ } else if (IS_ERR(hdmi->ref_clk)) { ++ DRM_DEV_ERROR(hdmi->dev, "failed to get reference clock\n"); ++ return PTR_ERR(hdmi->ref_clk); + } + + hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); +@@ -262,7 +263,7 @@ static void dw_hdmi_rockchip_encoder_mod + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + +- clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); ++ clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000); + } + + static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) +@@ -542,9 +543,9 @@ static int dw_hdmi_rockchip_bind(struct + return ret; + } + +- ret = clk_prepare_enable(hdmi->vpll_clk); ++ ret = clk_prepare_enable(hdmi->ref_clk); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ++ DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", + ret); + return ret; + } +@@ -563,7 +564,7 @@ static int dw_hdmi_rockchip_bind(struct + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); + drm_encoder_cleanup(encoder); +- clk_disable_unprepare(hdmi->vpll_clk); ++ clk_disable_unprepare(hdmi->ref_clk); + } + + return ret; +@@ -575,7 +576,7 @@ static void dw_hdmi_rockchip_unbind(stru + struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); + + dw_hdmi_unbind(hdmi->hdmi); +- clk_disable_unprepare(hdmi->vpll_clk); ++ clk_disable_unprepare(hdmi->ref_clk); + } + + static const struct component_ops dw_hdmi_rockchip_ops = { diff --git a/target/linux/rockchip/patches-5.18/230-dt-bindings-display-rockchip-dw-hdmi-use-ref-as-cloc.patch b/target/linux/rockchip/patches-5.18/230-dt-bindings-display-rockchip-dw-hdmi-use-ref-as-cloc.patch new file mode 100644 index 000000000..3f321fd2b --- /dev/null +++ b/target/linux/rockchip/patches-5.18/230-dt-bindings-display-rockchip-dw-hdmi-use-ref-as-cloc.patch @@ -0,0 +1,45 @@ +From d06891fd7ea0600086ab9b1fff5bf158372163e3 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:19 +0200 +Subject: [PATCH 30/50] dt-bindings: display: rockchip: dw-hdmi: use "ref" as + clock name + +"vpll" is a misnomer. A clock input to a device should be named after +the usage in the device, not after the clock that drives it. On the +rk3568 the same clock is driven by the HPLL. +This patch adds "ref" as a new alternative clock name for "vpll" + +Signed-off-by: Sascha Hauer +Acked-by: Rob Herring +--- + .../bindings/display/rockchip/rockchip,dw-hdmi.yaml | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +@@ -36,7 +36,8 @@ properties: + # order when present. + - description: The HDMI CEC controller main clock + - description: Power for GRF IO +- - description: External clock for some HDMI PHY ++ - description: External clock for some HDMI PHY (old clock name, deprecated) ++ - description: External clock for some HDMI PHY (new name) + + clock-names: + minItems: 2 +@@ -47,10 +48,14 @@ properties: + - cec + - grf + - vpll ++ - ref + - enum: + - grf + - vpll +- - const: vpll ++ - ref ++ - enum: ++ - vpll ++ - ref + + ddc-i2c-bus: + $ref: /schemas/types.yaml#/definitions/phandle diff --git a/target/linux/rockchip/patches-5.18/231-arm64-dts-rockchip-rk3399-rename-HDMI-ref-clock-to-r.patch b/target/linux/rockchip/patches-5.18/231-arm64-dts-rockchip-rk3399-rename-HDMI-ref-clock-to-r.patch new file mode 100644 index 000000000..da32e575e --- /dev/null +++ b/target/linux/rockchip/patches-5.18/231-arm64-dts-rockchip-rk3399-rename-HDMI-ref-clock-to-r.patch @@ -0,0 +1,26 @@ +From cc0c0e69cedb3891ad422962e5d78808d9d4c1d1 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:20 +0200 +Subject: [PATCH 31/50] arm64: dts: rockchip: rk3399: rename HDMI ref clock to + 'ref' + +The reference clock for the HDMI controller has been renamed to 'ref', +the previous 'vpll' name is only left for compatibility in the driver. +Rename the clock to the new name. + +Signed-off-by: Sascha Hauer +--- + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -1884,7 +1884,7 @@ + <&cru SCLK_HDMI_CEC>, + <&cru PCLK_VIO_GRF>, + <&cru PLL_VPLL>; +- clock-names = "iahb", "isfr", "cec", "grf", "vpll"; ++ clock-names = "iahb", "isfr", "cec", "grf", "ref"; + power-domains = <&power RK3399_PD_HDCP>; + reg-io-width = <4>; + rockchip,grf = <&grf>; diff --git a/target/linux/rockchip/patches-5.18/232-drm-rockchip-dw_hdmi-add-rk3568-support.patch b/target/linux/rockchip/patches-5.18/232-drm-rockchip-dw_hdmi-add-rk3568-support.patch new file mode 100644 index 000000000..4aa737863 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/232-drm-rockchip-dw_hdmi-add-rk3568-support.patch @@ -0,0 +1,81 @@ +From d746208026235a92adb8d32d838f5aad23f33312 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:21 +0200 +Subject: [PATCH 32/50] drm/rockchip: dw_hdmi: add rk3568 support + +Add a new dw_hdmi_plat_data struct and new compatible for rk3568. + +Signed-off-by: Benjamin Gaignard +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 31 +++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -50,6 +50,10 @@ + #define RK3399_GRF_SOC_CON20 0x6250 + #define RK3399_HDMI_LCDC_SEL BIT(6) + ++#define RK3568_GRF_VO_CON1 0x0364 ++#define RK3568_HDMI_SDAIN_MSK BIT(15) ++#define RK3568_HDMI_SCLIN_MSK BIT(14) ++ + #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) + + /** +@@ -473,6 +477,19 @@ static const struct dw_hdmi_plat_data rk + .use_drm_infoframe = true, + }; + ++static struct rockchip_hdmi_chip_data rk3568_chip_data = { ++ .lcdsel_grf_reg = -1, ++}; ++ ++static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { ++ .mode_valid = dw_hdmi_rockchip_mode_valid, ++ .mpll_cfg = rockchip_mpll_cfg, ++ .cur_ctr = rockchip_cur_ctr, ++ .phy_config = rockchip_phy_config, ++ .phy_data = &rk3568_chip_data, ++ .use_drm_infoframe = true, ++}; ++ + static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { + { .compatible = "rockchip,rk3228-dw-hdmi", + .data = &rk3228_hdmi_drv_data +@@ -486,6 +503,9 @@ static const struct of_device_id dw_hdmi + { .compatible = "rockchip,rk3399-dw-hdmi", + .data = &rk3399_hdmi_drv_data + }, ++ { .compatible = "rockchip,rk3568-dw-hdmi", ++ .data = &rk3568_hdmi_drv_data ++ }, + {}, + }; + MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); +@@ -520,6 +540,9 @@ static int dw_hdmi_rockchip_bind(struct + encoder = &hdmi->encoder.encoder; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); ++ rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, ++ dev->of_node, 0, 0); ++ + /* + * If we failed to find the CRTC(s) which this encoder is + * supposed to be connected to, it's because the CRTC has +@@ -550,6 +573,14 @@ static int dw_hdmi_rockchip_bind(struct + return ret; + } + ++ if (hdmi->chip_data == &rk3568_chip_data) { ++ regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, ++ HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | ++ RK3568_HDMI_SCLIN_MSK, ++ RK3568_HDMI_SDAIN_MSK | ++ RK3568_HDMI_SCLIN_MSK)); ++ } ++ + drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); + diff --git a/target/linux/rockchip/patches-5.18/233-dt-bindings-display-rockchip-dw-hdmi-Add-compatible-.patch b/target/linux/rockchip/patches-5.18/233-dt-bindings-display-rockchip-dw-hdmi-Add-compatible-.patch new file mode 100644 index 000000000..1e88afbf6 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/233-dt-bindings-display-rockchip-dw-hdmi-Add-compatible-.patch @@ -0,0 +1,27 @@ +From e38f7e13f12eec345462ae67e8009b94a41be116 Mon Sep 17 00:00:00 2001 +From: Benjamin Gaignard +Date: Fri, 8 Apr 2022 13:22:22 +0200 +Subject: [PATCH 33/50] dt-bindings: display: rockchip: dw-hdmi: Add compatible + for rk3568 HDMI + +Define a new compatible for rk3568 HDMI. +This version of HDMI hardware block needs two new clocks hclk_vio and hclk +to provide phy reference clocks. + +Signed-off-by: Benjamin Gaignard +Reviewed-by: Rob Herring +Signed-off-by: Sascha Hauer +--- + .../devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +@@ -23,6 +23,7 @@ properties: + - rockchip,rk3288-dw-hdmi + - rockchip,rk3328-dw-hdmi + - rockchip,rk3399-dw-hdmi ++ - rockchip,rk3568-dw-hdmi + + reg-io-width: + const: 4 diff --git a/target/linux/rockchip/patches-5.18/234-drm-rockchip-dw_hdmi-add-regulator-support.patch b/target/linux/rockchip/patches-5.18/234-drm-rockchip-dw_hdmi-add-regulator-support.patch new file mode 100644 index 000000000..357ae4144 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/234-drm-rockchip-dw_hdmi-add-regulator-support.patch @@ -0,0 +1,106 @@ +From 414fe5e5ddd91f3977617464c09a6af04e3d38ae Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:23 +0200 +Subject: [PATCH 34/50] drm/rockchip: dw_hdmi: add regulator support + +The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed +for the HDMI port. add support for these to the driver for boards which +have them supplied by switchable regulators. + +Signed-off-by: Sascha Hauer +Reviewed-by: Dmitry Osipenko +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 41 +++++++++++++++++++-- + 1 file changed, 38 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -76,6 +77,8 @@ struct rockchip_hdmi { + struct clk *ref_clk; + struct clk *grf_clk; + struct dw_hdmi *hdmi; ++ struct regulator *avdd_0v9; ++ struct regulator *avdd_1v8; + struct phy *phy; + }; + +@@ -226,6 +229,14 @@ static int rockchip_hdmi_parse_dt(struct + return PTR_ERR(hdmi->grf_clk); + } + ++ hdmi->avdd_0v9 = devm_regulator_get(hdmi->dev, "avdd-0v9"); ++ if (IS_ERR(hdmi->avdd_0v9)) ++ return PTR_ERR(hdmi->avdd_0v9); ++ ++ hdmi->avdd_1v8 = devm_regulator_get(hdmi->dev, "avdd-1v8"); ++ if (IS_ERR(hdmi->avdd_1v8)) ++ return PTR_ERR(hdmi->avdd_1v8); ++ + return 0; + } + +@@ -566,11 +577,23 @@ static int dw_hdmi_rockchip_bind(struct + return ret; + } + ++ ret = regulator_enable(hdmi->avdd_0v9); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); ++ goto err_avdd_0v9; ++ } ++ ++ ret = regulator_enable(hdmi->avdd_1v8); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); ++ goto err_avdd_1v8; ++ } ++ + ret = clk_prepare_enable(hdmi->ref_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", + ret); +- return ret; ++ goto err_clk; + } + + if (hdmi->chip_data == &rk3568_chip_data) { +@@ -594,10 +617,19 @@ static int dw_hdmi_rockchip_bind(struct + */ + if (IS_ERR(hdmi->hdmi)) { + ret = PTR_ERR(hdmi->hdmi); +- drm_encoder_cleanup(encoder); +- clk_disable_unprepare(hdmi->ref_clk); ++ goto err_bind; + } + ++ return 0; ++ ++err_bind: ++ clk_disable_unprepare(hdmi->ref_clk); ++ drm_encoder_cleanup(encoder); ++err_clk: ++ regulator_disable(hdmi->avdd_1v8); ++err_avdd_1v8: ++ regulator_disable(hdmi->avdd_0v9); ++err_avdd_0v9: + return ret; + } + +@@ -608,6 +640,9 @@ static void dw_hdmi_rockchip_unbind(stru + + dw_hdmi_unbind(hdmi->hdmi); + clk_disable_unprepare(hdmi->ref_clk); ++ ++ regulator_disable(hdmi->avdd_1v8); ++ regulator_disable(hdmi->avdd_0v9); + } + + static const struct component_ops dw_hdmi_rockchip_ops = { diff --git a/target/linux/rockchip/patches-5.18/235-dt-bindings-display-rockchip-dw-hdmi-Add-regulator-s.patch b/target/linux/rockchip/patches-5.18/235-dt-bindings-display-rockchip-dw-hdmi-Add-regulator-s.patch new file mode 100644 index 000000000..7299ba8f2 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/235-dt-bindings-display-rockchip-dw-hdmi-Add-regulator-s.patch @@ -0,0 +1,35 @@ +From 32118137e182b52fdda4054673d49a7a9ed27b07 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:24 +0200 +Subject: [PATCH 35/50] dt-bindings: display: rockchip: dw-hdmi: Add regulator + support + +The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs +needed for the HDMI port. Add the binding for these supplies. + +Signed-off-by: Sascha Hauer +Acked-by: Rob Herring +--- + .../bindings/display/rockchip/rockchip,dw-hdmi.yaml | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +@@ -28,6 +28,17 @@ properties: + reg-io-width: + const: 4 + ++ avdd-0v9-supply: ++ description: ++ A 0.9V supply that powers up the SoC internal circuitry. The actual pin name ++ varies between the different SoCs and is usually HDMI_TX_AVDD_0V9 or sometimes ++ HDMI_AVDD_1V0. ++ ++ avdd-1v8-supply: ++ description: ++ A 1.8V supply that powers up the SoC internal circuitry. The pin name on the ++ SoC usually is HDMI_TX_AVDD_1V8. ++ + clocks: + minItems: 2 + items: diff --git a/target/linux/rockchip/patches-5.18/236-drm-rockchip-dw_hdmi-Use-auto-generated-tables.patch b/target/linux/rockchip/patches-5.18/236-drm-rockchip-dw_hdmi-Use-auto-generated-tables.patch new file mode 100644 index 000000000..5388bac57 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/236-drm-rockchip-dw_hdmi-Use-auto-generated-tables.patch @@ -0,0 +1,193 @@ +From 2e1285fea641313f28766fbd7d0723e33ffdeba8 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Fri, 8 Apr 2022 13:22:25 +0200 +Subject: [PATCH 36/50] drm/rockchip: dw_hdmi: Use auto-generated tables + +The previous tables for mpll_cfg and curr_ctrl were created using the +20-pages of example settings provided by the PHY vendor. Those +example settings weren't particularly dense, so there were places +where we were guessing what the settings would be for 10-bit and +12-bit (not that we use those anyway). It was also always a lot of +extra work every time we wanted to add a new clock rate since we had +to cross-reference several tables. + +In I've gone through the work to figure +out how to generate this table automatically. Let's now use the +automatically generated table and then we'll never need to look at it +again. + +We only support 8-bit mode right now and only support a small number +of clock rates and I've verified that the only 8-bit rate that was +affected was 148.5. That mode appears to have been wrong in the old +table. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 130 +++++++++++--------- + 1 file changed, 69 insertions(+), 61 deletions(-) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -91,80 +91,88 @@ static struct rockchip_hdmi *to_rockchip + + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { + { +- 27000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} +- }, +- }, { +- 36000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} +- }, +- }, { +- 40000000, { +- { 0x00b3, 0x0000}, +- { 0x2153, 0x0000}, +- { 0x40f3, 0x0000} +- }, +- }, { +- 54000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, +- }, +- }, { +- 65000000, { +- { 0x0072, 0x0001}, +- { 0x2142, 0x0001}, +- { 0x40a2, 0x0001}, +- }, +- }, { +- 66000000, { +- { 0x013e, 0x0003}, +- { 0x217e, 0x0002}, +- { 0x4061, 0x0002} +- }, +- }, { +- 74250000, { +- { 0x0072, 0x0001}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} +- }, +- }, { +- 83500000, { +- { 0x0072, 0x0001}, +- }, +- }, { +- 108000000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} +- }, +- }, { +- 106500000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} +- }, +- }, { +- 146250000, { +- { 0x0051, 0x0002}, +- { 0x2145, 0x0002}, +- { 0x4061, 0x0002} +- }, +- }, { +- 148500000, { +- { 0x0051, 0x0003}, +- { 0x214c, 0x0003}, +- { 0x4064, 0x0003} ++ 30666000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40f3, 0x0000 }, ++ }, ++ }, { ++ 36800000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2153, 0x0000 }, ++ { 0x40a2, 0x0001 }, ++ }, ++ }, { ++ 46000000, { ++ { 0x00b3, 0x0000 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, ++ }, ++ }, { ++ 61333000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x40a2, 0x0001 }, ++ }, ++ }, { ++ 73600000, { ++ { 0x0072, 0x0001 }, ++ { 0x2142, 0x0001 }, ++ { 0x4061, 0x0002 }, ++ }, ++ }, { ++ 92000000, { ++ { 0x0072, 0x0001 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, ++ }, ++ }, { ++ 122666000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4061, 0x0002 }, ++ }, ++ }, { ++ 147200000, { ++ { 0x0051, 0x0002 }, ++ { 0x2145, 0x0002 }, ++ { 0x4064, 0x0003 }, ++ }, ++ }, { ++ 184000000, { ++ { 0x0051, 0x0002 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, ++ }, ++ }, { ++ 226666000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x4064, 0x0003 }, ++ }, ++ }, { ++ 272000000, { ++ { 0x0040, 0x0003 }, ++ { 0x214c, 0x0003 }, ++ { 0x5a64, 0x0003 }, ++ }, ++ }, { ++ 340000000, { ++ { 0x0040, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, ++ }, ++ }, { ++ 600000000, { ++ { 0x1a40, 0x0003 }, ++ { 0x3b4c, 0x0003 }, ++ { 0x5a64, 0x0003 }, + }, +- }, { ++ }, { + ~0UL, { +- { 0x00a0, 0x000a }, +- { 0x2001, 0x000f }, +- { 0x4002, 0x000f }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, ++ { 0x0000, 0x0000 }, + }, + } + }; diff --git a/target/linux/rockchip/patches-5.18/237-drm-rockchip-dw_hdmi-drop-mode_valid-hook.patch b/target/linux/rockchip/patches-5.18/237-drm-rockchip-dw_hdmi-drop-mode_valid-hook.patch new file mode 100644 index 000000000..5dd1f030b --- /dev/null +++ b/target/linux/rockchip/patches-5.18/237-drm-rockchip-dw_hdmi-drop-mode_valid-hook.patch @@ -0,0 +1,85 @@ +From ac7d452ab34962172f64ad1ecf244b42fdb4bccf Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:26 +0200 +Subject: [PATCH 37/50] drm/rockchip: dw_hdmi: drop mode_valid hook + +The driver checks if the pixel clock of the given mode matches an entry +in the mpll config table. The frequencies in the mpll table are meant as +a frequency range up to which the entry works, not as a frequency that +must match the pixel clock. The downstream Kernel also does not have +this check, so drop it to allow for more display resolutions. + +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 25 --------------------- + 1 file changed, 25 deletions(-) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -248,26 +248,6 @@ static int rockchip_hdmi_parse_dt(struct + return 0; + } + +-static enum drm_mode_status +-dw_hdmi_rockchip_mode_valid(struct dw_hdmi *hdmi, void *data, +- const struct drm_display_info *info, +- const struct drm_display_mode *mode) +-{ +- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; +- int pclk = mode->clock * 1000; +- bool valid = false; +- int i; +- +- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { +- if (pclk == mpll_cfg[i].mpixelclock) { +- valid = true; +- break; +- } +- } +- +- return (valid) ? MODE_OK : MODE_BAD; +-} +- + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + { + } +@@ -433,7 +413,6 @@ static struct rockchip_hdmi_chip_data rk + }; + + static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { +- .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, +@@ -450,7 +429,6 @@ static struct rockchip_hdmi_chip_data rk + }; + + static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { +- .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, +@@ -470,7 +448,6 @@ static struct rockchip_hdmi_chip_data rk + }; + + static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { +- .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, +@@ -488,7 +465,6 @@ static struct rockchip_hdmi_chip_data rk + }; + + static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { +- .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, +@@ -501,7 +477,6 @@ static struct rockchip_hdmi_chip_data rk + }; + + static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { +- .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, diff --git a/target/linux/rockchip/patches-5.18/238-drm-rockchip-dw_hdmi-Set-cur_ctr-to-0-always.patch b/target/linux/rockchip/patches-5.18/238-drm-rockchip-dw_hdmi-Set-cur_ctr-to-0-always.patch new file mode 100644 index 000000000..fa2808b84 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/238-drm-rockchip-dw_hdmi-Set-cur_ctr-to-0-always.patch @@ -0,0 +1,42 @@ +From b6d0ebd771c8309839ff4d478ee1e58d701384ef Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Fri, 8 Apr 2022 13:22:27 +0200 +Subject: [PATCH 38/50] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always + +Jitter was improved by lowering the MPLL bandwidth to account for high +frequency noise in the rk3288 PLL. In each case MPLL bandwidth was +lowered only enough to get us a comfortable margin. We believe that +lowering the bandwidth like this is safe given sufficient testing. + +Signed-off-by: Douglas Anderson +Signed-off-by: Yakir Yang +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -180,20 +180,8 @@ static const struct dw_hdmi_mpll_config + static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { + /* pixelclk bpp8 bpp10 bpp12 */ + { +- 40000000, { 0x0018, 0x0018, 0x0018 }, +- }, { +- 65000000, { 0x0028, 0x0028, 0x0028 }, +- }, { +- 66000000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 74250000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 83500000, { 0x0028, 0x0038, 0x0038 }, +- }, { +- 146250000, { 0x0038, 0x0038, 0x0038 }, +- }, { +- 148500000, { 0x0000, 0x0038, 0x0038 }, +- }, { ++ 600000000, { 0x0000, 0x0000, 0x0000 }, ++ }, { + ~0UL, { 0x0000, 0x0000, 0x0000}, + } + }; diff --git a/target/linux/rockchip/patches-5.18/239-drm-rockchip-dw_hdmi-add-default-594Mhz-clk-for-4K-6.patch b/target/linux/rockchip/patches-5.18/239-drm-rockchip-dw_hdmi-add-default-594Mhz-clk-for-4K-6.patch new file mode 100644 index 000000000..2b0c5e272 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/239-drm-rockchip-dw_hdmi-add-default-594Mhz-clk-for-4K-6.patch @@ -0,0 +1,24 @@ +From f4cfa5e962d5d537751f42d23151c12598349716 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Fri, 8 Apr 2022 13:22:28 +0200 +Subject: [PATCH 39/50] drm/rockchip: dw_hdmi: add default 594Mhz clk for + 4K@60hz + +add 594Mhz configuration parameters in rockchip_phy_config + +Signed-off-by: Nickey Yang +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -191,6 +191,7 @@ static const struct dw_hdmi_phy_config r + { 74250000, 0x8009, 0x0004, 0x0272}, + { 148500000, 0x802b, 0x0004, 0x028d}, + { 297000000, 0x8039, 0x0005, 0x028d}, ++ { 594000000, 0x8039, 0x0000, 0x019d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + diff --git a/target/linux/rockchip/patches-5.18/240-dt-bindings-display-rockchip-dw-hdmi-Make-unwedge-pi.patch b/target/linux/rockchip/patches-5.18/240-dt-bindings-display-rockchip-dw-hdmi-Make-unwedge-pi.patch new file mode 100644 index 000000000..a8c2efeaf --- /dev/null +++ b/target/linux/rockchip/patches-5.18/240-dt-bindings-display-rockchip-dw-hdmi-Make-unwedge-pi.patch @@ -0,0 +1,25 @@ +From 25d65f298b8d1c95a3e231c97272d8b930a85a5b Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:29 +0200 +Subject: [PATCH 40/50] dt-bindings: display: rockchip: dw-hdmi: Make unwedge + pinctrl optional + +None of the upstream device tree files has a "unwedge" pinctrl +specified. Make it optional. + +Signed-off-by: Sascha Hauer +Acked-by: Rob Herring +--- + .../devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +@@ -89,6 +89,7 @@ properties: + The unwedge pinctrl entry shall drive the DDC SDA line low. This is + intended to work around a hardware errata that can cause the DDC I2C + bus to be wedged. ++ minItems: 1 + items: + - const: default + - const: unwedge diff --git a/target/linux/rockchip/patches-5.18/241-arm64-dts-rockchip-rk356x-Add-VOP2-nodes.patch b/target/linux/rockchip/patches-5.18/241-arm64-dts-rockchip-rk356x-Add-VOP2-nodes.patch new file mode 100644 index 000000000..838af4144 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/241-arm64-dts-rockchip-rk356x-Add-VOP2-nodes.patch @@ -0,0 +1,123 @@ +From 62ff79396d8d4137b65195fcd20e3010b96b0902 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:30 +0200 +Subject: [PATCH 41/50] arm64: dts: rockchip: rk356x: Add VOP2 nodes + +The VOP2 is the display output controller on the RK3568. Add the node +for it to the dtsi file along with the required display-subsystem node +and the iommu node. + +Signed-off-by: Sascha Hauer +Acked-by: Rob Herring +--- + arch/arm64/boot/dts/rockchip/rk3566.dtsi | 4 ++ + arch/arm64/boot/dts/rockchip/rk3568.dtsi | 4 ++ + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 51 ++++++++++++++++++++++++ + include/dt-bindings/soc/rockchip,vop2.h | 14 +++++++ + 4 files changed, 73 insertions(+) + create mode 100644 include/dt-bindings/soc/rockchip,vop2.h + +--- a/arch/arm64/boot/dts/rockchip/rk3566.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3566.dtsi +@@ -29,3 +29,7 @@ + extcon = <&usb2phy0>; + maximum-speed = "high-speed"; + }; ++ ++&vop { ++ compatible = "rockchip,rk3566-vop"; ++}; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -137,3 +137,7 @@ + phys = <&usb2phy0_otg>, <&combphy0 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + }; ++ ++&vop { ++ compatible = "rockchip,rk3568-vop"; ++}; +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -129,6 +129,11 @@ + }; + }; + ++ display_subsystem: display-subsystem { ++ compatible = "rockchip,display-subsystem"; ++ ports = <&vop_out>; ++ }; ++ + firmware { + scmi: scmi { + compatible = "arm,scmi-smc"; +@@ -632,6 +637,52 @@ + }; + }; + ++ vop: vop@fe040000 { ++ reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>; ++ reg-names = "regs", "gamma_lut"; ++ interrupts = ; ++ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, ++ <&cru DCLK_VOP1>, <&cru DCLK_VOP2>; ++ clock-names = "aclk", "hclk", "dclk_vp0", "dclk_vp1", "dclk_vp2"; ++ iommus = <&vop_mmu>; ++ power-domains = <&power RK3568_PD_VO>; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ ++ vop_out: ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vp0: port@0 { ++ reg = <0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ vp1: port@1 { ++ reg = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ vp2: port@2 { ++ reg = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++ vop_mmu: iommu@fe043e00 { ++ compatible = "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>; ++ interrupts = ; ++ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>; ++ clock-names = "aclk", "iface"; ++ #iommu-cells = <0>; ++ status = "disabled"; ++ }; ++ + qos_gpu: qos@fe128000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe128000 0x0 0x20>; +--- /dev/null ++++ b/include/dt-bindings/soc/rockchip,vop2.h +@@ -0,0 +1,14 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++ ++#ifndef __DT_BINDINGS_ROCKCHIP_VOP2_H ++#define __DT_BINDINGS_ROCKCHIP_VOP2_H ++ ++#define ROCKCHIP_VOP2_EP_RGB0 1 ++#define ROCKCHIP_VOP2_EP_HDMI0 2 ++#define ROCKCHIP_VOP2_EP_EDP0 3 ++#define ROCKCHIP_VOP2_EP_MIPI0 4 ++#define ROCKCHIP_VOP2_EP_LVDS0 5 ++#define ROCKCHIP_VOP2_EP_MIPI1 6 ++#define ROCKCHIP_VOP2_EP_LVDS1 7 ++ ++#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */ diff --git a/target/linux/rockchip/patches-5.18/242-arm64-dts-rockchip-rk356x-Add-HDMI-nodes.patch b/target/linux/rockchip/patches-5.18/242-arm64-dts-rockchip-rk356x-Add-HDMI-nodes.patch new file mode 100644 index 000000000..634bed0ac --- /dev/null +++ b/target/linux/rockchip/patches-5.18/242-arm64-dts-rockchip-rk356x-Add-HDMI-nodes.patch @@ -0,0 +1,53 @@ +From 193346cae13e4d78d144ccf75451611779630274 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:31 +0200 +Subject: [PATCH 42/50] arm64: dts: rockchip: rk356x: Add HDMI nodes + +Add support for the HDMI port found on RK3568. + +Signed-off-by: Sascha Hauer +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 32 ++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -683,6 +683,38 @@ + status = "disabled"; + }; + ++ hdmi: hdmi@fe0a0000 { ++ compatible = "rockchip,rk3568-dw-hdmi"; ++ reg = <0x0 0xfe0a0000 0x0 0x20000>; ++ interrupts = ; ++ clocks = <&cru PCLK_HDMI_HOST>, ++ <&cru CLK_HDMI_SFR>, ++ <&cru CLK_HDMI_CEC>, ++ <&pmucru CLK_HDMI_REF>, ++ <&cru HCLK_VO>; ++ clock-names = "iahb", "isfr", "cec", "ref"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>; ++ power-domains = <&power RK3568_PD_VO>; ++ reg-io-width = <4>; ++ rockchip,grf = <&grf>; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hdmi_in: port@0 { ++ reg = <0>; ++ }; ++ ++ hdmi_out: port@1 { ++ reg = <1>; ++ }; ++ }; ++ }; ++ + qos_gpu: qos@fe128000 { + compatible = "rockchip,rk3568-qos", "syscon"; + reg = <0x0 0xfe128000 0x0 0x20>; diff --git a/target/linux/rockchip/patches-5.18/243-arm64-dts-rockchip-rk3568-evb-Enable-VOP2-and-hdmi.patch b/target/linux/rockchip/patches-5.18/243-arm64-dts-rockchip-rk3568-evb-Enable-VOP2-and-hdmi.patch new file mode 100644 index 000000000..f05a9b0fe --- /dev/null +++ b/target/linux/rockchip/patches-5.18/243-arm64-dts-rockchip-rk3568-evb-Enable-VOP2-and-hdmi.patch @@ -0,0 +1,88 @@ +From 9e34cf6dd7d8ede178ed8c216735eeeb6db892a7 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:32 +0200 +Subject: [PATCH 43/50] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi + +This enabled the VOP2 display controller along with hdmi and the +required port routes which is enough to get a picture out of the +hdmi port of the board. + +Signed-off-by: Sascha Hauer +--- + .../boot/dts/rockchip/rk3568-evb1-v10.dts | 47 +++++++++++++++++++ + 1 file changed, 47 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include "rk3568.dtsi" + + / { +@@ -34,6 +35,17 @@ + regulator-max-microvolt = <12000000>; + }; + ++ hdmi-con { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -189,6 +201,24 @@ + status = "okay"; + }; + ++&hdmi { ++ avdd-0v9-supply = <&vdda0v9_image>; ++ avdd-1v8-supply = <&vcca1v8_image>; ++ status = "okay"; ++}; ++ ++&hdmi_in { ++ hdmi_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi>; ++ }; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2c0 { + status = "okay"; + +@@ -589,3 +619,20 @@ + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; + }; ++ ++&vop { ++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; ++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi_in_vp0>; ++ }; ++}; diff --git a/target/linux/rockchip/patches-5.18/244-arm64-dts-rockchip-enable-vop2-and-hdmi-tx-on-quartz.patch b/target/linux/rockchip/patches-5.18/244-arm64-dts-rockchip-enable-vop2-and-hdmi-tx-on-quartz.patch new file mode 100644 index 000000000..4a51a0c91 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/244-arm64-dts-rockchip-enable-vop2-and-hdmi-tx-on-quartz.patch @@ -0,0 +1,89 @@ +From db058732d929fd685c14f848246eac70f7e1da71 Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Fri, 8 Apr 2022 13:22:33 +0200 +Subject: [PATCH 44/50] arm64: dts: rockchip: enable vop2 and hdmi tx on + quartz64a + +Enable the RK356x Video Output Processor (VOP) 2 on the Pine64 +Quartz64 Model A. + +Signed-off-by: Michael Riesch +Signed-off-by: Sascha Hauer +--- + .../boot/dts/rockchip/rk3566-quartz64-a.dts | 47 +++++++++++++++++++ + 1 file changed, 47 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include "rk3566.dtsi" + + / { +@@ -37,6 +38,17 @@ + #cooling-cells = <2>; + }; + ++ hdmi-con { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -280,6 +292,24 @@ + status = "okay"; + }; + ++&hdmi { ++ avdd-0v9-supply = <&vdda_0v9>; ++ avdd-1v8-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&hdmi_in { ++ hdmi_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi>; ++ }; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2c0 { + status = "okay"; + +@@ -781,3 +811,20 @@ + phy-supply = <&vcc5v0_usb20_host>; + status = "okay"; + }; ++ ++&vop { ++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; ++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi_in_vp0>; ++ }; ++}; diff --git a/target/linux/rockchip/patches-5.18/245-drm-rockchip-Make-VOP-driver-optional.patch b/target/linux/rockchip/patches-5.18/245-drm-rockchip-Make-VOP-driver-optional.patch new file mode 100644 index 000000000..d60d1ad90 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/245-drm-rockchip-Make-VOP-driver-optional.patch @@ -0,0 +1,61 @@ +From c1dd77c13169d70bbfd79f69c1f57ac5601ae68c Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:35 +0200 +Subject: [PATCH 45/50] drm/rockchip: Make VOP driver optional + +With upcoming VOP2 support VOP won't be the only choice anymore, so make +the VOP driver optional. + +This also adds a dependency from ROCKCHIP_ANALOGIX_DP to ROCKCHIP_VOP, +because that driver currently only links and works with the VOP driver. + +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/Kconfig | 8 ++++++++ + drivers/gpu/drm/rockchip/Makefile | 3 ++- + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +- + 3 files changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/rockchip/Kconfig ++++ b/drivers/gpu/drm/rockchip/Kconfig +@@ -23,8 +23,16 @@ config DRM_ROCKCHIP + + if DRM_ROCKCHIP + ++config ROCKCHIP_VOP ++ bool "Rockchip VOP driver" ++ default y ++ help ++ This selects support for the VOP driver. You should enable it ++ on older SoCs. ++ + config ROCKCHIP_ANALOGIX_DP + bool "Rockchip specific extensions for Analogix DP driver" ++ depends on ROCKCHIP_VOP + help + This selects support for Rockchip SoC specific extensions + for the Analogix Core DP driver. If you want to enable DP +--- a/drivers/gpu/drm/rockchip/Makefile ++++ b/drivers/gpu/drm/rockchip/Makefile +@@ -4,8 +4,9 @@ + # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. + + rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ +- rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o ++ rockchip_drm_gem.o + ++rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o + rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +@@ -481,7 +481,7 @@ static int __init rockchip_drm_init(void + return -ENODEV; + + num_rockchip_sub_drivers = 0; +- ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP); ++ ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, + CONFIG_ROCKCHIP_LVDS); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, diff --git a/target/linux/rockchip/patches-5.18/246-drm-rockchip-Add-VOP2-driver.patch b/target/linux/rockchip/patches-5.18/246-drm-rockchip-Add-VOP2-driver.patch new file mode 100644 index 000000000..869926b61 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/246-drm-rockchip-Add-VOP2-driver.patch @@ -0,0 +1,3619 @@ +From 7b08706f8e27edbb5610c0b5a8453fc4309b7fca Mon Sep 17 00:00:00 2001 +From: Andy Yan +Date: Fri, 8 Apr 2022 13:22:36 +0200 +Subject: [PATCH 46/50] drm: rockchip: Add VOP2 driver + +The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568. +It replaces the VOP unit found in the older Rockchip SoCs. + +This driver has been derived from the downstream Rockchip Kernel and +heavily modified: + +- All nonstandard DRM properties have been removed +- dropped struct vop2_plane_state and pass around less data between + functions +- Dropped all DRM_FORMAT_* not known on upstream +- rework register access to get rid of excessively used macros +- Drop all waiting for framesyncs + +The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB +board. Overlay support is tested with the modetest utility. AFBC support +on the cluster windows is tested with weston-simple-dmabuf-egl on +weston using the (yet to be upstreamed) panfrost driver support. + +Signed-off-by: Andy Yan +Co-Developed-by: Sascha Hauer +Signed-off-by: Sascha Hauer +--- + drivers/gpu/drm/rockchip/Kconfig | 6 + + drivers/gpu/drm/rockchip/Makefile | 1 + + drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 6 +- + drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 + + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 15 + + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2706 ++++++++++++++++++ + drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 477 +++ + drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 281 ++ + 9 files changed, 3494 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c + create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.h + create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c + +--- a/drivers/gpu/drm/rockchip/Kconfig ++++ b/drivers/gpu/drm/rockchip/Kconfig +@@ -30,6 +30,12 @@ config ROCKCHIP_VOP + This selects support for the VOP driver. You should enable it + on older SoCs. + ++config ROCKCHIP_VOP2 ++ bool "Rockchip VOP2 driver" ++ help ++ This selects support for the VOP2 driver. The VOP2 hardware is ++ first found on the RK3568. ++ + config ROCKCHIP_ANALOGIX_DP + bool "Rockchip specific extensions for Analogix DP driver" + depends on ROCKCHIP_VOP +--- a/drivers/gpu/drm/rockchip/Makefile ++++ b/drivers/gpu/drm/rockchip/Makefile +@@ -6,6 +6,7 @@ + rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ + rockchip_drm_gem.o + ++rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o + rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o + rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +@@ -482,6 +482,7 @@ static int __init rockchip_drm_init(void + + num_rockchip_sub_drivers = 0; + ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP); ++ ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, + CONFIG_ROCKCHIP_LVDS); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, +--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +@@ -18,7 +18,7 @@ + + #define ROCKCHIP_MAX_FB_BUFFER 3 + #define ROCKCHIP_MAX_CONNECTOR 2 +-#define ROCKCHIP_MAX_CRTC 2 ++#define ROCKCHIP_MAX_CRTC 4 + + struct drm_device; + struct drm_connector; +@@ -31,6 +31,9 @@ struct rockchip_crtc_state { + int output_bpc; + int output_flags; + bool enable_afbc; ++ u32 bus_format; ++ u32 bus_flags; ++ int color_space; + }; + #define to_rockchip_crtc_state(s) \ + container_of(s, struct rockchip_crtc_state, base) +@@ -72,6 +75,7 @@ extern struct platform_driver rockchip_d + extern struct platform_driver rockchip_lvds_driver; + extern struct platform_driver vop_platform_driver; + extern struct platform_driver rk3066_hdmi_driver; ++extern struct platform_driver vop2_platform_driver; + + static inline struct rockchip_encoder *to_rockchip_encoder(struct drm_encoder *encoder) + { +--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +@@ -134,4 +134,6 @@ void rockchip_drm_mode_config_init(struc + + dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; + dev->mode_config.helper_private = &rockchip_mode_config_helpers; ++ ++ dev->mode_config.normalize_zpos = true; + } +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -54,9 +54,23 @@ struct vop_afbc { + struct vop_reg enable; + struct vop_reg win_sel; + struct vop_reg format; ++ struct vop_reg rb_swap; ++ struct vop_reg uv_swap; ++ struct vop_reg auto_gating_en; ++ struct vop_reg block_split_en; ++ struct vop_reg pic_vir_width; ++ struct vop_reg tile_num; + struct vop_reg hreg_block_split; ++ struct vop_reg pic_offset; + struct vop_reg pic_size; ++ struct vop_reg dsp_offset; ++ struct vop_reg transform_offset; + struct vop_reg hdr_ptr; ++ struct vop_reg half_block_en; ++ struct vop_reg xmirror; ++ struct vop_reg ymirror; ++ struct vop_reg rotate_270; ++ struct vop_reg rotate_90; + struct vop_reg rstn; + }; + +@@ -410,4 +424,5 @@ static inline int scl_vop_cal_lb_mode(in + } + + extern const struct component_ops vop_component_ops; ++ + #endif /* _ROCKCHIP_DRM_VOP_H */ +--- /dev/null ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -0,0 +1,2706 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 Rockchip Electronics Co., Ltd. ++ * Author: Andy Yan ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "rockchip_drm_drv.h" ++#include "rockchip_drm_gem.h" ++#include "rockchip_drm_fb.h" ++#include "rockchip_drm_vop2.h" ++ ++/* ++ * VOP2 architecture ++ * ++ +----------+ +-------------+ +-----------+ ++ | Cluster | | Sel 1 from 6| | 1 from 3 | ++ | window0 | | Layer0 | | RGB | ++ +----------+ +-------------+ +---------------+ +-------------+ +-----------+ ++ +----------+ +-------------+ |N from 6 layers| | | ++ | Cluster | | Sel 1 from 6| | Overlay0 +--->| Video Port0 | +-----------+ ++ | window1 | | Layer1 | | | | | | 1 from 3 | ++ +----------+ +-------------+ +---------------+ +-------------+ | LVDS | ++ +----------+ +-------------+ +-----------+ ++ | Esmart | | Sel 1 from 6| ++ | window0 | | Layer2 | +---------------+ +-------------+ +-----------+ ++ +----------+ +-------------+ |N from 6 Layers| | | +--> | 1 from 3 | ++ +----------+ +-------------+ --------> | Overlay1 +--->| Video Port1 | | MIPI | ++ | Esmart | | Sel 1 from 6| --------> | | | | +-----------+ ++ | Window1 | | Layer3 | +---------------+ +-------------+ ++ +----------+ +-------------+ +-----------+ ++ +----------+ +-------------+ | 1 from 3 | ++ | Smart | | Sel 1 from 6| +---------------+ +-------------+ | HDMI | ++ | Window0 | | Layer4 | |N from 6 Layers| | | +-----------+ ++ +----------+ +-------------+ | Overlay2 +--->| Video Port2 | ++ +----------+ +-------------+ | | | | +-----------+ ++ | Smart | | Sel 1 from 6| +---------------+ +-------------+ | 1 from 3 | ++ | Window1 | | Layer5 | | eDP | ++ +----------+ +-------------+ +-----------+ ++ * ++ */ ++ ++enum vop2_data_format { ++ VOP2_FMT_ARGB8888 = 0, ++ VOP2_FMT_RGB888, ++ VOP2_FMT_RGB565, ++ VOP2_FMT_XRGB101010, ++ VOP2_FMT_YUV420SP, ++ VOP2_FMT_YUV422SP, ++ VOP2_FMT_YUV444SP, ++ VOP2_FMT_YUYV422 = 8, ++ VOP2_FMT_YUYV420, ++ VOP2_FMT_VYUY422, ++ VOP2_FMT_VYUY420, ++ VOP2_FMT_YUV420SP_TILE_8x4 = 0x10, ++ VOP2_FMT_YUV420SP_TILE_16x2, ++ VOP2_FMT_YUV422SP_TILE_8x4, ++ VOP2_FMT_YUV422SP_TILE_16x2, ++ VOP2_FMT_YUV420SP_10, ++ VOP2_FMT_YUV422SP_10, ++ VOP2_FMT_YUV444SP_10, ++}; ++ ++enum vop2_afbc_format { ++ VOP2_AFBC_FMT_RGB565, ++ VOP2_AFBC_FMT_ARGB2101010 = 2, ++ VOP2_AFBC_FMT_YUV420_10BIT, ++ VOP2_AFBC_FMT_RGB888, ++ VOP2_AFBC_FMT_ARGB8888, ++ VOP2_AFBC_FMT_YUV420 = 9, ++ VOP2_AFBC_FMT_YUV422 = 0xb, ++ VOP2_AFBC_FMT_YUV422_10BIT = 0xe, ++ VOP2_AFBC_FMT_INVALID = -1, ++}; ++ ++union vop2_alpha_ctrl { ++ u32 val; ++ struct { ++ /* [0:1] */ ++ u32 color_mode:1; ++ u32 alpha_mode:1; ++ /* [2:3] */ ++ u32 blend_mode:2; ++ u32 alpha_cal_mode:1; ++ /* [5:7] */ ++ u32 factor_mode:3; ++ /* [8:9] */ ++ u32 alpha_en:1; ++ u32 src_dst_swap:1; ++ u32 reserved:6; ++ /* [16:23] */ ++ u32 glb_alpha:8; ++ } bits; ++}; ++ ++struct vop2_alpha { ++ union vop2_alpha_ctrl src_color_ctrl; ++ union vop2_alpha_ctrl dst_color_ctrl; ++ union vop2_alpha_ctrl src_alpha_ctrl; ++ union vop2_alpha_ctrl dst_alpha_ctrl; ++}; ++ ++struct vop2_alpha_config { ++ bool src_premulti_en; ++ bool dst_premulti_en; ++ bool src_pixel_alpha_en; ++ bool dst_pixel_alpha_en; ++ u16 src_glb_alpha_value; ++ u16 dst_glb_alpha_value; ++}; ++ ++struct vop2_win { ++ struct vop2 *vop2; ++ struct drm_plane base; ++ const struct vop2_win_data *data; ++ struct regmap_field *reg[VOP2_WIN_MAX_REG]; ++ ++ /** ++ * @win_id: graphic window id, a cluster may be split into two ++ * graphics windows. ++ */ ++ u8 win_id; ++ u8 delay; ++ u32 offset; ++ ++ enum drm_plane_type type; ++}; ++ ++struct vop2_video_port { ++ struct drm_crtc crtc; ++ struct vop2 *vop2; ++ struct clk *dclk; ++ unsigned int id; ++ const struct vop2_video_port_regs *regs; ++ const struct vop2_video_port_data *data; ++ ++ struct completion dsp_hold_completion; ++ ++ /** ++ * @win_mask: Bitmask of windows attached to the video port; ++ */ ++ u32 win_mask; ++ ++ struct vop2_win *primary_plane; ++ struct drm_pending_vblank_event *event; ++ ++ unsigned int nlayers; ++}; ++ ++struct vop2 { ++ struct device *dev; ++ struct drm_device *drm; ++ struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; ++ ++ const struct vop2_data *data; ++ /* ++ * Number of windows that are registered as plane, may be less than the ++ * total number of hardware windows. ++ */ ++ u32 registered_num_wins; ++ ++ void __iomem *regs; ++ struct regmap *map; ++ ++ struct regmap *grf; ++ ++ /* physical map length of vop2 register */ ++ u32 len; ++ ++ void __iomem *lut_regs; ++ ++ /* protects crtc enable/disable */ ++ struct mutex vop2_lock; ++ ++ int irq; ++ ++ /* ++ * Some global resources are shared between all video ports(crtcs), so ++ * we need a ref counter here. ++ */ ++ unsigned int enable_count; ++ struct clk *hclk; ++ struct clk *aclk; ++ ++ /* must be put at the end of the struct */ ++ struct vop2_win win[]; ++}; ++ ++static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) ++{ ++ return container_of(crtc, struct vop2_video_port, crtc); ++} ++ ++static struct vop2_win *to_vop2_win(struct drm_plane *p) ++{ ++ return container_of(p, struct vop2_win, base); ++} ++ ++static void vop2_lock(struct vop2 *vop2) ++{ ++ mutex_lock(&vop2->vop2_lock); ++} ++ ++static void vop2_unlock(struct vop2 *vop2) ++{ ++ mutex_unlock(&vop2->vop2_lock); ++} ++ ++static void vop2_writel(struct vop2 *vop2, u32 offset, u32 v) ++{ ++ regmap_write(vop2->map, offset, v); ++} ++ ++static void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v) ++{ ++ regmap_write(vp->vop2->map, vp->data->offset + offset, v); ++} ++ ++static u32 vop2_readl(struct vop2 *vop2, u32 offset) ++{ ++ u32 val; ++ ++ regmap_read(vop2->map, offset, &val); ++ ++ return val; ++} ++ ++static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v) ++{ ++ regmap_field_write(win->reg[reg], v); ++} ++ ++static bool vop2_cluster_window(const struct vop2_win *win) ++{ ++ return win->data->feature & WIN_FEATURE_CLUSTER; ++} ++ ++static void vop2_cfg_done(struct vop2_video_port *vp) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ ++ regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, ++ BIT(vp->id) | RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); ++} ++ ++static void vop2_win_disable(struct vop2_win *win) ++{ ++ vop2_win_write(win, VOP2_WIN_ENABLE, 0); ++ ++ if (vop2_cluster_window(win)) ++ vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 0); ++} ++ ++static enum vop2_data_format vop2_convert_format(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ABGR8888: ++ return VOP2_FMT_ARGB8888; ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_BGR888: ++ return VOP2_FMT_RGB888; ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_BGR565: ++ return VOP2_FMT_RGB565; ++ case DRM_FORMAT_NV12: ++ return VOP2_FMT_YUV420SP; ++ case DRM_FORMAT_NV16: ++ return VOP2_FMT_YUV422SP; ++ case DRM_FORMAT_NV24: ++ return VOP2_FMT_YUV444SP; ++ case DRM_FORMAT_YUYV: ++ case DRM_FORMAT_YVYU: ++ return VOP2_FMT_VYUY422; ++ case DRM_FORMAT_VYUY: ++ case DRM_FORMAT_UYVY: ++ return VOP2_FMT_YUYV422; ++ default: ++ DRM_ERROR("unsupported format[%08x]\n", format); ++ return -EINVAL; ++ } ++} ++ ++static enum vop2_afbc_format vop2_convert_afbc_format(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ABGR8888: ++ return VOP2_AFBC_FMT_ARGB8888; ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_BGR888: ++ return VOP2_AFBC_FMT_RGB888; ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_BGR565: ++ return VOP2_AFBC_FMT_RGB565; ++ case DRM_FORMAT_NV12: ++ return VOP2_AFBC_FMT_YUV420; ++ case DRM_FORMAT_NV16: ++ return VOP2_AFBC_FMT_YUV422; ++ default: ++ return VOP2_AFBC_FMT_INVALID; ++ } ++ ++ return VOP2_AFBC_FMT_INVALID; ++} ++ ++static bool vop2_win_rb_swap(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ABGR8888: ++ case DRM_FORMAT_BGR888: ++ case DRM_FORMAT_BGR565: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool vop2_afbc_rb_swap(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV24: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool vop2_afbc_uv_swap(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV16: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool vop2_win_uv_swap(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_NV12: ++ case DRM_FORMAT_NV16: ++ case DRM_FORMAT_NV24: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool vop2_win_dither_up(u32 format) ++{ ++ switch (format) { ++ case DRM_FORMAT_BGR565: ++ case DRM_FORMAT_RGB565: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool vop2_output_uv_swap(u32 bus_format, u32 output_mode) ++{ ++ /* ++ * FIXME: ++ * ++ * There is no media type for YUV444 output, ++ * so when out_mode is AAAA or P888, assume output is YUV444 on ++ * yuv format. ++ * ++ * From H/W testing, YUV444 mode need a rb swap. ++ */ ++ if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || ++ bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || ++ bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || ++ bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || ++ ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || ++ bus_format == MEDIA_BUS_FMT_YUV10_1X30) && ++ (output_mode == ROCKCHIP_OUT_MODE_AAAA || ++ output_mode == ROCKCHIP_OUT_MODE_P888))) ++ return true; ++ else ++ return false; ++} ++ ++static bool is_yuv_output(u32 bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_YUYV8_2X8: ++ case MEDIA_BUS_FMT_YVYU8_2X8: ++ case MEDIA_BUS_FMT_UYVY8_2X8: ++ case MEDIA_BUS_FMT_VYUY8_2X8: ++ case MEDIA_BUS_FMT_YUYV8_1X16: ++ case MEDIA_BUS_FMT_YVYU8_1X16: ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_VYUY8_1X16: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool rockchip_afbc(struct drm_plane *plane, u64 modifier) ++{ ++ int i; ++ ++ if (modifier == DRM_FORMAT_MOD_LINEAR) ++ return false; ++ ++ for (i = 0 ; i < plane->modifier_count; i++) ++ if (plane->modifiers[i] == modifier) ++ return true; ++ ++ return false; ++ ++} ++ ++static bool rockchip_vop2_mod_supported(struct drm_plane *plane, u32 format, ++ u64 modifier) ++{ ++ struct vop2_win *win = to_vop2_win(plane); ++ struct vop2 *vop2 = win->vop2; ++ ++ if (modifier == DRM_FORMAT_MOD_INVALID) ++ return false; ++ ++ if (modifier == DRM_FORMAT_MOD_LINEAR) ++ return true; ++ ++ if (!rockchip_afbc(plane, modifier)) { ++ drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", ++ modifier); ++ ++ return false; ++ } ++ ++ return vop2_convert_afbc_format(format) >= 0; ++} ++ ++static u32 vop2_afbc_transform_offset(struct drm_plane_state *pstate, ++ bool afbc_half_block_en) ++{ ++ struct drm_rect *src = &pstate->src; ++ struct drm_framebuffer *fb = pstate->fb; ++ u32 bpp = fb->format->cpp[0] * 8; ++ u32 vir_width = (fb->pitches[0] << 3) / bpp; ++ u32 width = drm_rect_width(src) >> 16; ++ u32 height = drm_rect_height(src) >> 16; ++ u32 act_xoffset = src->x1 >> 16; ++ u32 act_yoffset = src->y1 >> 16; ++ u32 align16_crop = 0; ++ u32 align64_crop = 0; ++ u32 height_tmp; ++ u8 tx, ty; ++ u8 bottom_crop_line_num = 0; ++ ++ /* 16 pixel align */ ++ if (height & 0xf) ++ align16_crop = 16 - (height & 0xf); ++ ++ height_tmp = height + align16_crop; ++ ++ /* 64 pixel align */ ++ if (height_tmp & 0x3f) ++ align64_crop = 64 - (height_tmp & 0x3f); ++ ++ bottom_crop_line_num = align16_crop + align64_crop; ++ ++ switch (pstate->rotation & ++ (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y | ++ DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270)) { ++ case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y: ++ tx = 16 - ((act_xoffset + width) & 0xf); ++ ty = bottom_crop_line_num - act_yoffset; ++ break; ++ case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90: ++ tx = bottom_crop_line_num - act_yoffset; ++ ty = vir_width - width - act_xoffset; ++ break; ++ case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270: ++ tx = act_yoffset; ++ ty = act_xoffset; ++ break; ++ case DRM_MODE_REFLECT_X: ++ tx = 16 - ((act_xoffset + width) & 0xf); ++ ty = act_yoffset; ++ break; ++ case DRM_MODE_REFLECT_Y: ++ tx = act_xoffset; ++ ty = bottom_crop_line_num - act_yoffset; ++ break; ++ case DRM_MODE_ROTATE_90: ++ tx = bottom_crop_line_num - act_yoffset; ++ ty = act_xoffset; ++ break; ++ case DRM_MODE_ROTATE_270: ++ tx = act_yoffset; ++ ty = vir_width - width - act_xoffset; ++ break; ++ case 0: ++ tx = act_xoffset; ++ ty = act_yoffset; ++ break; ++ } ++ ++ if (afbc_half_block_en) ++ ty &= 0x7f; ++ ++#define TRANSFORM_XOFFSET GENMASK(7, 0) ++#define TRANSFORM_YOFFSET GENMASK(23, 16) ++ return FIELD_PREP(TRANSFORM_XOFFSET, tx) | ++ FIELD_PREP(TRANSFORM_YOFFSET, ty); ++} ++ ++/* ++ * A Cluster window has 2048 x 16 line buffer, which can ++ * works at 2048 x 16(Full) or 4096 x 8 (Half) mode. ++ * for Cluster_lb_mode register: ++ * 0: half mode, for plane input width range 2048 ~ 4096 ++ * 1: half mode, for cluster work at 2 * 2048 plane mode ++ * 2: half mode, for rotate_90/270 mode ++ * ++ */ ++static int vop2_get_cluster_lb_mode(struct vop2_win *win, ++ struct drm_plane_state *pstate) ++{ ++ if ((pstate->rotation & DRM_MODE_ROTATE_270) || ++ (pstate->rotation & DRM_MODE_ROTATE_90)) ++ return 2; ++ else ++ return 0; ++} ++ ++static u16 vop2_scale_factor(u32 src, u32 dst) ++{ ++ u32 fac; ++ int shift; ++ ++ if (src == dst) ++ return 0; ++ ++ if (dst < 2) ++ return U16_MAX; ++ ++ if (src < 2) ++ return 0; ++ ++ if (src > dst) ++ shift = 12; ++ else ++ shift = 16; ++ ++ src--; ++ dst--; ++ ++ fac = DIV_ROUND_UP(src << shift, dst) - 1; ++ ++ if (fac > U16_MAX) ++ return U16_MAX; ++ ++ return fac; ++} ++ ++static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, ++ u32 src_w, u32 src_h, u32 dst_w, ++ u32 dst_h, u32 pixel_format) ++{ ++ const struct drm_format_info *info; ++ u16 hor_scl_mode, ver_scl_mode; ++ u16 hscl_filter_mode, vscl_filter_mode; ++ u8 gt2 = 0; ++ u8 gt4 = 0; ++ u32 val; ++ ++ info = drm_format_info(pixel_format); ++ ++ if (src_h >= (4 * dst_h)) { ++ gt4 = 1; ++ src_h >>= 2; ++ } else if (src_h >= (2 * dst_h)) { ++ gt2 = 1; ++ src_h >>= 1; ++ } ++ ++ hor_scl_mode = scl_get_scl_mode(src_w, dst_w); ++ ver_scl_mode = scl_get_scl_mode(src_h, dst_h); ++ ++ if (hor_scl_mode == SCALE_UP) ++ hscl_filter_mode = VOP2_SCALE_UP_BIC; ++ else ++ hscl_filter_mode = VOP2_SCALE_DOWN_BIL; ++ ++ if (ver_scl_mode == SCALE_UP) ++ vscl_filter_mode = VOP2_SCALE_UP_BIL; ++ else ++ vscl_filter_mode = VOP2_SCALE_DOWN_BIL; ++ ++ /* ++ * RK3568 VOP Esmart/Smart dsp_w should be even pixel ++ * at scale down mode ++ */ ++ if (!(win->data->feature & WIN_FEATURE_AFBDC)) { ++ if ((hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) { ++ drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", ++ win->data->name, dst_w); ++ dst_w++; ++ } ++ } ++ ++ val = vop2_scale_factor(src_w, dst_w); ++ vop2_win_write(win, VOP2_WIN_SCALE_YRGB_X, val); ++ val = vop2_scale_factor(src_h, dst_h); ++ vop2_win_write(win, VOP2_WIN_SCALE_YRGB_Y, val); ++ ++ vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT4, gt4); ++ vop2_win_write(win, VOP2_WIN_VSD_YRGB_GT2, gt2); ++ ++ vop2_win_write(win, VOP2_WIN_YRGB_HOR_SCL_MODE, hor_scl_mode); ++ vop2_win_write(win, VOP2_WIN_YRGB_VER_SCL_MODE, ver_scl_mode); ++ ++ if (vop2_cluster_window(win)) ++ return; ++ ++ vop2_win_write(win, VOP2_WIN_YRGB_HSCL_FILTER_MODE, hscl_filter_mode); ++ vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); ++ ++ if (info->is_yuv) { ++ src_w /= info->hsub; ++ src_h /= info->vsub; ++ ++ gt4 = gt2 = 0; ++ ++ if (src_h >= (4 * dst_h)) { ++ gt4 = 1; ++ src_h >>= 2; ++ } else if (src_h >= (2 * dst_h)) { ++ gt2 = 1; ++ src_h >>= 1; ++ } ++ ++ hor_scl_mode = scl_get_scl_mode(src_w, dst_w); ++ ver_scl_mode = scl_get_scl_mode(src_h, dst_h); ++ ++ val = vop2_scale_factor(src_w, dst_w); ++ vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); ++ ++ val = vop2_scale_factor(src_h, dst_h); ++ vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); ++ ++ vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4); ++ vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT2, gt2); ++ vop2_win_write(win, VOP2_WIN_CBCR_HOR_SCL_MODE, hor_scl_mode); ++ vop2_win_write(win, VOP2_WIN_CBCR_VER_SCL_MODE, ver_scl_mode); ++ vop2_win_write(win, VOP2_WIN_CBCR_HSCL_FILTER_MODE, hscl_filter_mode); ++ vop2_win_write(win, VOP2_WIN_CBCR_VSCL_FILTER_MODE, vscl_filter_mode); ++ } ++} ++ ++static int vop2_convert_csc_mode(int csc_mode) ++{ ++ switch (csc_mode) { ++ case V4L2_COLORSPACE_SMPTE170M: ++ case V4L2_COLORSPACE_470_SYSTEM_M: ++ case V4L2_COLORSPACE_470_SYSTEM_BG: ++ return CSC_BT601L; ++ case V4L2_COLORSPACE_REC709: ++ case V4L2_COLORSPACE_SMPTE240M: ++ case V4L2_COLORSPACE_DEFAULT: ++ return CSC_BT709L; ++ case V4L2_COLORSPACE_JPEG: ++ return CSC_BT601F; ++ case V4L2_COLORSPACE_BT2020: ++ return CSC_BT2020; ++ default: ++ return CSC_BT709L; ++ } ++} ++ ++/* ++ * colorspace path: ++ * Input Win csc Output ++ * 1. YUV(2020) --> Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709) ++ * RGB --> R2Y __/ ++ * ++ * 2. YUV(2020) --> bypasss --> YUV_OUTPUT(2020) ++ * RGB --> 709To2020->R2Y __/ ++ * ++ * 3. YUV(2020) --> Y2R->2020To709 --> RGB_OUTPUT(709) ++ * RGB --> R2Y __/ ++ * ++ * 4. YUV(601/709)-> Y2R->709To2020->R2Y --> YUV_OUTPUT(2020) ++ * RGB --> 709To2020->R2Y __/ ++ * ++ * 5. YUV(601/709)-> bypass --> YUV_OUTPUT(709) ++ * RGB --> R2Y __/ ++ * ++ * 6. YUV(601/709)-> bypass --> YUV_OUTPUT(601) ++ * RGB --> R2Y(601) __/ ++ * ++ * 7. YUV --> Y2R(709) --> RGB_OUTPUT(709) ++ * RGB --> bypass __/ ++ * ++ * 8. RGB --> 709To2020->R2Y --> YUV_OUTPUT(2020) ++ * ++ * 9. RGB --> R2Y(709) --> YUV_OUTPUT(709) ++ * ++ * 10. RGB --> R2Y(601) --> YUV_OUTPUT(601) ++ * ++ * 11. RGB --> bypass --> RGB_OUTPUT(709) ++ */ ++ ++static void vop2_setup_csc_mode(struct vop2_video_port *vp, ++ struct vop2_win *win, ++ struct drm_plane_state *pstate) ++{ ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); ++ int is_input_yuv = pstate->fb->format->is_yuv; ++ int is_output_yuv = is_yuv_output(vcstate->bus_format); ++ int input_csc = V4L2_COLORSPACE_DEFAULT; ++ int output_csc = vcstate->color_space; ++ bool r2y_en, y2r_en; ++ int csc_mode; ++ ++ if (is_input_yuv && !is_output_yuv) { ++ y2r_en = true; ++ r2y_en = false; ++ csc_mode = vop2_convert_csc_mode(input_csc); ++ } else if (!is_input_yuv && is_output_yuv) { ++ y2r_en = false; ++ r2y_en = true; ++ csc_mode = vop2_convert_csc_mode(output_csc); ++ } else { ++ y2r_en = false; ++ r2y_en = false; ++ csc_mode = false; ++ } ++ ++ vop2_win_write(win, VOP2_WIN_Y2R_EN, y2r_en); ++ vop2_win_write(win, VOP2_WIN_R2Y_EN, r2y_en); ++ vop2_win_write(win, VOP2_WIN_CSC_MODE, csc_mode); ++} ++ ++static void vop2_crtc_enable_irq(struct vop2_video_port *vp, u32 irq) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ ++ vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irq << 16 | irq); ++ vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16 | irq); ++} ++ ++static void vop2_crtc_disable_irq(struct vop2_video_port *vp, u32 irq) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ ++ vop2_writel(vop2, RK3568_VP_INT_EN(vp->id), irq << 16); ++} ++ ++static int vop2_core_clks_prepare_enable(struct vop2 *vop2) ++{ ++ int ret; ++ ++ ret = clk_prepare_enable(vop2->hclk); ++ if (ret < 0) { ++ drm_err(vop2->drm, "failed to enable hclk - %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(vop2->aclk); ++ if (ret < 0) { ++ drm_err(vop2->drm, "failed to enable aclk - %d\n", ret); ++ goto err; ++ } ++ ++ return 0; ++err: ++ clk_disable_unprepare(vop2->hclk); ++ ++ return ret; ++} ++ ++static void vop2_enable(struct vop2 *vop2) ++{ ++ int ret; ++ ++ ret = pm_runtime_get_sync(vop2->dev); ++ if (ret < 0) { ++ drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret); ++ return; ++ } ++ ++ ret = vop2_core_clks_prepare_enable(vop2); ++ if (ret) { ++ pm_runtime_put_sync(vop2->dev); ++ return; ++ } ++ ++ ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev); ++ if (ret) { ++ drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret); ++ return; ++ } ++ ++ if (vop2->data->soc_id == 3566) ++ vop2_writel(vop2, RK3568_OTP_WIN_EN, 1); ++ ++ vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); ++ ++ /* ++ * Disable auto gating, this is a workaround to ++ * avoid display image shift when a window enabled. ++ */ ++ regmap_clear_bits(vop2->map, RK3568_SYS_AUTO_GATING_CTRL, ++ RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN); ++ ++ vop2_writel(vop2, RK3568_SYS0_INT_CLR, ++ VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); ++ vop2_writel(vop2, RK3568_SYS0_INT_EN, ++ VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); ++ vop2_writel(vop2, RK3568_SYS1_INT_CLR, ++ VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); ++ vop2_writel(vop2, RK3568_SYS1_INT_EN, ++ VOP2_INT_BUS_ERRPR << 16 | VOP2_INT_BUS_ERRPR); ++} ++ ++static void vop2_disable(struct vop2 *vop2) ++{ ++ rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); ++ ++ pm_runtime_put_sync(vop2->dev); ++ ++ clk_disable_unprepare(vop2->aclk); ++ clk_disable_unprepare(vop2->hclk); ++} ++ ++static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct vop2 *vop2 = vp->vop2; ++ int ret; ++ ++ vop2_lock(vop2); ++ ++ drm_crtc_vblank_off(crtc); ++ ++ /* ++ * Vop standby will take effect at end of current frame, ++ * if dsp hold valid irq happen, it means standby complete. ++ * ++ * we must wait standby complete when we want to disable aclk, ++ * if not, memory bus maybe dead. ++ */ ++ reinit_completion(&vp->dsp_hold_completion); ++ ++ vop2_crtc_enable_irq(vp, VP_INT_DSP_HOLD_VALID); ++ ++ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, RK3568_VP_DSP_CTRL__STANDBY); ++ ++ ret = wait_for_completion_timeout(&vp->dsp_hold_completion, ++ msecs_to_jiffies(50)); ++ if (!ret) ++ drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id); ++ ++ vop2_crtc_disable_irq(vp, VP_INT_DSP_HOLD_VALID); ++ ++ clk_disable_unprepare(vp->dclk); ++ ++ vop2->enable_count--; ++ ++ if (!vop2->enable_count) ++ vop2_disable(vop2); ++ ++ vop2_unlock(vop2); ++ ++ if (crtc->state->event && !crtc->state->active) { ++ spin_lock_irq(&crtc->dev->event_lock); ++ drm_crtc_send_vblank_event(crtc, crtc->state->event); ++ spin_unlock_irq(&crtc->dev->event_lock); ++ ++ crtc->state->event = NULL; ++ } ++} ++ ++static int vop2_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *astate) ++{ ++ struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane); ++ struct drm_framebuffer *fb = pstate->fb; ++ struct drm_crtc *crtc = pstate->crtc; ++ struct drm_crtc_state *cstate; ++ struct vop2_video_port *vp; ++ struct vop2 *vop2; ++ const struct vop2_data *vop2_data; ++ struct drm_rect *dest = &pstate->dst; ++ struct drm_rect *src = &pstate->src; ++ int min_scale = FRAC_16_16(1, 8); ++ int max_scale = FRAC_16_16(8, 1); ++ int format; ++ int ret; ++ ++ if (!crtc) ++ return 0; ++ ++ vp = to_vop2_video_port(crtc); ++ vop2 = vp->vop2; ++ vop2_data = vop2->data; ++ ++ cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc); ++ if (WARN_ON(!cstate)) ++ return -EINVAL; ++ ++ ret = drm_atomic_helper_check_plane_state(pstate, cstate, ++ min_scale, max_scale, ++ true, true); ++ if (ret) ++ return ret; ++ ++ if (!pstate->visible) ++ return 0; ++ ++ format = vop2_convert_format(fb->format->format); ++ if (format < 0) ++ return format; ++ ++ if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 || ++ drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) { ++ drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n", ++ drm_rect_width(src) >> 16, drm_rect_height(src) >> 16, ++ drm_rect_width(dest), drm_rect_height(dest)); ++ pstate->visible = false; ++ return 0; ++ } ++ ++ if (drm_rect_width(src) >> 16 > vop2_data->max_input.width || ++ drm_rect_height(src) >> 16 > vop2_data->max_input.height) { ++ drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n", ++ drm_rect_width(src) >> 16, ++ drm_rect_height(src) >> 16, ++ vop2_data->max_input.width, ++ vop2_data->max_input.height); ++ return -EINVAL; ++ } ++ ++ /* ++ * Src.x1 can be odd when do clip, but yuv plane start point ++ * need align with 2 pixel. ++ */ ++ if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) { ++ drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void vop2_plane_atomic_disable(struct drm_plane *plane, ++ struct drm_atomic_state *state) ++{ ++ struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane); ++ struct vop2_win *win = to_vop2_win(plane); ++ struct vop2 *vop2 = win->vop2; ++ ++ drm_dbg(vop2->drm, "%s disable\n", win->data->name); ++ ++ if (!old_pstate->crtc) ++ return; ++ ++ vop2_win_disable(win); ++ vop2_win_write(win, VOP2_WIN_YUV_CLIP, 0); ++} ++ ++/* ++ * The color key is 10 bit, so all format should ++ * convert to 10 bit here. ++ */ ++static void vop2_plane_setup_color_key(struct drm_plane *plane, u32 color_key) ++{ ++ struct drm_plane_state *pstate = plane->state; ++ struct drm_framebuffer *fb = pstate->fb; ++ struct vop2_win *win = to_vop2_win(plane); ++ u32 color_key_en = 0; ++ u32 r = 0; ++ u32 g = 0; ++ u32 b = 0; ++ ++ if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { ++ vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, 0); ++ return; ++ } ++ ++ switch (fb->format->format) { ++ case DRM_FORMAT_RGB565: ++ case DRM_FORMAT_BGR565: ++ r = (color_key & 0xf800) >> 11; ++ g = (color_key & 0x7e0) >> 5; ++ b = (color_key & 0x1f); ++ r <<= 5; ++ g <<= 4; ++ b <<= 5; ++ color_key_en = 1; ++ break; ++ case DRM_FORMAT_XRGB8888: ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ABGR8888: ++ case DRM_FORMAT_RGB888: ++ case DRM_FORMAT_BGR888: ++ r = (color_key & 0xff0000) >> 16; ++ g = (color_key & 0xff00) >> 8; ++ b = (color_key & 0xff); ++ r <<= 2; ++ g <<= 2; ++ b <<= 2; ++ color_key_en = 1; ++ break; ++ } ++ ++ vop2_win_write(win, VOP2_WIN_COLOR_KEY_EN, color_key_en); ++ vop2_win_write(win, VOP2_WIN_COLOR_KEY, (r << 20) | (g << 10) | b); ++} ++ ++static void vop2_plane_atomic_update(struct drm_plane *plane, ++ struct drm_atomic_state *state) ++{ ++ struct drm_plane_state *pstate = plane->state; ++ struct drm_crtc *crtc = pstate->crtc; ++ struct vop2_win *win = to_vop2_win(plane); ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; ++ struct vop2 *vop2 = win->vop2; ++ struct drm_framebuffer *fb = pstate->fb; ++ u32 bpp = fb->format->cpp[0] * 8; ++ u32 actual_w, actual_h, dsp_w, dsp_h; ++ u32 act_info, dsp_info; ++ u32 format; ++ u32 afbc_format; ++ u32 rb_swap; ++ u32 uv_swap; ++ struct drm_rect *src = &pstate->src; ++ struct drm_rect *dest = &pstate->dst; ++ u32 afbc_tile_num; ++ u32 transform_offset; ++ bool dither_up; ++ bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; ++ bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; ++ bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; ++ bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; ++ struct rockchip_gem_object *rk_obj; ++ unsigned long offset; ++ bool afbc_en; ++ dma_addr_t yrgb_mst; ++ dma_addr_t uv_mst; ++ ++ /* ++ * can't update plane when vop2 is disabled. ++ */ ++ if (WARN_ON(!crtc)) ++ return; ++ ++ if (!pstate->visible) { ++ vop2_plane_atomic_disable(plane, state); ++ return; ++ } ++ ++ afbc_en = rockchip_afbc(plane, fb->modifier); ++ ++ offset = (src->x1 >> 16) * fb->format->cpp[0]; ++ ++ /* ++ * AFBC HDR_PTR must set to the zero offset of the framebuffer. ++ */ ++ if (afbc_en) ++ offset = 0; ++ else if (pstate->rotation & DRM_MODE_REFLECT_Y) ++ offset += ((src->y2 >> 16) - 1) * fb->pitches[0]; ++ else ++ offset += (src->y1 >> 16) * fb->pitches[0]; ++ ++ rk_obj = to_rockchip_obj(fb->obj[0]); ++ ++ yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; ++ if (fb->format->is_yuv) { ++ int hsub = fb->format->hsub; ++ int vsub = fb->format->vsub; ++ ++ offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub; ++ offset += (src->y1 >> 16) * fb->pitches[1] / vsub; ++ ++ if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en) ++ offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2) / vsub; ++ ++ rk_obj = to_rockchip_obj(fb->obj[0]); ++ uv_mst = rk_obj->dma_addr + offset + fb->offsets[1]; ++ } ++ ++ actual_w = drm_rect_width(src) >> 16; ++ actual_h = drm_rect_height(src) >> 16; ++ dsp_w = drm_rect_width(dest); ++ ++ if (dest->x1 + dsp_w > adjusted_mode->hdisplay) { ++ drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n", ++ vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay); ++ dsp_w = adjusted_mode->hdisplay - dest->x1; ++ if (dsp_w < 4) ++ dsp_w = 4; ++ actual_w = dsp_w * actual_w / drm_rect_width(dest); ++ } ++ ++ dsp_h = drm_rect_height(dest); ++ ++ if (dest->y1 + dsp_h > adjusted_mode->vdisplay) { ++ drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n", ++ vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay); ++ dsp_h = adjusted_mode->vdisplay - dest->y1; ++ if (dsp_h < 4) ++ dsp_h = 4; ++ actual_h = dsp_h * actual_h / drm_rect_height(dest); ++ } ++ ++ /* ++ * This is workaround solution for IC design: ++ * esmart can't support scale down when actual_w % 16 == 1. ++ */ ++ if (!(win->data->feature & WIN_FEATURE_AFBDC)) { ++ if (actual_w > dsp_w && (actual_w & 0xf) == 1) { ++ drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", ++ vp->id, win->data->name, actual_w); ++ actual_w -= 1; ++ } ++ } ++ ++ if (afbc_en && actual_w % 4) { ++ drm_err(vop2->drm, "vp%d %s actual_w[%d] not 4 pixel aligned\n", ++ vp->id, win->data->name, actual_w); ++ actual_w = ALIGN_DOWN(actual_w, 4); ++ } ++ ++ act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); ++ dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff); ++ ++ format = vop2_convert_format(fb->format->format); ++ ++ drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n", ++ vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h, ++ dest->x1, dest->y1, ++ &fb->format->format, ++ afbc_en ? "AFBC" : "", &yrgb_mst); ++ ++ if (afbc_en) { ++ u32 stride; ++ ++ /* the afbc superblock is 16 x 16 */ ++ afbc_format = vop2_convert_afbc_format(fb->format->format); ++ ++ /* Enable color transform for YTR */ ++ if (fb->modifier & AFBC_FORMAT_MOD_YTR) ++ afbc_format |= (1 << 4); ++ ++ afbc_tile_num = ALIGN(actual_w, 16) >> 4; ++ ++ /* ++ * AFBC pic_vir_width is count by pixel, this is different ++ * with WIN_VIR_STRIDE. ++ */ ++ stride = (fb->pitches[0] << 3) / bpp; ++ if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270)) ++ drm_err(vop2->drm, "vp%d %s stride[%d] not 64 pixel aligened\n", ++ vp->id, win->data->name, stride); ++ ++ rb_swap = vop2_afbc_rb_swap(fb->format->format); ++ uv_swap = vop2_afbc_uv_swap(fb->format->format); ++ /* ++ * This is a workaround for crazy IC design, Cluster ++ * and Esmart/Smart use different format configuration map: ++ * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart. ++ * ++ * This is one thing we can make the convert simple: ++ * AFBCD decode all the YUV data to YUV444. So we just ++ * set all the yuv 10 bit to YUV444_10. ++ */ ++ if (fb->format->is_yuv && (bpp == 10)) ++ format = VOP2_CLUSTER_YUV444_10; ++ ++ if (vop2_cluster_window(win)) ++ vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 1); ++ vop2_win_write(win, VOP2_WIN_AFBC_FORMAT, afbc_format); ++ vop2_win_write(win, VOP2_WIN_AFBC_RB_SWAP, rb_swap); ++ vop2_win_write(win, VOP2_WIN_AFBC_UV_SWAP, uv_swap); ++ vop2_win_write(win, VOP2_WIN_AFBC_AUTO_GATING_EN, 0); ++ vop2_win_write(win, VOP2_WIN_AFBC_BLOCK_SPLIT_EN, 0); ++ if (pstate->rotation & (DRM_MODE_ROTATE_270 | DRM_MODE_ROTATE_90)) { ++ vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 0); ++ transform_offset = vop2_afbc_transform_offset(pstate, false); ++ } else { ++ vop2_win_write(win, VOP2_WIN_AFBC_HALF_BLOCK_EN, 1); ++ transform_offset = vop2_afbc_transform_offset(pstate, true); ++ } ++ vop2_win_write(win, VOP2_WIN_AFBC_HDR_PTR, yrgb_mst); ++ vop2_win_write(win, VOP2_WIN_AFBC_PIC_SIZE, act_info); ++ vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, transform_offset); ++ vop2_win_write(win, VOP2_WIN_AFBC_PIC_OFFSET, ((src->x1 >> 16) | src->y1)); ++ vop2_win_write(win, VOP2_WIN_AFBC_DSP_OFFSET, (dest->x1 | (dest->y1 << 16))); ++ vop2_win_write(win, VOP2_WIN_AFBC_PIC_VIR_WIDTH, stride); ++ vop2_win_write(win, VOP2_WIN_AFBC_TILE_NUM, afbc_tile_num); ++ vop2_win_write(win, VOP2_WIN_XMIRROR, xmirror); ++ vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270); ++ vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90); ++ } else { ++ vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4)); ++ } ++ ++ vop2_win_write(win, VOP2_WIN_YMIRROR, ymirror); ++ ++ if (rotate_90 || rotate_270) { ++ act_info = swahw32(act_info); ++ actual_w = drm_rect_height(src) >> 16; ++ actual_h = drm_rect_width(src) >> 16; ++ } ++ ++ vop2_win_write(win, VOP2_WIN_FORMAT, format); ++ vop2_win_write(win, VOP2_WIN_YRGB_MST, yrgb_mst); ++ ++ rb_swap = vop2_win_rb_swap(fb->format->format); ++ vop2_win_write(win, VOP2_WIN_RB_SWAP, rb_swap); ++ if (!vop2_cluster_window(win)) { ++ uv_swap = vop2_win_uv_swap(fb->format->format); ++ vop2_win_write(win, VOP2_WIN_UV_SWAP, uv_swap); ++ } ++ ++ if (fb->format->is_yuv) { ++ vop2_win_write(win, VOP2_WIN_UV_VIR, DIV_ROUND_UP(fb->pitches[1], 4)); ++ vop2_win_write(win, VOP2_WIN_UV_MST, uv_mst); ++ } ++ ++ vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); ++ if (!vop2_cluster_window(win)) ++ vop2_plane_setup_color_key(plane, 0); ++ vop2_win_write(win, VOP2_WIN_ACT_INFO, act_info); ++ vop2_win_write(win, VOP2_WIN_DSP_INFO, dsp_info); ++ vop2_win_write(win, VOP2_WIN_DSP_ST, dest->y1 << 16 | (dest->x1 & 0xffff)); ++ ++ vop2_setup_csc_mode(vp, win, pstate); ++ ++ dither_up = vop2_win_dither_up(fb->format->format); ++ vop2_win_write(win, VOP2_WIN_DITHER_UP, dither_up); ++ ++ vop2_win_write(win, VOP2_WIN_ENABLE, 1); ++ ++ if (vop2_cluster_window(win)) { ++ int lb_mode = vop2_get_cluster_lb_mode(win, pstate); ++ ++ vop2_win_write(win, VOP2_WIN_CLUSTER_LB_MODE, lb_mode); ++ vop2_win_write(win, VOP2_WIN_CLUSTER_ENABLE, 1); ++ } ++} ++ ++static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = { ++ .atomic_check = vop2_plane_atomic_check, ++ .atomic_update = vop2_plane_atomic_update, ++ .atomic_disable = vop2_plane_atomic_disable, ++}; ++ ++static const struct drm_plane_funcs vop2_plane_funcs = { ++ .update_plane = drm_atomic_helper_update_plane, ++ .disable_plane = drm_atomic_helper_disable_plane, ++ .destroy = drm_plane_cleanup, ++ .reset = drm_atomic_helper_plane_reset, ++ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, ++ .format_mod_supported = rockchip_vop2_mod_supported, ++}; ++ ++static int vop2_crtc_enable_vblank(struct drm_crtc *crtc) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ ++ vop2_crtc_enable_irq(vp, VP_INT_FS_FIELD); ++ ++ return 0; ++} ++ ++static void vop2_crtc_disable_vblank(struct drm_crtc *crtc) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ ++ vop2_crtc_disable_irq(vp, VP_INT_FS_FIELD); ++} ++ ++static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, ++ const struct drm_display_mode *mode, ++ struct drm_display_mode *adj_mode) ++{ ++ drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | ++ CRTC_STEREO_DOUBLE); ++ ++ return true; ++} ++ ++static void vop2_dither_setup(struct drm_crtc *crtc, u32 *dsp_ctrl) ++{ ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); ++ ++ switch (vcstate->bus_format) { ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; ++ break; ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: ++ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: ++ *dsp_ctrl |= RK3568_VP_DSP_CTRL__DITHER_DOWN_EN; ++ *dsp_ctrl |= RGB888_TO_RGB666; ++ break; ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; ++ break; ++ default: ++ break; ++ } ++ ++ if (vcstate->output_mode != ROCKCHIP_OUT_MODE_AAAA) ++ *dsp_ctrl |= RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN; ++ ++ *dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL, ++ DITHER_DOWN_ALLEGRO); ++} ++ ++static void vop2_post_config(struct drm_crtc *crtc) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct drm_display_mode *mode = &crtc->state->adjusted_mode; ++ u16 vtotal = mode->crtc_vtotal; ++ u16 hdisplay = mode->crtc_hdisplay; ++ u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; ++ u16 vdisplay = mode->crtc_vdisplay; ++ u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; ++ u32 left_margin = 100, right_margin = 100; ++ u32 top_margin = 100, bottom_margin = 100; ++ u16 hsize = hdisplay * (left_margin + right_margin) / 200; ++ u16 vsize = vdisplay * (top_margin + bottom_margin) / 200; ++ u16 hact_end, vact_end; ++ u32 val; ++ ++ vsize = rounddown(vsize, 2); ++ hsize = rounddown(hsize, 2); ++ hact_st += hdisplay * (100 - left_margin) / 200; ++ hact_end = hact_st + hsize; ++ val = hact_st << 16; ++ val |= hact_end; ++ vop2_vp_write(vp, RK3568_VP_POST_DSP_HACT_INFO, val); ++ vact_st += vdisplay * (100 - top_margin) / 200; ++ vact_end = vact_st + vsize; ++ val = vact_st << 16; ++ val |= vact_end; ++ vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO, val); ++ val = scl_cal_scale2(vdisplay, vsize) << 16; ++ val |= scl_cal_scale2(hdisplay, hsize); ++ vop2_vp_write(vp, RK3568_VP_POST_SCL_FACTOR_YRGB, val); ++ ++ val = 0; ++ if (hdisplay != hsize) ++ val |= RK3568_VP_POST_SCL_CTRL__HSCALEDOWN; ++ if (vdisplay != vsize) ++ val |= RK3568_VP_POST_SCL_CTRL__VSCALEDOWN; ++ vop2_vp_write(vp, RK3568_VP_POST_SCL_CTRL, val); ++ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ++ u16 vact_st_f1 = vtotal + vact_st + 1; ++ u16 vact_end_f1 = vact_st_f1 + vsize; ++ ++ val = vact_st_f1 << 16 | vact_end_f1; ++ vop2_vp_write(vp, RK3568_VP_POST_DSP_VACT_INFO_F1, val); ++ } ++ ++ vop2_vp_write(vp, RK3568_VP_DSP_BG, 0); ++} ++ ++static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id, ++ u32 polflags) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ u32 die, dip; ++ ++ die = vop2_readl(vop2, RK3568_DSP_IF_EN); ++ dip = vop2_readl(vop2, RK3568_DSP_IF_POL); ++ ++ switch (id) { ++ case ROCKCHIP_VOP2_EP_RGB0: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_RGB_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_RGB | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_RGB_MUX, vp->id); ++ if (polflags & POLFLAG_DCLK_INV) ++ regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16) | BIT(3)); ++ else ++ regmap_write(vop2->grf, RK3568_GRF_VO_CON1, BIT(3 + 16)); ++ break; ++ case ROCKCHIP_VOP2_EP_HDMI0: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_HDMI | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id); ++ break; ++ case ROCKCHIP_VOP2_EP_EDP0: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_EDP | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id); ++ break; ++ case ROCKCHIP_VOP2_EP_MIPI0: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_MIPI0 | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX, vp->id); ++ dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; ++ dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); ++ break; ++ case ROCKCHIP_VOP2_EP_MIPI1: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_MIPI1 | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX, vp->id); ++ dip &= ~RK3568_DSP_IF_POL__MIPI_PIN_POL; ++ dip |= FIELD_PREP(RK3568_DSP_IF_POL__MIPI_PIN_POL, polflags); ++ break; ++ case ROCKCHIP_VOP2_EP_LVDS0: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_LVDS0 | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX, vp->id); ++ dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; ++ dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); ++ break; ++ case ROCKCHIP_VOP2_EP_LVDS1: ++ die &= ~RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX; ++ die |= RK3568_SYS_DSP_INFACE_EN_LVDS1 | ++ FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX, vp->id); ++ dip &= ~RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL; ++ dip |= FIELD_PREP(RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL, polflags); ++ break; ++ default: ++ drm_err(vop2->drm, "Invalid interface id %d on vp%d\n", id, vp->id); ++ return; ++ }; ++ ++ dip |= RK3568_DSP_IF_POL__CFG_DONE_IMD; ++ ++ vop2_writel(vop2, RK3568_DSP_IF_EN, die); ++ vop2_writel(vop2, RK3568_DSP_IF_POL, dip); ++} ++ ++static int us_to_vertical_line(struct drm_display_mode *mode, int us) ++{ ++ return us * mode->clock / mode->htotal / 1000; ++} ++ ++static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct vop2 *vop2 = vp->vop2; ++ const struct vop2_data *vop2_data = vop2->data; ++ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; ++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); ++ struct drm_display_mode *mode = &crtc->state->adjusted_mode; ++ unsigned long clock = mode->crtc_clock * 1000; ++ u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; ++ u16 hdisplay = mode->crtc_hdisplay; ++ u16 htotal = mode->crtc_htotal; ++ u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start; ++ u16 hact_end = hact_st + hdisplay; ++ u16 vdisplay = mode->crtc_vdisplay; ++ u16 vtotal = mode->crtc_vtotal; ++ u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; ++ u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start; ++ u16 vact_end = vact_st + vdisplay; ++ u8 out_mode; ++ u32 dsp_ctrl = 0; ++ int act_end; ++ u32 val, polflags; ++ int ret; ++ struct drm_encoder *encoder; ++ ++ drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", ++ hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", ++ drm_mode_vrefresh(mode), vcstate->output_type, vp->id); ++ ++ vop2_lock(vop2); ++ ++ ret = clk_prepare_enable(vp->dclk); ++ if (ret < 0) { ++ drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", ++ vp->id, ret); ++ return; ++ } ++ ++ if (!vop2->enable_count) ++ vop2_enable(vop2); ++ ++ vop2->enable_count++; ++ ++ vop2_crtc_enable_irq(vp, VP_INT_POST_BUF_EMPTY); ++ ++ polflags = 0; ++ if (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ++ polflags |= POLFLAG_DCLK_INV; ++ if (mode->flags & DRM_MODE_FLAG_PHSYNC) ++ polflags |= BIT(HSYNC_POSITIVE); ++ if (mode->flags & DRM_MODE_FLAG_PVSYNC) ++ polflags |= BIT(VSYNC_POSITIVE); ++ ++ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ rk3568_set_intf_mux(vp, rkencoder->crtc_endpoint_id, polflags); ++ } ++ ++ if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && ++ !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ++ out_mode = ROCKCHIP_OUT_MODE_P888; ++ else ++ out_mode = vcstate->output_mode; ++ ++ dsp_ctrl |= FIELD_PREP(RK3568_VP_DSP_CTRL__OUT_MODE, out_mode); ++ ++ if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_RB_SWAP; ++ ++ if (is_yuv_output(vcstate->bus_format)) ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y; ++ ++ vop2_dither_setup(crtc, &dsp_ctrl); ++ ++ vop2_vp_write(vp, RK3568_VP_DSP_HTOTAL_HS_END, (htotal << 16) | hsync_len); ++ val = hact_st << 16; ++ val |= hact_end; ++ vop2_vp_write(vp, RK3568_VP_DSP_HACT_ST_END, val); ++ ++ val = vact_st << 16; ++ val |= vact_end; ++ vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END, val); ++ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ++ u16 vact_st_f1 = vtotal + vact_st + 1; ++ u16 vact_end_f1 = vact_st_f1 + vdisplay; ++ ++ val = vact_st_f1 << 16 | vact_end_f1; ++ vop2_vp_write(vp, RK3568_VP_DSP_VACT_ST_END_F1, val); ++ ++ val = vtotal << 16 | (vtotal + vsync_len); ++ vop2_vp_write(vp, RK3568_VP_DSP_VS_ST_END_F1, val); ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_INTERLACE; ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_FILED_POL; ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__P2I_EN; ++ vtotal += vtotal + 1; ++ act_end = vact_end_f1; ++ } else { ++ act_end = vact_end; ++ } ++ ++ vop2_writel(vop2, RK3568_VP_LINE_FLAG(vp->id), ++ (act_end - us_to_vertical_line(mode, 0)) << 16 | act_end); ++ ++ vop2_vp_write(vp, RK3568_VP_DSP_VTOTAL_VS_END, vtotal << 16 | vsync_len); ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) { ++ dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV; ++ clock *= 2; ++ } ++ ++ vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); ++ ++ clk_set_rate(vp->dclk, clock); ++ ++ vop2_post_config(crtc); ++ ++ vop2_cfg_done(vp); ++ ++ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); ++ ++ drm_crtc_vblank_on(crtc); ++ ++ vop2_unlock(vop2); ++} ++ ++static int vop2_crtc_atomic_check(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct drm_plane *plane; ++ int nplanes = 0; ++ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); ++ ++ drm_atomic_crtc_state_for_each_plane(plane, crtc_state) ++ nplanes++; ++ ++ if (nplanes > vp->nlayers) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static bool is_opaque(u16 alpha) ++{ ++ return (alpha >> 8) == 0xff; ++} ++ ++static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config, ++ struct vop2_alpha *alpha) ++{ ++ int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1; ++ int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1; ++ int src_color_mode = alpha_config->src_premulti_en ? ++ ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; ++ int dst_color_mode = alpha_config->dst_premulti_en ? ++ ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL; ++ ++ alpha->src_color_ctrl.val = 0; ++ alpha->dst_color_ctrl.val = 0; ++ alpha->src_alpha_ctrl.val = 0; ++ alpha->dst_alpha_ctrl.val = 0; ++ ++ if (!alpha_config->src_pixel_alpha_en) ++ alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; ++ else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en) ++ alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX; ++ else ++ alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; ++ ++ alpha->src_color_ctrl.bits.alpha_en = 1; ++ ++ if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) { ++ alpha->src_color_ctrl.bits.color_mode = src_color_mode; ++ alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; ++ } else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) { ++ alpha->src_color_ctrl.bits.color_mode = src_color_mode; ++ alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE; ++ } else { ++ alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL; ++ alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL; ++ } ++ alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8; ++ alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; ++ alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; ++ ++ alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; ++ alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; ++ alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL; ++ alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8; ++ alpha->dst_color_ctrl.bits.color_mode = dst_color_mode; ++ alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; ++ ++ alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; ++ alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode; ++ alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION; ++ alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE; ++ ++ alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT; ++ if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en) ++ alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX; ++ else ++ alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL; ++ alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION; ++ alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE; ++} ++ ++static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, u8 port_id) ++{ ++ struct vop2_video_port *vp; ++ int used_layer = 0; ++ int i; ++ ++ for (i = 0; i < port_id; i++) { ++ vp = &vop2->vps[i]; ++ used_layer += hweight32(vp->win_mask); ++ } ++ ++ return used_layer; ++} ++ ++static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_win *main_win) ++{ ++ u32 offset = (main_win->data->phys_id * 0x10); ++ struct vop2_alpha_config alpha_config; ++ struct vop2_alpha alpha; ++ struct drm_plane_state *bottom_win_pstate; ++ bool src_pixel_alpha_en = false; ++ u16 src_glb_alpha_val, dst_glb_alpha_val; ++ bool premulti_en = false; ++ bool swap = false; ++ ++ /* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */ ++ bottom_win_pstate = main_win->base.state; ++ src_glb_alpha_val = 0; ++ dst_glb_alpha_val = main_win->base.state->alpha; ++ ++ if (!bottom_win_pstate->fb) ++ return; ++ ++ alpha_config.src_premulti_en = premulti_en; ++ alpha_config.dst_premulti_en = false; ++ alpha_config.src_pixel_alpha_en = src_pixel_alpha_en; ++ alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ ++ alpha_config.src_glb_alpha_value = src_glb_alpha_val; ++ alpha_config.dst_glb_alpha_value = dst_glb_alpha_val; ++ vop2_parse_alpha(&alpha_config, &alpha); ++ ++ alpha.src_color_ctrl.bits.src_dst_swap = swap; ++ vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL + offset, ++ alpha.src_color_ctrl.val); ++ vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_COLOR_CTRL + offset, ++ alpha.dst_color_ctrl.val); ++ vop2_writel(vop2, RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL + offset, ++ alpha.src_alpha_ctrl.val); ++ vop2_writel(vop2, RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL + offset, ++ alpha.dst_alpha_ctrl.val); ++} ++ ++static void vop2_setup_alpha(struct vop2_video_port *vp) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ struct drm_framebuffer *fb; ++ struct vop2_alpha_config alpha_config; ++ struct vop2_alpha alpha; ++ struct drm_plane *plane; ++ int pixel_alpha_en; ++ int premulti_en, gpremulti_en = 0; ++ int mixer_id; ++ u32 offset; ++ bool bottom_layer_alpha_en = false; ++ u32 dst_global_alpha = DRM_BLEND_ALPHA_OPAQUE; ++ ++ mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id); ++ alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */ ++ ++ drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { ++ struct vop2_win *win = to_vop2_win(plane); ++ ++ if (plane->state->normalized_zpos == 0 && ++ !is_opaque(plane->state->alpha) && ++ !vop2_cluster_window(win)) { ++ /* ++ * If bottom layer have global alpha effect [except cluster layer, ++ * because cluster have deal with bottom layer global alpha value ++ * at cluster mix], bottom layer mix need deal with global alpha. ++ */ ++ bottom_layer_alpha_en = true; ++ dst_global_alpha = plane->state->alpha; ++ } ++ } ++ ++ drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { ++ struct vop2_win *win = to_vop2_win(plane); ++ int zpos = plane->state->normalized_zpos; ++ ++ if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) ++ premulti_en = 1; ++ else ++ premulti_en = 0; ++ ++ plane = &win->base; ++ fb = plane->state->fb; ++ ++ pixel_alpha_en = fb->format->has_alpha; ++ ++ alpha_config.src_premulti_en = premulti_en; ++ ++ if (bottom_layer_alpha_en && zpos == 1) { ++ gpremulti_en = premulti_en; ++ /* Cd = Cs + (1 - As) * Cd * Agd */ ++ alpha_config.dst_premulti_en = false; ++ alpha_config.src_pixel_alpha_en = pixel_alpha_en; ++ alpha_config.src_glb_alpha_value = plane->state->alpha; ++ alpha_config.dst_glb_alpha_value = dst_global_alpha; ++ } else if (vop2_cluster_window(win)) { ++ /* Mix output data only have pixel alpha */ ++ alpha_config.dst_premulti_en = true; ++ alpha_config.src_pixel_alpha_en = true; ++ alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; ++ alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; ++ } else { ++ /* Cd = Cs + (1 - As) * Cd */ ++ alpha_config.dst_premulti_en = true; ++ alpha_config.src_pixel_alpha_en = pixel_alpha_en; ++ alpha_config.src_glb_alpha_value = plane->state->alpha; ++ alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; ++ } ++ ++ vop2_parse_alpha(&alpha_config, &alpha); ++ ++ offset = (mixer_id + zpos - 1) * 0x10; ++ vop2_writel(vop2, RK3568_MIX0_SRC_COLOR_CTRL + offset, ++ alpha.src_color_ctrl.val); ++ vop2_writel(vop2, RK3568_MIX0_DST_COLOR_CTRL + offset, ++ alpha.dst_color_ctrl.val); ++ vop2_writel(vop2, RK3568_MIX0_SRC_ALPHA_CTRL + offset, ++ alpha.src_alpha_ctrl.val); ++ vop2_writel(vop2, RK3568_MIX0_DST_ALPHA_CTRL + offset, ++ alpha.dst_alpha_ctrl.val); ++ } ++ ++ if (vp->id == 0) { ++ if (bottom_layer_alpha_en) { ++ /* Transfer pixel alpha to hdr mix */ ++ alpha_config.src_premulti_en = gpremulti_en; ++ alpha_config.dst_premulti_en = true; ++ alpha_config.src_pixel_alpha_en = true; ++ alpha_config.src_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; ++ alpha_config.dst_glb_alpha_value = DRM_BLEND_ALPHA_OPAQUE; ++ vop2_parse_alpha(&alpha_config, &alpha); ++ ++ vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, ++ alpha.src_color_ctrl.val); ++ vop2_writel(vop2, RK3568_HDR0_DST_COLOR_CTRL, ++ alpha.dst_color_ctrl.val); ++ vop2_writel(vop2, RK3568_HDR0_SRC_ALPHA_CTRL, ++ alpha.src_alpha_ctrl.val); ++ vop2_writel(vop2, RK3568_HDR0_DST_ALPHA_CTRL, ++ alpha.dst_alpha_ctrl.val); ++ } else { ++ vop2_writel(vop2, RK3568_HDR0_SRC_COLOR_CTRL, 0); ++ } ++ } ++} ++ ++static void vop2_setup_layer_mixer(struct vop2_video_port *vp) ++{ ++ struct vop2 *vop2 = vp->vop2; ++ struct drm_plane *plane; ++ u32 layer_sel = 0; ++ u32 port_sel; ++ unsigned int nlayer, ofs; ++ struct drm_display_mode *adjusted_mode; ++ u16 hsync_len; ++ u16 hdisplay; ++ u32 bg_dly; ++ u32 pre_scan_dly; ++ int i; ++ struct vop2_video_port *vp0 = &vop2->vps[0]; ++ struct vop2_video_port *vp1 = &vop2->vps[1]; ++ struct vop2_video_port *vp2 = &vop2->vps[2]; ++ ++ adjusted_mode = &vp->crtc.state->adjusted_mode; ++ hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; ++ hdisplay = adjusted_mode->crtc_hdisplay; ++ ++ bg_dly = vp->data->pre_scan_max_dly[3]; ++ vop2_writel(vop2, RK3568_VP_BG_MIX_CTRL(vp->id), ++ FIELD_PREP(RK3568_VP_BG_MIX_CTRL__BG_DLY, bg_dly)); ++ ++ pre_scan_dly = ((bg_dly + (hdisplay >> 1) - 1) << 16) | hsync_len; ++ vop2_vp_write(vp, RK3568_VP_PRE_SCAN_HTIMING, pre_scan_dly); ++ ++ vop2_writel(vop2, RK3568_OVL_CTRL, 0); ++ port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); ++ port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; ++ ++ if (vp0->nlayers) ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, ++ vp0->nlayers - 1); ++ else ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT0_MUX, 8); ++ ++ if (vp1->nlayers) ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, ++ (vp0->nlayers + vp1->nlayers - 1)); ++ else ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); ++ ++ if (vp2->nlayers) ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, ++ (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); ++ else ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); ++ ++ layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); ++ ++ ofs = 0; ++ for (i = 0; i < vp->id; i++) ++ ofs += vop2->vps[i].nlayers; ++ ++ nlayer = 0; ++ drm_atomic_crtc_for_each_plane(plane, &vp->crtc) { ++ struct vop2_win *win = to_vop2_win(plane); ++ ++ switch (win->data->phys_id) { ++ case ROCKCHIP_VOP2_CLUSTER0: ++ port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER0; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER0, vp->id); ++ break; ++ case ROCKCHIP_VOP2_CLUSTER1: ++ port_sel &= ~RK3568_OVL_PORT_SEL__CLUSTER1; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__CLUSTER1, vp->id); ++ break; ++ case ROCKCHIP_VOP2_ESMART0: ++ port_sel &= ~RK3568_OVL_PORT_SEL__ESMART0; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART0, vp->id); ++ break; ++ case ROCKCHIP_VOP2_ESMART1: ++ port_sel &= ~RK3568_OVL_PORT_SEL__ESMART1; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__ESMART1, vp->id); ++ break; ++ case ROCKCHIP_VOP2_SMART0: ++ port_sel &= ~RK3568_OVL_PORT_SEL__SMART0; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART0, vp->id); ++ break; ++ case ROCKCHIP_VOP2_SMART1: ++ port_sel &= ~RK3568_OVL_PORT_SEL__SMART1; ++ port_sel |= FIELD_PREP(RK3568_OVL_PORT_SEL__SMART1, vp->id); ++ break; ++ } ++ ++ layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, ++ 0x7); ++ layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(plane->state->normalized_zpos + ofs, ++ win->data->layer_sel_id); ++ nlayer++; ++ } ++ ++ /* configure unused layers to 0x5 (reserved) */ ++ for (; nlayer < vp->nlayers; nlayer++) { ++ layer_sel &= ~RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 0x7); ++ layer_sel |= RK3568_OVL_LAYER_SEL__LAYER(nlayer + ofs, 5); ++ } ++ ++ vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); ++ vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); ++ vop2_writel(vop2, RK3568_OVL_CTRL, RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD); ++} ++ ++static void vop2_setup_dly_for_windows(struct vop2 *vop2) ++{ ++ struct vop2_win *win; ++ int i = 0; ++ u32 cdly = 0, sdly = 0; ++ ++ for (i = 0; i < vop2->data->win_size; i++) { ++ u32 dly; ++ ++ win = &vop2->win[i]; ++ dly = win->delay; ++ ++ switch (win->data->phys_id) { ++ case ROCKCHIP_VOP2_CLUSTER0: ++ cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_0, dly); ++ cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER0_1, dly); ++ break; ++ case ROCKCHIP_VOP2_CLUSTER1: ++ cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_0, dly); ++ cdly |= FIELD_PREP(RK3568_CLUSTER_DLY_NUM__CLUSTER1_1, dly); ++ break; ++ case ROCKCHIP_VOP2_ESMART0: ++ sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART0, dly); ++ break; ++ case ROCKCHIP_VOP2_ESMART1: ++ sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__ESMART1, dly); ++ break; ++ case ROCKCHIP_VOP2_SMART0: ++ sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART0, dly); ++ break; ++ case ROCKCHIP_VOP2_SMART1: ++ sdly |= FIELD_PREP(RK3568_SMART_DLY_NUM__SMART1, dly); ++ break; ++ } ++ } ++ ++ vop2_writel(vop2, RK3568_CLUSTER_DLY_NUM, cdly); ++ vop2_writel(vop2, RK3568_SMART_DLY_NUM, sdly); ++} ++ ++static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct vop2 *vop2 = vp->vop2; ++ struct drm_plane *plane; ++ ++ vp->win_mask = 0; ++ ++ drm_atomic_crtc_for_each_plane(plane, crtc) { ++ struct vop2_win *win = to_vop2_win(plane); ++ ++ win->delay = win->data->dly[VOP2_DLY_MODE_DEFAULT]; ++ ++ vp->win_mask |= BIT(win->data->phys_id); ++ ++ if (vop2_cluster_window(win)) ++ vop2_setup_cluster_alpha(vop2, win); ++ } ++ ++ if (!vp->win_mask) ++ return; ++ ++ vop2_setup_layer_mixer(vp); ++ vop2_setup_alpha(vp); ++ vop2_setup_dly_for_windows(vop2); ++} ++ ++static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ ++ vop2_post_config(crtc); ++ ++ vop2_cfg_done(vp); ++ ++ spin_lock_irq(&crtc->dev->event_lock); ++ ++ if (crtc->state->event) { ++ WARN_ON(drm_crtc_vblank_get(crtc)); ++ vp->event = crtc->state->event; ++ crtc->state->event = NULL; ++ } ++ ++ spin_unlock_irq(&crtc->dev->event_lock); ++} ++ ++static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = { ++ .mode_fixup = vop2_crtc_mode_fixup, ++ .atomic_check = vop2_crtc_atomic_check, ++ .atomic_begin = vop2_crtc_atomic_begin, ++ .atomic_flush = vop2_crtc_atomic_flush, ++ .atomic_enable = vop2_crtc_atomic_enable, ++ .atomic_disable = vop2_crtc_atomic_disable, ++}; ++ ++static void vop2_crtc_reset(struct drm_crtc *crtc) ++{ ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); ++ ++ if (crtc->state) { ++ __drm_atomic_helper_crtc_destroy_state(crtc->state); ++ kfree(vcstate); ++ } ++ ++ vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL); ++ if (!vcstate) ++ return; ++ ++ crtc->state = &vcstate->base; ++ crtc->state->crtc = crtc; ++} ++ ++static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) ++{ ++ struct rockchip_crtc_state *vcstate, *old_vcstate; ++ ++ old_vcstate = to_rockchip_crtc_state(crtc->state); ++ ++ vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL); ++ if (!vcstate) ++ return NULL; ++ ++ __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); ++ ++ return &vcstate->base; ++} ++ ++static void vop2_crtc_destroy_state(struct drm_crtc *crtc, ++ struct drm_crtc_state *state) ++{ ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state); ++ ++ __drm_atomic_helper_crtc_destroy_state(&vcstate->base); ++ kfree(vcstate); ++} ++ ++static const struct drm_crtc_funcs vop2_crtc_funcs = { ++ .set_config = drm_atomic_helper_set_config, ++ .page_flip = drm_atomic_helper_page_flip, ++ .destroy = drm_crtc_cleanup, ++ .reset = vop2_crtc_reset, ++ .atomic_duplicate_state = vop2_crtc_duplicate_state, ++ .atomic_destroy_state = vop2_crtc_destroy_state, ++ .enable_vblank = vop2_crtc_enable_vblank, ++ .disable_vblank = vop2_crtc_disable_vblank, ++}; ++ ++static irqreturn_t vop2_isr(int irq, void *data) ++{ ++ struct vop2 *vop2 = data; ++ const struct vop2_data *vop2_data = vop2->data; ++ u32 axi_irqs[VOP2_SYS_AXI_BUS_NUM]; ++ int ret = IRQ_NONE; ++ int i; ++ ++ /* ++ * The irq is shared with the iommu. If the runtime-pm state of the ++ * vop2-device is disabled the irq has to be targeted at the iommu. ++ */ ++ if (!pm_runtime_get_if_in_use(vop2->dev)) ++ return IRQ_NONE; ++ ++ for (i = 0; i < vop2_data->nr_vps; i++) { ++ struct vop2_video_port *vp = &vop2->vps[i]; ++ struct drm_crtc *crtc = &vp->crtc; ++ u32 irqs; ++ ++ irqs = vop2_readl(vop2, RK3568_VP_INT_STATUS(vp->id)); ++ vop2_writel(vop2, RK3568_VP_INT_CLR(vp->id), irqs << 16 | irqs); ++ ++ if (irqs & VP_INT_DSP_HOLD_VALID) { ++ complete(&vp->dsp_hold_completion); ++ ret = IRQ_HANDLED; ++ } ++ ++ if (irqs & VP_INT_FS_FIELD) { ++ drm_crtc_handle_vblank(crtc); ++ spin_lock(&crtc->dev->event_lock); ++ if (vp->event) { ++ u32 val = vop2_readl(vop2, RK3568_REG_CFG_DONE); ++ ++ if (!(val & BIT(vp->id))) { ++ drm_crtc_send_vblank_event(crtc, vp->event); ++ vp->event = NULL; ++ drm_crtc_vblank_put(crtc); ++ } ++ } ++ spin_unlock(&crtc->dev->event_lock); ++ ++ ret = IRQ_HANDLED; ++ } ++ ++ if (irqs & VP_INT_POST_BUF_EMPTY) { ++ drm_err_ratelimited(vop2->drm, ++ "POST_BUF_EMPTY irq err at vp%d\n", ++ vp->id); ++ ret = IRQ_HANDLED; ++ } ++ } ++ ++ axi_irqs[0] = vop2_readl(vop2, RK3568_SYS0_INT_STATUS); ++ vop2_writel(vop2, RK3568_SYS0_INT_CLR, axi_irqs[0] << 16 | axi_irqs[0]); ++ axi_irqs[1] = vop2_readl(vop2, RK3568_SYS1_INT_STATUS); ++ vop2_writel(vop2, RK3568_SYS1_INT_CLR, axi_irqs[1] << 16 | axi_irqs[1]); ++ ++ for (i = 0; i < ARRAY_SIZE(axi_irqs); i++) { ++ if (axi_irqs[i] & VOP2_INT_BUS_ERRPR) { ++ drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n"); ++ ret = IRQ_HANDLED; ++ } ++ } ++ ++ pm_runtime_put(vop2->dev); ++ ++ return ret; ++} ++ ++static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, ++ unsigned long possible_crtcs) ++{ ++ const struct vop2_win_data *win_data = win->data; ++ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | ++ BIT(DRM_MODE_BLEND_PREMULTI) | ++ BIT(DRM_MODE_BLEND_COVERAGE); ++ int ret; ++ ++ ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs, ++ &vop2_plane_funcs, win_data->formats, ++ win_data->nformats, ++ win_data->format_modifiers, ++ win->type, win_data->name); ++ if (ret) { ++ drm_err(vop2->drm, "failed to initialize plane %d\n", ret); ++ return ret; ++ } ++ ++ drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs); ++ ++ if (win->data->supported_rotations) ++ drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0, ++ DRM_MODE_ROTATE_0 | ++ win->data->supported_rotations); ++ drm_plane_create_alpha_property(&win->base); ++ drm_plane_create_blend_mode_property(&win->base, blend_caps); ++ drm_plane_create_zpos_property(&win->base, win->win_id, 0, ++ vop2->registered_num_wins - 1); ++ ++ return 0; ++} ++ ++static struct vop2_video_port *find_vp_without_primary(struct vop2 *vop2) ++{ ++ int i; ++ ++ for (i = 0; i < vop2->data->nr_vps; i++) { ++ struct vop2_video_port *vp = &vop2->vps[i]; ++ ++ if (!vp->crtc.port) ++ continue; ++ if (vp->primary_plane) ++ continue; ++ ++ return vp; ++ } ++ ++ return NULL; ++} ++ ++#define NR_LAYERS 6 ++ ++static int vop2_create_crtc(struct vop2 *vop2) ++{ ++ const struct vop2_data *vop2_data = vop2->data; ++ struct drm_device *drm = vop2->drm; ++ struct device *dev = vop2->dev; ++ struct drm_plane *plane; ++ struct device_node *port; ++ struct vop2_video_port *vp; ++ int i, nvp, nvps = 0; ++ int ret; ++ ++ for (i = 0; i < vop2_data->nr_vps; i++) { ++ const struct vop2_video_port_data *vp_data; ++ struct device_node *np; ++ char dclk_name[9]; ++ ++ vp_data = &vop2_data->vp[i]; ++ vp = &vop2->vps[i]; ++ vp->vop2 = vop2; ++ vp->id = vp_data->id; ++ vp->regs = vp_data->regs; ++ vp->data = vp_data; ++ ++ snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); ++ vp->dclk = devm_clk_get(vop2->dev, dclk_name); ++ if (IS_ERR(vp->dclk)) { ++ drm_err(vop2->drm, "failed to get %s\n", dclk_name); ++ return PTR_ERR(vp->dclk); ++ } ++ ++ np = of_graph_get_remote_node(dev->of_node, i, -1); ++ if (!np) { ++ drm_dbg(vop2->drm, "%s: No remote for vp%d\n", __func__, i); ++ continue; ++ } ++ of_node_put(np); ++ ++ port = of_graph_get_port_by_id(dev->of_node, i); ++ if (!port) { ++ drm_err(vop2->drm, "no port node found for video_port%d\n", i); ++ return -ENOENT; ++ } ++ ++ vp->crtc.port = port; ++ nvps++; ++ } ++ ++ nvp = 0; ++ for (i = 0; i < vop2->registered_num_wins; i++) { ++ struct vop2_win *win = &vop2->win[i]; ++ u32 possible_crtcs; ++ ++ if (vop2->data->soc_id == 3566) { ++ /* ++ * On RK3566 these windows don't have an independent ++ * framebuffer. They share the framebuffer with smart0, ++ * esmart0 and cluster0 respectively. ++ */ ++ switch (win->data->phys_id) { ++ case ROCKCHIP_VOP2_SMART1: ++ case ROCKCHIP_VOP2_ESMART1: ++ case ROCKCHIP_VOP2_CLUSTER1: ++ continue; ++ } ++ } ++ ++ if (win->type == DRM_PLANE_TYPE_PRIMARY) { ++ vp = find_vp_without_primary(vop2); ++ if (vp) { ++ possible_crtcs = BIT(nvp); ++ vp->primary_plane = win; ++ nvp++; ++ } else { ++ /* change the unused primary window to overlay window */ ++ win->type = DRM_PLANE_TYPE_OVERLAY; ++ } ++ } ++ ++ if (win->type == DRM_PLANE_TYPE_OVERLAY) ++ possible_crtcs = (1 << nvps) - 1; ++ ++ ret = vop2_plane_init(vop2, win, possible_crtcs); ++ if (ret) { ++ drm_err(vop2->drm, "failed to init plane %s: %d\n", ++ win->data->name, ret); ++ return ret; ++ } ++ } ++ ++ for (i = 0; i < vop2_data->nr_vps; i++) { ++ vp = &vop2->vps[i]; ++ ++ if (!vp->crtc.port) ++ continue; ++ ++ plane = &vp->primary_plane->base; ++ ++ ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL, ++ &vop2_crtc_funcs, ++ "video_port%d", vp->id); ++ if (ret) { ++ drm_err(vop2->drm, "crtc init for video_port%d failed\n", i); ++ return ret; ++ } ++ ++ drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs); ++ ++ init_completion(&vp->dsp_hold_completion); ++ } ++ ++ /* ++ * On the VOP2 it's very hard to change the number of layers on a VP ++ * during runtime, so we distribute the layers equally over the used ++ * VPs ++ */ ++ for (i = 0; i < vop2->data->nr_vps; i++) { ++ struct vop2_video_port *vp = &vop2->vps[i]; ++ ++ if (vp->crtc.port) ++ vp->nlayers = NR_LAYERS / nvps; ++ } ++ ++ return 0; ++} ++ ++static void vop2_destroy_crtc(struct drm_crtc *crtc) ++{ ++ of_node_put(crtc->port); ++ ++ /* ++ * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane() ++ * references the CRTC. ++ */ ++ drm_crtc_cleanup(crtc); ++} ++ ++static struct reg_field vop2_cluster_regs[VOP2_WIN_MAX_REG] = { ++ [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 0, 0), ++ [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 1, 5), ++ [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 14, 14), ++ [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 18, 18), ++ [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_ACT_INFO, 0, 31), ++ [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_INFO, 0, 31), ++ [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_CLUSTER_WIN_DSP_ST, 0, 31), ++ [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_CLUSTER_WIN_YRGB_MST, 0, 31), ++ [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_CLUSTER_WIN_CBR_MST, 0, 31), ++ [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 19, 19), ++ [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 0, 15), ++ [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_CLUSTER_WIN_VIR, 16, 31), ++ [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 8, 8), ++ [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 9, 9), ++ [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL0, 10, 11), ++ ++ /* Scale */ ++ [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0, 15), ++ [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 16, 31), ++ [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 14, 15), ++ [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 12, 13), ++ [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 2, 3), ++ [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 28, 28), ++ [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_CLUSTER_WIN_CTRL1, 29, 29), ++ ++ /* cluster regs */ ++ [VOP2_WIN_AFBC_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 1, 1), ++ [VOP2_WIN_CLUSTER_ENABLE] = REG_FIELD(RK3568_CLUSTER_CTRL, 0, 0), ++ [VOP2_WIN_CLUSTER_LB_MODE] = REG_FIELD(RK3568_CLUSTER_CTRL, 4, 7), ++ ++ /* afbc regs */ ++ [VOP2_WIN_AFBC_FORMAT] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 2, 6), ++ [VOP2_WIN_AFBC_RB_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 9, 9), ++ [VOP2_WIN_AFBC_UV_SWAP] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 10, 10), ++ [VOP2_WIN_AFBC_AUTO_GATING_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 4, 4), ++ [VOP2_WIN_AFBC_HALF_BLOCK_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 7, 7), ++ [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_CTRL, 8, 8), ++ [VOP2_WIN_AFBC_HDR_PTR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0, 31), ++ [VOP2_WIN_AFBC_PIC_SIZE] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0, 31), ++ [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0, 15), ++ [VOP2_WIN_AFBC_TILE_NUM] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 16, 31), ++ [VOP2_WIN_AFBC_PIC_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0, 31), ++ [VOP2_WIN_AFBC_DSP_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0, 31), ++ [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0, 31), ++ [VOP2_WIN_AFBC_ROTATE_90] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0, 0), ++ [VOP2_WIN_AFBC_ROTATE_270] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 1, 1), ++ [VOP2_WIN_XMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 2, 2), ++ [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 3, 3), ++ [VOP2_WIN_UV_SWAP] = { .reg = 0xffffffff }, ++ [VOP2_WIN_COLOR_KEY] = { .reg = 0xffffffff }, ++ [VOP2_WIN_COLOR_KEY_EN] = { .reg = 0xffffffff }, ++ [VOP2_WIN_SCALE_CBCR_X] = { .reg = 0xffffffff }, ++ [VOP2_WIN_SCALE_CBCR_Y] = { .reg = 0xffffffff }, ++ [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CBCR_VER_SCL_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CBCR_HOR_SCL_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_VSD_CBCR_GT2] = { .reg = 0xffffffff }, ++ [VOP2_WIN_VSD_CBCR_GT4] = { .reg = 0xffffffff }, ++}; ++ ++static int vop2_cluster_init(struct vop2_win *win) ++{ ++ struct vop2 *vop2 = win->vop2; ++ struct reg_field *cluster_regs; ++ int ret, i; ++ ++ cluster_regs = kmemdup(vop2_cluster_regs, sizeof(vop2_cluster_regs), ++ GFP_KERNEL); ++ if (!cluster_regs) ++ return -ENOMEM; ++ ++ for (i = 0; i < ARRAY_SIZE(vop2_cluster_regs); i++) ++ if (cluster_regs[i].reg != 0xffffffff) ++ cluster_regs[i].reg += win->offset; ++ ++ ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, ++ cluster_regs, ++ ARRAY_SIZE(vop2_cluster_regs)); ++ ++ kfree(cluster_regs); ++ ++ return ret; ++}; ++ ++static struct reg_field vop2_esmart_regs[VOP2_WIN_MAX_REG] = { ++ [VOP2_WIN_ENABLE] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 0, 0), ++ [VOP2_WIN_FORMAT] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 1, 5), ++ [VOP2_WIN_DITHER_UP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 12, 12), ++ [VOP2_WIN_RB_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 14, 14), ++ [VOP2_WIN_UV_SWAP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 16, 16), ++ [VOP2_WIN_ACT_INFO] = REG_FIELD(RK3568_SMART_REGION0_ACT_INFO, 0, 31), ++ [VOP2_WIN_DSP_INFO] = REG_FIELD(RK3568_SMART_REGION0_DSP_INFO, 0, 31), ++ [VOP2_WIN_DSP_ST] = REG_FIELD(RK3568_SMART_REGION0_DSP_ST, 0, 28), ++ [VOP2_WIN_YRGB_MST] = REG_FIELD(RK3568_SMART_REGION0_YRGB_MST, 0, 31), ++ [VOP2_WIN_UV_MST] = REG_FIELD(RK3568_SMART_REGION0_CBR_MST, 0, 31), ++ [VOP2_WIN_YUV_CLIP] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 17, 17), ++ [VOP2_WIN_YRGB_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 0, 15), ++ [VOP2_WIN_UV_VIR] = REG_FIELD(RK3568_SMART_REGION0_VIR, 16, 31), ++ [VOP2_WIN_Y2R_EN] = REG_FIELD(RK3568_SMART_CTRL0, 0, 0), ++ [VOP2_WIN_R2Y_EN] = REG_FIELD(RK3568_SMART_CTRL0, 1, 1), ++ [VOP2_WIN_CSC_MODE] = REG_FIELD(RK3568_SMART_CTRL0, 2, 3), ++ [VOP2_WIN_YMIRROR] = REG_FIELD(RK3568_SMART_CTRL1, 31, 31), ++ [VOP2_WIN_COLOR_KEY] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 0, 29), ++ [VOP2_WIN_COLOR_KEY_EN] = REG_FIELD(RK3568_SMART_COLOR_KEY_CTRL, 31, 31), ++ ++ /* Scale */ ++ [VOP2_WIN_SCALE_YRGB_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0, 15), ++ [VOP2_WIN_SCALE_YRGB_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 16, 31), ++ [VOP2_WIN_SCALE_CBCR_X] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0, 15), ++ [VOP2_WIN_SCALE_CBCR_Y] = REG_FIELD(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 16, 31), ++ [VOP2_WIN_YRGB_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 0, 1), ++ [VOP2_WIN_YRGB_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 2, 3), ++ [VOP2_WIN_YRGB_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 4, 5), ++ [VOP2_WIN_YRGB_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 6, 7), ++ [VOP2_WIN_CBCR_HOR_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 8, 9), ++ [VOP2_WIN_CBCR_HSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 10, 11), ++ [VOP2_WIN_CBCR_VER_SCL_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 12, 13), ++ [VOP2_WIN_CBCR_VSCL_FILTER_MODE] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 14, 15), ++ [VOP2_WIN_BIC_COE_SEL] = REG_FIELD(RK3568_SMART_REGION0_SCL_CTRL, 16, 17), ++ [VOP2_WIN_VSD_YRGB_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 8, 8), ++ [VOP2_WIN_VSD_YRGB_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 9, 9), ++ [VOP2_WIN_VSD_CBCR_GT2] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 10, 10), ++ [VOP2_WIN_VSD_CBCR_GT4] = REG_FIELD(RK3568_SMART_REGION0_CTRL, 11, 11), ++ [VOP2_WIN_XMIRROR] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CLUSTER_ENABLE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_ENABLE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_CLUSTER_LB_MODE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_FORMAT] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_RB_SWAP] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_UV_SWAP] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_AUTO_GATING_EN] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_BLOCK_SPLIT_EN] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_PIC_VIR_WIDTH] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_TILE_NUM] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_PIC_OFFSET] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_PIC_SIZE] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_DSP_OFFSET] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_TRANSFORM_OFFSET] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_HDR_PTR] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_HALF_BLOCK_EN] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_ROTATE_270] = { .reg = 0xffffffff }, ++ [VOP2_WIN_AFBC_ROTATE_90] = { .reg = 0xffffffff }, ++}; ++ ++static int vop2_esmart_init(struct vop2_win *win) ++{ ++ struct vop2 *vop2 = win->vop2; ++ struct reg_field *esmart_regs; ++ int ret, i; ++ ++ esmart_regs = kmemdup(vop2_esmart_regs, sizeof(vop2_esmart_regs), ++ GFP_KERNEL); ++ if (!esmart_regs) ++ return -ENOMEM; ++ ++ for (i = 0; i < ARRAY_SIZE(vop2_esmart_regs); i++) ++ if (esmart_regs[i].reg != 0xffffffff) ++ esmart_regs[i].reg += win->offset; ++ ++ ret = devm_regmap_field_bulk_alloc(vop2->dev, vop2->map, win->reg, ++ esmart_regs, ++ ARRAY_SIZE(vop2_esmart_regs)); ++ ++ kfree(esmart_regs); ++ ++ return ret; ++}; ++ ++static int vop2_win_init(struct vop2 *vop2) ++{ ++ const struct vop2_data *vop2_data = vop2->data; ++ struct vop2_win *win; ++ int i, ret; ++ ++ for (i = 0; i < vop2_data->win_size; i++) { ++ const struct vop2_win_data *win_data = &vop2_data->win[i]; ++ ++ win = &vop2->win[i]; ++ win->data = win_data; ++ win->type = win_data->type; ++ win->offset = win_data->base; ++ win->win_id = i; ++ win->vop2 = vop2; ++ if (vop2_cluster_window(win)) ++ ret = vop2_cluster_init(win); ++ else ++ ret = vop2_esmart_init(win); ++ if (ret) ++ return ret; ++ } ++ ++ vop2->registered_num_wins = vop2_data->win_size; ++ ++ return 0; ++} ++ ++/* ++ * The window registers are only updated when config done is written. ++ * Until that they read back the old value. As we read-modify-write ++ * these registers mark them as non-volatile. This makes sure we read ++ * the new values from the regmap register cache. ++ */ ++static const struct regmap_range vop2_nonvolatile_range[] = { ++ regmap_reg_range(0x1000, 0x23ff), ++}; ++ ++static const struct regmap_access_table vop2_volatile_table = { ++ .no_ranges = vop2_nonvolatile_range, ++ .n_no_ranges = ARRAY_SIZE(vop2_nonvolatile_range), ++}; ++ ++static const struct regmap_config vop2_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x3000, ++ .name = "vop2", ++ .volatile_table = &vop2_volatile_table, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ ++static int vop2_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ const struct vop2_data *vop2_data; ++ struct drm_device *drm = data; ++ struct vop2 *vop2; ++ struct resource *res; ++ size_t alloc_size; ++ int ret; ++ ++ vop2_data = of_device_get_match_data(dev); ++ if (!vop2_data) ++ return -ENODEV; ++ ++ /* Allocate vop2 struct and its vop2_win array */ ++ alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size; ++ vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL); ++ if (!vop2) ++ return -ENOMEM; ++ ++ vop2->dev = dev; ++ vop2->data = vop2_data; ++ vop2->drm = drm; ++ ++ dev_set_drvdata(dev, vop2); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); ++ if (!res) { ++ drm_err(vop2->drm, "failed to get vop2 register byname\n"); ++ return -EINVAL; ++ } ++ ++ vop2->regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(vop2->regs)) ++ return PTR_ERR(vop2->regs); ++ vop2->len = resource_size(res); ++ ++ vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config); ++ ++ ret = vop2_win_init(vop2); ++ if (ret) ++ return ret; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut"); ++ if (res) { ++ vop2->lut_regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(vop2->lut_regs)) ++ return PTR_ERR(vop2->lut_regs); ++ } ++ ++ vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); ++ ++ vop2->hclk = devm_clk_get(vop2->dev, "hclk"); ++ if (IS_ERR(vop2->hclk)) { ++ drm_err(vop2->drm, "failed to get hclk source\n"); ++ return PTR_ERR(vop2->hclk); ++ } ++ ++ vop2->aclk = devm_clk_get(vop2->dev, "aclk"); ++ if (IS_ERR(vop2->aclk)) { ++ drm_err(vop2->drm, "failed to get aclk source\n"); ++ return PTR_ERR(vop2->aclk); ++ } ++ ++ vop2->irq = platform_get_irq(pdev, 0); ++ if (vop2->irq < 0) { ++ drm_err(vop2->drm, "cannot find irq for vop2\n"); ++ return vop2->irq; ++ } ++ ++ mutex_init(&vop2->vop2_lock); ++ ++ ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); ++ if (ret) ++ return ret; ++ ++ ret = vop2_create_crtc(vop2); ++ if (ret) ++ return ret; ++ ++ rockchip_drm_dma_init_device(vop2->drm, vop2->dev); ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ return 0; ++} ++ ++static void vop2_unbind(struct device *dev, struct device *master, void *data) ++{ ++ struct vop2 *vop2 = dev_get_drvdata(dev); ++ struct drm_device *drm = vop2->drm; ++ struct list_head *plane_list = &drm->mode_config.plane_list; ++ struct list_head *crtc_list = &drm->mode_config.crtc_list; ++ struct drm_crtc *crtc, *tmpc; ++ struct drm_plane *plane, *tmpp; ++ ++ pm_runtime_disable(dev); ++ ++ list_for_each_entry_safe(plane, tmpp, plane_list, head) ++ drm_plane_cleanup(plane); ++ ++ list_for_each_entry_safe(crtc, tmpc, crtc_list, head) ++ vop2_destroy_crtc(crtc); ++} ++ ++const struct component_ops vop2_component_ops = { ++ .bind = vop2_bind, ++ .unbind = vop2_unbind, ++}; ++EXPORT_SYMBOL_GPL(vop2_component_ops); +--- /dev/null ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +@@ -0,0 +1,477 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd ++ * Author:Mark Yao ++ */ ++ ++#ifndef _ROCKCHIP_DRM_VOP2_H ++#define _ROCKCHIP_DRM_VOP2_H ++ ++#include "rockchip_drm_vop.h" ++ ++#include ++#include ++ ++#define VOP_FEATURE_OUTPUT_10BIT BIT(0) ++ ++#define WIN_FEATURE_AFBDC BIT(0) ++#define WIN_FEATURE_CLUSTER BIT(1) ++ ++/* ++ * the delay number of a window in different mode. ++ */ ++enum win_dly_mode { ++ VOP2_DLY_MODE_DEFAULT, /**< default mode */ ++ VOP2_DLY_MODE_HISO_S, /** HDR in SDR out mode, as a SDR window */ ++ VOP2_DLY_MODE_HIHO_H, /** HDR in HDR out mode, as a HDR window */ ++ VOP2_DLY_MODE_MAX, ++}; ++ ++struct vop_rect { ++ int width; ++ int height; ++}; ++ ++enum vop2_scale_up_mode { ++ VOP2_SCALE_UP_NRST_NBOR, ++ VOP2_SCALE_UP_BIL, ++ VOP2_SCALE_UP_BIC, ++}; ++ ++enum vop2_scale_down_mode { ++ VOP2_SCALE_DOWN_NRST_NBOR, ++ VOP2_SCALE_DOWN_BIL, ++ VOP2_SCALE_DOWN_AVG, ++}; ++ ++enum vop2_win_regs { ++ VOP2_WIN_ENABLE, ++ VOP2_WIN_FORMAT, ++ VOP2_WIN_CSC_MODE, ++ VOP2_WIN_XMIRROR, ++ VOP2_WIN_YMIRROR, ++ VOP2_WIN_RB_SWAP, ++ VOP2_WIN_UV_SWAP, ++ VOP2_WIN_ACT_INFO, ++ VOP2_WIN_DSP_INFO, ++ VOP2_WIN_DSP_ST, ++ VOP2_WIN_YRGB_MST, ++ VOP2_WIN_UV_MST, ++ VOP2_WIN_YRGB_VIR, ++ VOP2_WIN_UV_VIR, ++ VOP2_WIN_YUV_CLIP, ++ VOP2_WIN_Y2R_EN, ++ VOP2_WIN_R2Y_EN, ++ VOP2_WIN_COLOR_KEY, ++ VOP2_WIN_COLOR_KEY_EN, ++ VOP2_WIN_DITHER_UP, ++ ++ /* scale regs */ ++ VOP2_WIN_SCALE_YRGB_X, ++ VOP2_WIN_SCALE_YRGB_Y, ++ VOP2_WIN_SCALE_CBCR_X, ++ VOP2_WIN_SCALE_CBCR_Y, ++ VOP2_WIN_YRGB_HOR_SCL_MODE, ++ VOP2_WIN_YRGB_HSCL_FILTER_MODE, ++ VOP2_WIN_YRGB_VER_SCL_MODE, ++ VOP2_WIN_YRGB_VSCL_FILTER_MODE, ++ VOP2_WIN_CBCR_VER_SCL_MODE, ++ VOP2_WIN_CBCR_HSCL_FILTER_MODE, ++ VOP2_WIN_CBCR_HOR_SCL_MODE, ++ VOP2_WIN_CBCR_VSCL_FILTER_MODE, ++ VOP2_WIN_VSD_CBCR_GT2, ++ VOP2_WIN_VSD_CBCR_GT4, ++ VOP2_WIN_VSD_YRGB_GT2, ++ VOP2_WIN_VSD_YRGB_GT4, ++ VOP2_WIN_BIC_COE_SEL, ++ ++ /* cluster regs */ ++ VOP2_WIN_CLUSTER_ENABLE, ++ VOP2_WIN_AFBC_ENABLE, ++ VOP2_WIN_CLUSTER_LB_MODE, ++ ++ /* afbc regs */ ++ VOP2_WIN_AFBC_FORMAT, ++ VOP2_WIN_AFBC_RB_SWAP, ++ VOP2_WIN_AFBC_UV_SWAP, ++ VOP2_WIN_AFBC_AUTO_GATING_EN, ++ VOP2_WIN_AFBC_BLOCK_SPLIT_EN, ++ VOP2_WIN_AFBC_PIC_VIR_WIDTH, ++ VOP2_WIN_AFBC_TILE_NUM, ++ VOP2_WIN_AFBC_PIC_OFFSET, ++ VOP2_WIN_AFBC_PIC_SIZE, ++ VOP2_WIN_AFBC_DSP_OFFSET, ++ VOP2_WIN_AFBC_TRANSFORM_OFFSET, ++ VOP2_WIN_AFBC_HDR_PTR, ++ VOP2_WIN_AFBC_HALF_BLOCK_EN, ++ VOP2_WIN_AFBC_ROTATE_270, ++ VOP2_WIN_AFBC_ROTATE_90, ++ VOP2_WIN_MAX_REG, ++}; ++ ++struct vop2_win_data { ++ const char *name; ++ unsigned int phys_id; ++ ++ u32 base; ++ enum drm_plane_type type; ++ ++ u32 nformats; ++ const u32 *formats; ++ const uint64_t *format_modifiers; ++ const unsigned int supported_rotations; ++ ++ /** ++ * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2 ++ */ ++ unsigned int layer_sel_id; ++ uint64_t feature; ++ ++ unsigned int max_upscale_factor; ++ unsigned int max_downscale_factor; ++ const u8 dly[VOP2_DLY_MODE_MAX]; ++}; ++ ++struct vop2_video_port_data { ++ unsigned int id; ++ u32 feature; ++ u16 gamma_lut_len; ++ u16 cubic_lut_len; ++ struct vop_rect max_output; ++ const u8 pre_scan_max_dly[4]; ++ const struct vop2_video_port_regs *regs; ++ unsigned int offset; ++}; ++ ++struct vop2_data { ++ u8 nr_vps; ++ const struct vop2_ctrl *ctrl; ++ const struct vop2_win_data *win; ++ const struct vop2_video_port_data *vp; ++ const struct vop_csc_table *csc_table; ++ struct vop_rect max_input; ++ struct vop_rect max_output; ++ ++ unsigned int win_size; ++ unsigned int soc_id; ++}; ++ ++/* interrupt define */ ++#define FS_NEW_INTR BIT(4) ++#define ADDR_SAME_INTR BIT(5) ++#define LINE_FLAG1_INTR BIT(6) ++#define WIN0_EMPTY_INTR BIT(7) ++#define WIN1_EMPTY_INTR BIT(8) ++#define WIN2_EMPTY_INTR BIT(9) ++#define WIN3_EMPTY_INTR BIT(10) ++#define HWC_EMPTY_INTR BIT(11) ++#define POST_BUF_EMPTY_INTR BIT(12) ++#define PWM_GEN_INTR BIT(13) ++#define DMA_FINISH_INTR BIT(14) ++#define FS_FIELD_INTR BIT(15) ++#define FE_INTR BIT(16) ++#define WB_UV_FIFO_FULL_INTR BIT(17) ++#define WB_YRGB_FIFO_FULL_INTR BIT(18) ++#define WB_COMPLETE_INTR BIT(19) ++ ++/* ++ * display output interface supported by rockchip lcdc ++ */ ++#define ROCKCHIP_OUT_MODE_P888 0 ++#define ROCKCHIP_OUT_MODE_BT1120 0 ++#define ROCKCHIP_OUT_MODE_P666 1 ++#define ROCKCHIP_OUT_MODE_P565 2 ++#define ROCKCHIP_OUT_MODE_BT656 5 ++#define ROCKCHIP_OUT_MODE_S888 8 ++#define ROCKCHIP_OUT_MODE_S888_DUMMY 12 ++#define ROCKCHIP_OUT_MODE_YUV420 14 ++/* for use special outface */ ++#define ROCKCHIP_OUT_MODE_AAAA 15 ++ ++enum vop_csc_format { ++ CSC_BT601L, ++ CSC_BT709L, ++ CSC_BT601F, ++ CSC_BT2020, ++}; ++ ++enum src_factor_mode { ++ SRC_FAC_ALPHA_ZERO, ++ SRC_FAC_ALPHA_ONE, ++ SRC_FAC_ALPHA_DST, ++ SRC_FAC_ALPHA_DST_INVERSE, ++ SRC_FAC_ALPHA_SRC, ++ SRC_FAC_ALPHA_SRC_GLOBAL, ++}; ++ ++enum dst_factor_mode { ++ DST_FAC_ALPHA_ZERO, ++ DST_FAC_ALPHA_ONE, ++ DST_FAC_ALPHA_SRC, ++ DST_FAC_ALPHA_SRC_INVERSE, ++ DST_FAC_ALPHA_DST, ++ DST_FAC_ALPHA_DST_GLOBAL, ++}; ++ ++#define RK3568_GRF_VO_CON1 0x0364 ++/* System registers definition */ ++#define RK3568_REG_CFG_DONE 0x000 ++#define RK3568_VERSION_INFO 0x004 ++#define RK3568_SYS_AUTO_GATING_CTRL 0x008 ++#define RK3568_SYS_AXI_LUT_CTRL 0x024 ++#define RK3568_DSP_IF_EN 0x028 ++#define RK3568_DSP_IF_CTRL 0x02c ++#define RK3568_DSP_IF_POL 0x030 ++#define RK3568_WB_CTRL 0x40 ++#define RK3568_WB_XSCAL_FACTOR 0x44 ++#define RK3568_WB_YRGB_MST 0x48 ++#define RK3568_WB_CBR_MST 0x4C ++#define RK3568_OTP_WIN_EN 0x050 ++#define RK3568_LUT_PORT_SEL 0x058 ++#define RK3568_SYS_STATUS0 0x060 ++#define RK3568_VP_LINE_FLAG(vp) (0x70 + (vp) * 0x4) ++#define RK3568_SYS0_INT_EN 0x80 ++#define RK3568_SYS0_INT_CLR 0x84 ++#define RK3568_SYS0_INT_STATUS 0x88 ++#define RK3568_SYS1_INT_EN 0x90 ++#define RK3568_SYS1_INT_CLR 0x94 ++#define RK3568_SYS1_INT_STATUS 0x98 ++#define RK3568_VP_INT_EN(vp) (0xA0 + (vp) * 0x10) ++#define RK3568_VP_INT_CLR(vp) (0xA4 + (vp) * 0x10) ++#define RK3568_VP_INT_STATUS(vp) (0xA8 + (vp) * 0x10) ++#define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10) ++ ++/* Video Port registers definition */ ++#define RK3568_VP_DSP_CTRL 0x00 ++#define RK3568_VP_MIPI_CTRL 0x04 ++#define RK3568_VP_COLOR_BAR_CTRL 0x08 ++#define RK3568_VP_3D_LUT_CTRL 0x10 ++#define RK3568_VP_3D_LUT_MST 0x20 ++#define RK3568_VP_DSP_BG 0x2C ++#define RK3568_VP_PRE_SCAN_HTIMING 0x30 ++#define RK3568_VP_POST_DSP_HACT_INFO 0x34 ++#define RK3568_VP_POST_DSP_VACT_INFO 0x38 ++#define RK3568_VP_POST_SCL_FACTOR_YRGB 0x3C ++#define RK3568_VP_POST_SCL_CTRL 0x40 ++#define RK3568_VP_POST_DSP_VACT_INFO_F1 0x44 ++#define RK3568_VP_DSP_HTOTAL_HS_END 0x48 ++#define RK3568_VP_DSP_HACT_ST_END 0x4C ++#define RK3568_VP_DSP_VTOTAL_VS_END 0x50 ++#define RK3568_VP_DSP_VACT_ST_END 0x54 ++#define RK3568_VP_DSP_VS_ST_END_F1 0x58 ++#define RK3568_VP_DSP_VACT_ST_END_F1 0x5C ++#define RK3568_VP_BCSH_CTRL 0x60 ++#define RK3568_VP_BCSH_BCS 0x64 ++#define RK3568_VP_BCSH_H 0x68 ++#define RK3568_VP_BCSH_COLOR_BAR 0x6C ++ ++/* Overlay registers definition */ ++#define RK3568_OVL_CTRL 0x600 ++#define RK3568_OVL_LAYER_SEL 0x604 ++#define RK3568_OVL_PORT_SEL 0x608 ++#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610 ++#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614 ++#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618 ++#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C ++#define RK3568_MIX0_SRC_COLOR_CTRL 0x650 ++#define RK3568_MIX0_DST_COLOR_CTRL 0x654 ++#define RK3568_MIX0_SRC_ALPHA_CTRL 0x658 ++#define RK3568_MIX0_DST_ALPHA_CTRL 0x65C ++#define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0 ++#define RK3568_HDR0_DST_COLOR_CTRL 0x6C4 ++#define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8 ++#define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC ++#define RK3568_VP_BG_MIX_CTRL(vp) (0x6E0 + (vp) * 4) ++#define RK3568_CLUSTER_DLY_NUM 0x6F0 ++#define RK3568_SMART_DLY_NUM 0x6F8 ++ ++/* Cluster register definition, offset relative to window base */ ++#define RK3568_CLUSTER_WIN_CTRL0 0x00 ++#define RK3568_CLUSTER_WIN_CTRL1 0x04 ++#define RK3568_CLUSTER_WIN_YRGB_MST 0x10 ++#define RK3568_CLUSTER_WIN_CBR_MST 0x14 ++#define RK3568_CLUSTER_WIN_VIR 0x18 ++#define RK3568_CLUSTER_WIN_ACT_INFO 0x20 ++#define RK3568_CLUSTER_WIN_DSP_INFO 0x24 ++#define RK3568_CLUSTER_WIN_DSP_ST 0x28 ++#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB 0x30 ++#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET 0x3C ++#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL 0x50 ++#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE 0x54 ++#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR 0x58 ++#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH 0x5C ++#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE 0x60 ++#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET 0x64 ++#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET 0x68 ++#define RK3568_CLUSTER_WIN_AFBCD_CTRL 0x6C ++ ++#define RK3568_CLUSTER_CTRL 0x100 ++ ++/* (E)smart register definition, offset relative to window base */ ++#define RK3568_SMART_CTRL0 0x00 ++#define RK3568_SMART_CTRL1 0x04 ++#define RK3568_SMART_REGION0_CTRL 0x10 ++#define RK3568_SMART_REGION0_YRGB_MST 0x14 ++#define RK3568_SMART_REGION0_CBR_MST 0x18 ++#define RK3568_SMART_REGION0_VIR 0x1C ++#define RK3568_SMART_REGION0_ACT_INFO 0x20 ++#define RK3568_SMART_REGION0_DSP_INFO 0x24 ++#define RK3568_SMART_REGION0_DSP_ST 0x28 ++#define RK3568_SMART_REGION0_SCL_CTRL 0x30 ++#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB 0x34 ++#define RK3568_SMART_REGION0_SCL_FACTOR_CBR 0x38 ++#define RK3568_SMART_REGION0_SCL_OFFSET 0x3C ++#define RK3568_SMART_REGION1_CTRL 0x40 ++#define RK3568_SMART_REGION1_YRGB_MST 0x44 ++#define RK3568_SMART_REGION1_CBR_MST 0x48 ++#define RK3568_SMART_REGION1_VIR 0x4C ++#define RK3568_SMART_REGION1_ACT_INFO 0x50 ++#define RK3568_SMART_REGION1_DSP_INFO 0x54 ++#define RK3568_SMART_REGION1_DSP_ST 0x58 ++#define RK3568_SMART_REGION1_SCL_CTRL 0x60 ++#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB 0x64 ++#define RK3568_SMART_REGION1_SCL_FACTOR_CBR 0x68 ++#define RK3568_SMART_REGION1_SCL_OFFSET 0x6C ++#define RK3568_SMART_REGION2_CTRL 0x70 ++#define RK3568_SMART_REGION2_YRGB_MST 0x74 ++#define RK3568_SMART_REGION2_CBR_MST 0x78 ++#define RK3568_SMART_REGION2_VIR 0x7C ++#define RK3568_SMART_REGION2_ACT_INFO 0x80 ++#define RK3568_SMART_REGION2_DSP_INFO 0x84 ++#define RK3568_SMART_REGION2_DSP_ST 0x88 ++#define RK3568_SMART_REGION2_SCL_CTRL 0x90 ++#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB 0x94 ++#define RK3568_SMART_REGION2_SCL_FACTOR_CBR 0x98 ++#define RK3568_SMART_REGION2_SCL_OFFSET 0x9C ++#define RK3568_SMART_REGION3_CTRL 0xA0 ++#define RK3568_SMART_REGION3_YRGB_MST 0xA4 ++#define RK3568_SMART_REGION3_CBR_MST 0xA8 ++#define RK3568_SMART_REGION3_VIR 0xAC ++#define RK3568_SMART_REGION3_ACT_INFO 0xB0 ++#define RK3568_SMART_REGION3_DSP_INFO 0xB4 ++#define RK3568_SMART_REGION3_DSP_ST 0xB8 ++#define RK3568_SMART_REGION3_SCL_CTRL 0xC0 ++#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB 0xC4 ++#define RK3568_SMART_REGION3_SCL_FACTOR_CBR 0xC8 ++#define RK3568_SMART_REGION3_SCL_OFFSET 0xCC ++#define RK3568_SMART_COLOR_KEY_CTRL 0xD0 ++ ++/* HDR register definition */ ++#define RK3568_HDR_LUT_CTRL 0x2000 ++#define RK3568_HDR_LUT_MST 0x2004 ++#define RK3568_SDR2HDR_CTRL 0x2010 ++#define RK3568_HDR2SDR_CTRL 0x2020 ++#define RK3568_HDR2SDR_SRC_RANGE 0x2024 ++#define RK3568_HDR2SDR_NORMFACEETF 0x2028 ++#define RK3568_HDR2SDR_DST_RANGE 0x202C ++#define RK3568_HDR2SDR_NORMFACCGAMMA 0x2030 ++#define RK3568_HDR_EETF_OETF_Y0 0x203C ++#define RK3568_HDR_SAT_Y0 0x20C0 ++#define RK3568_HDR_EOTF_OETF_Y0 0x20F0 ++#define RK3568_HDR_OETF_DX_POW1 0x2200 ++#define RK3568_HDR_OETF_XN1 0x2300 ++ ++#define RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN BIT(15) ++ ++#define RK3568_VP_DSP_CTRL__STANDBY BIT(31) ++#define RK3568_VP_DSP_CTRL__DITHER_DOWN_MODE BIT(20) ++#define RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL GENMASK(19, 18) ++#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17) ++#define RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN BIT(16) ++#define RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y BIT(15) ++#define RK3568_VP_DSP_CTRL__DSP_RB_SWAP BIT(9) ++#define RK3568_VP_DSP_CTRL__DSP_INTERLACE BIT(7) ++#define RK3568_VP_DSP_CTRL__DSP_FILED_POL BIT(6) ++#define RK3568_VP_DSP_CTRL__P2I_EN BIT(5) ++#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4) ++#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0) ++ ++#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1) ++#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0) ++ ++#define RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX GENMASK(26, 25) ++#define RK3568_SYS_DSP_INFACE_EN_LVDS1 BIT(24) ++#define RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21) ++#define RK3568_SYS_DSP_INFACE_EN_MIPI1 BIT(20) ++#define RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX GENMASK(19, 18) ++#define RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(17, 16) ++#define RK3568_SYS_DSP_INFACE_EN_EDP_MUX GENMASK(15, 14) ++#define RK3568_SYS_DSP_INFACE_EN_HDMI_MUX GENMASK(11, 10) ++#define RK3568_SYS_DSP_INFACE_EN_RGB_MUX GENMASK(9, 8) ++#define RK3568_SYS_DSP_INFACE_EN_LVDS0 BIT(5) ++#define RK3568_SYS_DSP_INFACE_EN_MIPI0 BIT(4) ++#define RK3568_SYS_DSP_INFACE_EN_EDP BIT(3) ++#define RK3568_SYS_DSP_INFACE_EN_HDMI BIT(1) ++#define RK3568_SYS_DSP_INFACE_EN_RGB BIT(0) ++ ++#define RK3568_DSP_IF_POL__MIPI_PIN_POL GENMASK(19, 16) ++#define RK3568_DSP_IF_POL__EDP_PIN_POL GENMASK(15, 12) ++#define RK3568_DSP_IF_POL__HDMI_PIN_POL GENMASK(7, 4) ++#define RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL GENMASK(3, 0) ++ ++#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5) ++#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4) ++ ++#define RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN BIT(31) ++ ++#define RK3568_DSP_IF_POL__CFG_DONE_IMD BIT(28) ++ ++#define VOP2_SYS_AXI_BUS_NUM 2 ++ ++#define VOP2_CLUSTER_YUV444_10 0x12 ++ ++#define VOP2_COLOR_KEY_MASK BIT(31) ++ ++#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD BIT(28) ++ ++#define RK3568_VP_BG_MIX_CTRL__BG_DLY GENMASK(31, 24) ++ ++#define RK3568_OVL_PORT_SEL__SEL_PORT GENMASK(31, 16) ++#define RK3568_OVL_PORT_SEL__SMART1 GENMASK(31, 30) ++#define RK3568_OVL_PORT_SEL__SMART0 GENMASK(29, 28) ++#define RK3568_OVL_PORT_SEL__ESMART1 GENMASK(27, 26) ++#define RK3568_OVL_PORT_SEL__ESMART0 GENMASK(25, 24) ++#define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18) ++#define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16) ++#define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8) ++#define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4) ++#define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0) ++#define RK3568_OVL_LAYER_SEL__LAYER(layer, x) ((x) << ((layer) * 4)) ++ ++#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_1 GENMASK(31, 24) ++#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_0 GENMASK(23, 16) ++#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_1 GENMASK(15, 8) ++#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_0 GENMASK(7, 0) ++ ++#define RK3568_SMART_DLY_NUM__SMART1 GENMASK(31, 24) ++#define RK3568_SMART_DLY_NUM__SMART0 GENMASK(23, 16) ++#define RK3568_SMART_DLY_NUM__ESMART1 GENMASK(15, 8) ++#define RK3568_SMART_DLY_NUM__ESMART0 GENMASK(7, 0) ++ ++#define VP_INT_DSP_HOLD_VALID BIT(6) ++#define VP_INT_FS_FIELD BIT(5) ++#define VP_INT_POST_BUF_EMPTY BIT(4) ++#define VP_INT_LINE_FLAG1 BIT(3) ++#define VP_INT_LINE_FLAG0 BIT(2) ++#define VOP2_INT_BUS_ERRPR BIT(1) ++#define VP_INT_FS BIT(0) ++ ++#define POLFLAG_DCLK_INV BIT(3) ++ ++enum vop2_layer_phy_id { ++ ROCKCHIP_VOP2_CLUSTER0 = 0, ++ ROCKCHIP_VOP2_CLUSTER1, ++ ROCKCHIP_VOP2_ESMART0, ++ ROCKCHIP_VOP2_ESMART1, ++ ROCKCHIP_VOP2_SMART0, ++ ROCKCHIP_VOP2_SMART1, ++ ROCKCHIP_VOP2_CLUSTER2, ++ ROCKCHIP_VOP2_CLUSTER3, ++ ROCKCHIP_VOP2_ESMART2, ++ ROCKCHIP_VOP2_ESMART3, ++ ROCKCHIP_VOP2_PHY_ID_INVALID = -1, ++}; ++ ++extern const struct component_ops vop2_component_ops; ++ ++#endif /* _ROCKCHIP_DRM_VOP2_H */ +--- /dev/null ++++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +@@ -0,0 +1,281 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) Rockchip Electronics Co.Ltd ++ * Author: Andy Yan ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rockchip_drm_vop2.h" ++ ++static const uint32_t formats_win_full_10bit[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_ABGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565, ++ DRM_FORMAT_BGR565, ++ DRM_FORMAT_NV12, ++ DRM_FORMAT_NV16, ++ DRM_FORMAT_NV24, ++}; ++ ++static const uint32_t formats_win_full_10bit_yuyv[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_ABGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565, ++ DRM_FORMAT_BGR565, ++ DRM_FORMAT_NV12, ++ DRM_FORMAT_NV16, ++ DRM_FORMAT_NV24, ++ DRM_FORMAT_YVYU, ++ DRM_FORMAT_VYUY, ++}; ++ ++static const uint32_t formats_win_lite[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_ARGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_ABGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565, ++ DRM_FORMAT_BGR565, ++}; ++ ++static const uint64_t format_modifiers[] = { ++ DRM_FORMAT_MOD_LINEAR, ++ DRM_FORMAT_MOD_INVALID, ++}; ++ ++static const uint64_t format_modifiers_afbc[] = { ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_SPARSE), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_CBR), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR | ++ AFBC_FORMAT_MOD_SPARSE), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_CBR | ++ AFBC_FORMAT_MOD_SPARSE), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR | ++ AFBC_FORMAT_MOD_CBR), ++ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR | ++ AFBC_FORMAT_MOD_CBR | ++ AFBC_FORMAT_MOD_SPARSE), ++ ++ /* SPLIT mandates SPARSE, RGB modes mandates YTR */ ++ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | ++ AFBC_FORMAT_MOD_YTR | ++ AFBC_FORMAT_MOD_SPARSE | ++ AFBC_FORMAT_MOD_SPLIT), ++ DRM_FORMAT_MOD_INVALID, ++}; ++ ++static const struct vop2_video_port_data rk3568_vop_video_ports[] = { ++ { ++ .id = 0, ++ .feature = VOP_FEATURE_OUTPUT_10BIT, ++ .gamma_lut_len = 1024, ++ .cubic_lut_len = 9 * 9 * 9, ++ .max_output = { 4096, 2304 }, ++ .pre_scan_max_dly = { 69, 53, 53, 42 }, ++ .offset = 0xc00, ++ }, { ++ .id = 1, ++ .gamma_lut_len = 1024, ++ .max_output = { 2048, 1536 }, ++ .pre_scan_max_dly = { 40, 40, 40, 40 }, ++ .offset = 0xd00, ++ }, { ++ .id = 2, ++ .gamma_lut_len = 1024, ++ .max_output = { 1920, 1080 }, ++ .pre_scan_max_dly = { 40, 40, 40, 40 }, ++ .offset = 0xe00, ++ }, ++}; ++ ++/* ++ * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win. ++ * Every cluster can work as 4K win or split into two win. ++ * All win in cluster support AFBCD. ++ * ++ * Every esmart win and smart win support 4 Multi-region. ++ * ++ * Scale filter mode: ++ * ++ * * Cluster: bicubic for horizontal scale up, others use bilinear ++ * * ESmart: ++ * * nearest-neighbor/bilinear/bicubic for scale up ++ * * nearest-neighbor/bilinear/average for scale down ++ * ++ * ++ * @TODO describe the wind like cpu-map dt nodes; ++ */ ++static const struct vop2_win_data rk3568_vop_win_data[] = { ++ { ++ .name = "Smart0-win0", ++ .phys_id = ROCKCHIP_VOP2_SMART0, ++ .base = 0x1c00, ++ .formats = formats_win_lite, ++ .nformats = ARRAY_SIZE(formats_win_lite), ++ .format_modifiers = format_modifiers, ++ .layer_sel_id = 3, ++ .supported_rotations = DRM_MODE_REFLECT_Y, ++ .type = DRM_PLANE_TYPE_PRIMARY, ++ .max_upscale_factor = 8, ++ .max_downscale_factor = 8, ++ .dly = { 20, 47, 41 }, ++ }, { ++ .name = "Smart1-win0", ++ .phys_id = ROCKCHIP_VOP2_SMART1, ++ .formats = formats_win_lite, ++ .nformats = ARRAY_SIZE(formats_win_lite), ++ .format_modifiers = format_modifiers, ++ .base = 0x1e00, ++ .layer_sel_id = 7, ++ .supported_rotations = DRM_MODE_REFLECT_Y, ++ .type = DRM_PLANE_TYPE_PRIMARY, ++ .max_upscale_factor = 8, ++ .max_downscale_factor = 8, ++ .dly = { 20, 47, 41 }, ++ }, { ++ .name = "Esmart1-win0", ++ .phys_id = ROCKCHIP_VOP2_ESMART1, ++ .formats = formats_win_full_10bit_yuyv, ++ .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), ++ .format_modifiers = format_modifiers, ++ .base = 0x1a00, ++ .layer_sel_id = 6, ++ .supported_rotations = DRM_MODE_REFLECT_Y, ++ .type = DRM_PLANE_TYPE_PRIMARY, ++ .max_upscale_factor = 8, ++ .max_downscale_factor = 8, ++ .dly = { 20, 47, 41 }, ++ }, { ++ .name = "Esmart0-win0", ++ .phys_id = ROCKCHIP_VOP2_ESMART0, ++ .formats = formats_win_full_10bit_yuyv, ++ .nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv), ++ .format_modifiers = format_modifiers, ++ .base = 0x1800, ++ .layer_sel_id = 2, ++ .supported_rotations = DRM_MODE_REFLECT_Y, ++ .type = DRM_PLANE_TYPE_OVERLAY, ++ .max_upscale_factor = 8, ++ .max_downscale_factor = 8, ++ .dly = { 20, 47, 41 }, ++ }, { ++ .name = "Cluster0-win0", ++ .phys_id = ROCKCHIP_VOP2_CLUSTER0, ++ .base = 0x1000, ++ .formats = formats_win_full_10bit, ++ .nformats = ARRAY_SIZE(formats_win_full_10bit), ++ .format_modifiers = format_modifiers_afbc, ++ .layer_sel_id = 0, ++ .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | ++ DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ .dly = { 0, 27, 21 }, ++ .type = DRM_PLANE_TYPE_OVERLAY, ++ .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, ++ }, { ++ .name = "Cluster1-win0", ++ .phys_id = ROCKCHIP_VOP2_CLUSTER1, ++ .base = 0x1200, ++ .formats = formats_win_full_10bit, ++ .nformats = ARRAY_SIZE(formats_win_full_10bit), ++ .format_modifiers = format_modifiers_afbc, ++ .layer_sel_id = 1, ++ .supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 | ++ DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y, ++ .type = DRM_PLANE_TYPE_OVERLAY, ++ .max_upscale_factor = 4, ++ .max_downscale_factor = 4, ++ .dly = { 0, 27, 21 }, ++ .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER, ++ }, ++}; ++ ++static const struct vop2_data rk3566_vop = { ++ .nr_vps = 3, ++ .max_input = { 4096, 2304 }, ++ .max_output = { 4096, 2304 }, ++ .vp = rk3568_vop_video_ports, ++ .win = rk3568_vop_win_data, ++ .win_size = ARRAY_SIZE(rk3568_vop_win_data), ++ .soc_id = 3566, ++}; ++ ++static const struct vop2_data rk3568_vop = { ++ .nr_vps = 3, ++ .max_input = { 4096, 2304 }, ++ .max_output = { 4096, 2304 }, ++ .vp = rk3568_vop_video_ports, ++ .win = rk3568_vop_win_data, ++ .win_size = ARRAY_SIZE(rk3568_vop_win_data), ++ .soc_id = 3568, ++}; ++ ++static const struct of_device_id vop2_dt_match[] = { ++ { ++ .compatible = "rockchip,rk3566-vop", ++ .data = &rk3566_vop, ++ }, { ++ .compatible = "rockchip,rk3568-vop", ++ .data = &rk3568_vop, ++ }, { ++ }, ++}; ++MODULE_DEVICE_TABLE(of, vop2_dt_match); ++ ++static int vop2_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ ++ return component_add(dev, &vop2_component_ops); ++} ++ ++static int vop2_remove(struct platform_device *pdev) ++{ ++ component_del(&pdev->dev, &vop2_component_ops); ++ ++ return 0; ++} ++ ++struct platform_driver vop2_platform_driver = { ++ .probe = vop2_probe, ++ .remove = vop2_remove, ++ .driver = { ++ .name = "rockchip-vop2", ++ .of_match_table = of_match_ptr(vop2_dt_match), ++ }, ++}; diff --git a/target/linux/rockchip/patches-5.18/247-dt-bindings-display-rockchip-Add-binding-for-VOP2.patch b/target/linux/rockchip/patches-5.18/247-dt-bindings-display-rockchip-Add-binding-for-VOP2.patch new file mode 100644 index 000000000..1f9a38fa2 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/247-dt-bindings-display-rockchip-Add-binding-for-VOP2.patch @@ -0,0 +1,159 @@ +From c706114d54630045eb2ac12ff72744482b227058 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:37 +0200 +Subject: [PATCH 47/50] dt-bindings: display: rockchip: Add binding for VOP2 + +The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566. +The binding differs slightly from the existing VOP binding, so add a new +binding file for it. + +Signed-off-by: Sascha Hauer +Reviewed-by: Rob Herring +--- + .../display/rockchip/rockchip-vop2.yaml | 140 ++++++++++++++++++ + 1 file changed, 140 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +@@ -0,0 +1,140 @@ ++# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip SoC display controller (VOP2) ++ ++description: ++ VOP2 (Video Output Processor v2) is the display controller for the Rockchip ++ series of SoCs which transfers the image data from a video memory ++ buffer to an external LCD interface. ++ ++maintainers: ++ - Sandy Huang ++ - Heiko Stuebner ++ ++properties: ++ compatible: ++ enum: ++ - rockchip,rk3566-vop ++ - rockchip,rk3568-vop ++ ++ reg: ++ minItems: 1 ++ items: ++ - description: ++ Must contain one entry corresponding to the base address and length ++ of the register space. ++ - description: ++ Can optionally contain a second entry corresponding to ++ the CRTC gamma LUT address. ++ ++ interrupts: ++ maxItems: 1 ++ description: ++ The VOP interrupt is shared by several interrupt sources, such as ++ frame start (VSYNC), line flag and other status interrupts. ++ ++ clocks: ++ items: ++ - description: Clock for ddr buffer transfer. ++ - description: Clock for the ahb bus to R/W the phy regs. ++ - description: Pixel clock for video port 0. ++ - description: Pixel clock for video port 1. ++ - description: Pixel clock for video port 2. ++ ++ clock-names: ++ items: ++ - const: aclk ++ - const: hclk ++ - const: dclk_vp0 ++ - const: dclk_vp1 ++ - const: dclk_vp2 ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to GRF regs used for misc control ++ ++ ports: ++ $ref: /schemas/graph.yaml#/properties/ports ++ ++ properties: ++ port@0: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Output endpoint of VP0 ++ ++ port@1: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Output endpoint of VP1 ++ ++ port@2: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Output endpoint of VP2 ++ ++ iommus: ++ maxItems: 1 ++ ++ power-domains: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ - ports ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ bus { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ vop: vop@fe040000 { ++ compatible = "rockchip,rk3568-vop"; ++ reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru ACLK_VOP>, ++ <&cru HCLK_VOP>, ++ <&cru DCLK_VOP0>, ++ <&cru DCLK_VOP1>, ++ <&cru DCLK_VOP2>; ++ clock-names = "aclk", ++ "hclk", ++ "dclk_vp0", ++ "dclk_vp1", ++ "dclk_vp2"; ++ power-domains = <&power RK3568_PD_VO>; ++ iommus = <&vop_mmu>; ++ vop_out: ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ vp0: port@0 { ++ reg = <0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ vp1: port@1 { ++ reg = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ vp2: port@2 { ++ reg = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ }; diff --git a/target/linux/rockchip/patches-5.18/248-dt-bindings-display-rockchip-dw-hdmi-fix-ports-descr.patch b/target/linux/rockchip/patches-5.18/248-dt-bindings-display-rockchip-dw-hdmi-fix-ports-descr.patch new file mode 100644 index 000000000..4f3109574 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/248-dt-bindings-display-rockchip-dw-hdmi-fix-ports-descr.patch @@ -0,0 +1,66 @@ +From 513cc8e325c2485e953965388b5c38a370190da2 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 8 Apr 2022 13:22:38 +0200 +Subject: [PATCH 48/50] dt-bindings: display: rockchip: dw-hdmi: fix ports + description + +Current port description doesn't cover all possible cases. It currently +expects one single port with two endpoints. + +When the HDMI connector is described in the device tree there can be two +ports, first one going to the VOP and the second one going to the connector. + +Also on SoCs which only have a single VOP there will be only one +endpoint instead of two. + +This patch addresses both issues. With this there can either be a single +port ("port") , or two of them ("port@0", "port@1") when the connector +is also in the device tree. Also the first or only port can either have +one endpoint ("endpoint") for single VOP SoCs or two ("endpoint@0", +"endpoint@1") for dual VOP SoCs. + +Signed-off-by: Sascha Hauer +Reviewed-by: Rob Herring +--- + .../display/rockchip/rockchip,dw-hdmi.yaml | 24 +++++++------------ + 1 file changed, 9 insertions(+), 15 deletions(-) + +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +@@ -97,27 +97,21 @@ properties: + ports: + $ref: /schemas/graph.yaml#/properties/ports + +- properties: +- port: +- $ref: /schemas/graph.yaml#/$defs/port-base +- unevaluatedProperties: false ++ patternProperties: ++ "^port(@0)?$": ++ $ref: /schemas/graph.yaml#/properties/port + description: Input of the DWC HDMI TX +- + properties: ++ endpoint: ++ description: Connection to the VOP + endpoint@0: +- $ref: /schemas/graph.yaml#/properties/endpoint + description: Connection to the VOPB +- + endpoint@1: +- $ref: /schemas/graph.yaml#/properties/endpoint + description: Connection to the VOPL +- +- required: +- - endpoint@0 +- - endpoint@1 +- +- required: +- - port ++ properties: ++ port@1: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: Output of the DWC HDMI TX + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle diff --git a/target/linux/rockchip/patches-5.18/249-arm64-dts-rockchip-rk356x-Add-HDMI-audio-nodes.patch b/target/linux/rockchip/patches-5.18/249-arm64-dts-rockchip-rk356x-Add-HDMI-audio-nodes.patch new file mode 100644 index 000000000..e976b5114 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/249-arm64-dts-rockchip-rk356x-Add-HDMI-audio-nodes.patch @@ -0,0 +1,64 @@ +From f63ef05247648703034ccbccf1fd7ad492fe2c35 Mon Sep 17 00:00:00 2001 +From: Nicolas Frattaroli +Date: Fri, 26 Nov 2021 13:27:17 +0100 +Subject: [PATCH 49/50] arm64: dts: rockchip: rk356x: Add HDMI audio nodes + +This adds the i2s0 node and an hdmi-sound sound device to the +rk356x device tree. On the rk356[68], the i2s0 controller is +connected to HDMI audio. + +Tested-by: Michael Riesch +Signed-off-by: Nicolas Frattaroli +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 33 ++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -183,6 +183,22 @@ + }; + }; + ++ hdmi_sound: hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ status = "disabled"; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0_8ch>; ++ }; ++ }; ++ + pmu { + compatible = "arm,cortex-a55-pmu"; + interrupts = , +@@ -952,6 +968,23 @@ + #sound-dai-cells = <0>; + status = "disabled"; + }; ++ ++ i2s0_8ch: i2s@fe400000 { ++ compatible = "rockchip,rk3568-i2s-tdm"; ++ reg = <0x0 0xfe400000 0x0 0x1000>; ++ interrupts = ; ++ assigned-clocks = <&cru CLK_I2S0_8CH_TX_SRC>, <&cru CLK_I2S0_8CH_RX_SRC>; ++ assigned-clock-rates = <1188000000>, <1188000000>; ++ clocks = <&cru MCLK_I2S0_8CH_TX>, <&cru MCLK_I2S0_8CH_RX>, <&cru HCLK_I2S0_8CH>; ++ clock-names = "mclk_tx", "mclk_rx", "hclk"; ++ dmas = <&dmac1 0>; ++ dma-names = "tx"; ++ resets = <&cru SRST_M_I2S0_8CH_TX>, <&cru SRST_M_I2S0_8CH_RX>; ++ reset-names = "tx-m", "rx-m"; ++ rockchip,grf = <&grf>; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; + + i2s1_8ch: i2s@fe410000 { + compatible = "rockchip,rk3568-i2s-tdm"; diff --git a/target/linux/rockchip/patches-5.18/250-arm64-dts-rockchip-Enable-HDMI-audio-on-Quartz64-A.patch b/target/linux/rockchip/patches-5.18/250-arm64-dts-rockchip-Enable-HDMI-audio-on-Quartz64-A.patch new file mode 100644 index 000000000..12806078e --- /dev/null +++ b/target/linux/rockchip/patches-5.18/250-arm64-dts-rockchip-Enable-HDMI-audio-on-Quartz64-A.patch @@ -0,0 +1,37 @@ +From 0e741e34d1f3fc9a01becaa0ed9e0961a262b046 Mon Sep 17 00:00:00 2001 +From: Nicolas Frattaroli +Date: Fri, 26 Nov 2021 13:27:18 +0100 +Subject: [PATCH 50/50] arm64: dts: rockchip: Enable HDMI audio on Quartz64 A + +This enables the i2s0 controller and the hdmi-sound node on +the PINE64 Quartz64 Model A single-board computer. + +Signed-off-by: Nicolas Frattaroli +--- + arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts +@@ -310,6 +310,10 @@ + }; + }; + ++&hdmi_sound { ++ status = "okay"; ++}; ++ + &i2c0 { + status = "okay"; + +@@ -540,6 +544,10 @@ + status = "okay"; + }; + ++&i2s0_8ch { ++ status = "okay"; ++}; ++ + &i2s1_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s1m0_sclktx diff --git a/target/linux/rockchip/patches-5.18/251-missing-rk3568-cru-bindings.patch b/target/linux/rockchip/patches-5.18/251-missing-rk3568-cru-bindings.patch new file mode 100644 index 000000000..923ea2fc3 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/251-missing-rk3568-cru-bindings.patch @@ -0,0 +1,38 @@ +From b21445db9818ccb9fa1c0ba81fd3705eb8d347e3 Mon Sep 17 00:00:00 2001 +From: Peter Geis +Date: Wed, 11 May 2022 11:01:12 -0400 +Subject: [PATCH] dt-binding: clock: Add missing rk3568 cru bindings + +The rk3568 cru requires a clock input and a phandle to the grf node. Add +these bindings to clear some dtbs_check warnings. + +Signed-off-by: Peter Geis +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220511150117.113070-2-pgwipeout@gmail.com +Signed-off-by: Heiko Stuebner +--- + .../bindings/clock/rockchip,rk3568-cru.yaml | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml ++++ b/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml +@@ -34,6 +34,19 @@ properties: + "#reset-cells": + const: 1 + ++ clocks: ++ maxItems: 1 ++ ++ clock-names: ++ const: xin24m ++ ++ rockchip,grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the syscon managing the "general register files" (GRF), ++ if missing pll rates are not changeable, due to the missing pll ++ lock status. ++ + required: + - compatible + - reg diff --git a/target/linux/rockchip/patches-5.18/252-arm64-dts-rockchip-add-basic-dts-for-the-radxa-rock3-model-a.patch b/target/linux/rockchip/patches-5.18/252-arm64-dts-rockchip-add-basic-dts-for-the-radxa-rock3-model-a.patch new file mode 100644 index 000000000..1d4e8c4eb --- /dev/null +++ b/target/linux/rockchip/patches-5.18/252-arm64-dts-rockchip-add-basic-dts-for-the-radxa-rock3-model-a.patch @@ -0,0 +1,531 @@ +From 22a442e6586c898a6da1fbc57fab1b31dfc3e4b5 Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Thu, 10 Mar 2022 22:03:51 +0100 +Subject: [PATCH] arm64: dts: rockchip: add basic dts for the radxa rock3 model + a + +Add basic device tree for the Radxa ROCK3 Model A board (with +the Rockchip RK3568 SoC) including Ethernet, USB2 and headphone +connector. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20220310210352.451136-3-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../boot/dts/rockchip/rk3568-rock-3a.dts | 502 ++++++++++++++++++ + 2 files changed, 503 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts + +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -62,3 +62,4 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pi + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -0,0 +1,502 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/dts-v1/; ++#include ++#include ++#include ++#include "rk3568.dtsi" ++ ++/ { ++ model = "Radxa ROCK3 Model A"; ++ compatible = "radxa,rock3a", "rockchip,rk3568"; ++ ++ aliases { ++ ethernet0 = &gmac1; ++ mmc0 = &sdmmc0; ++ mmc1 = &sdhci; ++ }; ++ ++ chosen: chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_user: led-0 { ++ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; ++ function = LED_FUNCTION_HEARTBEAT; ++ color = ; ++ linux,default-trigger = "heartbeat"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&led_user_en>; ++ }; ++ }; ++ ++ rk809-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "Analog RK809"; ++ simple-audio-card,mclk-fs = <256>; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1_8ch>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&rk809>; ++ }; ++ }; ++ ++ vcc12v_dcin: vcc12v-dcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb: vcc5v0-usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb_host: vcc5v0-usb-host { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_host_en>; ++ regulator-name = "vcc5v0_usb_host"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_cpu>; ++}; ++ ++&gmac1 { ++ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; ++ assigned-clock-rates = <0>, <125000000>; ++ clock_in_out = "output"; ++ phy-handle = <&rgmii_phy1>; ++ phy-mode = "rgmii-id"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac1m1_miim ++ &gmac1m1_tx_bus2 ++ &gmac1m1_rx_bus2 ++ &gmac1m1_rgmii_clk ++ &gmac1m1_rgmii_bus>; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ++ vdd_cpu: regulator@1c { ++ compatible = "tcs,tcs4525"; ++ reg = <0x1c>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk809: pmic@20 { ++ compatible = "rockchip,rk809"; ++ reg = <0x20>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ assigned-clocks = <&cru I2S1_MCLKOUT_TX>; ++ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>; ++ #clock-cells = <1>; ++ clock-names = "mclk"; ++ clocks = <&cru I2S1_MCLKOUT_TX>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int>, <&i2s1m0_mclk>; ++ rockchip,system-power-controller; ++ #sound-dai-cells = <0>; ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc5-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ wakeup-source; ++ ++ regulators { ++ vdd_logic: DCDC_REG1 { ++ regulator-name = "vdd_logic"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: DCDC_REG2 { ++ regulator-name = "vdd_gpu"; ++ regulator-always-on; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-mode = <0x2>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vdd_npu: DCDC_REG4 { ++ regulator-name = "vdd_npu"; ++ regulator-init-microvolt = <900000>; ++ regulator-initial-mode = <0x2>; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG5 { ++ regulator-name = "vcc_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_image: LDO_REG1 { ++ regulator-name = "vdda0v9_image"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda_0v9: LDO_REG2 { ++ regulator-name = "vdda_0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdda0v9_pmu: LDO_REG3 { ++ regulator-name = "vdda0v9_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vccio_acodec: LDO_REG4 { ++ regulator-name = "vccio_acodec"; ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd: LDO_REG5 { ++ regulator-name = "vccio_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_pmu: LDO_REG6 { ++ regulator-name = "vcc3v3_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG7 { ++ regulator-name = "vcca_1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcca1v8_pmu: LDO_REG8 { ++ regulator-name = "vcca1v8_pmu"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_image: LDO_REG9 { ++ regulator-name = "vcca1v8_image"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3: SWITCH_REG1 { ++ regulator-name = "vcc_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_sd: SWITCH_REG2 { ++ regulator-name = "vcc3v3_sd"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ ++ codec { ++ mic-in-differential; ++ }; ++ }; ++}; ++ ++&i2s1_8ch { ++ rockchip,trcm-sync-tx-only; ++ status = "okay"; ++}; ++ ++&mdio1 { ++ rgmii_phy1: ethernet-phy@0 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð_phy_rst>; ++ reset-assert-us = <20000>; ++ reset-deassert-us = <100000>; ++ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&pinctrl { ++ ethernet { ++ eth_phy_rst: eth_phy_rst { ++ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ leds { ++ led_user_en: led_user_en { ++ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int: pmic_int { ++ rockchip,pins = ++ <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ vcc5v0_usb_host_en: vcc5v0_usb_host_en { ++ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ pmuio1-supply = <&vcc3v3_pmu>; ++ pmuio2-supply = <&vcc3v3_pmu>; ++ vccio1-supply = <&vccio_acodec>; ++ vccio2-supply = <&vcc_1v8>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_1v8>; ++ vccio5-supply = <&vcc_3v3>; ++ vccio6-supply = <&vcc_1v8>; ++ vccio7-supply = <&vcc_3v3>; ++ status = "okay"; ++}; ++ ++&saradc { ++ vref-supply = <&vcca_1v8>; ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_1v8>; ++ status = "okay"; ++}; ++ ++&sdmmc0 { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc3v3_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <1>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usb2phy1 { ++ status = "okay"; ++}; ++ ++&usb2phy1_host { ++ phy-supply = <&vcc5v0_usb_host>; ++ status = "okay"; ++}; ++ ++&usb2phy1_otg { ++ phy-supply = <&vcc5v0_usb_host>; ++ status = "okay"; ++}; diff --git a/target/linux/rockchip/patches-5.18/253-arm64-dts-rockchip-add-usb3-support-to-the-radxa-rock3-model-a.patch b/target/linux/rockchip/patches-5.18/253-arm64-dts-rockchip-add-usb3-support-to-the-radxa-rock3-model-a.patch new file mode 100644 index 000000000..c972cec2c --- /dev/null +++ b/target/linux/rockchip/patches-5.18/253-arm64-dts-rockchip-add-usb3-support-to-the-radxa-rock3-model-a.patch @@ -0,0 +1,92 @@ +From 254a1f6a29e7a273adb1a1d032305ec58ef83a69 Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Mon, 25 Apr 2022 15:35:01 +0200 +Subject: [PATCH] arm64: dts: rockchip: add usb3 support to the radxa rock3 + model a + +The Radxa ROCK3 Model A features one USB 3.0 host port and one USB 3.0 +OTG/DRD port. Enable them in the device tree. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20220425133502.405512-2-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + .../boot/dts/rockchip/rk3568-rock-3a.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -96,6 +96,26 @@ + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; ++ ++ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_otg_en>; ++ regulator-name = "vcc5v0_usb_otg"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++}; ++ ++&combphy0 { ++ status = "okay"; ++}; ++ ++&combphy1 { ++ status = "okay"; + }; + + &cpu0 { +@@ -416,6 +436,9 @@ + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; ++ vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { ++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + }; + }; + +@@ -479,6 +502,11 @@ + status = "okay"; + }; + ++&usb_host0_xhci { ++ extcon = <&usb2phy0>; ++ status = "okay"; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +@@ -487,6 +515,24 @@ + status = "okay"; + }; + ++&usb_host1_xhci { ++ status = "okay"; ++}; ++ ++&usb2phy0 { ++ status = "okay"; ++}; ++ ++&usb2phy0_host { ++ phy-supply = <&vcc5v0_usb_host>; ++ status = "okay"; ++}; ++ ++&usb2phy0_otg { ++ vbus-supply = <&vcc5v0_usb_otg>; ++ status = "okay"; ++}; ++ + &usb2phy1 { + status = "okay"; + }; diff --git a/target/linux/rockchip/patches-5.18/254-arm64-dts-rockchip-enable-usb-hub-on-the-radxa-rock3-model-a.patch b/target/linux/rockchip/patches-5.18/254-arm64-dts-rockchip-enable-usb-hub-on-the-radxa-rock3-model-a.patch new file mode 100644 index 000000000..9cc5559d9 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/254-arm64-dts-rockchip-enable-usb-hub-on-the-radxa-rock3-model-a.patch @@ -0,0 +1,46 @@ +From 160f126b89e10bd58491e10067a44c7e3f85fa2c Mon Sep 17 00:00:00 2001 +From: Michael Riesch +Date: Mon, 25 Apr 2022 15:35:02 +0200 +Subject: [PATCH] arm64: dts: rockchip: enable usb hub on the radxa rock3 model + a + +One USB 2.0 host port on the Radxa ROCK3 Model A is connected to the +SoC via a hub. Introduce a voltage regulator to enable this USB hub. + +Signed-off-by: Michael Riesch +Link: https://lore.kernel.org/r/20220425133502.405512-3-michael.riesch@wolfvision.net +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -97,6 +97,17 @@ + vin-supply = <&vcc5v0_usb>; + }; + ++ vcc5v0_usb_hub: vcc5v0-usb-hub-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_usb_hub_en>; ++ regulator-name = "vcc5v0_usb_hub"; ++ regulator-always-on; ++ vin-supply = <&vcc5v0_usb>; ++ }; ++ + vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -436,6 +447,9 @@ + vcc5v0_usb_host_en: vcc5v0_usb_host_en { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; ++ vcc5v0_usb_hub_en: vcc5v0_usb_hub_en { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; + vcc5v0_usb_otg_en: vcc5v0_usb_otg_en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; diff --git a/target/linux/rockchip/patches-5.18/255-rorck-3a-add-pcie-hdmi.patch b/target/linux/rockchip/patches-5.18/255-rorck-3a-add-pcie-hdmi.patch new file mode 100644 index 000000000..eefc8f679 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/255-rorck-3a-add-pcie-hdmi.patch @@ -0,0 +1,211 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include "rk3568.dtsi" + + / { +@@ -20,6 +21,24 @@ + stdout-path = "serial2:1500000n8"; + }; + ++ gmac1_clkin: external-gmac1-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac1_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ hdmi-con { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -94,7 +113,8 @@ + regulator-name = "vcc5v0_usb_host"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +- vin-supply = <&vcc5v0_usb>; ++ regulator-always-on; ++ regulator-boot-on; + }; + + vcc5v0_usb_hub: vcc5v0-usb-hub-regulator { +@@ -117,7 +137,41 @@ + regulator-name = "vcc5v0_usb_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +- vin-supply = <&vcc5v0_usb>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ pcie30_avdd0v9: pcie30-avdd0v9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcie30_avdd0v9"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ vin-supply = <&vcc3v3_sys>; ++ }; ++ ++ pcie30_avdd1v8: pcie30-avdd1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcie30_avdd1v8"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc3v3_sys>; ++ }; ++ ++ pcie30_3v3: gpio-regulator { ++ compatible = "regulator-gpio"; ++ regulator-name = "pcie30_3v3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <100000>; ++ regulator-max-microvolt = <3300000>; ++ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; ++ gpios-states = <0x1>; ++ states = <100000 0x0 ++ 3300000 0x1>; + }; + }; + +@@ -145,19 +199,33 @@ + cpu-supply = <&vdd_cpu>; + }; + ++&combphy2 { ++ status = "okay"; ++}; ++ + &gmac1 { ++ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ /* Reset time is 20ms, 100ms for rtl8211f */ ++ snps,reset-delays-us = <0 20000 100000>; ++ + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; +- assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>; +- assigned-clock-rates = <0>, <125000000>; +- clock_in_out = "output"; ++ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>; ++ clock_in_out = "input"; + phy-handle = <&rgmii_phy1>; +- phy-mode = "rgmii-id"; ++ phy-mode = "rgmii"; ++ + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk +- &gmac1m1_rgmii_bus>; ++ &gmac1m1_rgmii_bus ++ &gmac1m1_clkinout>; ++ ++ tx_delay = <0x4f>; ++ rx_delay = <0x26>; ++ + status = "okay"; + }; + +@@ -166,6 +234,24 @@ + status = "okay"; + }; + ++&hdmi { ++ avdd-0v9-supply = <&vdda0v9_image>; ++ avdd-1v8-supply = <&vcca1v8_image>; ++ status = "okay"; ++}; ++ ++&hdmi_in { ++ hdmi_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi>; ++ }; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2c0 { + status = "okay"; + +@@ -415,11 +501,6 @@ + rgmii_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; +- pinctrl-names = "default"; +- pinctrl-0 = <ð_phy_rst>; +- reset-assert-us = <20000>; +- reset-deassert-us = <100000>; +- reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + }; + }; + +@@ -498,6 +579,17 @@ + status = "okay"; + }; + ++&sfc { ++ status = "okay"; ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <108000000>; ++ spi-rx-bus-width = <2>; ++ spi-tx-bus-width = <2>; ++ }; ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <1>; + rockchip,hw-tshut-polarity = <0>; +@@ -560,3 +652,28 @@ + phy-supply = <&vcc5v0_usb_host>; + status = "okay"; + }; ++ ++&pcie2x1 { ++ reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; ++ vpcie3v3-supply = <&pcie30_3v3>; ++ pinctrl-0 = <&pcie20m1_pins>; ++ bus-scan-delay-ms = <1000>; ++ status = "okay"; ++}; ++ ++&vop { ++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; ++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi_in_vp0>; ++ }; ++}; diff --git a/target/linux/rockchip/patches-5.18/256-rk356x-pcie3-support.patch b/target/linux/rockchip/patches-5.18/256-rk356x-pcie3-support.patch new file mode 100644 index 000000000..f3fd44b02 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/256-rk356x-pcie3-support.patch @@ -0,0 +1,539 @@ +--- /dev/null ++++ b/include/dt-bindings/phy/phy-rockchip-pcie3.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ */ ++ ++#ifndef _DT_BINDINGS_PHY_ROCKCHIP_PCIE3 ++#define _DT_BINDINGS_PHY_ROCKCHIP_PCIE3 ++ ++/* ++ * pcie30_phy_mode[2:0] ++ * bit2: aggregation ++ * bit1: bifurcation for port 1 ++ * bit0: bifurcation for port 0 ++ */ ++#define PHY_MODE_PCIE_AGGREGATION 4 /* PCIe3x4 */ ++#define PHY_MODE_PCIE_NANBNB 0 /* P1:PCIe3x2 + P0:PCIe3x2 */ ++#define PHY_MODE_PCIE_NANBBI 1 /* P1:PCIe3x2 + P0:PCIe3x1*2 */ ++#define PHY_MODE_PCIE_NABINB 2 /* P1:PCIe3x1*2 + P0:PCIe3x2 */ ++#define PHY_MODE_PCIE_NABIBI 3 /* P1:PCIe3x1*2 + P0:PCIe3x1*2 */ ++ ++#endif /* _DT_BINDINGS_PHY_ROCKCHIP_PCIE3 */ +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -83,6 +83,15 @@ config PHY_ROCKCHIP_PCIE + help + Enable this to support the Rockchip PCIe PHY. + ++config PHY_ROCKCHIP_SNPS_PCIE3 ++ tristate "Rockchip Snps PCIe3 PHY Driver" ++ depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST ++ depends on HAS_IOMEM ++ select GENERIC_PHY ++ select MFD_SYSCON ++ help ++ Enable this to support the Rockchip snps PCIe3 PHY. ++ + config PHY_ROCKCHIP_TYPEC + tristate "Rockchip TYPEC PHY Driver" + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -8,5 +8,6 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o + obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o ++obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +@@ -0,0 +1,278 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Rockchip PCIE3.0 phy driver ++ * ++ * Copyright (C) 2020 Rockchip Electronics Co., Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Register for RK3568 */ ++#define GRF_PCIE30PHY_CON1 0x4 ++#define GRF_PCIE30PHY_CON6 0x18 ++#define GRF_PCIE30PHY_CON9 0x24 ++#define GRF_PCIE30PHY_STATUS0 0x80 ++#define SRAM_INIT_DONE(reg) (reg & BIT(14)) ++ ++/* Register for RK3588 */ ++#define PHP_GRF_PCIESEL_CON 0x100 ++#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0 ++#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904 ++#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04 ++#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0)) ++ ++struct rockchip_p3phy_ops; ++ ++struct rockchip_p3phy_priv { ++ const struct rockchip_p3phy_ops *ops; ++ void __iomem *mmio; ++ /* mode: RC, EP */ ++ int mode; ++ /* pcie30_phymode: Aggregation, Bifurcation */ ++ int pcie30_phymode; ++ struct regmap *phy_grf; ++ struct regmap *pipe_grf; ++ struct reset_control *p30phy; ++ struct phy *phy; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ bool is_bifurcation; ++}; ++ ++struct rockchip_p3phy_ops { ++ int (*phy_init)(struct rockchip_p3phy_priv *priv); ++}; ++ ++static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ /* Actually We don't care EP/RC mode, but just record it */ ++ switch (submode) { ++ case PHY_MODE_PCIE_RC: ++ priv->mode = PHY_MODE_PCIE_RC; ++ break; ++ case PHY_MODE_PCIE_EP: ++ priv->mode = PHY_MODE_PCIE_EP; ++ break; ++ case PHY_MODE_PCIE_BIFURCATION: ++ priv->is_bifurcation = true; ++ break; ++ default: ++ dev_err(&phy->dev, "%s, invalid mode\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) ++{ ++ int ret; ++ u32 reg; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, ++ BIT(15) | BIT(31)); ++ /* Set bifurcation if needed, and it doesn't care RC/EP */ ++ if (priv->is_bifurcation) { ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6, ++ 0x1 | (0xf << 16)); ++ regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1, ++ BIT(15) | BIT(31)); ++ } ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ GRF_PCIE30PHY_STATUS0, ++ reg, SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n", ++ __func__, reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3568_ops = { ++ .phy_init = rockchip_p3phy_rk3568_init, ++}; ++ ++static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv) ++{ ++ int ret; ++ u32 reg; ++ ++ /* Deassert PCIe PMA output clamp mode */ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, ++ BIT(8) | BIT(24)); ++ ++ reset_control_deassert(priv->p30phy); ++ ++ ret = regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY0_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ ret |= regmap_read_poll_timeout(priv->phy_grf, ++ RK3588_PCIE3PHY_GRF_PHY1_STATUS1, ++ reg, RK3588_SRAM_INIT_DONE(reg), ++ 0, 500); ++ if (ret) ++ pr_err("%s: lock failed 0x%x, check input refclk and power supply\n", ++ __func__, reg); ++ return ret; ++} ++ ++static const struct rockchip_p3phy_ops rk3588_ops = { ++ .phy_init = rockchip_p3phy_rk3588_init, ++}; ++ ++static int rochchip_p3phy_init(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ pr_err("failed to enable PCIe bulk clks %d\n", ret); ++ return ret; ++ } ++ ++ reset_control_assert(priv->p30phy); ++ udelay(1); ++ ++ if (priv->ops->phy_init) { ++ ret = priv->ops->phy_init(priv); ++ if (ret) ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ } ++ ++ return ret; ++} ++ ++static int rochchip_p3phy_exit(struct phy *phy) ++{ ++ struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++ reset_control_assert(priv->p30phy); ++ return 0; ++} ++ ++static const struct phy_ops rochchip_p3phy_ops = { ++ .init = rochchip_p3phy_init, ++ .exit = rochchip_p3phy_exit, ++ .set_mode = rockchip_p3phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static int rockchip_p3phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rockchip_p3phy_priv *priv; ++ struct device_node *np = dev->of_node; ++ struct resource *res; ++ int ret; ++ u32 val, reg; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->mmio = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->mmio)) { ++ ret = PTR_ERR(priv->mmio); ++ return ret; ++ } ++ ++ priv->ops = of_device_get_match_data(&pdev->dev); ++ if (!priv->ops) { ++ dev_err(&pdev->dev, "no of match data provided\n"); ++ return -EINVAL; ++ } ++ ++ priv->phy_grf = syscon_regmap_lookup_by_phandle(np, "rockchip,phy-grf"); ++ if (IS_ERR(priv->phy_grf)) { ++ dev_err(dev, "failed to find rockchip,phy_grf regmap\n"); ++ return PTR_ERR(priv->phy_grf); ++ } ++ ++ priv->pipe_grf = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,pipe-grf"); ++ if (IS_ERR(priv->pipe_grf)) ++ dev_info(dev, "failed to find rockchip,pipe_grf regmap\n"); ++ ++ ret = device_property_read_u32(dev, "rockchip,pcie30-phymode", &val); ++ if (!ret) ++ priv->pcie30_phymode = val; ++ else ++ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; ++ ++ /* Select correct pcie30_phymode */ ++ if (priv->pcie30_phymode > 4) ++ priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; ++ ++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, ++ (0x7<<16) | priv->pcie30_phymode); ++ ++ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */ ++ if (!IS_ERR(priv->pipe_grf)) { ++ reg = priv->pcie30_phymode & 3; ++ if (reg) ++ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON, ++ (reg << 16) | reg); ++ } ++ ++ priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops); ++ if (IS_ERR(priv->phy)) { ++ dev_err(dev, "failed to create combphy\n"); ++ return PTR_ERR(priv->phy); ++ } ++ ++ priv->p30phy = devm_reset_control_get_exclusive(dev, "phy"); ++ if (IS_ERR(priv->p30phy)) { ++ dev_warn(dev, "no phy reset control specified\n"); ++ priv->p30phy = NULL; ++ } ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -ENODEV; ++ ++ dev_set_drvdata(dev, priv); ++ phy_set_drvdata(priv->phy, priv); ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id rockchip_p3phy_of_match[] = { ++ { .compatible = "rockchip,rk3568-pcie3-phy", .data = &rk3568_ops }, ++ { .compatible = "rockchip,rk3588-pcie3-phy", .data = &rk3588_ops }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_p3phy_of_match); ++ ++static struct platform_driver rockchip_p3phy_driver = { ++ .probe = rockchip_p3phy_probe, ++ .driver = { ++ .name = "rockchip-snps-pcie3-phy", ++ .of_match_table = rockchip_p3phy_of_match, ++ }, ++}; ++module_platform_driver(rockchip_p3phy_driver); ++MODULE_DESCRIPTION("Rockchip Synopsys PCIe 3.0 PHY driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/linux/phy/pcie.h +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ */ ++#ifndef __PHY_PCIE_H ++#define __PHY_PCIE_H ++ ++#define PHY_MODE_PCIE_RC 20 ++#define PHY_MODE_PCIE_EP 21 ++#define PHY_MODE_PCIE_BIFURCATION 22 ++ ++#endif +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include "pcie-designware.h" + +@@ -58,6 +59,8 @@ struct rockchip_pcie { + struct gpio_desc *rst_gpio; + struct regulator *vpcie3v3; + struct irq_domain *irq_domain; ++ bool bifurcation; ++ u32 lane_map[2]; + }; + + static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip, +@@ -262,6 +265,12 @@ static int rockchip_pcie_phy_init(struct + return dev_err_probe(dev, PTR_ERR(rockchip->phy), + "missing PHY\n"); + ++ if (rockchip->bifurcation) { ++ ret = phy_set_mode_ext(rockchip->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION); ++ if (ret) ++ return ret; ++ } ++ + ret = phy_init(rockchip->phy); + if (ret < 0) + return ret; +@@ -288,8 +297,10 @@ static int rockchip_pcie_probe(struct pl + { + struct device *dev = &pdev->dev; + struct rockchip_pcie *rockchip; ++ unsigned int lanecnt = 0; + struct pcie_port *pp; + int ret; ++ int len; + + rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); + if (!rockchip) +@@ -326,6 +337,17 @@ static int rockchip_pcie_probe(struct pl + } + } + ++ len = of_property_read_variable_u32_array(dev->of_node, "lane-map", rockchip->lane_map, ++ 2, ARRAY_SIZE(rockchip->lane_map)); ++ ++ for (int i = 0; i < len; i++) ++ if (rockchip->lane_map[i]) ++ lanecnt++; ++ ++ rockchip->bifurcation = ((lanecnt > 0) && (lanecnt != len)); ++ ++ dev_info(dev, "bifurcation: %s\n", rockchip->bifurcation ? "true" : "false"); ++ + ret = rockchip_pcie_phy_init(rockchip); + if (ret) + goto disable_regulator; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -42,6 +42,128 @@ + reg = <0x0 0xfe190200 0x0 0x20>; + }; + ++ pcie30_phy_grf: syscon@fdcb8000 { ++ compatible = "rockchip,rk3568-pcie3-phy-grf", "syscon"; ++ reg = <0x0 0xfdcb8000 0x0 0x10000>; ++ }; ++ ++ pcie30phy: phy@fe8c0000 { ++ compatible = "rockchip,rk3568-pcie3-phy"; ++ reg = <0x0 0xfe8c0000 0x0 0x20000>; ++ #phy-cells = <0>; ++ clocks = <&pmucru CLK_PCIE30PHY_REF_M>, <&pmucru CLK_PCIE30PHY_REF_N>, ++ <&cru PCLK_PCIE30PHY>; ++ clock-names = "refclk_m", "refclk_n", "pclk"; ++ resets = <&cru SRST_PCIE30PHY>; ++ reset-names = "phy"; ++ rockchip,phy-grf = <&pcie30_phy_grf>; ++ status = "disabled"; ++ }; ++ ++ pcie3x1: pcie@fe270000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x10 0x1f>; ++ clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, ++ <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, ++ <&cru CLK_PCIE30X1_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x1_intc 0>, ++ <0 0 0 2 &pcie3x1_intc 1>, ++ <0 0 0 3 &pcie3x1_intc 2>, ++ <0 0 0 4 &pcie3x1_intc 3>; ++ linux,pci-domain = <1>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x1000 &gic 0x1000 0x1000>; ++ num-lanes = <1>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0400000 0x0 0x00400000>, ++ <0x0 0xfe270000 0x0 0x00010000>, ++ <0x3 0x40000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x01000000 0x3 0x41000000 0x0 0x00100000>, ++ <0x02000000 0x0 0x02000000 0x3 0x41100000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X1_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane1 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x1_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ ++ pcie3x2: pcie@fe280000 { ++ compatible = "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x20 0x2f>; ++ clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, ++ <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, ++ <&cru CLK_PCIE30X2_AUX_NDFT>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", "aux"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie3x2_intc 0>, ++ <0 0 0 2 &pcie3x2_intc 1>, ++ <0 0 0 3 &pcie3x2_intc 2>, ++ <0 0 0 4 &pcie3x2_intc 3>; ++ linux,pci-domain = <2>; ++ num-ib-windows = <6>; ++ num-ob-windows = <2>; ++ max-link-speed = <3>; ++ msi-map = <0x2000 &gic 0x2000 0x1000>; ++ num-lanes = <2>; ++ phys = <&pcie30phy>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3568_PD_PIPE>; ++ reg = <0x3 0xc0800000 0x0 0x00400000>, ++ <0x0 0xfe280000 0x0 0x00010000>, ++ <0x3 0x80000000 0x0 0x01000000>; ++ ranges = <0x01000000 0x0 0x01000000 0x3 0x81000000 0x0 0x00100000>, ++ <0x02000000 0x0 0x02000000 0x3 0x81100000 0x0 0x3ef00000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE30X2_POWERUP>; ++ reset-names = "pipe"; ++ /* bifurcation; lane0 when using 1+1 */ ++ status = "disabled"; ++ ++ pcie3x2_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ + gmac0: ethernet@fe2a0000 { + compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe2a0000 0x0 0x10000>; diff --git a/target/linux/rockchip/patches-5.18/257-add-PCIe-3-to-ROCK3A.patch b/target/linux/rockchip/patches-5.18/257-add-PCIe-3-to-ROCK3A.patch new file mode 100644 index 000000000..b643980e8 --- /dev/null +++ b/target/linux/rockchip/patches-5.18/257-add-PCIe-3-to-ROCK3A.patch @@ -0,0 +1,22 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts +@@ -653,6 +653,19 @@ + status = "okay"; + }; + ++&pcie30phy { ++ status = "okay"; ++}; ++ ++&pcie3x2 { ++ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; ++ vpcie3v3-supply = <&pcie30_3v3>; ++ //num-lanes = <2>; ++ pinctrl-0 = <&pcie30x2m1_pins>; ++ bus-scan-delay-ms = <1000>; ++ status = "okay"; ++}; ++ + &pcie2x1 { + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&pcie30_3v3>;