target: add phytium support (#11798)

* target: add phytium support

* kernel/video: add phytium platform ARM GPU support

* config: add EFI support to phytium armv8

* target: phytium: remove rtl8821cs driver

* target: phytium: refresh dts
This commit is contained in:
HunZI 2024-01-18 15:16:24 +08:00 committed by GitHub
parent 03b416d21f
commit a462d2b757
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
203 changed files with 67909 additions and 4 deletions

View File

@ -206,12 +206,13 @@ menu "Target Images"
config GRUB_EFI_IMAGES
bool "Build GRUB EFI images"
depends on TARGET_x86 || TARGET_armvirt || TARGET_loongarch64
depends on TARGET_x86 || TARGET_armvirt || TARGET_loongarch64 || TARGET_phytium_armv8
depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS
select PACKAGE_grub2 if TARGET_x86
select PACKAGE_grub2-efi if TARGET_x86
select PACKAGE_grub2-bios-setup if TARGET_x86
select PACKAGE_grub2-efi-arm if TARGET_armvirt
select PACKAGE_grub2-efi-arm if TARGET_phytium_armv8
select PACKAGE_kmod-fs-vfat
default y

View File

@ -42,6 +42,7 @@ endef
Package/grub2=$(call Package/grub2/Default,x86,pc)
Package/grub2-efi=$(call Package/grub2/Default,x86,efi)
Package/grub2-efi-arm=$(call Package/grub2/Default,armsr,efi)
Package/grub2-efi-arm=$(call Package/grub2/Default,phytium_armv8,efi)
Package/grub2-efi-loongarch64=$(call Package/grub2/Default,loongarch64,efi)
define Package/grub2-editenv

View File

@ -57,7 +57,7 @@ $(eval $(call KernelPackage,backlight-pwm))
define KernelPackage/acpi-video
SUBMENU:=$(VIDEO_MENU)
TITLE:=ACPI Extensions For Display Adapters
DEPENDS:=@TARGET_x86||TARGET_loongarch64 +kmod-backlight
DEPENDS:=@TARGET_x86||TARGET_loongarch64||TARGET_phytium +kmod-backlight
HIDDEN:=1
KCONFIG:=CONFIG_ACPI_VIDEO
FILES:=$(LINUX_DIR)/drivers/acpi/video.ko
@ -386,7 +386,7 @@ $(eval $(call KernelPackage,drm-display-helper))
define KernelPackage/drm-amdgpu
SUBMENU:=$(VIDEO_MENU)
TITLE:=AMDGPU DRM support
DEPENDS:=@TARGET_x86||TARGET_loongarch64 @DISPLAY_SUPPORT +kmod-backlight +kmod-drm-ttm \
DEPENDS:=@TARGET_x86||TARGET_loongarch64||TARGET_phytium @DISPLAY_SUPPORT +kmod-backlight +kmod-drm-ttm \
+kmod-drm-ttm-helper +kmod-drm-kms-helper +kmod-i2c-algo-bit +amdgpu-firmware \
+kmod-drm-display-helper +kmod-drm-buddy +kmod-acpi-video
KCONFIG:=CONFIG_DRM_AMDGPU \
@ -525,7 +525,7 @@ $(eval $(call KernelPackage,drm-panfrost))
define KernelPackage/drm-radeon
SUBMENU:=$(VIDEO_MENU)
TITLE:=Radeon DRM support
DEPENDS:=@TARGET_x86 @DISPLAY_SUPPORT +kmod-backlight +kmod-drm-kms-helper \
DEPENDS:=@TARGET_x86||TARGET_phytium @DISPLAY_SUPPORT +kmod-backlight +kmod-drm-kms-helper \
+kmod-drm-ttm +kmod-i2c-algo-bit +LINUX_6_1:kmod-acpi-video +radeon-firmware
KCONFIG:=CONFIG_DRM_RADEON
FILES:=$(LINUX_DIR)/drivers/gpu/drm/radeon/radeon.ko

View File

@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (c) 2023 Phytium Technology Co., Ltd.
# Copyright (C) 2023-2024 Ailick <277498654@qq.com>
include $(TOPDIR)/rules.mk
BOARD:=phytium
BOARDNAME:=Phytium
FEATURES:=fpu pci pcie rtc usb boot-part rootfs-part
FEATURES+=cpiogz ext4 ramdisk squashfs targz vmdk usb gpio fpu pci pcie jffs2
SUBTARGETS:=armv8 e2000 phytiumpi
KERNEL_PATCHVER:=5.10
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += mkf2fs e2fsprogs
# blkid used for resolving PARTUUID
# in sysupgrade. vfat required for
# mounting ESP partition
DEFAULT_PACKAGES += blkid kmod-fs-vfat kmod-usb2 kmod-usb3 kmod-hwmon-phytium
$(eval $(call BuildTarget))

View File

@ -0,0 +1,5 @@
This target generates images that can be used on ARM machines with EFI
support (e.g EDKII/TianoCore or U-Boot with bootefi).
Tested:
THTF ChaoXiang TF830-V050

View File

@ -0,0 +1,827 @@
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_USELIB=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_RCU_EXPERT=y
CONFIG_RCU_NOCB_CPU=y
CONFIG_RCU_FANOUT=64
CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_TASKS_TRACE_RCU_READ_MB is not set
# CONFIG_UCLAMP_TASK is not set
CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_ZONE_DMA32=y
CONFIG_NUMA=y
CONFIG_NODES_SHIFT=8
CONFIG_UNMAP_KERNEL_AT_EL0=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
CONFIG_DMI=y
# CONFIG_HIBERNATION is not set
# CONFIG_HIBERNATION_SNAPSHOT_DEV is not set
CONFIG_PM_STD_PARTITION=""
CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_ACPI_CPPC_CPUFREQ is not set
# CONFIG_ARM_SCMI_CPUFREQ is not set
# CONFIG_ARM_SCMI_TRANSPORT_FORCE_POLLING is not set
CONFIG_ARM_SCMI_POWER_DOMAIN=y
CONFIG_DMIID=y
# CONFIG_DMI_SYSFS is not set
# CONFIG_ISCSI_IBFT is not set
CONFIG_EFI_ARMSTUB_DTB_LOADER=y
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
# CONFIG_EFI_TEST is not set
# CONFIG_EFI_DISABLE_PCI_DMA is not set
# CONFIG_EFI_CUSTOM_SSDT_OVERLAYS is not set
CONFIG_ACPI_DEBUGGER=y
# CONFIG_ACPI_EC_DEBUGFS is not set
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
# CONFIG_ACPI_TINY_POWER_BUTTON is not set
CONFIG_ACPI_FAN=y
# CONFIG_ACPI_TAD is not set
CONFIG_ACPI_PROCESSOR=y
# CONFIG_ACPI_IPMI is not set
CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_CUSTOM_DSDT_FILE=""
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_HMAT is not set
# CONFIG_ACPI_APEI_ERST_DEBUG is not set
# CONFIG_ACPI_DEBUGGER_USER is not set
CONFIG_KVM_ARM_PMU=y
CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_BLK_WBT_MQ=y
# CONFIG_LDM_DEBUG is not set
# CONFIG_BFQ_CGROUP_DEBUG is not set
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_BALLOON_COMPACTION=y
# CONFIG_HWPOISON_INJECT is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y
CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y
# CONFIG_ZSWAP_ZPOOL_DEFAULT_Z3FOLD is not set
# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC is not set
# CONFIG_ZSWAP_DEFAULT_ON is not set
# CONFIG_Z3FOLD is not set
# CONFIG_BPFILTER_UMH is not set
# CONFIG_NCSI_OEM_CMD_GET_MAC is not set
# CONFIG_NET_9P_XEN is not set
# CONFIG_NET_9P_DEBUG is not set
# CONFIG_NFC_DIGITAL is not set
# CONFIG_NFC_NCI_SPI is not set
# CONFIG_NFC_NCI_UART is not set
# CONFIG_NFC_HCI is not set
# CONFIG_NFC_FDP is not set
# CONFIG_NFC_PN533_USB is not set
# CONFIG_NFC_PN533_I2C is not set
# CONFIG_NFC_PN532_UART is not set
# CONFIG_NFC_MRVL_USB is not set
# CONFIG_NFC_ST_NCI_I2C is not set
# CONFIG_NFC_ST_NCI_SPI is not set
# CONFIG_NFC_NXP_NCI is not set
# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
CONFIG_PCI_XGENE_MSI=y
# CONFIG_PCIE_HISI_ERR is not set
# CONFIG_PCIE_CADENCE_PLAT_EP is not set
# CONFIG_PCI_J721E_EP is not set
CONFIG_FW_CACHE=y
CONFIG_PROC_EVENTS=y
CONFIG_MTD_PHYSMAP_START=0x8000000
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
# CONFIG_MTD_DATAFLASH_OTP is not set
# CONFIG_MTD_NAND_PHYTIUM_PCI is not set
# CONFIG_SPI_HISI_SFC is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
# CONFIG_XEN_BLKDEV_BACKEND is not set
CONFIG_SCSI_SAS_HOST_SMP=y
# CONFIG_MEGARAID_MM is not set
CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
# CONFIG_SCSI_UFSHCD_PCI is not set
# CONFIG_SCSI_UFS_CDNS_PLATFORM is not set
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
# CONFIG_SCSI_UFS_BSG is not set
# CONFIG_XEN_SCSI_FRONTEND is not set
# CONFIG_SCSI_DH_RDAC is not set
# CONFIG_SCSI_DH_HP_SW is not set
# CONFIG_SCSI_DH_EMC is not set
# CONFIG_SCSI_DH_ALUA is not set
# CONFIG_DM_INIT is not set
# CONFIG_DM_ZONED is not set
CONFIG_FUSION_MAX_SGE=128
# CONFIG_MACB_PCI is not set
# CONFIG_HNS3_HCLGEVF is not set
# CONFIG_STMMAC_SELFTESTS is not set
# CONFIG_ROADRUNNER is not set
# CONFIG_MOTORCOMM_PHY is not set
# CONFIG_DLCI is not set
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_NETDEV_BACKEND is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYSTICK is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_BPF=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
CONFIG_SGETMASK_SYSCALL=y
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_USERFAULTFD=y
# CONFIG_SLUB_DEBUG is not set
CONFIG_SLUB_MEMCG_SYSFS_ON=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB_MERGE_DEFAULT is not set
CONFIG_PROFILING=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_VEXPRESS=y
CONFIG_ARCH_PHYTIUM=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_COMPAT=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_PMEM=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_ARM64_ACPI_PARKING_PROTOCOL=y
CONFIG_CMDLINE="pcie_aspm=off"
CONFIG_HIBERNATION=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_ARM_SCMI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_RESET_ATTACK_MITIGATION=y
CONFIG_ACPI=y
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_PCI_SLOT=y
CONFIG_ACPI_BGRT=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_PMIC_OPREGION=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
# CONFIG_VMAP_STACK is not set
CONFIG_MODVERSIONS=y
CONFIG_UNUSED_SYMBOLS=y
CONFIG_BLK_DEV_ZONED=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_DEV_THROTTLING_LOW=y
CONFIG_BLK_CMDLINE_PARSER=y
CONFIG_BLK_WBT=y
CONFIG_BLK_CGROUP_IOLATENCY=y
# CONFIG_BLK_DEBUG_FS is not set
CONFIG_BLK_SED_OPAL=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_OSF_PARTITION=y
CONFIG_ATARI_PARTITION=y
CONFIG_MAC_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
CONFIG_LDM_PARTITION=y
CONFIG_SGI_PARTITION=y
CONFIG_ULTRIX_PARTITION=y
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_SYSV68_PARTITION=y
CONFIG_IOSCHED_BFQ=y
CONFIG_BFQ_GROUP_IOSCHED=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_FRONTSWAP=y
CONFIG_ZSWAP=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_XFRM_SUB_POLICY=y
CONFIG_XDP_SOCKETS=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_NET_FOU=y
CONFIG_NET_FOU_IP_TUNNELS=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_MD5SIG=y
# CONFIG_IPV6_SIT is not set
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_IPV6_SEG6_LWTUNNEL=y
CONFIG_IPV6_SEG6_HMAC=y
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_IP_VS_IPV6=y
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y
CONFIG_NF_REJECT_IPV4=y
CONFIG_BPFILTER=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_DEFAULT=y
CONFIG_NET_EMATCH=y
CONFIG_NET_CLS_ACT=y
CONFIG_DCB=y
CONFIG_NET_NCSI=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_BPF_JIT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCIE_PTM=y
CONFIG_PCI_STUB=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PRI=y
CONFIG_PCI_PASID=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_HOTPLUG_PCI_CPCI=y
CONFIG_HOTPLUG_PCI_SHPC=y
CONFIG_PCI_FTPCI100=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_DW_PLAT_HOST=y
CONFIG_PCIE_DW_PLAT_EP=y
CONFIG_PCI_HISI=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_HISI_STB=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_DEVTMPFS=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
# CONFIG_ALLOW_DEV_COREDUMP is not set
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_CONNECTOR=y
CONFIG_MTD_PARTITIONED_MASTER=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_MAP_BANK_WIDTH_8=y
CONFIG_MTD_MAP_BANK_WIDTH_16=y
CONFIG_MTD_MAP_BANK_WIDTH_32=y
CONFIG_MTD_CFI_I4=y
CONFIG_MTD_CFI_I8=y
CONFIG_MTD_OTP=y
CONFIG_MTD_PHYSMAP_COMPAT=y
CONFIG_MTD_PHYSMAP_LEN=0x0
CONFIG_SPI_PHYTIUM_QUADSPI=y
# CONFIG_PNP_DEBUG_MESSAGES is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=8
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_NVME=y
CONFIG_NVME_MULTIPATH=y
CONFIG_SRAM=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_MEGARAID_NEWGEN=y
CONFIG_SCSI_DH=y
CONFIG_ATA=y
# CONFIG_ATA_ACPI is not set
CONFIG_SATA_AHCI=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_UEVENT=y
CONFIG_FUSION=y
CONFIG_FUSION_LOGGING=y
CONFIG_NET_FC=y
# CONFIG_NET_VENDOR_AMAZON is not set
CONFIG_AMD_XGBE_DCB=y
CONFIG_NET_TULIP=y
CONFIG_HNS3_DCB=y
CONFIG_IXGBE_DCB=y
CONFIG_I40E_DCB=y
# CONFIG_MLX4_DEBUG is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PCI=y
CONFIG_HIPPI=y
CONFIG_MARVELL_PHY=y
CONFIG_MDIO_HISI_FEMAC=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_MULTILINK=y
CONFIG_WIRELESS_WDS=y
CONFIG_WAN=y
CONFIG_ISDN=y
# CONFIG_INPUT_LEDS is not set
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TABLET=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HISI_POWERKEY=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_FINTEK=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=48
CONFIG_SERIAL_8250_RUNTIME_UARTS=32
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL010=y
CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_NONSTANDARD=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_I2C_SLAVE=y
CONFIG_SPI=y
CONFIG_SPI_PHYTIUM_PLAT=y
CONFIG_SPI_PHYTIUM_PCI=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_XGENE=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_GPIO_RESTART=y
CONFIG_POWER_RESET_HISI=y
CONFIG_POWER_RESET_LTC2952=y
CONFIG_POWER_RESET_RESTART=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_PMIC_DA903X=y
CONFIG_MFD_DA9052_SPI=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9055=y
CONFIG_MFD_DA9063=y
CONFIG_HTC_I2CPLD=y
CONFIG_MFD_88PM860X=y
CONFIG_MFD_MAX14577=y
CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX77693=y
CONFIG_MFD_MAX77843=y
CONFIG_MFD_MAX8925=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_MAX8998=y
CONFIG_EZX_PCAP=y
CONFIG_MFD_PHYTIUM_I2S_LSD=y
CONFIG_MFD_PHYTIUM_I2S_MMD=y
CONFIG_MFD_RC5T583=y
CONFIG_MFD_SEC_CORE=y
CONFIG_ABX500_CORE=y
CONFIG_AB3100_CORE=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_LP8788=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y
CONFIG_MFD_TPS65910=y
CONFIG_MFD_TPS65912_I2C=y
CONFIG_MFD_TPS65912_SPI=y
CONFIG_MFD_TPS80031=y
CONFIG_TWL4030_CORE=y
CONFIG_TWL6040_CORE=y
CONFIG_MFD_TC3589X=y
CONFIG_MFD_WM8400=y
CONFIG_MFD_WM831X_I2C=y
CONFIG_MFD_WM831X_SPI=y
CONFIG_MFD_WM8350_I2C=y
CONFIG_DVB_MAX_ADAPTERS=8
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_MEDIA_PCI_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_VIDEO_CADENCE=y
CONFIG_DVB_PLATFORM_DRIVERS=y
CONFIG_DRM=y
CONFIG_DRM_DP_AUX_CHARDEV=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_DP_CEC=y
CONFIG_DRM_RADEON_USERPTR=y
CONFIG_DRM_AMDGPU_SI=y
CONFIG_DRM_AMDGPU_CIK=y
CONFIG_DRM_AMDGPU_USERPTR=y
CONFIG_DRM_AMD_ACP=y
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_DRM_XEN=y
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_EFI=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_SOUND=y
# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
CONFIG_SND=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_HRTIMER=y
CONFIG_SND_SEQUENCER=y
CONFIG_SND_SEQ_DUMMY=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HDA_INTEL=y
CONFIG_SND_HDA_PHYTIUM=y
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=y
CONFIG_SND_HDA_CODEC_ANALOG=y
CONFIG_SND_HDA_CODEC_SIGMATEL=y
CONFIG_SND_HDA_CODEC_VIA=y
CONFIG_SND_HDA_CODEC_HDMI=y
CONFIG_SND_HDA_CODEC_CIRRUS=y
CONFIG_SND_HDA_CODEC_CONEXANT=y
CONFIG_SND_HDA_CODEC_CA0110=y
CONFIG_SND_HDA_CODEC_CA0132=y
CONFIG_SND_HDA_CODEC_CMEDIA=y
CONFIG_SND_HDA_CODEC_SI3054=y
CONFIG_SND_HDA_PREALLOC_SIZE=1024
CONFIG_SND_SOC_IMG=y
CONFIG_SND_SOC_PHYTIUM_I2S=y
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
CONFIG_HID_PID=y
CONFIG_USB_LED_TRIG=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DBGCAP=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_DWC3_ULPI=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_ULPI=y
CONFIG_MMC_PHYTIUM_SDCI=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307_CENTURY=y
CONFIG_RTC_DRV_RV8803=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_ZYNQMP=y
CONFIG_RTC_DRV_PL030=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
CONFIG_ASYNC_TX_DMA=y
CONFIG_SW_SYNC=y
CONFIG_AUXDISPLAY=y
CONFIG_VIRT_DRIVERS=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GNTDEV_DMABUF=y
CONFIG_XEN_GRANT_DMA_ALLOC=y
CONFIG_XEN_PVCALLS_BACKEND=y
CONFIG_STAGING=y
CONFIG_STAGING_MEDIA=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_CLK_QORIQ=y
CONFIG_SOC_BRCMSTB=y
CONFIG_SOC_TI=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_MEMORY=y
CONFIG_NTB=y
CONFIG_PWM=y
CONFIG_PHYTIUM_IXIC=y
CONFIG_POWERCAP=y
CONFIG_HISI_PMU=y
CONFIG_STM=y
CONFIG_STM_SOURCE_CONSOLE=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT4_FS=y
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
CONFIG_FS_DAX=y
CONFIG_FANOTIFY=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_AUTOFS4_FS=y
CONFIG_FSCACHE=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_UTF8=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_JFFS2_FS_WBUF_VERIFY=y
CONFIG_JFFS2_SUMMARY=y
CONFIG_JFFS2_FS_XATTR=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_DECOMP_MULTI=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
CONFIG_PSTORE_842_COMPRESS=y
CONFIG_PSTORE_ZSTD_COMPRESS=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_SWAP=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_NFS_V4_1_MIGRATION=y
CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_PERSISTENT_KEYRINGS=y
CONFIG_ENCRYPTED_KEYS=y
CONFIG_SECURITY_DMESG_RESTRICT=y
CONFIG_SECURITY=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_INDIRECT_PIO=y
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
# CONFIG_RCU_TRACE is not set
# CONFIG_STRICT_DEVMEM is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_EFI=y
CONFIG_MTD_NAND_PHYTIUM_PLAT=y
CONFIG_SERIAL_PHYTIUM_PCI=y
CONFIG_HW_RANDOM_PHYTIUM=y
CONFIG_I2C_PHYTIUM_PCI=y
CONFIG_I2C_PHYTIUM_PLATFORM=y
CONFIG_SPI_PHYTIUM_QSPI=y
CONFIG_W1_MASTER_PHYTIUM=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_PHYTIUM=y
# CONFIG_MMC_PHYTIUM_MCI_PCI is not set
CONFIG_EDAC_PHYTIUM=y
CONFIG_PHYTIUM_DDMA=y
CONFIG_HWSPINLOCK_PHYTIUM=y
CONFIG_PHYTIUM_ADC=y
CONFIG_PWM_PHYTIUM=y
CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y
CONFIG_ARM64_ERRATUM_826319=y
CONFIG_ARM64_ERRATUM_827319=y
CONFIG_ARM64_ERRATUM_824069=y
CONFIG_ARM64_ERRATUM_819472=y
CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_1742098=y
CONFIG_ARM64_ERRATUM_845719=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_1024718=y
CONFIG_ARM64_ERRATUM_1418040=y
CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y
CONFIG_ARM64_ERRATUM_1165522=y
CONFIG_ARM64_ERRATUM_1319367=y
CONFIG_ARM64_ERRATUM_1530923=y
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
CONFIG_ARM64_ERRATUM_1286807=y
CONFIG_ARM64_ERRATUM_1463225=y
CONFIG_ARM64_ERRATUM_1542419=y
CONFIG_ARM64_ERRATUM_1508412=y
CONFIG_ARM64_ERRATUM_2457168=y
CONFIG_CAVIUM_ERRATUM_22375=y
CONFIG_CAVIUM_ERRATUM_23154=y
CONFIG_CAVIUM_ERRATUM_27456=y
CONFIG_CAVIUM_ERRATUM_30115=y
CONFIG_CAVIUM_TX2_ERRATUM_219=y
CONFIG_FUJITSU_ERRATUM_010001=y
CONFIG_HISILICON_ERRATUM_161600802=y
CONFIG_QCOM_FALKOR_ERRATUM_1003=y
CONFIG_QCOM_FALKOR_ERRATUM_1009=y
CONFIG_QCOM_QDF2400_ERRATUM_0065=y
CONFIG_QCOM_FALKOR_ERRATUM_E1041=y
CONFIG_SOCIONEXT_SYNQUACER_PREITS=y
CONFIG_ARM64_4K_PAGES=y
# CONFIG_ARM64_16K_PAGES is not set
# CONFIG_ARM64_64K_PAGES is not set
# CONFIG_ARM64_VA_BITS_39 is not set
CONFIG_ARM64_VA_BITS=48
CONFIG_ARM64_PA_BITS_48=y
CONFIG_ARM64_PA_BITS=48
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_NR_CPUS=256
CONFIG_HOTPLUG_CPU=y
# CONFIG_ARM64_SW_TTBR0_PAN is not set
CONFIG_ARM64_TAGGED_ADDR_ABI=y
CONFIG_KUSER_HELPERS=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_PAN=y
CONFIG_AS_HAS_LSE_ATOMICS=y
CONFIG_ARM64_LSE_ATOMICS=y
CONFIG_ARM64_USE_LSE_ATOMICS=y
CONFIG_ARM64_RAS_EXTN=y
CONFIG_ARM64_CNP=y
CONFIG_ARM64_PTR_AUTH=y
CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y
CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y
CONFIG_AS_HAS_PAC=y
CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y
CONFIG_ARM64_AMU_EXTN=y
CONFIG_AS_HAS_ARMV8_4=y
CONFIG_ARM64_TLB_RANGE=y
CONFIG_ARM64_BTI=y
CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y
CONFIG_ARM64_E0PD=y
CONFIG_ARCH_RANDOM=y
CONFIG_ARM64_AS_HAS_MTE=y
CONFIG_ARM64_MTE=y
CONFIG_ARM64_MODULE_PLTS=y
# CONFIG_ARM64_PSEUDO_NMI is not set
CONFIG_RELOCATABLE=y
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
CONFIG_BRIDGE=y
CONFIG_QRTR=y
CONFIG_QRTR_TUN=y
CONFIG_CAN=y
CONFIG_NFC=y
CONFIG_NFC_NCI=y
CONFIG_NFC_S3FWRN5_I2C=y
CONFIG_PCI_EPF_TEST=y
CONFIG_BLK_DEV_NBD=y
CONFIG_PCI_ENDPOINT_TEST=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
CONFIG_UACCE=y
CONFIG_SCSI_MPT3SAS=y
CONFIG_BLK_DEV_MD=y
CONFIG_DM_MIRROR=y
CONFIG_DM_ZERO=y
CONFIG_MACVLAN=y
CONFIG_MACVTAP=y
CONFIG_VETH=y
CONFIG_ATL1C=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_DEVICE_INTERFACE=y
CONFIG_IPMI_SI=y
CONFIG_PHYTIUM_KCS_IPMI_BMC=y
CONFIG_PHYTIUM_BT_IPMI_BMC=y
CONFIG_I2C_GPIO=y
CONFIG_SPI_BITBANG=y
CONFIG_GPIO_ALTERA=y
CONFIG_GPIO_BD9571MWV=y
CONFIG_W1=y
CONFIG_W1_SLAVE_THERM=y
CONFIG_BATTERY_SBS=y
CONFIG_RC_CORE=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_DRM_I2C_CH7006=y
CONFIG_DRM_I2C_SIL164=y
CONFIG_DRM_I2C_NXP_TDA998X=y
CONFIG_DRM_MALI_DISPLAY=y
CONFIG_DRM_RCAR_DW_HDMI=y
CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=y
CONFIG_DRM_DISPLAY_CONNECTOR=y
CONFIG_DRM_LONTIUM_LT9611=y
CONFIG_DRM_NWL_MIPI_DSI=y
CONFIG_DRM_SII902X=y
CONFIG_DRM_SIMPLE_BRIDGE=y
CONFIG_DRM_THINE_THC63LVD1024=y
CONFIG_DRM_TI_SN65DSI86=y
CONFIG_DRM_I2C_ADV7511=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=y
CONFIG_DRM_DW_HDMI_I2S_AUDIO=y
CONFIG_DRM_DW_HDMI_CEC=y
CONFIG_SND_SOC_FSL_SAI=y
CONFIG_SND_SOC_AK4613=y
CONFIG_SND_SOC_CROS_EC_CODEC=y
CONFIG_SND_SOC_DMIC=y
CONFIG_SND_SOC_ES7134=y
CONFIG_SND_SOC_ES7241=y
CONFIG_SND_SOC_MAX98357A=y
CONFIG_SND_SOC_MAX98927=y
CONFIG_SND_SOC_PCM3168A_I2C=y
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=y
CONFIG_SND_SOC_SPDIF=y
CONFIG_SND_SOC_TAS571X=y
CONFIG_SND_SOC_WM8904=y
CONFIG_SND_SOC_WSA881X=y
CONFIG_I2C_HID=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_RK808=y
CONFIG_RTC_DRV_PCF85363=y
CONFIG_RTC_DRV_RX8581=y
CONFIG_RTC_DRV_SD3068=y
CONFIG_RTC_DRV_PCF2127=y
CONFIG_CROS_EC_CHARDEV=y
CONFIG_COMMON_CLK_BD718XX=y
CONFIG_SOUNDWIRE=y
CONFIG_SOUNDWIRE_QCOM=y
CONFIG_MAX9611=y
CONFIG_QCOM_SPMI_ADC5=y
CONFIG_IIO_CROS_EC_SENSORS_CORE=y
CONFIG_IIO_CROS_EC_SENSORS=y
CONFIG_IIO_CROS_EC_LIGHT_PROX=y
CONFIG_SENSORS_ISL29018=y
CONFIG_IIO_CROS_EC_BARO=y
CONFIG_MPL3115=y
CONFIG_PWM_CROS_EC=y
CONFIG_PHY_MIXEL_MIPI_DPHY=y
CONFIG_FPGA_BRIDGE=y
CONFIG_ALTERA_FREEZE_BRIDGE=y
CONFIG_FPGA_REGION=y
CONFIG_OF_FPGA_REGION=y
CONFIG_OVERLAY_FS=y

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023-2024 Ailick <277498654@qq.com>
ARCH:=aarch64
SUBTARGET:=armv8
BOARDNAME:=64-bit (armv8) SystemReady (EFI) compliant
define Target/Description
Build multi-platform images for the Phytium ARMv8 instruction set architecture
endef

View File

@ -0,0 +1,8 @@
GRUB_SERIAL:=$(call qstrip,$(CONFIG_GRUB_SERIAL))
ifeq ($(GRUB_SERIAL),)
$(error This platform requires CONFIG_GRUB_SERIAL be set!)
endif
define Package/base-files/install-target
$(SED) "s#@GRUB_SERIAL@#$(GRUB_SERIAL)#" $(1)/etc/inittab
endef

View File

@ -0,0 +1,19 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
. /lib/functions/uci-defaults.sh
board_config_update
board=$(board_name)
case "$board" in
traverse,ten64)
ucidef_set_led_netdev "sfp1" "SFP 1" "ten64:green:sfp1:down" "eth8" "link tx rx"
ucidef_set_led_netdev "sfp2" "SFP 2" "ten64:green:sfp2:up" "eth9" "link tx rx"
;;
esac
board_config_flush
exit 0

View File

@ -0,0 +1,18 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
. /lib/functions/system.sh
. /lib/functions/uci-defaults.sh
board_config_update
case "$(board_name)" in
traverse,ten64)
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
ucidef_set_interface_wan "eth6"
;;
esac
board_config_flush
exit 0

View File

@ -0,0 +1,23 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
. /lib/functions/uci-defaults.sh
board_config_update
board=$(board_name)
case "$board" in
traverse,ten64)
ucidef_add_gpio_switch "lte_reset" "Cell Modem Reset" "376"
ucidef_add_gpio_switch "lte_power" "Cell Modem Power" "377"
ucidef_add_gpio_switch "lte_disable" "Cell Modem Airplane mode" "378"
ucidef_add_gpio_switch "gnss_disable" "Cell Modem Disable GNSS receiver" "379"
ucidef_add_gpio_switch "lower_sfp_txidsable" "Lower SFP+ TX Disable" "369"
ucidef_add_gpio_switch "upper_sfp_txdisable" "Upper SFP+ TX Disable" "373"
;;
esac
board_config_flush
exit 0

View File

@ -0,0 +1,9 @@
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
ttyAMA0::askfirst:/usr/libexec/login.sh
@GRUB_SERIAL@::askfirst:/usr/libexec/login.sh
tty0::askfirst:/usr/libexec/login.sh
hvc0::askfirst:/usr/libexec/login.sh
ttymxc0::askfirst:/usr/libexec/login.sh
ttymxc1::askfirst:/usr/libexec/login.sh
ttymxc2::askfirst:/usr/libexec/login.sh

View File

@ -0,0 +1,52 @@
# SPDX-License-Identifier: GPL-2.0-or-later
sanitize_name_arm64() {
sed -e '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
s/[^a-z0-9_-]\+/-/g;
s/^-//;
s/-$//;
' "$@"
}
do_sysinfo_arm64() {
local vendor product file
for file in sys_vendor board_vendor; do
vendor="$(cat /sys/devices/virtual/dmi/id/$file 2>/dev/null)"
case "$vendor" in
empty | \
System\ manufacturer | \
To\ [bB]e\ [fF]illed\ [bB]y\ O\.E\.M\.)
continue
;;
esac
[ -n "$vendor" ] && break
done
for file in product_name board_name; do
product="$(cat /sys/devices/virtual/dmi/id/$file 2>/dev/null)"
case "$vendor:$product" in
?*:empty | \
?*:System\ Product\ Name | \
?*:To\ [bB]e\ [fF]illed\ [bB]y\ O\.E\.M\.)
continue
;;
?*:?*)
break
;;
esac
done
[ -d "/sys/firmware/devicetree/base" ] && return
[ -n "$vendor" -a -n "$product" ] || return
mkdir -p /tmp/sysinfo
echo "$vendor $product" > /tmp/sysinfo/model
sanitize_name_arm64 /tmp/sysinfo/model > /tmp/sysinfo/board_name
}
boot_hook_add preinit_main do_sysinfo_arm64

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-only
move_config() {
local partdev parttype=ext4
. /lib/upgrade/common.sh
if export_bootdevice && export_partdevice partdev 1; then
part_magic_fat "/dev/$partdev" && parttype=vfat
if mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt; then
if [ -f "/mnt/$BACKUP_FILE" ]; then
mv -f "/mnt/$BACKUP_FILE" /
fi
umount /mnt
fi
fi
}
boot_hook_add preinit_mount_root move_config

View File

@ -0,0 +1,165 @@
# SPDX-License-Identifier: GPL-2.0-or-later
RAMFS_COPY_BIN="/usr/sbin/blkid"
platform_check_image() {
local board=$(board_name)
local diskdev partdev diff
[ "$#" -gt 1 ] && return 1
v "Board is ${board}"
export_bootdevice && export_partdevice diskdev 0 || {
v "platform_check_image: Unable to determine upgrade device"
return 1
}
get_partitions "/dev/$diskdev" bootdisk
v "Extract boot sector from the image"
get_image_dd "$1" of=/tmp/image.bs count=63 bs=512b
get_partitions /tmp/image.bs image
#compare tables
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image
if [ -n "$diff" ]; then
v "Partition layout has changed. Full image will be written."
ask_bool 0 "Abort" && exit 1
return 0
fi
}
platform_copy_config() {
local partdev parttype=ext4
if export_partdevice partdev 1; then
part_magic_fat "/dev/$partdev" && parttype=vfat
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
cp -af "$UPGRADE_BACKUP" "/mnt/$BACKUP_FILE"
umount /mnt
else
v "ERROR: Unable to find partition to copy config data to"
fi
sleep 5
}
# To avoid writing over any firmware
# files (e.g ubootefi.var or firmware/X/ aka EBBR)
# Copy efi/openwrt and efi/boot from the new image
# to the existing ESP
platform_do_upgrade_efi_system_partition() {
local image_file=$1
local target_partdev=$2
local image_efisp_start=$3
local image_efisp_size=$4
v "Updating ESP on ${target_partdev}"
NEW_ESP_DIR="/mnt/new_esp_loop"
CUR_ESP_DIR="/mnt/cur_esp"
mkdir "${NEW_ESP_DIR}"
mkdir "${CUR_ESP_DIR}"
get_image_dd "$image_file" of="/tmp/new_efi_sys_part.img" \
skip="$image_efisp_start" count="$image_efisp_size"
mount -t vfat -o loop -o ro /tmp/new_efi_sys_part.img "${NEW_ESP_DIR}"
if [ ! -d "${NEW_ESP_DIR}/efi/boot" ]; then
v "ERROR: Image does not contain EFI boot files (/efi/boot)"
return 1
fi
mount -t vfat "/dev/$partdev" "${CUR_ESP_DIR}"
for d in $(find "${NEW_ESP_DIR}/efi/" -mindepth 1 -maxdepth 1 -type d); do
v "Copying ${d}"
newdir_bname=$(basename "${d}")
rm -rf "${CUR_ESP_DIR}/efi/${newdir_bname}"
cp -r "${d}" "${CUR_ESP_DIR}/efi"
done
umount "${NEW_ESP_DIR}"
umount "${CUR_ESP_DIR}"
}
platform_do_upgrade() {
local board=$(board_name)
local diskdev partdev diff
export_bootdevice && export_partdevice diskdev 0 || {
v "platform_do_upgrade: Unable to determine upgrade device"
return 1
}
sync
if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
get_partitions "/dev/$diskdev" bootdisk
v "Extract boot sector from the image"
get_image_dd "$1" of=/tmp/image.bs count=63 bs=512b
get_partitions /tmp/image.bs image
#compare tables
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
else
diff=1
fi
# Only change the partition table if sysupgrade -p is set,
# otherwise doing so could interfere with embedded "single storage"
# (e.g SoC boot from SD card) setups, as well as other user
# created storage (like uvol)
if [ -n "$diff" ] && [ "${UPGRADE_OPT_SAVE_PARTITIONS}" = "0" ]; then
# Need to remove partitions before dd, otherwise the partitions
# that are added after will have minor numbers offset
partx -d - "/dev/$diskdev"
get_image_dd "$1" of="/dev/$diskdev" bs=4096 conv=fsync
# Separate removal and addtion is necessary; otherwise, partition 1
# will be missing if it overlaps with the old partition 2
partx -a - "/dev/$diskdev"
return 0
fi
#iterate over each partition from the image and write it to the boot disk
while read part start size; do
if export_partdevice partdev $part; then
v "Writing image to /dev/$partdev..."
if [ "$part" = "1" ]; then
platform_do_upgrade_efi_system_partition \
$1 $partdev $start $size || return 1
else
v "Normal partition, doing DD"
get_image_dd "$1" of="/dev/$partdev" ibs=512 obs=1M skip="$start" \
count="$size" conv=fsync
fi
else
v "Unable to find partition $part device, skipped."
fi
done < /tmp/partmap.image
local parttype=ext4
if (blkid > /dev/null) && export_partdevice partdev 1; then
part_magic_fat "/dev/$partdev" && parttype=vfat
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
if export_partdevice partdev 2; then
THIS_PART_BLKID=$(blkid -o value -s PARTUUID "/dev/${partdev}")
v "Setting rootfs PARTUUID=${THIS_PART_BLKID}"
sed -i "s/\(PARTUUID=\)[a-f0-9-]\+/\1${THIS_PART_BLKID}/ig" \
/mnt/efi/openwrt/grub.cfg
fi
umount /mnt
fi
# Provide time for the storage medium to flush before system reset
# (despite the sync/umount it appears NVMe etc. do it in the background)
sleep 5
}

View File

@ -0,0 +1,743 @@
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_NUMA_BALANCING=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
# CONFIG_ARCH_ACTIONS is not set
# CONFIG_ARCH_AGILEX is not set
# CONFIG_ARCH_SUNXI is not set
# CONFIG_ARCH_ALPINE is not set
# CONFIG_ARCH_BCM2835 is not set
# CONFIG_ARCH_BCM_IPROC is not set
# CONFIG_ARCH_BERLIN is not set
# CONFIG_ARCH_BRCMSTB is not set
# CONFIG_ARCH_EXYNOS is not set
# CONFIG_ARCH_K3 is not set
# CONFIG_ARCH_LAYERSCAPE is not set
# CONFIG_ARCH_LG1K is not set
# CONFIG_ARCH_HISI is not set
# CONFIG_ARCH_MEDIATEK is not set
# CONFIG_ARCH_MESON is not set
# CONFIG_ARCH_MVEBU is not set
# CONFIG_ARCH_MXC is not set
# CONFIG_ARCH_QCOM is not set
# CONFIG_ARCH_RENESAS is not set
# CONFIG_ARCH_ROCKCHIP is not set
# CONFIG_ARCH_S32 is not set
# CONFIG_ARCH_SEATTLE is not set
# CONFIG_ARCH_STRATIX10 is not set
# CONFIG_ARCH_SYNQUACER is not set
# CONFIG_ARCH_TEGRA is not set
# CONFIG_ARCH_SPRD is not set
# CONFIG_ARCH_THUNDER is not set
# CONFIG_ARCH_THUNDER2 is not set
# CONFIG_ARCH_UNIPHIER is not set
# CONFIG_ARCH_VEXPRESS is not set
# CONFIG_ARCH_VISCONTI is not set
# CONFIG_ARCH_XGENE is not set
# CONFIG_ARCH_ZX is not set
# CONFIG_ARCH_ZYNQMP is not set
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_NUMA=y
CONFIG_SECCOMP=y
CONFIG_KEXEC=y
CONFIG_KEXEC_FILE=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_COMPAT=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_HIBERNATION=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_ARM_QCOM_CPUFREQ_HW=y
CONFIG_ARM_TEGRA186_CPUFREQ=y
CONFIG_QORIQ_CPUFREQ=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_RASPBERRYPI_FIRMWARE=y
CONFIG_INTEL_STRATIX10_SERVICE=y
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_IMX_SCU=y
CONFIG_IMX_SCU_PD=y
CONFIG_ARCH_SUPPORTS_ACPI=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_PCIEAER=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_JUMP_LABEL=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_CLS_ACT=y
CONFIG_BPF_JIT=y
# CONFIG_BT_HS is not set
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_MAC80211_LEDS=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PASID=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_PCI_AARDVARK=y
CONFIG_PCI_TEGRA=y
CONFIG_PCIE_RCAR_HOST=y
CONFIG_PCIE_RCAR_EP=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
CONFIG_PCIE_ALTERA_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCI_LAYERSCAPE=y
CONFIG_PCIE_LAYERSCAPE_GEN4=y
CONFIG_PCI_HISI=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_ARMADA_8K=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_HISI_STB=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_HISILICON_LPC=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_FSL_MC_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_MARVELL=y
CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_SRAM=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_SCSI_HISI_SAS=y
CONFIG_SCSI_HISI_SAS_PCI=y
CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_HISI=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_CEVA=y
CONFIG_AHCI_MVEBU=y
CONFIG_AHCI_XGENE=y
CONFIG_AHCI_QORIQ=y
CONFIG_SATA_SIL24=y
CONFIG_SATA_RCAR=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
CONFIG_NETDEVICES=y
CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
CONFIG_FEC=y
CONFIG_FSL_FMAN=y
CONFIG_FSL_DPAA_ETH=y
CONFIG_FSL_DPAA2_ETH=y
CONFIG_FSL_ENETC=y
CONFIG_FSL_ENETC_VF=y
CONFIG_FSL_ENETC_QOS=y
CONFIG_HIX5HD2_GMAC=y
CONFIG_HNS_DSAF=y
CONFIG_HNS_ENET=y
CONFIG_HNS3=y
CONFIG_HNS3_HCLGE=y
CONFIG_HNS3_ENET=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_IGB=y
CONFIG_IGBVF=y
CONFIG_MVNETA=y
CONFIG_MVPP2=y
CONFIG_SKY2=y
CONFIG_MLX5_CORE_EN=y
CONFIG_SH_ETH=y
CONFIG_RAVB=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_SNI_AVE=y
CONFIG_SNI_NETSEC=y
CONFIG_TI_K3_AM65_CPSW_NUSS=y
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
CONFIG_AQUANTIA_PHY=y
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_AT803X_PHY=y
CONFIG_ROCKCHIP_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_HISI_POWERKEY=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_BCM2835AUX=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_OMAP=y
CONFIG_SERIAL_8250_MT6577=y
CONFIG_SERIAL_8250_UNIPHIER=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_MESON=y
CONFIG_SERIAL_MESON_CONSOLE=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_TEGRA_TCU=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_QCOM_GENI=y
CONFIG_SERIAL_QCOM_GENI_CONSOLE=y
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=y
CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
CONFIG_SERIAL_MVEBU_UART=y
CONFIG_SERIAL_OWL=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_IMX=y
CONFIG_I2C_IMX_LPI2C=y
CONFIG_I2C_MESON=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_OWL=y
CONFIG_I2C_PXA=y
CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_SH_MOBILE=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_RCAR=y
CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
CONFIG_SPI_ARMADA_3700=y
CONFIG_SPI_FSL_LPSPI=y
CONFIG_SPI_FSL_QUADSPI=y
CONFIG_SPI_NXP_FLEXSPI=y
CONFIG_SPI_FSL_DSPI=y
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=y
CONFIG_SPI_ROCKCHIP=y
CONFIG_SPI_QUP=y
CONFIG_SPI_S3C64XX=y
CONFIG_SPI_SUN6I=y
CONFIG_SPMI=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_OWL=y
CONFIG_PINCTRL_S700=y
CONFIG_PINCTRL_S900=y
CONFIG_PINCTRL_IMX8MM=y
CONFIG_PINCTRL_IMX8MN=y
CONFIG_PINCTRL_IMX8MP=y
CONFIG_PINCTRL_IMX8MQ=y
CONFIG_PINCTRL_IMX8QXP=y
CONFIG_PINCTRL_IMX8DXL=y
CONFIG_PINCTRL_IPQ8074=y
CONFIG_PINCTRL_IPQ6018=y
CONFIG_PINCTRL_MSM8916=y
CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_MSM8998=y
CONFIG_PINCTRL_QCS404=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_SC7180=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SM8150=y
CONFIG_PINCTRL_SM8250=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_MPC8XXX=y
CONFIG_GPIO_MXC=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_RCAR=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_GPIO_XGENE=y
CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
CONFIG_POWER_AVS=y
CONFIG_QCOM_CPR=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_SUN8I_THERMAL=y
CONFIG_RCAR_THERMAL=y
CONFIG_RCAR_GEN3_THERMAL=y
CONFIG_ARMADA_THERMAL=y
CONFIG_EXYNOS_THERMAL=y
CONFIG_QCOM_TSENS=y
CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_ARM_SMC_WATCHDOG=y
CONFIG_S3C2410_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_RENESAS_WDT=y
CONFIG_UNIPHIER_WATCHDOG=y
CONFIG_BCM2835_WDT=y
CONFIG_MFD_ALTERA_SYSMGR=y
CONFIG_MFD_BD9571MWV=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_HI655X_PMIC=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_RK808=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_SL28CPLD=y
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_HI655X=y
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_RPMH=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_SDR_PLATFORM_DRIVERS=y
CONFIG_DRM_EXYNOS5433_DECON=y
CONFIG_DRM_EXYNOS7_DECON=y
CONFIG_DRM_EXYNOS_DSI=y
# CONFIG_DRM_EXYNOS_DP is not set
CONFIG_DRM_EXYNOS_HDMI=y
CONFIG_DRM_EXYNOS_MIC=y
CONFIG_ROCKCHIP_ANALOGIX_DP=y
CONFIG_ROCKCHIP_CDN_DP=y
CONFIG_ROCKCHIP_DW_HDMI=y
CONFIG_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_ROCKCHIP_INNO_HDMI=y
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_EFI=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_TEGRA=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EXYNOS=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_EXYNOS=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_F_SDH30=y
CONFIG_MMC_MESON_GX=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_UNIPHIER=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_BCM2835=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_MMC_SDHCI_AM654=y
CONFIG_MMC_OWL=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_EDAC=y
CONFIG_EDAC_GHES=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_CROS_EC=y
CONFIG_RTC_DRV_S3C=y
CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_ARMADA38X=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_FSL_EDMA=y
CONFIG_K3_DMA=y
CONFIG_MV_XOR=y
CONFIG_MV_XOR_V2=y
CONFIG_OWL_DMA=y
CONFIG_PL330_DMA=y
CONFIG_TEGRA20_APB_DMA=y
CONFIG_QCOM_BAM_DMA=y
CONFIG_QCOM_HIDMA_MGMT=y
CONFIG_QCOM_HIDMA=y
CONFIG_RCAR_DMAC=y
CONFIG_TI_K3_UDMA=y
CONFIG_TI_K3_UDMA_GLUE_LAYER=y
CONFIG_VFIO=y
CONFIG_VFIO_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_MFD_CROS_EC_DEV=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=y
CONFIG_CROS_EC_SPI=y
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_FSL_SAI=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_COMMON_CLK_VC5=y
CONFIG_CLK_IMX8MM=y
CONFIG_CLK_IMX8MN=y
CONFIG_CLK_IMX8MP=y
CONFIG_CLK_IMX8MQ=y
CONFIG_CLK_IMX8QXP=y
CONFIG_TI_SCI_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_QCOM_A53PLL=y
CONFIG_QCOM_CLK_APCS_MSM8916=y
CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_QCOM_CLK_RPMH=y
CONFIG_IPQ_GCC_8074=y
CONFIG_IPQ_GCC_6018=y
CONFIG_MSM_GCC_8916=y
CONFIG_MSM_GCC_8994=y
CONFIG_MSM_MMCC_8996=y
CONFIG_MSM_GCC_8998=y
CONFIG_QCS_GCC_404=y
CONFIG_SC_GCC_7180=y
CONFIG_SDM_GCC_845=y
CONFIG_SDM_GPUCC_845=y
CONFIG_SDM_VIDEOCC_845=y
CONFIG_SDM_DISPCC_845=y
CONFIG_SM_GCC_8150=y
CONFIG_SM_GCC_8250=y
CONFIG_SM_GPUCC_8150=y
CONFIG_SM_GPUCC_8250=y
CONFIG_QCOM_HFPLL=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
CONFIG_PLATFORM_MHU=y
CONFIG_BCM2835_MBOX=y
CONFIG_QCOM_APCS_IPC=y
CONFIG_QCOM_IPCC=y
CONFIG_ROCKCHIP_IOMMU=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_OWL_PM_DOMAINS=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_FSL_DPAA=y
CONFIG_FSL_MC_DPIO=y
# CONFIG_QCOM_AOSS_QMP is not set
# CONFIG_QCOM_GENI_SE is not set
# CONFIG_QCOM_RPMH is not set
# CONFIG_QCOM_RPMHPD is not set
# CONFIG_QCOM_RPMPD is not set
# CONFIG_QCOM_SMEM is not set
# CONFIG_QCOM_SMD_RPM is not set
# CONFIG_QCOM_SMP2P is not set
# CONFIG_QCOM_SMSM is not set
# CONFIG_ARCH_R8A774A1 is not set
# CONFIG_ARCH_R8A774B1 is not set
# CONFIG_ARCH_R8A774C0 is not set
# CONFIG_ARCH_R8A774E1 is not set
# CONFIG_ARCH_R8A77950 is not set
# CONFIG_ARCH_R8A77951 is not set
# CONFIG_ARCH_R8A77960 is not set
# CONFIG_ARCH_R8A77961 is not set
# CONFIG_ARCH_R8A77965 is not set
# CONFIG_ARCH_R8A77970 is not set
# CONFIG_ARCH_R8A77980 is not set
# CONFIG_ARCH_R8A77990 is not set
# CONFIG_ARCH_R8A77995 is not set
# CONFIG_ROCKCHIP_PM_DOMAINS is not set
# CONFIG_ARCH_TEGRA_132_SOC is not set
# CONFIG_ARCH_TEGRA_210_SOC is not set
# CONFIG_ARCH_TEGRA_186_SOC is not set
# CONFIG_ARCH_TEGRA_194_SOC is not set
# CONFIG_ARCH_K3_AM6_SOC is not set
# CONFIG_ARCH_K3_J721E_SOC is not set
CONFIG_TI_SCI_PM_DOMAINS=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_PWM=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_PWM_SAMSUNG=y
CONFIG_SL28CPLD_INTC=y
CONFIG_QCOM_PDC=y
CONFIG_RESET_IMX7=y
CONFIG_RESET_QCOM_AOSS=y
CONFIG_RESET_TI_SCI=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_HISTB_COMBPHY=y
CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PHY_UNIPHIER_USB2=y
CONFIG_PHY_UNIPHIER_USB3=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
CONFIG_NVMEM_IMX_OCOTP=y
CONFIG_NVMEM_IMX_OCOTP_SCU=y
CONFIG_QCOM_QFPROM=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_UNIPHIER_EFUSE=y
CONFIG_FPGA=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_MUX_MMIO=y
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS4_FS=y
CONFIG_VFAT_FS=y
CONFIG_HUGETLBFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_EFIVAR_FS=y
CONFIG_SQUASHFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
# CONFIG_SHORTCUT_FE is not set
# CONFIG_RTL8821CS is not set

View File

@ -0,0 +1,35 @@
PART_NAME=dtb:kernel:rootfs
REQUIRE_IMAGE_METADATA=1
platform_do_upgrade() {
local board=$(board_name)
case "$board" in
e2000q-demo-board |\
e2000d-demo-board |\
e2000q-miniitx-board |\
e2000d-miniitx-board)
default_do_upgrade "$1"
;;
esac
}
platform_check_image() {
local board=$(board_name)
local magic="$(get_magic_long "$1")"
case "$board" in
e2000q-demo-board|\
e2000d-demo-board|\
e2000q-miniitx-board|\
e2000d-miniitx-board)
[ "$magic" != "d00dfeed" ] && {
echo "Invalid image type."
return 1
}
return 0
;;
esac
return 0
}

View File

@ -0,0 +1,604 @@
CONFIG_64BIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=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_PHYTIUM=y
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM64=y
CONFIG_ARM64_4K_PAGES=y
CONFIG_ARM64_CNP=y
CONFIG_ARM64_CRYPTO=y
CONFIG_ARM64_ERRATUM_1742098=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_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_UAO=y
CONFIG_ARM64_VA_BITS=48
# CONFIG_ARM64_VA_BITS_39 is not set
CONFIG_ARM64_VA_BITS_48=y
CONFIG_ARM64_VHE=y
CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=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_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_SCMI_CPUFREQ=y
CONFIG_ARM_SCMI_POWER_DOMAIN=y
CONFIG_ARM_SCMI_PROTOCOL=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_BLK_DEV_BSG=y
CONFIG_BLK_DEV_BSGLIB=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_NVME=y
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_PM=y
CONFIG_BLK_SCSI_REQUEST=y
CONFIG_BLOCK_COMPAT=y
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
CONFIG_CLKDEV_LOOKUP=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_SCMI is not set
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 is not set
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=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_CRC_T10DIF=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_CRYPTO_AES_ARM64=y
CONFIG_CRYPTO_AES_ARM64_CE=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_BLAKE2S=y
CONFIG_CRYPTO_CRC32=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_SIMD=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_BUGVERBOSE=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_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_REMAP=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
CONFIG_DT_IDLE_STATES=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DWMAC_DWC_QOS_ETH=y
CONFIG_DWMAC_GENERIC=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EEPROM_AT24=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_ENERGY_MODEL=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXTCON=y
CONFIG_F2FS_FS=y
CONFIG_FANOTIFY=y
CONFIG_FHANDLE=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
# CONFIG_FLATMEM_MANUAL is not set
# 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_FW_LOADER_PAGED_BUF=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_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_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_DWAPB=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GPIO_PHYTIUM_CORE=y
# CONFIG_GPIO_PHYTIUM_PCI is not set
CONFIG_GPIO_PHYTIUM_PLAT=y
# CONFIG_GPIO_PHYTIUM_SGPIO is not set
CONFIG_HANDLE_DOMAIN_IRQ=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_HID=y
CONFIG_HID_GENERIC=y
CONFIG_HOLES_IN_ZONE=y
CONFIG_HOTPLUG_CPU=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_HWMON=y
CONFIG_HWSPINLOCK=y
CONFIG_HW_CONSOLE=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_HELPER_AUTO=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_MISC is not set
CONFIG_IOMMU_API=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
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_KEXEC_CORE=y
CONFIG_KEXEC_FILE=y
CONFIG_KSM=y
# 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_MACB=y
# CONFIG_MACB_PCI is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_SERIAL=y
CONFIG_MAILBOX=y
# CONFIG_MAILBOX_TEST is not set
CONFIG_MANDATORY_FILE_LOCKING=y
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_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_CQHCI=y
# CONFIG_MMC_PHYTIUM_MCI_PLTFM is not set
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_MQ_IOSCHED_DEADLINE=y
# CONFIG_MTD_CFI is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_COMPLEX_MAPPINGS 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_FLOW_LIMIT=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_NR_CPUS=256
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_NVME_CORE=y
CONFIG_NVME_HWMON=y
CONFIG_NVME_MULTIPATH=y
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_NET=y
CONFIG_OF_OVERLAY=y
CONFIG_OF_RESOLVE=y
CONFIG_OLD_SIGSUSPEND3=y
# CONFIG_OVERLAY_FS_XINO_AUTO is not set
CONFIG_PADATA=y
CONFIG_PAGE_POOL=y
# 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_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_PME=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_ECAM=y
CONFIG_PCI_HOST_COMMON=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCI_STUB=y
CONFIG_PCS_XPCS=y
CONFIG_PGTABLE_LEVELS=4
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_PHYTIUM_MBOX=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PLATFORM_MHU=y
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_DEVFREQ=y
# CONFIG_PM_DEVFREQ_EVENT is not set
CONFIG_PM_GENERIC_DOMAINS=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_PM_OPP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_SUPPLY=y
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_PREEMPT=y
CONFIG_PREEMPTION=y
CONFIG_PREEMPT_COUNT=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_RCU=y
CONFIG_PRINTK_TIME=y
# CONFIG_PRINT_QUOTA_WARNING is not set
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_PROC_VMCORE=y
CONFIG_PWM=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_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_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_PWM=y
CONFIG_RELOCATABLE=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_SCMI=y
CONFIG_RFS_ACCEL=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
CONFIG_RPS=y
CONFIG_RSEQ=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_NVMEM=y
# CONFIG_RTL8821CS is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SATA_HOST=y
CONFIG_SCHED_MC=y
CONFIG_SCSI=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=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_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_SG_POOL=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_SLUB_DEBUG=y
CONFIG_SMP=y
CONFIG_SPARSEMEM=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_MANUAL=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_PHYTIUM=y
# CONFIG_SPI_PHYTIUM_PCI is not set
CONFIG_SPI_PHYTIUM_PLAT=y
CONFIG_SPI_PHYTIUM_QSPI=y
CONFIG_SPI_PHYTIUM_QUADSPI=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_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_PER_TASK=y
CONFIG_STACKPROTECTOR_STRONG=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_SYS_SUPPORTS_HUGETLBFS=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_TRACE_CLOCK=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
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_STUSB160X is not set
# CONFIG_TYPEC_TCPCI is not set
CONFIG_TYPEC_TCPM=y
# CONFIG_TYPEC_TPS6598X is not set
# CONFIG_UACCE 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_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_GADGET=y
CONFIG_USB_HID=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_PHY=y
CONFIG_USB_PHYTIUM=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_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

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (c) 2023 Phytium Technology Co., Ltd.
ARCH:=aarch64
SUBTARGET:=e2000
BOARDNAME:=E2000
define Target/Description
Build firmware image for Phytium E2000 devices.
endef

View File

@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
title: Phytium DDMA Controller bindings
description:
The Phytium DDMA is a general-purpose direct memory access controller capable of
supporting 8 independent DMA channels. Each channel can have up to 32 requests.
DMA clients connected to the Phytium DDMA controller must use the format
described in the dma.txt file, using a two-cell specifier for each
channel: a phandle to the DMA controller plus the following two integer cells:
1. The channel id
2. The request line number
maintainers:
- Huang Jie <huangjie1663@phytium.com.cn>
allOf:
- $ref: "dma-controller.yaml#"
properties:
"#dma-cells":
const: 2
compatible:
const: phytium,ddma
reg:
maxItems: 1
interrupts:
maxItems: 1
dma-channels:
minItems: 1
maxItems: 8
description: it indicates that the number of channels are used
required:
- compatible
- reg
- interrupts
- dma-channels
unevaluatedProperties: false
examples:
ddma0: ddma@28003000 {
compatible = "phytium,ddma";
reg = <0x0 0x28003000 0x0 0x1000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <2>;
dma-channels = <8>;
};
...

View File

@ -0,0 +1,23 @@
* Phytium Pe220x SoC EDAC node
EDAC node is defined to describe on-chip error detection and correction.
The follow error types are supported:
SoC - SoC IP's such as Ethernet, SATA, and etc
The following section describes the EDAC DT node binding.
Required properties:
- compatible: Shall be "phytium,pe220x-edac".
- reg: Shall be the Pe220x RAS resource.
- interrupts: Interrupt-specifier for RAS error IRQ(s).
Example:
edac: edac@32b28000 {
compatible = "phytium,pe220x-edac";
reg = <0x0 0x32b28000 0x0 0x1000>,
<0x0 0x31400000 0x0 0x1000>,
<0x0 0x31401000 0x0 0x1000>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
};

View File

@ -0,0 +1,32 @@
* Phytium SGPIO controller
This SGPIO controller is for Phytium Pe220x SoC, which supports up to
96 (32x3) Serial GPIOs.
Required properties:
- compatible : Should contain "phytium,gpio"
- reg : Address and length of the register set for the device.
- interrupts: Interrupt mapping for GPIO IRQ.
- gpio-controller : Marks the device node as a gpio controller.
- #gpio-cells : Should be 2. The first cell is the pin number and
the second cell is used to specify the gpio polarity:
0 = active high
1 = active low
- ngpios: number of GPIO lines, see gpio.txt
(should be multiple of 32, up to 96 pins)
- bus-frequency: SGPIO CLK frequency
- clocks: A phandle to the APB clock for SGPIO clock division
Example:
sgpio: sgpio@2807d000 {
compatible = "phytium,sgpio";
reg = <0x0 0x2807d000 0x0 0x1000>;
interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_48mhz>;
ngpios = <96>;
bus-frequency = <48000>;
gpio-controller;
#gpio-cells = <2>;
};

View File

@ -0,0 +1,113 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/phytium,gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Phytium GPIO controller
description: |
Phytium GPIO controllers have one or two configurable ports, each of which
are intended to be represented as child nodes with the generic GPIO-controller
properties as desribed in this bindings file.
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
properties:
$nodename:
pattern: "^gpio@[0-9a-f]+$"
compatible:
const: phytium,gpio
reg:
maxItems: 1
gpio-controller: true
"#address-cells":
const: 1
"#size-cells":
const: 0
'#gpio-cells':
const: 2
interrupts:
description: |
The interrupts to the parent controller raised when GPIOs generate
the interrupts. If the controller provides one combined interrupt
for all GPIOs, specify a single interrupt. If the controller provides
one interrupt for each GPIO, provide a list of interrupts that
correspond to each of the GPIO pins.
minItems: 1
maxItems: 32
interrupt-controller: true
'#interrupt-cells':
const: 2
patternProperties:
"^gpio-(port|controller)@[0-9a-f]+$":
type: object
properties:
compatible:
const: phytium,gpio-port
reg:
maxItems: 1
nr-gpios:
description: The number of GPIO pins exported by the port.
default: 32
minimum: 1
maximum: 32
required:
- compatible
- reg
- gpio-controller
- '#gpio-cells'
dependencies:
interrupt-controller: [ interrupts ]
additionalProperties: false
additionalProperties: false
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
examples:
- |
gpio: gpio@28004000 {
compatible = "phytium,gpio";
reg = <0x0 0x28004000 0x0 0x1000>;
gpio-controller;
#gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
porta: gpio-port@0 {
compatible = "phytium,gpio-port";
reg = <0>;
nr-gpios = <8>;
};
portb: gpio-port@1 {
compatible = "phytium,gpio-port";
reg = <1>;
nr-gpios = <8>;
};
};
...

View File

@ -0,0 +1,21 @@
Phytium HwSpinlock Driver
========================
Required properties:
- compatible: Should be "phytium,hwspinlock"
- reg: Contains the hwspinlock module register address space
(base address and length)
- #hwlock-cells: Should be 1.
- nr-locks: The number of locks in the device.
Please look at the generic hwlock binding for usage information for consumers,
"Documentation/devicetree/bindings/hwlock/hwlock.txt"
Example:
hwspinlock: spinlock@40000000 {
compatible = "phytium,hwspinlock";
reg = <0x40000000 0x1000>;
#hwlock-cells = <1>;
nr-locks = <32>;
};

View File

@ -0,0 +1,48 @@
Phytium Fan Tacho and capture counter controller device driver
The controller can support one input signal. The function of controller is to
measure the speed of fan and the edge number of input signal. The function
can be selected by devicetree setting. The edging mode and anti-jitter level
can also setted in devicetree.
Required properties for tacho node:
- #address-cells : should be 1.
- #size-cells : should be 1.
- reg : address and length of the register set for the device.
- compatible : should be "phytium,tacho"
- clocks : phandle to clock provider with the clock number in the second cell
Optional properties for tacho node:
- tacho : set the controller work as fan tachometer, which is a default option.
- capture : set the controller work as capture counter.
-------------------------------------------------------------------------------
- up : set the input edging mode as ascending, which is a default option.
- down : set the input edging mode as descending.
- double : set the input edging mode as doule-edging.
-------------------------------------------------------------------------------
- debounce-level : set the debounce-levle, which can be 0, 1, 2 and 3.
Examples:
tacho: tacho@28054000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0x0 0x28054000 0x0 0x1000>;
compatible = "phytium,tacho";
clocks = <&sysclk>;
tacho;
up;
debounce-level = <2>;
};

View File

@ -0,0 +1,48 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/snps,designware-i2c.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Phytium I2C/SMBus Controller
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
const: phytium,i2c
reg:
minItems: 1
items:
- description: Offset and length of the memory mapped registers
interrupts:
maxItems: 1
clocks:
minItems: 1
items:
- description: I2C controller reference clock source
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
i2c0: i2c@28011000 {
compatible = "phytium,i2c";
reg = <0x0 0x28011000 0x0 0x1000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "smbus_alert";
clocks = <&sysclk_48mhz>;
};
...

View File

@ -0,0 +1,57 @@
Phytium ADC
This device is a 10-bit converter for 8 voltage channels. All inputs are
single ended.
Required properties:
- compatible: Should be "phytium,adc"
- reg: memory window mapping address and length
- interrupts: Interrupt for the ADC control interface.
- clocks: Input clock used to derive the sample clock.
- #address-cells: Should be <1> (settings for the subnodes).
- #size-cells: Should be <0> (settings for the subnodes).
Required subnodes:
The ADC channels are configured as subnodes of the ADC.
Required channel node properties:
- reg: should contain the hardware channel number.
Examples:
adc0: adc@2807b000 {
compatible = "phytium,adc";
reg = <0x0 0x2807b000 0x0 0x1000>;
interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_48mhz>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
};
channel@1 {
reg = <1>;
};
channel@2 {
reg = <2>;
};
channel@3 {
reg = <3>;
};
channel@4 {
reg = <4>;
};
channel@5 {
reg = <5>;
};
channel@6 {
reg = <6>;
};
channel@7 {
reg = <7>;
};
};

View File

@ -0,0 +1,41 @@
* Phytium Keypad Port device tree bindings
The keypad port is designed to interface with a keypad matrix, which
simplify the software task of scanning a keypad matrix. It is capable
of detecting, debouncing, and decoding one or multiple keys pressed
simultaneously on a keypad.
Required SoC Specific Properties:
- compatible: Should be "phytium,keypad".
- reg: Physical base address and length of memory mapped region.
- interrupts: Interrupt number to the CPU(s).
Required Board Specific Properties:
- linux,keymap: The definition can be found at
bindings/input/matrix-keymap.txt.
Example:
keypad: keypad@2807a000 {
compatible = "phytium,keypad";
reg = <0x 0x2807a000 0x0 0x1000>;
interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
keypad,num-rows = <4>;
keypad,num-columns = <4>;
linux,keymap = <0x00000067 /* KEY_UP */
0x0001006c /* KEY_DOWN */
0x00020072 /* KEY_VOLUMEDOWN */
0x00030066 /* KEY_HOME */
0x0100006a /* KEY_RIGHT */
0x01010069 /* KEY_LEFT */
0x0102001c /* KEY_ENTER */
0x01030073 /* KEY_VOLUMEUP */
0x02000040 /* KEY_F6 */
0x02010042 /* KEY_F8 */
0x02020043 /* KEY_F9 */
0x02030044 /* KEY_F10 */
0x0300003b /* KEY_F1 */
0x0301003c /* KEY_F2 */
0x0302003d /* KEY_F3 */
0x03030074>; /* KEY_POWER */
};

View File

@ -0,0 +1,28 @@
Phytium INTx interrupt controller (IXIC)
This is a pseudo interrupt controller to handle PCI legacy interrupt on
some Phytium SoCs, which sits between the PCI INTx devices and the GIC
and forwards the 4 INTx input signals to 4 adjacent GICv3 SPIs.
Required properties:
- compatible : "phytium,ixic"
- reg : Specifies two regions of the register set, which
are called 'ctr' and 'hpb'.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The value must be 3.
- intx-spi-base : The SPI number of the first SPI of the 4 adjacent
ones the IXIC forwards its interrupts to.
Example:
ixic: interrupt-controller@29000000 {
compatible = "phytium,ixic";
reg-names = "ctr", "hpb";
reg = <0x0 0x29000000 0x0 0x00060000>,
<0x0 0x29100000 0x0 0x00002000>;
interrupt-controller;
interrupt-parent = <&gic>;
#interrupt-cells = <3>;
intx-spi-base = <28>;
};

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/interrupt-controller/phytium,ixic.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Phytium INTx interrupt controller (IXIC)
description: |
This is a psuedo interrupt controller to handle PCI legacy interrupt on
Phytium D2000 and FT-2000/4C SoC, which sits between the PCI INTx devices
and the GIC and forwards the 4 INTx input signals to 4 adjacent GICv3 SPIs.
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
allOf:
- $ref: /schemas/interrupt-controller.yaml#
properties:
compatible:
enum:
- phytium,d2000-ixic
- phytium,ft2004c-ixic
reg:
description: |
Specifies two regions of the register set, which are called
'ctr' and 'hpb'
minItems: 2
maxItems: 2
interrupt-controller: true
'#interrupt-cells':
description: |
Specifies the number of cells needed to encode an interrupt source.
const: 3
intx-spi-base:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
The SPI number of the first SPI of the 4 adjacent ones the IXIC
forwards its interrupts to.
required:
- compatible
- reg
- interrupt-controller
- '#interrupt-cells'
- intx-spi-base
additionalProperties: false
examples:
- |
ixic: interrupt-controller@29000000 {
compatible = "phytium,d2000-ixic";
reg-names = "ctr", "hpb";
reg = <0x0 0x29000000 0x0 0x00060000>,
<0x0 0x29100000 0x0 0x00002000>;
interrupt-controller;
interrupt-parent = <&gic>;
#interrupt-cells = <3>;
intx-spi-base = <28>;
};

View File

@ -0,0 +1,51 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mailbox/arm,mhuv2.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Phytium Mailbox Controller
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
description: |
The Phytium mailbox controller that has a channel/link to communicate
with the remote end. A link raises interrupt for any received data. However,
there is no specified way of knowing if the sent data has been read by the
remote. This driver assumes the sender polls STAT register and the remote
clears it after having read the data.
properties:
compatible:
- enum: phytium,mbox
reg:
maxItems: 1
interrupts:
description: |
Contains the interrupt information corresponding to the link
maxItems: 1
'#mbox-cells':
description: |
It should be 1, which is the index of the channel needed.
const: 1
required:
- compatible
- reg
- interrupts
- '#mbox-cells'
additionalProperties: false
examples:
- |
mbox: mailbox@2a000000 {
compatible = "phytium,mbox";
reg = <0x0 0x2a000000 0x0 0x1000>;
#mbox-cells = <1>;
interrupts = <0 48 4>;
};

View File

@ -0,0 +1,21 @@
* Device tree bindings for Phytium JPEG Engine
The JPEG Engine embedded in the Phytium SOCs can capture
and compress video data from digital or analog sources.
Required properties:
- compatible: "phytium,jpeg"
- reg: contains the offset and length of the
JPEG Engine memory region
- interrupts: the interrupt associated with the VE on this platform
- phytium,ocm-buf-addr the physical address used to storage the inputing video data
Example:
jpeg: jpeg@32b32000 {
compatible = "phytium,jpeg";
reg = <0x0 0x32b32000 0 0x1000>;
interrupts = <0 41 4>;
phytium,ocm-buf-addr = <0x30c40000 0x30c60000>;
status = "okay";
};

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/mmc/phytium,sdci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Phytium SDCI Controller Binding
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
allOf:
- $ref: mmc-controller.yaml#
properties:
compatible:
enum:
- phytium,sdci
reg:
maxItems: 1
interrupts:
minItems: 3
maxItems: 3
clocks:
minItems: 1
items:
- description: core clock
clock-names:
minItems: 1
items:
- const: phytium_sdc_clk
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
sdci: sdci@28207c00 {
compatible = "phytium,sdci";
reg = <0x0 0x28207c00 0x0 0x100>;
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_600mhz>;
clock-names = "phytium_sdc_clk";
};
...

View File

@ -0,0 +1,36 @@
* Phytium Multimedia Card Interface controller
The highspeed MMC host controller on Phytium SoCs provides an interface
for MMC, SD and SDIO types of memory cards.
Required properties:
- compatible : should be "phytium,mci".
- reg: mmc controller base registers.
- clocks : phandles to input clocks.
- clock-names : should be "phytium_mci_clk".
- interrupts : mmc controller interrupt.
Examples:
- Within .dtsi:
mmc0: mmc@28000000 {
compatible = "phytium,mci";
reg = <0x0 0x28000000 0x0 0x1000>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_1200mhz>;
clock-names = "phytium_mci_clk";
status = "disabled";
};
- Within dts:
&mmc0 {
bus-width = <4>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
sd-uhs-sdr12;
sd-uhs-sdr25;
sd-uhs-sdr50;
no-mmc;
status = "ok";
};

View File

@ -0,0 +1,29 @@
Phytium CAN controller
------------------------
Required properties:
- compatible: Should be:
- "phytium,can" for Phytium CAN controllers
- "phytium,canfd" for Phytium CAN controllers with CANFD support
- reg: Should contain CANFD controller registers location and length
- interrupts: Should contain IRQ line for the CANFD controller
- clocks: CLocks used by the controller
- clock-names: Input clock names, should be "can_clk"
- tx-fifo-depth: Indicates the length of TX FIFO
- rx-fifo-depth: Indicates the length of TX FIFO
Optional property:
- extend_brp: Indicates to apply the extend BRP parameter of bit timming for
early version of CAN controller
Example:
can0: can@2800a000{
compatible = "phytium,canfd";
reg = <0x0 0x2800a000 0x0 0x1000>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_600mhz>;
clock-names = "can_clk";
tx-fifo-depth = <64>;
rx-fifo-depth = <64>;
};

View File

@ -0,0 +1,54 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/net/phytium,gmac.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Phytium 10/100/1000 Ethernet driver (GMAC)
maintainers:
- Chen Baozi <chenbaozi@phytium.com.cn>
# We need a select here so we don't match all nodes with 'snps,dwmac'
select:
properties:
compatible:
contains:
enum:
- phytium,gmac
required:
- compatible
allOf:
- $ref: "snps,dwmac.yaml#"
properties:
compatible:
- items:
- enum:
- phytium,gmac
clock-frequency: true
required:
- compatible
- clock-frequency
unevaluatedProperties: false
examples:
- |
gmac0: eth@2820c000 {
compatible = "phytium,gmac";
reg = <0x0 0x2820c000 0x0 0x2000>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <250000000>;
snps,pbl = <16>;
snps,fixed-burst;
snps,multicast-filter-bins = <64>;
snps,perfect-filter-entries = <128>;
tx-fifo-depth = <4096>;
rx-fifo-depth = <4096>;
max-frame-size = <9000>;
};

View File

@ -0,0 +1,23 @@
Phytium PWM controller
Required properties:
- compatible: should be "phytium,pwm"
- reg: physical base address and length of the controller's registers
- interrupts: interrupt for the pwm controller
- clocks : clock specifiers for both ipg and per clocks.
- phytium,db: One or two <cntmod dutymod div updbcly dbpolarity> to describe dead-band configurations.
"cntmod" indicates the counter mode (0 for modulo, 1 for up-and-down).
"dutymod" indicdates which duty to compare with (0 for PMW_CCR, 1 for FIFO).
"div" selects the clock divider value, from 0 to 1023.
"updbcly" selects the rising edge delay cycles.
"dbpolarity" selects the polarity for dead-band.
Example:
pwm0: pwm@2804a000 {
compatible = "phytium,pwm";
reg= <0x0 0x2804a000 0x0 0x1000>;
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_48mhz>;
phytium,db = <0 0 0 1000 0>;
};

View File

@ -0,0 +1,39 @@
homogeneous remoteproc driver
==========================================
This driver implements communication between remote processors under a homogeneous CPU architecture(SMP).
Homogeneous RemoteProc Device Node:
=================================
A homo_remoteproc device node is used to represent the remote core instance within SoC.
Required properties:
--------------------
- compatible : should be "homo,rproc"
- remote-processor: remote processor's linux cpu logical number
- inter-processor-interrupt: IPI/SGI interrupt number, default is 9
- memory-region: reserved memory which will be used by remote processor
- firmware-name: the name of openamp image, default is "openamp_core0.elf"
Example:
--------
reserved-memory {
#address-cells = <0x2>;
#size-cells = <0x2>;
ranges;
rproc: rproc@b0100000 {
no-map;
reg = <0x0 0xb0100000 0x0 0x19900000>;
};
};
homo_rproc: homo_rproc@0 {
compatible = "homo,rproc";
remote-processor = <3>;
inter-processor-interrupt = <9>;
memory-region = <&rproc>;
firmware-name = "openamp_core0.elf";
status = "disabled";
};

View File

@ -0,0 +1,13 @@
Phytium Random Number Generator
Required properties:
- compatible : Should be "phytium,rng"
- reg : Offset and length of the register set of this block
Example:
rng@0x31a06000 {
compatible = "phytium,rng";
reg = <0x0 0x31a06000 0x0 0x1000>;
};

View File

@ -0,0 +1,24 @@
Phytium SPI controller
Required properties:
- compatible: should be "phytium,spi"
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
- reg: address and length of the spi master registers
- interrupts: should contain one interrupt
- clocks: spi clock phandle
- num-cs: see spi-bus.txt
Optional properties:
- cs-gpios: see spi-bus.txt
Example:
spi0: spi@2800c000 {
compatible = "phytium,spi";
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x0 0x2800c000 0x0 0x1000>;
clocks = <&sysclk_48mhz>;
num-cs = <4>;
};

View File

@ -0,0 +1,14 @@
* Phytium 1-wire bus master controller
Required properties:
- compatible : should be "phytium,w1"
- reg : Address and length of the register set for the device
- interrupts : interrupt line.
Example:
onewire0: onewire@2803f000 {
compatible = "phytium,w1";
reg = <0x0 0x2803f000 0x0 0x1000>;
interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
## pe220x general demo development board series.
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-demo-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000d-demo-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000s-demo-board.dtb
## pe220x specific industry development board series.
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-miniitx-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000d-miniitx-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-vpx-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-edu-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-come-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000d-power-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000q-hanwei-board.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += phytiumpi_firefly.dtb
dtb-$(CONFIG_ARCH_PHYTIUM) += e2000d-chillipi-edu-board.dtb

View File

@ -0,0 +1,339 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2202 chillipi education board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2202.dtsi"
#include "dt-bindings/gpio/gpio.h"
/{
model = "Pe2202 CHILLIPI EDUCATION BOARD";
compatible = "phytium,pe2202";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x80000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,pin-switches = "mic-in";
simple-audio-card,widgets = "Microphone","mic-in";
simple-audio-card,routing = "MIC2","mic-in";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio6: i2c@28020000 {
compatible = "phytium,i2c";
reg = <0x0 0x28020000 0x0 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
oled@3c {
compatible = "SinoWealth,sh1106";
reg = <0x3c>;
};
pcf8591@48 {
compatible = "philips,pcf8591";
reg = <0x48>;
};
};
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
/* localized chillipi education board use this rtc device */
rtc@32 {
compatible = "wave,sd3068";
reg = <0x32>;
status = "disabled";
};
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
status = "disabled";
};
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
codec0: es8336@10 {
det-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
sel-gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
status = "disabled";
};
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
interrupt-controller;
#interrupt-cells = <2>;
status = "okay";
};
&gpio5 {
status = "okay";
};
&watchdog0 {
status = "okay";
};
&watchdog1 {
status = "okay";
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "host";
status = "okay";
};
&usb2_1 {
dr_mode = "host";
status = "disabled";
};
&usb2_2 {
dr_mode = "host";
status = "disabled";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
/*
* In chillipi education board, M.2 interface may insert two types of disks: PCIE (nvme protocol) or SATA (ahci protocol),
* so here enable 'sata0' node by default to correspond to the sata drive case. Pin multiplexing exists
* in PCIE2 and SATA0, when used as a boot disk, the BIOS can automatically recognize these two conditions.
*/
&sata0 {
status = "disabled";
};
&sata1 {
status = "disabled";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "okay";
ILI9488@0 {
compatible = "ilitek,ili9488";
reg = <0>;
spi-max-frequency = <50000000>;
rotate = <0>;
fps = <30>;
buswidth = <8>;
regwidth = <8>;
bgr;
reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
dc-gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
//cs-gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
//backlight = <&backlight>;
debug = <0>;
};
ADS7843@1 {
compatible = "ti,ads7843";
spi-max-frequency = <1000000>;
reg = <1>;
//cs-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
interrupt-parent = <&gpio4>;
interrupts = <12 0>;
pendown-gpio = <&gpio4 12 0>;
ti,x-min = /bits/ 16 <0>;
//ti,x-max = /bits/ 16 <8000>;
ti,x-max = /bits/ 16 <3200>;
ti,y-min = /bits/ 16 <0>;
//ti,y-max = /bits/ 16 <4800>;
ti,y-max = /bits/ 16 <4800>;
ti,x-plate-ohms = /bits/ 16 <40>;
ti,pressure-max = /bits/ 16 <255>;
wakeup-source;
};
};
&spi2 {
global-cs = <1>;
status = "okay";
mpu6500@0 {
compatible = "InvenSense,mpu6500";
spi-max-frequency = <500000>;
reg = <0>;
spi-cpol;
spi-cpha;
};
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&mmc0 {
bus-width = <0x00000008>;
max-frequency = <100000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
mmc-hs200-1_8v;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
bus-width = <0x00000004>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-sdio;
no-mmc;
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
status = "okay";
};
&dc0 {
pipe_mask = /bits/ 8 <0x2>;
edp_mask = /bits/ 8 <0x0>;
status = "okay";
};
&i2s_dp1 {
status = "okay";
};
&pmdk_dp {
num-dp = <1>;
dp-mask = /bits/ 8 <0x2>;
status = "okay";
};
&rng0 {
status = "okay";
};
&pwm0 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};
&pwm1 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};

View File

@ -0,0 +1,242 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2202 demo board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2202.dtsi"
#include "dt-bindings/gpio/gpio.h"
/{
model = "Pe2202 DEMO DDR4";
compatible = "phytium,pe2202";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x80000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,pin-switches = "mic-in";
simple-audio-card,widgets = "Microphone","mic-in";
simple-audio-card,routing = "MIC2","mic-in";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
/* localized demo board use this rtc device */
rtc@32 {
compatible = "wave,sd3068";
reg = <0x32>;
};
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
sel-gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
};
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&watchdog0 {
status = "okay";
};
&watchdog1 {
status = "okay";
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "peripheral";
status = "okay";
};
&usb2_2 {
dr_mode = "peripheral";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
/*
* In demo board, M.2 interface may insert two types of disks: PCIE (nvme protocol) or SATA (ahci protocol),
* so here enable 'sata0' node by default to correspond to the sata drive case. Pin multiplexing exists
* in PCIE2 and SATA0, when used as a boot disk, the BIOS can automatically recognize these two conditions.
*/
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi2 {
global-cs = <1>;
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&mmc0 {
bus-width = <0x00000008>;
max-frequency = <100000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
mmc-hs200-1_8v;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
bus-width = <0x00000004>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-sdio;
no-mmc;
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
status = "okay";
};
&dc0 {
pipe_mask = /bits/ 8 <0x2>;
edp_mask = /bits/ 8 <0x0>;
status = "okay";
};
&i2s_dp1 {
status = "okay";
};
&pmdk_dp {
num-dp = <1>;
dp-mask = /bits/ 8 <0x2>;
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2202 miniitx board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Hongmin Qi <qihongmin@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2202.dtsi"
/{
model = "Pe2202 MINIITX Board";
compatible = "phytium,pe2202";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x1 0x00000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec {
sound-dai = <&codec0>;
};
};
};
&soc {
mio0: uart@28014000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28014000 0x0 0x1000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
mio1: uart@28016000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28016000 0x0 0x1000>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio6: uart@28020000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28020000 0x0 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio7: uart@28022000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28022000 0x0 0x1000>;
interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 5 0>;
sel-gpios = <&gpio2 6 0>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
mic-src = [20];
};
};
mio15: uart@28032000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "host";
status = "disabled";
};
&usb2_2 {
dr_mode = "host";
status = "disabled";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
status = "disabled";
};
&macb2 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb3 {
phy-mode = "sgmii";
use-mii;
status = "disabled";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
flash: w25q128@0 {
compatible = "winbond,w25q128", "jedec,spi-nor";
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
spi-max-frequency = <12000000>;
reg = <0x00>;
status = "disabled";
};
};
&spi2 {
global-cs = <1>;
status = "disabled";
};
&spi3 {
global-cs = <1>;
status = "disabled";
};
&mmc0 {
status = "okay";
bus-width = <0x4>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-mmc;
};
&mmc1 {
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&dc0 {
status = "okay";
pipe_mask = [02];
edp_mask = [00];
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&pwm1 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};

View File

@ -0,0 +1,243 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2202 power board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Hongmin Qi <qihongmin@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2202.dtsi"
/{
model = "Pe2202S power Board";
compatible = "phytium,pe2202";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x1 0x00000000>;
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <0x0 0x65 0x4>;
clocks = <&sysclk_50mhz>;
#address-cells = <0x1>;
#size-cells = <0x0>;
status = "okay";
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio6: i2c@28020000 {
status = "okay";
compatible = "phytium,i2c";
reg = <0x0 0x28020000 0x0 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <0x1>;
#size-cells = <0x0>;
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <1>;
};
};
mio10: uart@28028000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28028000 0x0 0x1000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio11: uart@2802a000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2802a000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio13: uart@2802e000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2802e000 0x0 0x1000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio14: uart@28030000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb2 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb3 {
phy-mode = "sgmii";
use-mii;
status = "disabled";
};
&dc0 {
pipe_mask = [02];
edp_mask = [00];
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
};
&mmc0 {
bus-width = <8>;
max-frequency = <50000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};

View File

@ -0,0 +1,265 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2204 come board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Hongmin Qi <qihongmin@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
/{
model = "Pe2204 come Board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
};
&soc {
mio3: i2c@2801a000 {
status = "okay";
compatible = "phytium,i2c";
reg = <0x0 0x2801a000 0x0 0x1000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <1>;
};
};
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
rtc@32 {
compatible = "wave,sd3068";
reg = <0x32>;
};
};
mio6: uart@28020000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28020000 0x0 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio10: uart@28028000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28028000 0x0 0x1000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio14: uart@28030000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
status = "disabled";
};
&macb2 {
phy-mode = "rgmii";
use-mii;
status = "disabled";
};
&macb3 {
phy-mode = "rgmii";
use-mii;
status = "disabled";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
};
&spi2 {
global-cs = <1>;
status = "okay";
flash: w25q128@0 {
compatible = "winbond,w25q128", "jedec,spi-nor";
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
spi-max-frequency = <12000000>;
reg = <0x00>;
};
};
&mmc0 {
bus-width = <4>;
max-frequency = <25000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&hda0 {
status = "okay";
};
&dc0 {
status = "okay";
pipe_mask = [03];
edp_mask = [00];
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&pwm1 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};

View File

@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2204 demo board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
#include "dt-bindings/gpio/gpio.h"
/{
model = "Pe2204 DEMO DDR4";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x80000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,pin-switches = "mic-in";
simple-audio-card,widgets = "Microphone","mic-in";
simple-audio-card,routing = "MIC2","mic-in";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
/* localized demo board use this rtc device */
rtc@32 {
compatible = "wave,sd3068";
reg = <0x32>;
};
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
sel-gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0x0>;
compatible = "everest,es8336";
reg = <0x10>;
};
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&watchdog0 {
status = "okay";
};
&watchdog1 {
status = "okay";
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "peripheral";
status = "okay";
};
&usb2_2 {
dr_mode = "peripheral";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
/*
* In demo board, M.2 interface may insert two types of disks: PCIE (nvme protocol) or SATA (ahci protocol),
* so here enable 'sata0' node by default to correspond to the sata drive case. Pin multiplexing exists
* in PCIE2 and SATA0, when used as a boot disk, the BIOS can automatically recognize these two conditions.
*/
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi2 {
global-cs = <1>;
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&mmc0 {
bus-width = <0x00000008>;
max-frequency = <100000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
mmc-hs200-1_8v;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
bus-width = <0x00000004>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-sdio;
no-mmc;
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&dc0 {
pipe_mask = /bits/ 8 <0x3>;
edp_mask = /bits/ 8 <0x0>;
status = "okay";
};
&i2s_dp0 {
status = "okay";
};
&i2s_dp1 {
status = "okay";
};
&pmdk_dp {
num-dp = <2>;
dp-mask = /bits/ 8 <0x3>;
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,343 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2204 edu board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Hongmin Qi <qihongmin@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
/{
model = "Pe2204 edu Board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec {
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <0x1>;
#size-cells = <0x0>;
status = "okay";
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio8: i2c@28024000 {
compatible = "phytium,i2c";
reg = <0x0 0x28024000 0x0 0x1000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <0x1>;
#size-cells = <0x0>;
status = "okay";
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <0x1>;
#size-cells = <0x0>;
status = "okay";
codec0:es8336@10 {
det-gpios = <&gpio2 5 0>;
sel-gpios = <&gpio2 6 0>;
#sound-dai-cells = <0x0>;
compatible = "everest,es8336";
reg = <0x10>;
mic-src = [30];
};
};
mio0: uart@28014000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28014000 0x0 0x1000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio1: uart@28016000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28016000 0x0 0x1000>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio11: uart@2802A000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2802a000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&gpio2 {
status = "okay";
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
//status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "host";
//status = "okay";
};
&usb2_2 {
dr_mode = "host";
//status = "okay";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
//status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
//status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
//status = "okay";
};
&macb2 {
phy-mode = "sgmii";
use-mii;
//status = "okay";
};
&macb3 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "okay";
flash: w25q128@0 {
compatible = "jedec,spi-nor";
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
spi-max-frequency = <12000000>;
reg = <0x00>;
status = "okay";
};
};
&mmc0 {
bus-width = <0x8>;
max-frequency = <50000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&mmc1 {
bus-width = <0x4>;
max-frequency = <25000000>;
cap-sdio-irq;
cap-sd-highspeed;
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&sata0 {
//status = "okay";
};
&sata1 {
status = "okay";
};
&dc0 {
status = "okay";
pipe_mask = [01];
edp_mask = [00];
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&i2s_dp0 {
status = "okay";
};
&pmdk_dp {
num-dp = <1>;
dp-mask = /bits/ 8 <0x1>;
status = "okay";
};
&pwm0 {
phytium,db = <0 0 0 0 0 0>;
status = "okay";
};
&pwm1 {
phytium,db = <0 0 0 0 0 0>;
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&keypad {
keypad,num-rows = <4>;
keypad,num-columns = <4>;
linux,keymap = <0x00000011
0x00010012
0x00020013
0x00030014
0x01000021 /*KEY_21*/
0x01010022 /*KEY_22*/
0x01020023 /*KEY_23*/
0x01030024 /*KEY_24*/
0x02000031 /*KEY_31*/
0x02010032 /*KEY_32*/
0x02020033 /*KEY_33*/
0x02030034 /*KEY_34*/
0x03000041 /*KEY_41*/
0x03010042 /*KEY_42*/
0x03020043 /*KEY_43*/
0x03030044 /*KEY_44*/>;
status = "okay";
};

View File

@ -0,0 +1,215 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2204 hanwei board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Hongmin Qi <qihongmin@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
/{
model = "Pe2204 hanwei Board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
};
&soc {
mio3: uart@2801a000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2801a000 0x0 0x1000>;
interrupts = <0x0 0x5f 0x4>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio8: uart@28024000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28024000 0x0 0x1000>;
interrupts = <0x0 0x64 0x4>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio10: uart@28028000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28028000 0x0 0x1000>;
interrupts = <0x0 0x66 0x4>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio14: uart@28030000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <0x0 0x6a 0x4>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <0x0 0x6b 0x4>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb2 {
phy-mode = "rgmii";
use-mii;
status = "okay";
};
&macb3 {
phy-mode = "rgmii";
use-mii;
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
};
&mmc0 {
bus-width = <8>;
max-frequency = <25000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "disabled";
};
&mmc1 {
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};

View File

@ -0,0 +1,329 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium miniITX-Pe2204 development board.
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Shaojun Yang <yangshaojun@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
/memreserve/ 0xf4000000 0x4000000;
#include "pe2204.dtsi"
/{
model = "miniITX-Pe2204 Board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
aliases {
serial4 = &mio0;
serial5 = &mio1;
serial6 = &mio8;
serial7 = &mio11;
serial8 = &mio15;
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 5 0>;
sel-gpios = <&gpio2 6 0>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
mic-src = [20];
};
};
mio0: uart@28014000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28014000 0x0 0x1000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio1: uart@28016000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28016000 0x0 0x1000>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio8: uart@28024000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28024000 0x0 0x1000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio11: uart@2802A000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x2802A000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&watchdog0 {
status = "okay";
};
&watchdog1 {
status = "okay";
};
&pcie {
status = "okay";
};
&sata1 {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "peripheral";
status = "disabled";
};
&usb2_2 {
dr_mode = "peripheral";
status = "disabled";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb2 {
phy-mode = "rgmii";
use-mii;
status = "okay";
};
&dc0 {
reg = <0x0 0x32000000 0x0 0x8000>,
<0x0 0xf4000000 0x0 0x4000000>; // (optional)
pipe_mask = [03];
edp_mask = [00];
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&i2s_dp0 {
dai-name = "phytium-i2s-dp0";
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
flash: w25q128@0 {
compatible = "winbond,w25q128", "jedec,spi-nor";
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
spi-max-frequency = <12000000>;
reg = <0x00>;
status = "disabled";
};
};
&spi1 {
global-cs = <1>;
status = "disabled";
};
&spi2 {
global-cs = <1>;
status = "disabled";
};
&mmc0 {
bus-width = <0x00000004>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-mmc;
status = "okay";
};
&mmc1 {
bus-width = <0x00000008>;
max-frequency = <50000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "disabled";
};
&pwm0 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};
&pwm1 {
phytium,db = <0 0 0 1000 1000 0>;
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,322 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2204 vpx board.
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* Tianyu Liu <liutianyu1250@phytium.com.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
/{
model = "Pe2204 vpx board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
aliases {
serial4 = &mio3;
serial5 = &mio8;
serial6 = &mio10;
serial7 = &mio11;
serial8 = &mio15;
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
rtc@68 {
compatible = "dallas,ds1339";
reg = <0x68>;
};
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 5 0>;
sel-gpios = <&gpio2 6 0>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
mic-src = [30];
};
};
mio3: uart@2801A000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x2801A000 0x0 0x1000>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio8: uart@28024000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28024000 0x0 0x1000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio10: uart@28028000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28028000 0x0 0x1000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio11: uart@2802A000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x2802A000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio13: uart@2802E000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x2802E000 0x0 0x1000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&pcie {
status = "okay";
};
&sata0 {
status = "okay";
};
&sata1 {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "host";
status = "disabled";
};
&usb2_2 {
dr_mode = "host";
status = "disabled";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb2 {
phy-mode = "rgmii";
use-mii;
force-phy-mode;
status = "okay";
};
&macb3 {
phy-mode = "rgmii";
use-mii;
status = "okay";
};
&dc0 {
pipe_mask = [03];
edp_mask = [00];
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&i2s_dp0 {
status = "okay";
};
&i2s_dp1 {
status = "okay";
};
&pmdk_dp {
num-dp = <2>;
dp-mask = /bits/ 8 <0x3>;
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "disabled";
flash: w25q128@0 {
compatible = "winbond,w25q128", "jedec,spi-nor";
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
spi-max-frequency = <12000000>;
reg = <0x00>;
status = "disabled";
};
};
&spi2 {
global-cs = <1>;
status = "disabled";
};
&mmc0 {
bus-width = <0x00000008>;
max-frequency = <25000000>;
cap-mmc-hw-reset;
cap-mmc-highspeed;
no-sdio;
no-sd;
non-removable;
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pe2201 demo board
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2201.dtsi"
/{
model = "Pe2201 DEMO DDR4";
compatible = "phytium,pe2201";
chosen {
stdout-path = "serial1:115200n8";
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x80000000>;
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
};
&pcie {
status = "okay";
};
&usb2_0 {
dr_mode = "otg";
status = "okay";
};
&usb2_1 {
dr_mode = "peripheral";
status = "okay";
};
&usb2_2 {
dr_mode = "peripheral";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi2 {
global-cs = <1>;
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&mmc0 {
status = "okay";
};
&mmc1 {
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,232 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dts file for Phytium Pe2201 SoC
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*/
#include "pe220x.dtsi"
/ {
compatible = "phytium,pe2201";
aliases {
ethernet0 = &macb0;
ethernet1 = &macb1;
};
};
&cpu {
cpu0: cpu@0 {
device_type = "cpu";
compatible = "phytium,ftc310", "arm,armv8";
reg = <0x0 0x200>;
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
};
};
&soc {
i2c0: i2c@28011000 {
compatible = "phytium,i2c";
reg = <0x0 0x28011000 0x0 0x1000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "smbus_alert";
clocks = <&sysclk_50mhz>;
status = "disabled";
};
i2c1: i2c@28012000 {
compatible = "phytium,i2c";
reg = <0x0 0x28012000 0x0 0x1000>;
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "smbus_alert";
clocks = <&sysclk_50mhz>;
status = "disabled";
};
i2c2: i2c@28013000 {
compatible = "phytium,i2c";
reg = <0x0 0x28013000 0x0 0x1000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
onewire0: onewire@2803f000 {
compatible = "phytium,w1";
reg = <0x0 0x2803f000 0x0 0x1000>;
interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
pwm2: pwm@2804c000 {
compatible = "phytium,pwm";
reg = <0x0 0x2804c000 0x0 0x1000>;
interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
pwm3: pwm@2804d000 {
compatible = "phytium,pwm";
reg = <0x0 0x2804d000 0x0 0x1000>;
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
pwm4: pwm@2804e000 {
compatible = "phytium,pwm";
reg = <0x0 0x2804e000 0x0 0x1000>;
interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
pwm5: pwm@2804f000 {
compatible = "phytium,pwm";
reg = <0x0 0x2804f000 0x0 0x1000>;
interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
pwm6: pwm@28050000 {
compatible = "phytium,pwm";
reg = <0x0 0x28050000 0x0 0x1000>;
interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
pwm7: pwm@28051000 {
compatible = "phytium,pwm";
reg = <0x0 0x28051000 0x0 0x1000>;
interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
adc0: adc@2807b000 {
compatible = "phytium,adc";
reg = <0x0 0x2807b000 0x0 0x1000>;
interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
};
channel@1 {
reg = <1>;
};
channel@2 {
reg = <2>;
};
channel@3 {
reg = <3>;
};
channel@4 {
reg = <4>;
};
channel@5 {
reg = <5>;
};
channel@6 {
reg = <6>;
};
channel@7 {
reg = <7>;
};
};
adc1: adc@2807c000 {
compatible = "phytium,adc";
reg = <0x0 0x2807c000 0x0 0x1000>;
interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
};
channel@1 {
reg = <1>;
};
channel@2 {
reg = <2>;
};
channel@3 {
reg = <3>;
};
channel@4 {
reg = <4>;
};
channel@5 {
reg = <5>;
};
channel@6 {
reg = <6>;
};
channel@7 {
reg = <7>;
};
};
sgpio: sgpio@2807d000 {
compatible = "phytium,sgpio";
reg = <0x0 0x2807d000 0x0 0x1000>;
interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
ngpios = <96>;
bus-frequency = <48000>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
};
macb0: ethernet@32010000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32010000 0x0 0x2000>;
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
macb1: ethernet@32012000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32012000 0x0 0x2000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
jpeg0: jpeg@32b32000 {
compatible = "phytium,jpeg";
reg = <0x0 0x32b32000 0 0x1000>,
<0x0 0x28072000 0 0x30>,
<0x0 0x28073000 0 0x30>;
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
phytium,ocm-buf-addr = <0x30c40000 0x30c60000>;
status = "disabled";
};
};

View File

@ -0,0 +1,184 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dts file for Phytium Pe2202 SoC
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*/
#include "pe220x.dtsi"
/ {
compatible = "phytium,pe2202";
aliases {
ethernet0 = &macb0;
ethernet1 = &macb1;
ethernet2 = &macb2;
ethernet3 = &macb3;
};
};
&cpu {
cpu-map {
cluster0 {
core0 {
cpu = <&cpu_l0>;
};
core1 {
cpu = <&cpu_l1>;
};
};
};
cpu_l0: cpu@0 {
device_type = "cpu";
compatible = "phytium,ftc310", "arm,armv8";
reg = <0x0 0x200>;
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
};
cpu_l1: cpu@1 {
device_type = "cpu";
compatible = "phytium,ftc310", "arm,armv8";
reg = <0x0 0x201>;
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
};
};
&soc {
hda0: hda@28006000 {
compatible = "phytium,hda";
reg = <0x0 0x28006000 0x0 0x1000>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
i2s0: i2s@28009000 {
compatible = "phytium,i2s";
reg = <0x0 0x28009000 0x0 0x1000>,
<0x0 0x28005000 0x0 0x1000>;
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_600mhz>;
clock-names = "i2s_clk";
status = "disabled";
};
can0: can@2800a000 {
compatible = "phytium,canfd";
reg = <0x0 0x2800a000 0x0 0x1000>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_200mhz>;
clock-names = "can_clk";
tx-fifo-depth = <64>;
rx-fifo-depth = <64>;
status = "disabled";
};
can1: can@2800b000 {
compatible = "phytium,canfd";
reg = <0x0 0x2800b000 0x0 0x1000>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_200mhz>;
clock-names = "can_clk";
tx-fifo-depth = <64>;
rx-fifo-depth = <64>;
status = "disabled";
};
keypad: keypad@2807a000 {
compatible = "phytium,keypad";
reg = <0x0 0x2807a000 0x0 0x1000>;
interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
usb3_0: usb3@31a08000 {
compatible = "phytium,pe220x-xhci";
reg = <0x0 0x31a08000 0x0 0x18000>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
usb3_1: usb3@31a28000 {
compatible = "phytium,pe220x-xhci";
reg = <0x0 0x31a28000 0x0 0x18000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sata0: sata@31a40000 {
compatible = "generic-ahci";
reg = <0x0 0x31a40000 0x0 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sata1: sata@32014000 {
compatible = "generic-ahci";
reg = <0x0 0x32014000 0x0 0x1000>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
macb0: ethernet@3200c000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x3200c000 0x0 0x2000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
macb1: ethernet@3200e000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x3200e000 0x0 0x2000>;
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
macb2: ethernet@32010000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32010000 0x0 0x2000>;
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
use-mii;
status = "disabled";
};
macb3: ethernet@32012000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32012000 0x0 0x2000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
use-mii;
status = "disabled";
};
};

View File

@ -0,0 +1,216 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dts file for Phytium Pe2204 SoC
*
* Copyright (c) 2022-2023 Phytium Technology Co., Ltd.
*/
#include "pe220x.dtsi"
/ {
compatible = "phytium,pe2204";
aliases {
ethernet0 = &macb0;
ethernet1 = &macb1;
ethernet2 = &macb2;
ethernet3 = &macb3;
};
};
&cpu {
cpu-map {
cluster0 {
core0 {
cpu = <&cpu_b0>;
};
};
cluster1 {
core0 {
cpu = <&cpu_b1>;
};
};
cluster2 {
core0 {
cpu = <&cpu_l0>;
};
core1 {
cpu = <&cpu_l1>;
};
};
};
cpu_l0: cpu@0 {
device_type = "cpu";
compatible = "phytium,ftc310", "arm,armv8";
reg = <0x0 0x200>;
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
capacity-dmips-mhz = <2850>;
};
cpu_l1: cpu@1 {
device_type = "cpu";
compatible = "phytium,ftc310", "arm,armv8";
reg = <0x0 0x201>;
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
capacity-dmips-mhz = <2850>;
};
cpu_b0: cpu@100 {
device_type = "cpu";
compatible = "phytium,ftc664", "arm,armv8";
reg = <0x0 0x0>;
enable-method = "psci";
clocks = <&scmi_dvfs 0>;
capacity-dmips-mhz = <5660>;
};
cpu_b1: cpu@101 {
device_type = "cpu";
compatible = "phytium,ftc664", "arm,armv8";
reg = <0x0 0x100>;
enable-method = "psci";
clocks = <&scmi_dvfs 1>;
capacity-dmips-mhz = <5660>;
};
};
&soc {
hda0: hda@28006000 {
compatible = "phytium,hda";
reg = <0x0 0x28006000 0x0 0x1000>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
i2s0: i2s@28009000 {
compatible = "phytium,i2s";
reg = <0x0 0x28009000 0x0 0x1000>,
<0x0 0x28005000 0x0 0x1000>;
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_600mhz>;
clock-names = "i2s_clk";
status = "disabled";
};
can0: can@2800a000 {
compatible = "phytium,canfd";
reg = <0x0 0x2800a000 0x0 0x1000>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_200mhz>;
clock-names = "can_clk";
tx-fifo-depth = <64>;
rx-fifo-depth = <64>;
status = "disabled";
};
can1: can@2800b000 {
compatible = "phytium,canfd";
reg = <0x0 0x2800b000 0x0 0x1000>;
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_200mhz>;
clock-names = "can_clk";
tx-fifo-depth = <64>;
rx-fifo-depth = <64>;
status = "disabled";
};
keypad: keypad@2807a000 {
compatible = "phytium,keypad";
reg = <0x0 0x2807a000 0x0 0x1000>;
interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
status = "disabled";
};
usb3_0: usb3@31a08000 {
compatible = "phytium,pe220x-xhci";
reg = <0x0 0x31a08000 0x0 0x18000>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
usb3_1: usb3@31a28000 {
compatible = "phytium,pe220x-xhci";
reg = <0x0 0x31a28000 0x0 0x18000>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sata0: sata@31a40000 {
compatible = "generic-ahci";
reg = <0x0 0x31a40000 0x0 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sata1: sata@32014000 {
compatible = "generic-ahci";
reg = <0x0 0x32014000 0x0 0x1000>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
macb0: ethernet@3200c000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x3200c000 0x0 0x2000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
support-tsn;
status = "disabled";
};
macb1: ethernet@3200e000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x3200e000 0x0 0x2000>;
interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
macb2: ethernet@32010000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32010000 0x0 0x2000>;
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
macb3: ethernet@32012000 {
compatible = "cdns,phytium-gem-1.0";
reg = <0x0 0x32012000 0x0 0x2000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
clocks = <&sysclk_250mhz>, <&sysclk_48mhz>, <&sysclk_48mhz>, <&sysclk_250mhz>;
magic-packet;
status = "disabled";
};
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,316 @@
// SPDX-License-Identifier: GPL-2.0
/*
* DTS file for Phytium Pi development board.
*
* Copyright (C) 2023, Phytium Technology Co., Ltd.
*
* Shaojun Yang <yangshaojun@phytium.com.cn>
*/
/dts-v1/;
/memreserve/ 0x80000000 0x10000;
#include "pe2204.dtsi"
/{
model = "Phytium Pi Board";
compatible = "phytium,pe2204";
chosen {
stdout-path = "serial1:115200n8";
};
aliases {
serial4 = &mio0;
serial5 = &mio11;
serial6 = &mio15;
};
memory@00{
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x00000000>;
};
leds {
compatible = "gpio-leds";
sysled {
label = "sysled";
gpios = <&gpio1 5 0>;
linux,default-trigger = "none";
};
};
sound_card: sound {
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "phytium,pe220x-i2s-audio";
simple-audio-card,pin-switches = "mic-in";
simple-audio-card,widgets = "Microphone","mic-in";
simple-audio-card,routing = "MIC2","mic-in";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec{
sound-dai = <&codec0>;
};
};
};
&soc {
mio9: i2c@28026000 {
compatible = "phytium,i2c";
reg = <0x0 0x28026000 0x0 0x1000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
mio14: i2c@28030000 {
compatible = "phytium,i2c";
reg = <0x0 0x28030000 0x0 0x1000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
codec0: es8336@10 {
det-gpios = <&gpio2 11 0>;
sel-gpios = <&gpio2 7 0>;
#sound-dai-cells = <0>;
compatible = "everest,es8336";
reg = <0x10>;
};
};
mio0: uart@28014000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28014000 0x0 0x1000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio1: i2c@28016000 {
compatible = "phytium,i2c";
reg = <0x0 0x28016000 0x0 0x1000>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
mio8: i2c@28024000 {
compatible = "phytium,i2c";
reg = <0x0 0x28024000 0x0 0x1000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
mio11: uart@2802A000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x2802A000 0x0 0x1000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
mio15: uart@28032000 {
compatible = "arm,pl011","arm,primecell";
reg = <0x0 0x28032000 0x0 0x1000>;
interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&sysclk_50mhz &sysclk_50mhz>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
};
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&gpio2 {
status = "okay";
};
&gpio3 {
status = "okay";
};
&gpio4 {
status = "okay";
};
&gpio5 {
status = "okay";
};
&watchdog0 {
status = "okay";
};
&watchdog1 {
status = "okay";
};
&pcie {
status = "okay";
};
&usb3_0 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb2_0 {
dr_mode = "host";
status = "okay";
};
&usb2_1 {
dr_mode = "peripheral";
status = "disabled";
};
&usb2_2 {
dr_mode = "peripheral";
status = "disabled";
};
&usb2_3 {
dr_mode = "host";
status = "okay";
};
&usb2_4 {
dr_mode = "host";
status = "okay";
};
&macb0 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&macb1 {
phy-mode = "sgmii";
use-mii;
status = "okay";
};
&dc0 {
pipe_mask = /bits/ 8 <0x1>;
edp_mask = /bits/ 8 <0x0>;
status = "okay";
};
&i2s0 {
#sound-dai-cells = <0>;
dai-name = "phytium-i2s-lsd";
status = "okay";
};
&i2s_dp0 {
dai-name = "phytium-i2s-dp0";
status = "okay";
};
&qspi0 {
status = "okay";
flash@0 {
status = "okay";
};
};
&spi0 {
global-cs = <1>;
status = "okay";
spidev0: spidev@0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <50000000>;
status = "disabled";
};
};
&mmc0 {
bus-width = <0x00000004>;
max-frequency = <50000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-mmc;
status = "okay";
};
&mmc1 {
bus-width = <0x00000004>;
max-frequency = <25000000>;
cap-sdio-irq;
cap-sd-highspeed;
no-mmc;
no-sd;
non-removable;
status = "okay";
};
&pwm0 {
phytium,db = <0 0 100 1000 1000 0>;
status = "okay";
};
&pwm1 {
phytium,db = <0 0 100 1000 1000 0>;
status = "okay";
};
&uart0 {
status = "okay";
};
&uart1 {
status = "okay";
};
&uart2 {
status = "okay";
};
&uart3 {
status = "okay";
};
&can0 {
status = "okay";
};
&can1 {
status = "okay";
};
&pmdk_dp {
num-dp = <1>;
dp-mask = /bits/ 8 <0x1>;
status = "okay";
};
&rng0 {
status = "okay";
};

View File

@ -0,0 +1,770 @@
CONFIG_LOCALVERSION="-phytium-embeded-v2.0"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_PHYTIUM=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_KEXEC=y
CONFIG_KEXEC_FILE=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_COMPAT=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_HIBERNATION=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPUFREQ_DT=y
CONFIG_ACPI_CPPC_CPUFREQ=m
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_SCMI_CPUFREQ=y
CONFIG_ARM_SCMI_PROTOCOL=y
CONFIG_ARM_SCMI_TRANSPORT_FORCE_POLLING=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_SHA3_ARM64=m
CONFIG_CRYPTO_SM3_ARM64_CE=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_CMDLINE_PARTITION=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
CONFIG_CMA_AREAS=19
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IPV6=m
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_NET_DSA=m
CONFIG_NET_DSA_TAG_OCELOT=m
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBS=m
CONFIG_NET_SCH_ETF=m
CONFIG_NET_SCH_TAPRIO=m
CONFIG_NET_SCH_MQPRIO=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_GACT=m
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_GATE=m
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
CONFIG_CAN=m
CONFIG_CAN_FLEXCAN=m
CONFIG_CAN_PHYTIUM=m
CONFIG_CAN_PHYTIUM_PLATFORM=m
CONFIG_CAN_PHYTIUM_PCI=m
CONFIG_BT=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_HIDP=m
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_CFG80211=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NFC=m
CONFIG_NFC_NCI=m
CONFIG_NFC_S3FWRN5_I2C=m
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PASID=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
CONFIG_PCIE_ALTERA_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_LAYERSCAPE_GEN4=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_VEXPRESS_CONFIG=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_NAND_PHYTIUM_PLAT=m
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI_PHYTIUM_QUADSPI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=y
CONFIG_NVME_MULTIPATH=y
CONFIG_NVME_HWMON=y
CONFIG_NVME_FC=y
CONFIG_NVME_TCP=y
CONFIG_NVME_TARGET=y
CONFIG_NVME_TARGET_PASSTHRU=y
CONFIG_NVME_TARGET_LOOP=y
CONFIG_NVME_TARGET_FC=y
CONFIG_NVME_TARGET_FCLOOP=y
CONFIG_NVME_TARGET_TCP=y
CONFIG_SRAM=y
CONFIG_PCI_ENDPOINT_TEST=m
CONFIG_EEPROM_AT24=m
CONFIG_EEPROM_AT25=m
CONFIG_UACCE=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_LIBSAS=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_CEVA=y
CONFIG_AHCI_XGENE=y
CONFIG_AHCI_QORIQ=y
CONFIG_SATA_SIL24=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_BLK_DEV_DM=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_TUN=y
CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_ATL1C=m
CONFIG_BCMGENET=m
CONFIG_BNX2X=m
CONFIG_MACB=y
CONFIG_MACB_PCI=y
CONFIG_THUNDER_NIC_PF=y
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
CONFIG_E1000=m
CONFIG_E1000E=m
CONFIG_IGB=m
CONFIG_IGBVF=m
CONFIG_IXGB=m
CONFIG_IXGBE=m
CONFIG_IXGBEVF=m
CONFIG_I40E=m
CONFIG_I40EVF=m
CONFIG_MVMDIO=y
CONFIG_SKY2=y
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
CONFIG_QCOM_EMAC=m
CONFIG_RMNET=m
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_STMMAC_ETH=y
CONFIG_AQUANTIA_PHY=y
CONFIG_BROADCOM_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_AT803X_PHY=y
CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_PPP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
CONFIG_USB_NET_CDCETHER=m
CONFIG_USB_NET_CDC_NCM=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_NET1080=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_USB_NET_CDC_SUBSET=m
CONFIG_USB_NET_ZAURUS=m
CONFIG_USB_NET_QMI_WWAN=y
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_RTL_CARDS=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_RTL8821CS=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_KEYBOARD_PHYTIUM=m
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_PHYTIUM_PCI=m
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=y
CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_HISI_V2 is not set
CONFIG_HW_RANDOM_PHYTIUM=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_PHYTIUM_PCI=y
CONFIG_I2C_PHYTIUM_PLATFORM=y
CONFIG_I3C=y
CONFIG_CDNS_I3C_MASTER=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=m
CONFIG_SPI_PHYTIUM_PLAT=y
CONFIG_SPI_PHYTIUM_PCI=y
CONFIG_SPI_PHYTIUM_QSPI=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPMI=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_WCD934X=m
CONFIG_GPIO_XGENE=y
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_BD9571MWV=m
CONFIG_GPIO_MAX77620=y
CONFIG_W1=m
CONFIG_W1_MASTER_PHYTIUM=m
CONFIG_W1_SLAVE_THERM=m
CONFIG_POWER_RESET_BRCMSTB=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_SBS=m
CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCMI=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA3221=m
CONFIG_SENSORS_PHYTIUM=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_ARM_SMC_WATCHDOG=y
CONFIG_MFD_BD9571MWV=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_PHYTIUM_I2S_LSD=y
CONFIG_MFD_PHYTIUM_I2S_MMD=y
CONFIG_MFD_RK808=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_MFD_WCD934X=m
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_VCTRL=m
CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_SDR_PLATFORM_DRIVERS=y
CONFIG_VIDEO_IMX219=m
CONFIG_VIDEO_OV5645=m
CONFIG_DRM=y
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
CONFIG_DRM_MALI_DISPLAY=m
CONFIG_DRM_RCAR_DW_HDMI=m
CONFIG_DRM_RCAR_LVDS=m
CONFIG_DRM_PANEL_LVDS=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_RAYDIUM_RM67191=m
CONFIG_DRM_PANEL_SITRONIX_ST7703=m
CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
CONFIG_DRM_DISPLAY_CONNECTOR=m
CONFIG_DRM_LONTIUM_LT9611=m
CONFIG_DRM_NWL_MIPI_DSI=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
CONFIG_DRM_TI_SN65DSI86=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=m
CONFIG_DRM_PHYTIUM=y
CONFIG_DRM_LEGACY=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_HDA_PHYTIUM=y
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=y
CONFIG_SND_HDA_CODEC_HDMI=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_FSL_SAI=m
CONFIG_SND_SOC_PHYTIUM_I2S=y
CONFIG_SND_PMDK_ES8388=y
CONFIG_SND_PMDK_ES8336=y
CONFIG_SND_PMDK_DP=y
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_CROS_EC_CODEC=m
CONFIG_SND_SOC_DMIC=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
CONFIG_SND_SOC_MAX98357A=m
CONFIG_SND_SOC_MAX98927=m
CONFIG_SND_SOC_PCM3168A_I2C=m
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_WM8904=m
CONFIG_SND_SOC_WSA881X=m
CONFIG_SND_SIMPLE_CARD=y
CONFIG_SND_AUDIO_GRAPH_CARD=y
CONFIG_I2C_HID=m
CONFIG_USB_CONN_GPIO=y
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_PHYTIUM=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CH341=y
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_SNP_UDC_PLAT=y
CONFIG_USB_BDC_UDC=y
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_FUSB302=m
CONFIG_TYPEC_HD3SS3220=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_F_SDH30=y
CONFIG_MMC_SPI=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_MMC_SDHCI_AM654=y
# CONFIG_MMC_PHYTIUM_MCI_PCI is not set
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_EDAC=y
CONFIG_EDAC_GHES=y
CONFIG_EDAC_PHYTIUM=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=m
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_PCF85363=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RV8803=m
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_SD3068=m
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_PCF2127=m
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_CROS_EC=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
CONFIG_BCM_SBA_RAID=m
CONFIG_FSL_EDMA=y
CONFIG_MV_XOR_V2=y
CONFIG_PL330_DMA=y
CONFIG_PHYTIUM_DDMA=y
CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_DMEM_GENIRQ=m
CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_UIO_NETX=m
CONFIG_UIO_PRUSS=m
CONFIG_UIO_MF624=m
CONFIG_VFIO=y
CONFIG_VFIO_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=y
CONFIG_CROS_EC_SPI=y
CONFIG_CROS_EC_CHARDEV=m
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_XGENE=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_COMMON_CLK_VC5=y
CONFIG_COMMON_CLK_BD718XX=m
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_PHYTIUM=y
CONFIG_ARM_MHU=y
CONFIG_PLATFORM_MHU=y
CONFIG_PHYTIUM_MBOX=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_HOMO_REMOTEPROC=y
CONFIG_RPMSG_CHAR=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_SOUNDWIRE=m
CONFIG_SOUNDWIRE_QCOM=m
CONFIG_SOC_BRCMSTB=y
CONFIG_SOC_TI=y
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
CONFIG_DEVFREQ_GOV_POWERSAVE=y
CONFIG_EXTCON_PTN5150=m
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_MAX9611=m
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_PHYTIUM_ADC=m
CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_SENSORS_ISL29018=m
CONFIG_IIO_CROS_EC_BARO=m
CONFIG_MPL3115=m
CONFIG_PWM=y
CONFIG_PWM_CROS_EC=m
CONFIG_PWM_PHYTIUM=m
CONFIG_PHYTIUM_IXIC=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_FSL_IMX8MQ_USB=y
CONFIG_PHY_MIXEL_MIPI_DPHY=m
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_SAMSUNG_USB2=y
CONFIG_ARM_SMMU_V3_PMU=m
CONFIG_FPGA=y
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_FPGA_REGION=m
CONFIG_OF_FPGA_REGION=m
CONFIG_MUX_MMIO=y
CONFIG_SLIM_QCOM_CTRL=m
CONFIG_INTERCONNECT=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_OVERLAY_FS=m
CONFIG_ISO9660_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_EFIVAR_FS=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
CONFIG_SQUASHFS_EMBEDDED=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_NFSD=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_BLOCKLAYOUT=y
CONFIG_NFSD_SCSILAYOUT=y
CONFIG_NFSD_FLEXFILELAYOUT=y
CONFIG_NFSD_V4_2_INTER_SSC=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_CCREE=m
CONFIG_CRYPTO_DEV_HISI_SEC2=m
CONFIG_CRYPTO_DEV_HISI_ZIP=m
CONFIG_CRYPTO_DEV_HISI_HPRE=m
CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m
CONFIG_INDIRECT_PIO=y
CONFIG_DMA_CMA=y
CONFIG_DMA_PERNUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y

View File

@ -0,0 +1,2 @@
CONFIG_TEE=y
CONFIG_OPTEE=y

View File

@ -0,0 +1,738 @@
CONFIG_LOCALVERSION="-phytium-embeded-2023-v1.0-GA"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_ARCH_PHYTIUM=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_KEXEC=y
CONFIG_KEXEC_FILE=y
CONFIG_CRASH_DUMP=y
CONFIG_XEN=y
CONFIG_COMPAT=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_HIBERNATION=y
CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_ENERGY_MODEL=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_CPUFREQ_DT=y
CONFIG_ACPI_CPPC_CPUFREQ=m
CONFIG_ARM_SCPI_CPUFREQ=y
CONFIG_ARM_SCMI_CPUFREQ=y
CONFIG_ARM_SCMI_PROTOCOL=y
CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_ACPI=y
CONFIG_ACPI_APEI=y
CONFIG_ACPI_APEI_GHES=y
CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_APEI_EINJ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ARM64_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64_CE=m
CONFIG_CRYPTO_SHA3_ARM64=m
CONFIG_CRYPTO_SM3_ARM64_CE=m
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_CHACHA20_NEON=m
CONFIG_CRYPTO_AES_ARM64_BS=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_CMDLINE_PARTITION=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
CONFIG_CMA_AREAS=19
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IPV6=m
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP6_NF_IPTABLES=m
CONFIG_IP6_NF_FILTER=m
CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_NET_DSA=m
CONFIG_NET_DSA_TAG_OCELOT=m
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBS=m
CONFIG_NET_SCH_ETF=m
CONFIG_NET_SCH_TAPRIO=m
CONFIG_NET_SCH_MQPRIO=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_U32=m
CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_GACT=m
CONFIG_NET_ACT_MIRRED=m
CONFIG_NET_ACT_SKBEDIT=m
CONFIG_NET_ACT_GATE=m
CONFIG_QRTR=m
CONFIG_QRTR_SMD=m
CONFIG_QRTR_TUN=m
CONFIG_BPF_JIT=y
CONFIG_CAN=m
CONFIG_CAN_FLEXCAN=m
CONFIG_CAN_PHYTIUM=m
CONFIG_CAN_PHYTIUM_PLATFORM=m
CONFIG_BT=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=m
CONFIG_BT_HIDP=m
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_CFG80211=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NFC=m
CONFIG_NFC_NCI=m
CONFIG_NFC_S3FWRN5_I2C=m
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCI_IOV=y
CONFIG_PCI_PASID=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
CONFIG_PCIE_ALTERA_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_LAYERSCAPE_GEN4=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_BRCMSTB_GISB_ARB=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_VEXPRESS_CONFIG=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_SST25L=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI_PHYTIUM_QUADSPI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=y
CONFIG_NVME_MULTIPATH=y
CONFIG_NVME_HWMON=y
CONFIG_NVME_FC=y
CONFIG_NVME_TCP=y
CONFIG_NVME_TARGET=y
CONFIG_NVME_TARGET_PASSTHRU=y
CONFIG_NVME_TARGET_LOOP=y
CONFIG_NVME_TARGET_FC=y
CONFIG_NVME_TARGET_FCLOOP=y
CONFIG_NVME_TARGET_TCP=y
CONFIG_SRAM=y
CONFIG_PCI_ENDPOINT_TEST=m
CONFIG_EEPROM_AT24=m
CONFIG_EEPROM_AT25=m
CONFIG_UACCE=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_LIBSAS=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_CEVA=y
CONFIG_AHCI_XGENE=y
CONFIG_AHCI_QORIQ=y
CONFIG_SATA_SIL24=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_BLK_DEV_DM=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_TUN=y
CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_ATL1C=m
CONFIG_BCMGENET=m
CONFIG_BNX2X=m
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
CONFIG_E1000=m
CONFIG_E1000E=m
CONFIG_IGB=m
CONFIG_IGBVF=m
CONFIG_IXGB=m
CONFIG_IXGBE=m
CONFIG_IXGBEVF=m
CONFIG_I40E=m
CONFIG_I40EVF=m
CONFIG_MVMDIO=y
CONFIG_SKY2=y
CONFIG_MLX4_EN=m
CONFIG_MLX5_CORE=m
CONFIG_MLX5_CORE_EN=y
CONFIG_QCOM_EMAC=m
CONFIG_RMNET=m
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_STMMAC_ETH=m
CONFIG_AQUANTIA_PHY=y
CONFIG_BROADCOM_PHY=m
CONFIG_MARVELL_PHY=m
CONFIG_MARVELL_10G_PHY=m
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_AT803X_PHY=y
CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y
CONFIG_VITESSE_PHY=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
CONFIG_MDIO_BUS_MUX_MMIOREG=y
CONFIG_PPP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
CONFIG_USB_NET_CDCETHER=m
CONFIG_USB_NET_CDC_NCM=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_NET1080=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_USB_NET_CDC_SUBSET=m
CONFIG_USB_NET_ZAURUS=m
CONFIG_USB_NET_QMI_WWAN=y
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
CONFIG_RTL_CARDS=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_RTL8821CS=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_XILINX_PS_UART=y
CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
CONFIG_SERIAL_FSL_LINFLEXUART=y
CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_HISI_V2 is not set
CONFIG_HW_RANDOM_PHYTIUM=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_PHYTIUM_PLATFORM=y
CONFIG_I3C=m
CONFIG_SPI=y
CONFIG_SPI_BITBANG=m
CONFIG_SPI_PHYTIUM_PLAT=y
CONFIG_SPI_SPIDEV=y
CONFIG_SPMI=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_PINCTRL_MAX77620=y
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_MB86S7X=y
CONFIG_GPIO_PL061=y
CONFIG_GPIO_WCD934X=m
CONFIG_GPIO_XGENE=y
# CONFIG_GPIO_PHYTIUM_SGPIO is not set
CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_BD9571MWV=m
CONFIG_GPIO_MAX77620=y
CONFIG_W1=m
CONFIG_W1_SLAVE_THERM=m
CONFIG_POWER_RESET_BRCMSTB=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_BATTERY_SBS=m
CONFIG_BATTERY_BQ27XXX=y
CONFIG_SENSORS_ARM_SCMI=y
CONFIG_SENSORS_ARM_SCPI=y
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_INA2XX=m
CONFIG_SENSORS_INA3221=m
CONFIG_SENSORS_PHYTIUM=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_ARM_SMC_WATCHDOG=y
CONFIG_MFD_BD9571MWV=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_MAX77620=y
CONFIG_MFD_RK808=y
CONFIG_MFD_SEC_CORE=y
CONFIG_MFD_ROHM_BD718XX=y
CONFIG_MFD_WCD934X=m
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_BD718XX=y
CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_SPMI=y
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_VCTRL=m
CONFIG_RC_CORE=m
CONFIG_RC_DECODERS=y
CONFIG_RC_DEVICES=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
# CONFIG_DVB_NET is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_SDR_PLATFORM_DRIVERS=y
CONFIG_VIDEO_IMX219=m
CONFIG_VIDEO_OV5645=m
CONFIG_DRM=y
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
CONFIG_DRM_MALI_DISPLAY=m
CONFIG_DRM_RCAR_DW_HDMI=m
CONFIG_DRM_RCAR_LVDS=m
CONFIG_DRM_PANEL_LVDS=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_RAYDIUM_RM67191=m
CONFIG_DRM_PANEL_SITRONIX_ST7703=m
CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
CONFIG_DRM_DISPLAY_CONNECTOR=m
CONFIG_DRM_LONTIUM_LT9611=m
CONFIG_DRM_NWL_MIPI_DSI=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
CONFIG_DRM_TI_SN65DSI86=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=m
CONFIG_DRM_PHYTIUM=y
CONFIG_DRM_LEGACY=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_HDA_INTEL=m
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_HDMI=m
CONFIG_SND_SOC=y
CONFIG_SND_SOC_FSL_SAI=m
CONFIG_SND_SOC_PHYTIUM_I2S=y
CONFIG_SND_PMDK_ES8388=y
CONFIG_SND_PMDK_ES8336=y
CONFIG_SND_PMDK_DP=y
CONFIG_SND_SOC_AK4613=m
CONFIG_SND_SOC_CROS_EC_CODEC=m
CONFIG_SND_SOC_DMIC=m
CONFIG_SND_SOC_ES7134=m
CONFIG_SND_SOC_ES7241=m
CONFIG_SND_SOC_MAX98357A=m
CONFIG_SND_SOC_MAX98927=m
CONFIG_SND_SOC_PCM3168A_I2C=m
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
CONFIG_SND_SOC_SPDIF=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_WM8904=m
CONFIG_SND_SOC_WSA881X=m
CONFIG_SND_SIMPLE_CARD=y
CONFIG_SND_AUDIO_GRAPH_CARD=y
CONFIG_I2C_HID=m
CONFIG_USB_CONN_GPIO=y
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC2=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_ISP1760=y
CONFIG_USB_PHYTIUM=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CH341=y
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_SNP_UDC_PLAT=y
CONFIG_USB_BDC_UDC=y
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_FUSB302=m
CONFIG_TYPEC_HD3SS3220=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ACPI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_MMC_SDHCI_CADENCE=y
CONFIG_MMC_SDHCI_F_SDH30=y
CONFIG_MMC_SPI=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
CONFIG_MMC_SDHCI_XENON=y
CONFIG_MMC_SDHCI_AM654=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_DISK=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_EDAC=y
CONFIG_EDAC_GHES=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=m
CONFIG_RTC_DRV_MAX77686=y
CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_PCF85363=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RV8803=m
CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_SD3068=m
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_PCF2127=m
CONFIG_RTC_DRV_EFI=y
CONFIG_RTC_DRV_CROS_EC=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
CONFIG_BCM_SBA_RAID=m
CONFIG_FSL_EDMA=y
CONFIG_MV_XOR_V2=y
CONFIG_PL330_DMA=y
CONFIG_UIO=m
CONFIG_UIO_CIF=m
CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_DMEM_GENIRQ=m
CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_UIO_NETX=m
CONFIG_UIO_PRUSS=m
CONFIG_UIO_MF624=m
CONFIG_VFIO=y
CONFIG_VFIO_PCI=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=y
CONFIG_CROS_EC_SPI=y
CONFIG_CROS_EC_CHARDEV=m
CONFIG_COMMON_CLK_RK808=y
CONFIG_COMMON_CLK_SCPI=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_XGENE=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_COMMON_CLK_VC5=y
CONFIG_COMMON_CLK_BD718XX=m
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_PHYTIUM=y
CONFIG_ARM_MHU=y
CONFIG_PLATFORM_MHU=y
CONFIG_PHYTIUM_MBOX=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
CONFIG_REMOTEPROC=y
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_SOUNDWIRE=m
CONFIG_SOUNDWIRE_QCOM=m
CONFIG_SOC_BRCMSTB=y
CONFIG_SOC_TI=y
CONFIG_EXTCON_PTN5150=m
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_IIO=y
CONFIG_MAX9611=m
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_PHYTIUM_ADC=m
CONFIG_IIO_CROS_EC_SENSORS_CORE=m
CONFIG_IIO_CROS_EC_SENSORS=m
CONFIG_IIO_CROS_EC_LIGHT_PROX=m
CONFIG_SENSORS_ISL29018=m
CONFIG_IIO_CROS_EC_BARO=m
CONFIG_MPL3115=m
CONFIG_PWM=y
CONFIG_PWM_CROS_EC=m
CONFIG_PWM_PHYTIUM=m
CONFIG_PHY_XGENE=y
CONFIG_PHY_FSL_IMX8MQ_USB=y
CONFIG_PHY_MIXEL_MIPI_DPHY=m
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_SAMSUNG_USB2=y
CONFIG_ARM_SMMU_V3_PMU=m
CONFIG_FPGA=y
CONFIG_FPGA_BRIDGE=m
CONFIG_ALTERA_FREEZE_BRIDGE=m
CONFIG_FPGA_REGION=m
CONFIG_OF_FPGA_REGION=m
CONFIG_MUX_MMIO=y
CONFIG_SLIM_QCOM_CTRL=m
CONFIG_INTERCONNECT=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_EXPORTFS_BLOCK_OPS=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=m
CONFIG_CUSE=m
CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_EFIVAR_FS=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
CONFIG_SQUASHFS_EMBEDDED=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_CCREE=m
CONFIG_CRYPTO_DEV_HISI_SEC2=m
CONFIG_CRYPTO_DEV_HISI_ZIP=m
CONFIG_CRYPTO_DEV_HISI_HPRE=m
CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m
CONFIG_INDIRECT_PIO=y
CONFIG_DMA_CMA=y
CONFIG_DMA_PERNUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y

View File

@ -0,0 +1,155 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium SoC RNG Driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/bits.h>
#include <linux/err.h>
#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <linux/string.h>
#define TRNG_CR 0x00
#define TRNG_CR_RNGEN BIT(0)
#define TRNG_CR_ROSEN_MASK GENMASK(7, 4)
#define TRNG_CR_DIEN BIT(16)
#define TRNG_CR_ERIEN BIT(17)
#define TRNG_CR_IRQEN BIT(24)
#define TRNG_MSEL 0x04
#define TRNG_MSEL_MSEL BIT(0)
#define TRNG_SR 0x08
#define TRNG_SR_HTF BIT(0)
#define TRNG_SR_DRDY BIT(1)
#define TRNG_SR_ERERR BIT(3)
#define TRNG_DR 0x0C
#define TRNG_RESEED 0x40
#define TRNG_RESEED_RSED BIT(0)
#define DELAY 10
#define TIMEOUT 100
static int msel;
module_param(msel, int, 0444);
MODULE_PARM_DESC(msel, "Phytium RNG mode selection: 0 - TRNG. 1 - PRNG.");
struct phytium_rng {
struct hwrng rng;
void __iomem *base;
};
static int phytium_rng_init(struct hwrng *rng)
{
struct phytium_rng *priv = container_of(rng, struct phytium_rng, rng);
u32 reg;
/* Mode Selection */
reg = msel ? TRNG_MSEL_MSEL : 0;
writel(reg, priv->base + TRNG_MSEL);
/* If PRGN mode is on, do reseed operations */
if (msel)
writel(TRNG_RESEED_RSED, priv->base + TRNG_RESEED);
/* Clear status */
writel(0x7, priv->base + TRNG_SR);
/* Enable TRNG */
reg = readl(priv->base + TRNG_CR) | TRNG_CR_ROSEN_MASK | TRNG_CR_RNGEN;
writel(reg, priv->base + TRNG_CR);
return 0;
}
static void phytium_rng_cleanup(struct hwrng *rng)
{
struct phytium_rng *priv = container_of(rng, struct phytium_rng, rng);
writel(0x7, priv->base + TRNG_SR);
}
static int phytium_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
{
struct phytium_rng *priv = container_of(rng, struct phytium_rng, rng);
u32 reg;
int ret = 0;
/* TRNG can generate at most 8*32bit random number per time */
max = max > 32 ? 32 : max;
reg = readl(priv->base + TRNG_SR);
if (!(reg & TRNG_SR_DRDY) && wait) {
ret = readl_poll_timeout(priv->base + TRNG_SR, reg,
reg & TRNG_SR_DRDY, DELAY, TIMEOUT);
if (ret) {
dev_err((struct device *)priv->rng.priv,
"%s: timeout %x!\n", __func__, reg);
return -EIO;
}
}
while (max >= 4) {
*(u32 *)buf = readl(priv->base + TRNG_DR);
ret += sizeof(u32);
buf += sizeof(u32);
max -= sizeof(u32);
}
/* Clear DRDY by writing 1 */
writel(reg | TRNG_SR_DRDY, priv->base + TRNG_SR);
return ret;
}
static int phytium_rng_probe(struct platform_device *pdev)
{
struct phytium_rng *priv;
struct resource *mem;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
priv->rng.name = pdev->name;
priv->rng.init = phytium_rng_init;
priv->rng.cleanup = phytium_rng_cleanup;
priv->rng.read = phytium_rng_read;
priv->rng.priv = (unsigned long)&pdev->dev;
priv->rng.quality = 1000;
return devm_hwrng_register(&pdev->dev, &priv->rng);
}
static const struct of_device_id phytium_rng_dt_ids[] = {
{ .compatible = "phytium,rng" },
{ }
};
MODULE_DEVICE_TABLE(of, phytium_rng_dt_ids);
static struct platform_driver phytium_rng_driver = {
.probe = phytium_rng_probe,
.driver = {
.name = "phytium-rng",
.of_match_table = of_match_ptr(phytium_rng_dt_ids),
}
};
module_platform_driver(phytium_rng_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Phytium random number generator driver");
MODULE_AUTHOR("Chen Baozi <chenbaozi@phytium.com.cn>");

View File

@ -0,0 +1,533 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*
* Derived from drivers/char/ipmi/bt-bmc.c
* Copyright (c) 2015-2016, IBM Corporation.
*/
#include <linux/atomic.h>
#include <linux/bt-bmc.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/regmap.h>
#include <linux/sched.h>
#include <linux/timer.h>
/*
* This is a BMC device used to communicate to the host
*/
#define DEVICE_NAME "ipmi-bt-host"
#define BT_IO_BASE 0xe4
#define BT_IRQ 10
#define LPC_HICR0 0x00
#define LPC_HICR0_LPC3E BIT(7)
#define LPC_HICR0_LPC2E BIT(6)
#define LPC_HICR0_LPC1E BIT(5)
#define LPC_HICR0_SDWNE BIT(3) /* 0:disable, 1:enable for HICR1_SDWNB */
#define LPC_HICR0_PMEE BIT(2) /* 0:disable, 1:enable for HICR1_PMEB */
#define LPC_HICR2 0x08
#define LPC_HICR2_IBFIF3 BIT(3) /* 0:normal, 1:enable irq 3*/
#define LPC_HICR4 0x10
#define LPC_HICR4_LADR12AS BIT(7)
#define LPC_HICR4_KCSENBL BIT(2)
#define LPC_BTENABLE BIT(0) /* share bt channel enable, 0:disable, 1:enable */
#define LPC_LADR3H_BT 0x014
#define LPC_LADR3L_BT 0x018
#define BT_CR1 0x4C
#define BT_CR1_IRQ_H2B 0x04
#define BT_CR1_IRQ_HWRST 0x40
#define BT_CSR1 0x54
#define BT_CSR1_IRQ_H2B 0x04
#define BT_CSR1_IRQ_HWRST 0x40
#define BT_CTRL 0x58
#define BT_CTRL_B_BUSY 0x80
#define BT_CTRL_H_BUSY 0x40
#define BT_CTRL_OEM0 0x20
#define BT_CTRL_SMS_ATN 0x10
#define BT_CTRL_B2H_ATN 0x08
#define BT_CTRL_H2B_ATN 0x04
#define BT_CTRL_CLR_RD_PTR 0x02
#define BT_CTRL_CLR_WR_PTR 0x01
#define BT_BMC2HOST 0x5C
#define BT_HOST2BMC 0x98
#define BT_INTMASK 0x60
#define BT_INTMASK_B2H_IRQEN 0x01
#define BT_INTMASK_B2H_IRQ 0x02
#define BT_INTMASK_BMC_HWRST 0x80
#define BT_BMC_BUFFER_SIZE 256
struct bt_bmc {
struct device dev;
struct miscdevice miscdev;
struct regmap *map;
int irq;
wait_queue_head_t queue;
struct timer_list poll_timer;
struct mutex mutex;
};
static atomic_t open_count = ATOMIC_INIT(0);
static const struct regmap_config bt_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static u8 bt_inb(struct bt_bmc *bt_bmc, int reg)
{
uint32_t val = 0;
int rc;
rc = regmap_read(bt_bmc->map, reg, &val);
WARN(rc != 0, "regmap_read() failed: %d\n", rc);
return rc == 0 ? (u8) val : 0;
}
static void bt_outb(struct bt_bmc *bt_bmc, u8 data, int reg)
{
int rc;
rc = regmap_write(bt_bmc->map, reg, data);
WARN(rc != 0, "regmap_write() failed: %d\n", rc);
}
static void clr_rd_ptr(struct bt_bmc *bt_bmc)
{
bt_outb(bt_bmc, BT_CTRL_CLR_RD_PTR, BT_CTRL);
}
static void clr_wr_ptr(struct bt_bmc *bt_bmc)
{
bt_outb(bt_bmc, BT_CTRL_CLR_WR_PTR, BT_CTRL);
}
static void clr_h2b_atn(struct bt_bmc *bt_bmc)
{
bt_outb(bt_bmc, 0, BT_CTRL);
}
static void set_b_busy(struct bt_bmc *bt_bmc)
{
if (!(bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_B_BUSY))
bt_outb(bt_bmc, BT_CTRL_B_BUSY, BT_CTRL);
}
static void clr_b_busy(struct bt_bmc *bt_bmc)
{
if (bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_B_BUSY)
bt_outb(bt_bmc, 0, BT_CTRL);
}
static void set_b2h_atn(struct bt_bmc *bt_bmc)
{
bt_outb(bt_bmc, BT_CTRL_B2H_ATN, BT_CTRL);
}
static u8 bt_read(struct bt_bmc *bt_bmc)
{
return bt_inb(bt_bmc, BT_HOST2BMC);
}
static ssize_t bt_readn(struct bt_bmc *bt_bmc, u8 *buf, size_t n)
{
int i;
for (i = 0; i < n; i++)
buf[i] = bt_read(bt_bmc);
return n;
}
static void bt_write(struct bt_bmc *bt_bmc, u8 c)
{
bt_outb(bt_bmc, c, BT_BMC2HOST);
}
static ssize_t bt_writen(struct bt_bmc *bt_bmc, u8 *buf, size_t n)
{
int i;
for (i = 0; i < n; i++)
bt_write(bt_bmc, buf[i]);
return n;
}
static void set_sms_atn(struct bt_bmc *bt_bmc)
{
bt_outb(bt_bmc, BT_CTRL_SMS_ATN, BT_CTRL);
}
static struct bt_bmc *file_bt_bmc(struct file *file)
{
return container_of(file->private_data, struct bt_bmc, miscdev);
}
static int bt_bmc_open(struct inode *inode, struct file *file)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
if (atomic_inc_return(&open_count) == 1) {
clr_b_busy(bt_bmc);
return 0;
}
atomic_dec(&open_count);
return -EBUSY;
}
/*
* The BT (Block Transfer) interface means that entire messages are
* buffered by the host before a notification is sent to the BMC that
* there is data to be read. The first byte is the length and the
* message data follows. The read operation just tries to capture the
* whole before returning it to userspace.
*
* BT Message format :
*
* Byte 1 Byte 2 Byte 3 Byte 4 Byte 5:N
* Length NetFn/LUN Seq Cmd Data
*
*/
static ssize_t bt_bmc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
u8 len;
int len_byte = 1;
u8 kbuffer[BT_BMC_BUFFER_SIZE];
ssize_t ret = 0;
ssize_t nread;
WARN_ON(*ppos);
if (wait_event_interruptible(bt_bmc->queue,
bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_H2B_ATN))
return -ERESTARTSYS;
mutex_lock(&bt_bmc->mutex);
if (unlikely(!(bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_H2B_ATN))) {
ret = -EIO;
goto out_unlock;
}
set_b_busy(bt_bmc);
clr_h2b_atn(bt_bmc);
clr_rd_ptr(bt_bmc);
/*
* The BT frames start with the message length, which does not
* include the length byte.
*/
kbuffer[0] = bt_read(bt_bmc);
len = kbuffer[0];
/* We pass the length back to userspace as well */
if (len + 1 > count)
len = count - 1;
while (len) {
nread = min_t(ssize_t, len, sizeof(kbuffer) - len_byte);
bt_readn(bt_bmc, kbuffer + len_byte, nread);
if (copy_to_user(buf, kbuffer, nread + len_byte)) {
ret = -EFAULT;
break;
}
len -= nread;
buf += nread + len_byte;
ret += nread + len_byte;
len_byte = 0;
}
clr_b_busy(bt_bmc);
out_unlock:
mutex_unlock(&bt_bmc->mutex);
return ret;
}
/*
* BT Message response format :
*
* Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6:N
* Length NetFn/LUN Seq Cmd Code Data
*/
static ssize_t bt_bmc_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
u8 kbuffer[BT_BMC_BUFFER_SIZE];
ssize_t ret = 0;
ssize_t nwritten;
/*
* send a minimum response size
*/
if (count < 5)
return -EINVAL;
WARN_ON(*ppos);
/*
* There's no interrupt for clearing bmc busy so we have to
* poll
*/
if (wait_event_interruptible(bt_bmc->queue,
!(bt_inb(bt_bmc, BT_CTRL) &
(BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN))))
return -ERESTARTSYS;
mutex_lock(&bt_bmc->mutex);
if (unlikely(bt_inb(bt_bmc, BT_CTRL) &
(BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN))) {
ret = -EIO;
goto out_unlock;
}
clr_wr_ptr(bt_bmc);
while (count) {
nwritten = min_t(ssize_t, count, sizeof(kbuffer));
if (copy_from_user(&kbuffer, buf, nwritten)) {
ret = -EFAULT;
break;
}
bt_writen(bt_bmc, kbuffer, nwritten);
count -= nwritten;
buf += nwritten;
ret += nwritten;
}
set_b2h_atn(bt_bmc);
out_unlock:
mutex_unlock(&bt_bmc->mutex);
return ret;
}
static long bt_bmc_ioctl(struct file *file, unsigned int cmd,
unsigned long param)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
switch (cmd) {
case BT_BMC_IOCTL_SMS_ATN:
set_sms_atn(bt_bmc);
return 0;
}
return -EINVAL;
}
static int bt_bmc_release(struct inode *inode, struct file *file)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
atomic_dec(&open_count);
set_b_busy(bt_bmc);
return 0;
}
static __poll_t bt_bmc_poll(struct file *file, poll_table *wait)
{
struct bt_bmc *bt_bmc = file_bt_bmc(file);
__poll_t mask = 0;
u8 ctrl;
poll_wait(file, &bt_bmc->queue, wait);
ctrl = bt_inb(bt_bmc, BT_CTRL);
if (ctrl & BT_CTRL_H2B_ATN)
mask |= EPOLLIN;
if (!(ctrl & (BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN)))
mask |= EPOLLOUT;
return mask;
}
static const struct file_operations bt_bmc_fops = {
.owner = THIS_MODULE,
.open = bt_bmc_open,
.read = bt_bmc_read,
.write = bt_bmc_write,
.release = bt_bmc_release,
.poll = bt_bmc_poll,
.unlocked_ioctl = bt_bmc_ioctl,
};
static void poll_timer(struct timer_list *t)
{
struct bt_bmc *bt_bmc = from_timer(bt_bmc, t, poll_timer);
bt_bmc->poll_timer.expires += msecs_to_jiffies(500);
wake_up(&bt_bmc->queue);
add_timer(&bt_bmc->poll_timer);
}
static irqreturn_t bt_bmc_irq(int irq, void *arg)
{
struct bt_bmc *bt_bmc = arg;
u32 reg, intmsk;
int rc;
rc = regmap_read(bt_bmc->map, BT_CR1, &reg);
if (rc)
return IRQ_NONE;
reg &= BT_CR1_IRQ_H2B | BT_CR1_IRQ_HWRST;
if (!reg)
return IRQ_NONE;
/* ack pending IRQs */
regmap_write(bt_bmc->map, BT_CR1, 0);
if (reg & BT_CR1_IRQ_HWRST) {
regmap_read(bt_bmc->map, BT_INTMASK, &intmsk);
if (intmsk & BT_INTMASK_BMC_HWRST)
regmap_write(bt_bmc->map, BT_INTMASK, 0);
}
wake_up(&bt_bmc->queue);
return IRQ_HANDLED;
}
static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int rc;
bt_bmc->irq = platform_get_irq(pdev, 0);
if (!bt_bmc->irq)
return -ENODEV;
rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
DEVICE_NAME, bt_bmc);
if (rc < 0) {
dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
bt_bmc->irq = 0;
return rc;
}
/*
* Configure IRQs on the bmc clearing the H2B and HBUSY bits;
* H2B will be asserted when the bmc has data for us; HBUSY
* will be cleared (along with B2H) when we can write the next
* message to the BT buffer
*/
rc = regmap_update_bits(bt_bmc->map, BT_CSR1,
BT_CSR1_IRQ_H2B | BT_CSR1_IRQ_HWRST,
BT_CSR1_IRQ_H2B | BT_CSR1_IRQ_HWRST);
return rc;
}
static int bt_bmc_probe(struct platform_device *pdev)
{
struct bt_bmc *bt_bmc;
struct device *dev;
int rc;
if (!pdev || !pdev->dev.of_node)
return -ENODEV;
dev = &pdev->dev;
dev_info(dev, "Found bt bmc device\n");
bt_bmc = devm_kzalloc(dev, sizeof(*bt_bmc), GFP_KERNEL);
if (!bt_bmc)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, bt_bmc);
bt_bmc->map = syscon_node_to_regmap(pdev->dev.parent->of_node);
mutex_init(&bt_bmc->mutex);
init_waitqueue_head(&bt_bmc->queue);
bt_bmc->miscdev.minor = MISC_DYNAMIC_MINOR,
bt_bmc->miscdev.name = DEVICE_NAME,
bt_bmc->miscdev.fops = &bt_bmc_fops,
bt_bmc->miscdev.parent = dev;
rc = misc_register(&bt_bmc->miscdev);
if (rc) {
dev_err(dev, "Unable to register misc device\n");
return rc;
}
bt_bmc_config_irq(bt_bmc, pdev);
if (bt_bmc->irq) {
dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
} else {
dev_info(dev, "No IRQ; using timer\n");
timer_setup(&bt_bmc->poll_timer, poll_timer, 0);
bt_bmc->poll_timer.expires = jiffies + msecs_to_jiffies(10);
add_timer(&bt_bmc->poll_timer);
}
regmap_update_bits(bt_bmc->map, LPC_HICR0, LPC_HICR0_LPC3E, LPC_HICR0_LPC3E);
regmap_update_bits(bt_bmc->map, LPC_HICR4, LPC_BTENABLE, LPC_BTENABLE);
regmap_write(bt_bmc->map, LPC_LADR3H_BT, BT_IO_BASE >> 8);
regmap_write(bt_bmc->map, LPC_LADR3L_BT, BT_IO_BASE);
regmap_update_bits(bt_bmc->map, LPC_HICR2, LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3);
clr_b_busy(bt_bmc);
return 0;
}
static int bt_bmc_remove(struct platform_device *pdev)
{
struct bt_bmc *bt_bmc = dev_get_drvdata(&pdev->dev);
misc_deregister(&bt_bmc->miscdev);
if (!bt_bmc->irq)
del_timer_sync(&bt_bmc->poll_timer);
return 0;
}
static const struct of_device_id bt_bmc_match[] = {
{ .compatible = "phytium,bt-bmc" },
{ },
};
MODULE_DEVICE_TABLE(of, bt_bmc_match);
static struct platform_driver bt_bmc_driver = {
.driver = {
.name = DEVICE_NAME,
.of_match_table = bt_bmc_match,
},
.probe = bt_bmc_probe,
.remove = bt_bmc_remove,
};
module_platform_driver(bt_bmc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cheng Quan <chengquan@phytium.com.cn");
MODULE_DESCRIPTION("Linux device interface to the BT interface");

View File

@ -0,0 +1,327 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020-2023 Phytium Technology Co., Ltd.
*
* Derived from drivers/char/ipmi/kcs_bmc_aspeed.c
* Copyright (c) 2015-2018, Intel Corporation.
*/
#define pr_fmt(fmt) "phytium-kcs-bmc: " fmt
#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/regmap.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include "kcs_bmc.h"
#define DEVICE_NAME "phytium-kcs-bmc"
#define KCS_CHANNEL_MAX 4
/* mapped to lpc-bmc@0 IO space */
#define LPC_HICR0 0x000
#define LPC_HICR0_LPC3E BIT(7)
#define LPC_HICR0_LPC2E BIT(6)
#define LPC_HICR0_LPC1E BIT(5)
#define LPC_HICR0_SDWNE BIT(3) /* 0:disable, 1:enable for HICR1_SDWNB */
#define LPC_HICR0_PMEE BIT(2) /* 0:disable, 1:enable for HICR1_PMEB */
#define LPC_HICR1 0x004
#define LPC_HICR1_LPCBSY BIT(7) /* 0:idle, 1:trans busy */
#define LPC_HICR1_IRQBSY BIT(5) /* 0:idle, 1:trans data */
#define LPC_HICR1_LPCSWRST BIT(4) /* 0:normal, 1:reset */
#define LPC_HICR1_SDWNB BIT(3) /* 0:normal, 1:software shutdown */
#define LPC_HICR1_PMEB BIT(2) /* 0:LPCPD low, 1:LPCPD high */
#define LPC_HICR2 0x008
#define LPC_LPCSWRST_ERRIRQ BIT(6) /* 0:normal, 1:reset irq */
#define LPC_SDWN_ERRIRQ BIT(5) /* 0:normal, 1:lpcpd irq */
#define LPC_ABRT_ERRIRQ BIT(4) /* 0:normal, 1:lframe low when busy*/
#define LPC_HICR2_IBFIF3 BIT(3) /* 0:normal, 1:enable irq 3*/
#define LPC_HICR2_IBFIF2 BIT(2)
#define LPC_HICR2_IBFIF1 BIT(1)
/* 0:normal,1:enable err irq-reset,power down,abort */
#define LPC_HICR2_ERRIE BIT(0)
#define LPC_HICR3 0x00C
#define LPC_LFRAME_STATUS BIT(7) /* R */
#define LPC_SERIRQ_STATUS BIT(5) /* R */
#define LPC_LREST_STATUS BIT(4) /* R */
#define LPC_LPCPD_STATUS BIT(3) /* R */
#define LPC_PME_STATUS BIT(2) /* R */
#define LPC_HICR4 0x010
#define LPC_HICR4_LADR12AS BIT(7)
#define LPC_HICR4_KCSENBL BIT(2)
#define LPC_BTENABLE BIT(0) /* share bt channel enable, 0:disable, 1:enable */
#define LPC_LADR3H 0x014
#define LPC_LADR3L 0x018
#define LPC_LADR12H 0x01C
#define LPC_LADR12L 0x020
#define LPC_IDR1 0x024
#define LPC_IDR2 0x028
#define LPC_IDR3 0x02C
#define LPC_ODR1 0x030
#define LPC_ODR2 0x034
#define LPC_ODR3 0x038
#define LPC_STR1 0x03C
#define LPC_STR2 0x040
#define LPC_STR3 0x044
#define LPC_HICRB 0x80
#define LPC_HICRB_IBFIF4 BIT(1)
#define LPC_HICRB_LPC4E BIT(0)
#define LPC_LADR4 0x88
#define LPC_IDR4 0x8c
#define LPC_ODR4 0x90
#define LPC_STR4 0x94
struct phytium_kcs_bmc {
struct regmap *map;
};
static u8 phytium_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg)
{
struct phytium_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc);
u32 val = 0;
int rc;
rc = regmap_read(priv->map, reg, &val);
WARN(rc != 0, "regmap_read() failed: %d\n", rc);
return rc == 0 ? (u8) val : 0;
}
static void phytium_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data)
{
struct phytium_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc);
int rc;
rc = regmap_write(priv->map, reg, data);
WARN(rc != 0, "regmap_write() failed: %d\n", rc);
}
/*
* Background:
* we note D for Data, and C for Cmd/Status, default rules are
* A. KCS1 / KCS2 ( D / C:X / X+4 )
* D / C : CA0h / CA4h
* D / C : CA8h / CACh
* B. KCS3 ( D / C:XX2h / XX3h )
* D / C : CA2h / CA3h
* D / C : CB2h / CB3h -use
* C. KCS4
* D / C : CA4h / CA5h
* D / C : CB0h / CB1h -use
*/
static void phytium_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr)
{
struct phytium_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc);
switch (kcs_bmc->channel) {
case 1:
regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, 0);
regmap_write(priv->map, LPC_LADR12H, addr >> 8);
regmap_write(priv->map, LPC_LADR12L, addr & 0xFF);
break;
case 2:
regmap_update_bits(priv->map, LPC_HICR4,
LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS);
regmap_write(priv->map, LPC_LADR12H, addr >> 8);
regmap_write(priv->map, LPC_LADR12L, addr & 0xFF);
break;
case 3:
regmap_write(priv->map, LPC_LADR3H, addr >> 8);
regmap_write(priv->map, LPC_LADR3L, addr & 0xFF);
break;
case 4:
regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) |
addr);
break;
default:
break;
}
}
static void phytium_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable)
{
struct phytium_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc);
switch (kcs_bmc->channel) {
case 1:
if (enable) {
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1);
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC1E, LPC_HICR0_LPC1E);
} else {
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC1E, 0);
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF1, 0);
}
break;
case 2:
if (enable) {
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2);
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC2E, LPC_HICR0_LPC2E);
} else {
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC2E, 0);
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF2, 0);
}
break;
case 3:
if (enable) {
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3);
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC3E, LPC_HICR0_LPC3E);
regmap_update_bits(priv->map, LPC_HICR4,
LPC_HICR4_KCSENBL, LPC_HICR4_KCSENBL);
} else {
regmap_update_bits(priv->map, LPC_HICR0,
LPC_HICR0_LPC3E, 0);
regmap_update_bits(priv->map, LPC_HICR4,
LPC_HICR4_KCSENBL, 0);
regmap_update_bits(priv->map, LPC_HICR2,
LPC_HICR2_IBFIF3, 0);
}
break;
case 4:
if (enable)
regmap_update_bits(priv->map, LPC_HICRB,
LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E,
LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E);
else
regmap_update_bits(priv->map, LPC_HICRB,
LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E,
0);
break;
default:
break;
}
}
static irqreturn_t phytium_kcs_irq(int irq, void *arg)
{
struct kcs_bmc *kcs_bmc = arg;
if (!kcs_bmc_handle_event(kcs_bmc))
return IRQ_HANDLED;
return IRQ_NONE;
}
static int phytium_kcs_config_irq(struct kcs_bmc *kcs_bmc, struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int irq;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
return devm_request_irq(dev, irq, phytium_kcs_irq, IRQF_SHARED,
dev_name(dev), kcs_bmc);
}
static const struct kcs_ioreg phytium_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = {
{ .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 },
{ .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 },
{ .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 },
{ .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 },
};
static int phytium_kcs_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phytium_kcs_bmc *priv;
struct kcs_bmc *kcs_bmc;
u32 chan, addr;
int rc;
rc = of_property_read_u32(dev->of_node, "kcs_chan", &chan);
if ((rc != 0) || (chan == 0 || chan > KCS_CHANNEL_MAX)) {
dev_err(dev, "no valid 'kcs_chan' configured\n");
return -ENODEV;
}
rc = of_property_read_u32(dev->of_node, "kcs_addr", &addr);
if (rc) {
dev_err(dev, "no valid 'kcs_addr' configured\n");
return -ENODEV;
}
kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan);
if (!kcs_bmc)
return -ENOMEM;
priv = kcs_bmc_priv(kcs_bmc);
priv->map = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(priv->map)) {
dev_err(dev, "Couldn't get regmap\n");
return -ENODEV;
}
kcs_bmc->ioreg = phytium_kcs_bmc_ioregs[chan - 1];
kcs_bmc->io_inputb = phytium_kcs_inb;
kcs_bmc->io_outputb = phytium_kcs_outb;
dev_set_drvdata(dev, kcs_bmc);
phytium_kcs_set_address(kcs_bmc, addr);
phytium_kcs_enable_channel(kcs_bmc, true);
rc = phytium_kcs_config_irq(kcs_bmc, pdev);
if (rc)
return rc;
rc = misc_register(&kcs_bmc->miscdev);
if (rc) {
dev_err(dev, "Unable to register device\n");
return rc;
}
pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n",
chan, addr, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str);
return 0;
}
static int phytium_kcs_remove(struct platform_device *pdev)
{
struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev);
misc_deregister(&kcs_bmc->miscdev);
return 0;
}
static const struct of_device_id phytium_kcs_bmc_match[] = {
{ .compatible = "phytium,kcs-bmc" },
{ }
};
MODULE_DEVICE_TABLE(of, phytium_kcs_bmc_match);
static struct platform_driver phytium_kcs_bmc_driver = {
.driver = {
.name = DEVICE_NAME,
.of_match_table = phytium_kcs_bmc_match,
},
.probe = phytium_kcs_probe,
.remove = phytium_kcs_remove,
};
module_platform_driver(phytium_kcs_bmc_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Cheng Quan <chengquan@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium device interface to the KCS BMC device");

View File

@ -0,0 +1 @@
obj-$(CONFIG_PHYTIUM_DDMA) += phytium-ddmac.o

View File

@ -0,0 +1,945 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium Device DDMA Controller driver.
*
* Copyright (c) 2023 Phytium Technology Co., Ltd.
*/
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
#include <asm/barrier.h>
#include "phytium-ddmac.h"
static inline struct phytium_ddma_device *to_ddma_device(struct dma_chan *chan)
{
return container_of(chan->device, struct phytium_ddma_device, dma_dev);
}
static inline struct phytium_ddma_chan *to_ddma_chan(struct dma_chan *chan)
{
return container_of(chan, struct phytium_ddma_chan, vchan.chan);
}
static inline struct phytium_ddma_desc *to_ddma_desc(struct virt_dma_desc *vd)
{
return container_of(vd, struct phytium_ddma_desc, vdesc);
}
static inline struct device *chan_to_dev(struct phytium_ddma_chan *chan)
{
return chan->vchan.chan.device->dev;
}
static inline struct phytium_ddma_device *chan_to_ddma(
struct phytium_ddma_chan *chan)
{
return to_ddma_device(&chan->vchan.chan);
}
static inline void phytium_ddma_iowrite32(
const struct phytium_ddma_device *ddma,
const u32 reg, const u32 val)
{
iowrite32(val, ddma->base + reg);
}
static inline u32 phytium_ddma_ioread32(const struct phytium_ddma_device *ddma,
const u32 reg)
{
return ioread32(ddma->base + reg);
}
static inline void phytium_chan_iowrite32(const struct phytium_ddma_chan *chan,
const u32 reg, const u32 val)
{
iowrite32(val, chan->base + reg);
}
static inline u32 phytium_chan_ioread32(const struct phytium_ddma_chan *chan,
const u32 reg)
{
return ioread32(chan->base + reg);
}
static void phytium_ddma_disable(const struct phytium_ddma_device *ddma)
{
dev_dbg(ddma->dev, "ddma disable\n");
phytium_ddma_iowrite32(ddma, DMA_CTL, !DMA_CTL_EN);
}
static void phytium_ddma_enable(const struct phytium_ddma_device *ddma)
{
dev_dbg(ddma->dev, "ddma enable\n");
phytium_ddma_iowrite32(ddma, DMA_CTL, DMA_CTL_EN);
}
static void phytium_ddma_reset(const struct phytium_ddma_device *ddma)
{
u32 val = 0;
dev_dbg(ddma->dev, "dma reset\n");
val = phytium_ddma_ioread32(ddma, DMA_CTL);
val |= DMA_CTL_SRST;
phytium_ddma_iowrite32(ddma, DMA_CTL, val);
udelay(10);
val &= ~DMA_CTL_SRST;
phytium_ddma_iowrite32(ddma, DMA_CTL, val);
}
static void phytium_ddma_irq_disable(const struct phytium_ddma_device *ddma)
{
u32 val = 0;
dev_dbg(ddma->dev, "ddma irq disable\n");
val = phytium_ddma_ioread32(ddma, DMA_MASK_INT);
val |= DMA_INT_EN;
phytium_ddma_iowrite32(ddma, DMA_MASK_INT, val);
}
static void phytium_ddma_irq_enable(const struct phytium_ddma_device *ddma)
{
u32 val = 0;
dev_dbg(ddma->dev, "ddma irq enable\n");
val = phytium_ddma_ioread32(ddma, DMA_MASK_INT);
val &= ~DMA_INT_EN;
phytium_ddma_iowrite32(ddma, DMA_MASK_INT, val);
}
static u32 phytium_ddma_irq_read(const struct phytium_ddma_device *ddma)
{
u32 val = 0;
val = phytium_ddma_ioread32(ddma, DMA_STAT);
return val;
}
static void phytium_chan_irq_disable(struct phytium_ddma_chan *chan)
{
u32 val = 0;
dev_dbg(chan_to_dev(chan), "channel %d irq disable\n", chan->id);
val = phytium_ddma_ioread32(chan_to_ddma(chan), DMA_MASK_INT);
val |= DMA_INT_CHAL_EN(chan->id);
phytium_ddma_iowrite32(chan_to_ddma(chan), DMA_MASK_INT, val);
}
static void phytium_chan_irq_enable(struct phytium_ddma_chan *chan)
{
u32 val = 0;
dev_dbg(chan_to_dev(chan), "channel %d irq enable\n", chan->id);
val = phytium_ddma_ioread32(chan_to_ddma(chan), DMA_MASK_INT);
val &= ~DMA_INT_CHAL_EN(chan->id);
phytium_ddma_iowrite32(chan_to_ddma(chan), DMA_MASK_INT, val);
}
static void phytium_chan_irq_clear(struct phytium_ddma_chan *chan)
{
u32 val = 0;
dev_dbg(chan_to_dev(chan), "channel %d irq clear\n", chan->id);
val = DMA_STAT_CHAL(chan->id);
phytium_ddma_iowrite32(chan_to_ddma(chan), DMA_STAT, val);
}
static int phytium_chan_disable(struct phytium_ddma_chan *chan)
{
u32 val = 0;
int ret = 0;
dev_dbg(chan_to_dev(chan), "channel %d disable\n", chan->id);
val = phytium_chan_ioread32(chan, DMA_CHALX_CTL);
if (val | DMA_CHAL_EN) {
val &= ~DMA_CHAL_EN;
phytium_chan_iowrite32(chan, DMA_CHALX_CTL, val);
ret = readl_relaxed_poll_timeout_atomic(
chan->base + DMA_CHALX_CTL, val,
!(val & DMA_CHAL_EN), 0, 100000);
}
return ret;
}
static void phytium_chan_enable(struct phytium_ddma_chan *chan)
{
u32 val = 0;
dev_dbg(chan_to_dev(chan), "channel %d enable\n", chan->id);
val = phytium_chan_ioread32(chan, DMA_CHALX_CTL);
val |= DMA_CHAL_EN;
phytium_chan_iowrite32(chan, DMA_CHALX_CTL, val);
}
static bool phytium_chan_is_running(const struct phytium_ddma_chan *chan)
{
u32 val;
val = phytium_chan_ioread32(chan, DMA_CHALX_CTL);
if (val & DMA_CHAL_EN)
return true;
else
return false;
}
static void phytium_chan_reset(struct phytium_ddma_chan *chan)
{
u32 val = 0;
dev_dbg(chan_to_dev(chan), "channel %d reset\n", chan->id);
val = phytium_chan_ioread32(chan, DMA_CHALX_CTL);
val |= DMA_CHAL_SRST;
phytium_chan_iowrite32(chan, DMA_CHALX_CTL, val);
udelay(10);
val &= ~DMA_CHAL_SRST;
phytium_chan_iowrite32(chan, DMA_CHALX_CTL, val);
}
static void phytium_ddma_vdesc_free(struct virt_dma_desc *vd)
{
kfree(to_ddma_desc(vd));
}
static int phytium_chan_pause(struct dma_chan *chan)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
int ret = 0;
ret = phytium_chan_disable(pchan);
pchan->busy = false;
pchan->is_pasued = true;
return ret;
}
static int phytium_chan_resume(struct dma_chan *chan)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
phytium_chan_enable(pchan);
pchan->is_pasued = false;
return 0;
}
static void phytium_chan_start_xfer(struct phytium_ddma_chan *chan)
{
struct virt_dma_desc *vdesc = NULL;
struct phytium_ddma_sg_req *sg_req = NULL;
char *tmp = NULL;
int i = 0;
unsigned long flags = 0;
/* chan first xfer settings */
if (!chan->desc) {
vdesc = vchan_next_desc(&chan->vchan);
if (!vdesc)
return;
list_del(&vdesc->node);
chan->desc = to_ddma_desc(vdesc);
chan->next_sg = 0;
chan->current_sg = NULL;
dev_dbg(chan_to_dev(chan), "xfer start\n");
}
if (chan->next_sg == chan->desc->num_sgs)
chan->next_sg = 0;
sg_req = &chan->desc->sg_req[chan->next_sg];
chan->current_sg = sg_req;
/* fill to 4 bytes */
switch (sg_req->direction) {
case DMA_MEM_TO_DEV:
tmp = phys_to_virt(sg_req->mem_addr_l);
memset(chan->buf, 0, sg_req->len * 4);
for (i = 0; i < sg_req->len; i++)
chan->buf[i * 4] = tmp[i];
break;
case DMA_DEV_TO_MEM:
memset(chan->buf, 0, sg_req->len * 4);
break;
default:
break;
}
/* start transfer */
phytium_chan_iowrite32(chan, DMA_CHALX_DDR_LWADDR,
chan->paddr & 0xFFFFFFFF);
phytium_chan_iowrite32(chan, DMA_CHALX_DDR_UPADDR,
(chan->paddr >> 32) & 0xFFFFFFFF);
phytium_chan_iowrite32(chan, DMA_CHALX_DEV_ADDR, sg_req->dev_addr);
phytium_chan_iowrite32(chan, DMA_CHALX_TS, sg_req->len * 4);
spin_lock_irqsave(&chan_to_ddma(chan)->lock, flags);
phytium_chan_irq_enable(chan);
spin_unlock_irqrestore(&chan_to_ddma(chan)->lock, flags);
phytium_chan_enable(chan);
chan->next_sg++;
chan->busy = true;
}
static void phytium_chan_xfer_done(struct phytium_ddma_chan *chan)
{
struct phytium_ddma_sg_req *sg_req = chan->current_sg;
char *tmp = NULL;
int i = 0;
if (chan->desc) {
if (sg_req->direction == DMA_DEV_TO_MEM) {
tmp = phys_to_virt(sg_req->mem_addr_l);
for (i = 0; i < sg_req->len; i++)
tmp[i] = chan->buf[i * 4];
}
chan->busy = false;
if (chan->next_sg == chan->desc->num_sgs) {
dev_dbg(chan_to_dev(chan), "xfer complete\n");
vchan_cookie_complete(&chan->desc->vdesc);
chan->desc = NULL;
chan->current_sg = NULL;
}
phytium_chan_disable(chan);
phytium_chan_irq_clear(chan);
phytium_chan_start_xfer(chan);
}
}
static void phytium_dma_hw_init(struct phytium_ddma_device *ddma)
{
u32 i = 0;
int ret = 0;
phytium_ddma_disable(ddma);
phytium_ddma_reset(ddma);
phytium_ddma_irq_enable(ddma);
phytium_ddma_enable(ddma);
for (i = 0; i < ddma->dma_channels; i++) {
phytium_chan_irq_disable(&ddma->chan[i]);
ret = phytium_chan_disable(&ddma->chan[i]);
if (ret)
dev_err(ddma->dev, "can't disable channel %d\n", i);
}
}
static size_t phytium_ddma_desc_residue(struct phytium_ddma_chan *chan)
{
u32 trans_cnt = 0;
u32 residue = 0;
int i = 0;
trans_cnt = phytium_chan_ioread32(chan, DMA_CHALX_TRANS_CNT);
residue = chan->current_sg->len - trans_cnt;
for (i = chan->next_sg; i < chan->desc->num_sgs; i++)
residue += chan->desc->sg_req[i].len;
return residue;
}
static enum dma_status phytium_ddma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
struct virt_dma_desc *vd = NULL;
enum dma_status ret = 0;
unsigned long flags = 0;
size_t residue = 0;
ret = dma_cookie_status(chan, cookie, txstate);
if ((ret == DMA_COMPLETE) || !txstate)
return ret;
spin_lock_irqsave(&pchan->vchan.lock, flags);
vd = vchan_find_desc(&pchan->vchan, cookie);
if (pchan->desc && cookie == pchan->desc->vdesc.tx.cookie)
residue = phytium_ddma_desc_residue(pchan);
dma_set_residue(txstate, residue);
spin_unlock_irqrestore(&pchan->vchan.lock, flags);
if (pchan->is_pasued && ret == DMA_IN_PROGRESS)
ret = DMA_PAUSED;
return ret;
}
static void phytium_ddma_issue_pending(struct dma_chan *chan)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
unsigned long flags = 0;
spin_lock_irqsave(&pchan->vchan.lock, flags);
if (vchan_issue_pending(&pchan->vchan) && !pchan->desc && !pchan->busy)
phytium_chan_start_xfer(pchan);
spin_unlock_irqrestore(&pchan->vchan.lock, flags);
}
static int phytium_ddma_terminate_all(struct dma_chan *chan)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
unsigned long flags = 0;
LIST_HEAD(head);
spin_lock_irqsave(&pchan->vchan.lock, flags);
if (pchan->desc) {
vchan_terminate_vdesc(&pchan->desc->vdesc);
if (pchan->busy) {
u32 tmp_ctl, timeout;
phytium_chan_disable(pchan);
/* save some registers, reset will clear it */
timeout = phytium_chan_ioread32(pchan,
DMA_CHALX_TIMEOUT_CNT);
tmp_ctl = phytium_chan_ioread32(pchan,
DMA_CHALX_CTL);
spin_lock(&chan_to_ddma(pchan)->lock);
phytium_chan_irq_disable(pchan);
spin_unlock(&chan_to_ddma(pchan)->lock);
/* need reset when terminate */
phytium_chan_reset(pchan);
phytium_chan_irq_clear(pchan);
/* recover it */
phytium_chan_iowrite32(pchan,
DMA_CHALX_CTL, tmp_ctl);
phytium_chan_iowrite32(pchan,
DMA_CHALX_TIMEOUT_CNT, timeout);
pchan->busy = false;
}
pchan->desc = NULL;
}
vchan_get_all_descriptors(&pchan->vchan, &head);
spin_unlock_irqrestore(&pchan->vchan.lock, flags);
vchan_dma_desc_free_list(&pchan->vchan, &head);
return 0;
}
static int phytium_ddma_alloc_chan_resources(struct dma_chan *chan)
{
struct phytium_ddma_device *ddma = to_ddma_device(chan);
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
u32 bind_status = 0;
int ret = 0;
unsigned long flags = 0;
bind_status = phytium_ddma_ioread32(ddma, DMA_CHAL_BIND);
if ((pchan->is_used) || (bind_status & BIT(pchan->id))) {
dev_err(ddma->dev, "channel %d already used\n", pchan->id);
ret = -EBUSY;
goto out;
}
/* prepare channel */
ret = phytium_chan_disable(pchan);
if (ret) {
dev_err(ddma->dev, "can't disable channel %d\n", pchan->id);
goto out;
}
phytium_chan_reset(pchan);
phytium_chan_irq_clear(pchan);
/* channel bind */
spin_lock_irqsave(&chan_to_ddma(pchan)->lock, flags);
bind_status |= BIT(pchan->id);
phytium_ddma_iowrite32(ddma, DMA_CHAL_BIND, bind_status);
pchan->is_used = true;
spin_unlock_irqrestore(&chan_to_ddma(pchan)->lock, flags);
/* alloc dma memory */
pchan->buf = dma_alloc_coherent(ddma->dev, 4 * PAGE_SIZE, &pchan->paddr,
GFP_KERNEL);
if (!pchan->buf) {
ret = -EBUSY;
dev_err(ddma->dev, "failed to alloc dma memory\n");
}
dev_info(ddma->dev, "alloc channel %d\n", pchan->id);
out:
return ret;
}
static void phytium_ddma_free_chan_resources(struct dma_chan *chan)
{
struct phytium_ddma_device *ddma = to_ddma_device(chan);
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
u32 bind_status = 0;
unsigned long flags = 0;
if (!pchan->is_used)
return;
dev_dbg(ddma->dev, "free channel %d\n", pchan->id);
spin_lock_irqsave(&chan_to_ddma(pchan)->lock, flags);
bind_status = phytium_ddma_ioread32(ddma, DMA_CHAL_BIND);
bind_status &= ~BIT(pchan->id);
phytium_ddma_iowrite32(ddma, DMA_CHAL_BIND, bind_status);
spin_unlock_irqrestore(&chan_to_ddma(pchan)->lock, flags);
phytium_chan_disable(pchan);
spin_lock_irqsave(&chan_to_ddma(pchan)->lock, flags);
phytium_chan_irq_disable(pchan);
spin_unlock_irqrestore(&chan_to_ddma(pchan)->lock, flags);
vchan_free_chan_resources(to_virt_chan(chan));
pchan->is_used = false;
if (pchan->buf)
dma_free_coherent(ddma->dev, 4 * PAGE_SIZE,
pchan->buf, pchan->paddr);
}
static int phytium_ddma_slave_config(struct dma_chan *chan,
struct dma_slave_config *config)
{
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
u32 chal_cfg = 0;
u32 req_mode = 0;
const u32 timeout = 0xffff;
unsigned long flag = 0;
/* Check if chan will be configured for slave transfers */
if (!is_slave_direction(config->direction))
return -EINVAL;
memcpy(&pchan->dma_config, config, sizeof(*config));
/* set channel config reg */
spin_lock_irqsave(&chan_to_ddma(pchan)->lock, flag);
if (pchan->id > 3) {
chal_cfg = phytium_ddma_ioread32(chan_to_ddma(pchan),
DMA_CHAL_CFG_H);
chal_cfg &= ~(0xFF << ((pchan->id - 4) * 8));
chal_cfg |= DMA_CHAL_SEL((pchan->id - 4), pchan->request_line);
chal_cfg |= DMA_CHAL_SEL_EN(pchan->id - 4);
phytium_ddma_iowrite32(chan_to_ddma(pchan), DMA_CHAL_CFG_H,
chal_cfg);
} else {
chal_cfg = phytium_ddma_ioread32(chan_to_ddma(pchan),
DMA_CHAL_CFG_L);
chal_cfg &= ~(0xFF << (pchan->id * 8));
chal_cfg |= DMA_CHAL_SEL((pchan->id), pchan->request_line);
chal_cfg |= DMA_CHAL_SEL_EN(pchan->id);
phytium_ddma_iowrite32(chan_to_ddma(pchan), DMA_CHAL_CFG_L,
chal_cfg);
}
spin_unlock_irqrestore(&chan_to_ddma(pchan)->lock, flag);
/* set channel mode */
req_mode = (config->direction == DMA_DEV_TO_MEM) ?
DMA_RX_REQ : DMA_TX_REQ;
phytium_chan_iowrite32(pchan, DMA_CHALX_CTL, req_mode << 2);
/* set channel timeout */
phytium_chan_iowrite32(pchan, DMA_CHALX_TIMEOUT_CNT,
timeout | DMA_CHAL_TIMEOUT_EN);
return 0;
}
static struct dma_async_tx_descriptor *phytium_ddma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
u32 sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context)
{
struct phytium_ddma_device *ddma = to_ddma_device(chan);
struct phytium_ddma_chan *pchan = to_ddma_chan(chan);
struct dma_slave_config *sconfig = &pchan->dma_config;
struct phytium_ddma_desc *desc = NULL;
struct scatterlist *sg = NULL;
int i = 0;
char *tmp;
if (unlikely(!is_slave_direction(direction))) {
dev_err(ddma->dev, "invalid dma direction\n");
return NULL;
}
if (unlikely(sg_len < 1)) {
dev_err(ddma->dev, "invalid segment length: %d\n", sg_len);
return NULL;
}
desc = kzalloc(struct_size(desc, sg_req, sg_len), GFP_NOWAIT);
if (!desc)
return NULL;
/* set sg list */
for_each_sg(sgl, sg, sg_len, i) {
tmp = phys_to_virt(sg_dma_address(sg));
desc->sg_req[i].direction = direction;
switch (direction) {
case DMA_MEM_TO_DEV:
desc->sg_req[i].len = sg_dma_len(sg);
desc->sg_req[i].mem_addr_l =
sg_dma_address(sg) & 0xFFFFFFFF;
desc->sg_req[i].mem_addr_h =
(sg_dma_address(sg) >> 32) & 0xFFFFFFFF;
desc->sg_req[i].dev_addr =
sconfig->dst_addr & 0xFFFFFFFF;
break;
case DMA_DEV_TO_MEM:
desc->sg_req[i].len = sg_dma_len(sg);
desc->sg_req[i].mem_addr_l =
sg_dma_address(sg) & 0xFFFFFFFF;
desc->sg_req[i].mem_addr_h =
(sg_dma_address(sg) >> 32) & 0xFFFFFFFF;
desc->sg_req[i].dev_addr =
sconfig->src_addr & 0xFFFFFFFF;
break;
default:
return NULL;
}
}
desc->num_sgs = sg_len;
return vchan_tx_prep(&pchan->vchan, &desc->vdesc, flags);
}
static irqreturn_t phytium_dma_interrupt(int irq, void *dev_id)
{
struct phytium_ddma_device *ddma = dev_id;
struct phytium_ddma_chan *chan;
u32 irq_status = 0;
u32 i = 0;
u32 val = 0;
phytium_ddma_irq_disable(ddma);
irq_status = phytium_ddma_irq_read(ddma);
val = phytium_ddma_ioread32(ddma, DMA_CTL);
/* Poll, clear and process every chanel interrupt status */
for (i = 0; i < ddma->dma_channels; i++) {
if (!(irq_status & BIT(i * 4)))
continue;
chan = &ddma->chan[i];
phytium_chan_xfer_done(chan);
}
phytium_ddma_irq_enable(ddma);
return IRQ_HANDLED;
}
static struct dma_chan *phytium_ddma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
struct phytium_ddma_device *ddma = ofdma->of_dma_data;
struct device *dev = ddma->dev;
struct phytium_ddma_chan *chan = NULL;
struct dma_chan *c = NULL;
u32 channel_id = 0;
channel_id = dma_spec->args[0];
if (channel_id > ddma->dma_channels) {
dev_err(dev, "bad channel %d\n", channel_id);
return NULL;
}
chan = &ddma->chan[channel_id];
chan->request_line = dma_spec->args[1];
c = dma_get_slave_channel(&chan->vchan.chan);
if (!c) {
dev_err(dev, "no more channels available\n");
return NULL;
}
return c;
}
static int phytium_ddma_probe(struct platform_device *pdev)
{
struct phytium_ddma_device *ddma;
struct dma_device *dma_dev;
struct resource *mem;
u32 i = 0;
int ret = 0;
u32 nr_channels = 0;
ddma = devm_kzalloc(&pdev->dev, sizeof(*ddma), GFP_KERNEL);
if (!ddma) {
ret = -ENOMEM;
goto out;
}
dma_dev = &ddma->dma_dev;
ddma->dev = &pdev->dev;
spin_lock_init(&ddma->lock);
ddma->irq = platform_get_irq(pdev, 0);
if (ddma->irq < 0) {
dev_err(&pdev->dev, "no irq resource\n");
ret = -EINVAL;
goto out;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ddma->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(ddma->base)) {
dev_err(&pdev->dev, "no resource address");
ret = PTR_ERR(ddma->base);
goto out;
}
ret = of_property_read_u32(pdev->dev.of_node, "dma-channels",
&nr_channels);
if (ret < 0) {
dev_err(&pdev->dev,
"can't get the number of dma channels: %d\n", ret);
goto out;
}
if (nr_channels > DDMA_MAX_NR_PCHANNELS) {
dev_warn(&pdev->dev, "over the max number of channels\n");
nr_channels = DDMA_MAX_NR_PCHANNELS;
}
ddma->dma_channels = DDMA_MAX_NR_PCHANNELS;
ret = devm_request_irq(&pdev->dev, ddma->irq, phytium_dma_interrupt,
IRQF_SHARED, dev_name(&pdev->dev), ddma);
if (ret) {
dev_err(&pdev->dev, "could not to request irq %d", ddma->irq);
goto out;
}
/* Set capabilities */
dma_cap_set(DMA_SLAVE, ddma->dma_dev.cap_mask);
/* DMA capabilities */
dma_dev->dev = ddma->dev;
dma_dev->chancnt = ddma->dma_channels;
dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
dma_dev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
/* function callback */
dma_dev->device_tx_status = phytium_ddma_tx_status;
dma_dev->device_issue_pending = phytium_ddma_issue_pending;
dma_dev->device_terminate_all = phytium_ddma_terminate_all;
dma_dev->device_alloc_chan_resources =
phytium_ddma_alloc_chan_resources;
dma_dev->device_free_chan_resources = phytium_ddma_free_chan_resources;
dma_dev->device_config = phytium_ddma_slave_config;
dma_dev->device_prep_slave_sg = phytium_ddma_prep_slave_sg;
dma_dev->device_pause = phytium_chan_pause;
dma_dev->device_resume = phytium_chan_resume;
/* init dma physical channels */
INIT_LIST_HEAD(&dma_dev->channels);
ddma->chan = devm_kcalloc(ddma->dev, ddma->dma_channels,
sizeof(*ddma->chan), GFP_KERNEL);
if (!ddma->chan) {
ret = -ENOMEM;
goto out;
}
for (i = 0; i < ddma->dma_channels; i++) {
ddma->chan[i].id = i;
ddma->chan[i].buf = NULL;
ddma->chan[i].base = ddma->base + DMA_REG_LEN +
i * CHAN_REG_LEN;
ddma->chan[i].vchan.desc_free = phytium_ddma_vdesc_free;
ddma->chan[i].desc = NULL;
ddma->chan[i].current_sg = NULL;
vchan_init(&ddma->chan[i].vchan, dma_dev);
}
phytium_dma_hw_init(ddma);
ret = dma_async_device_register(dma_dev);
if (ret)
goto out;
ret = of_dma_controller_register(pdev->dev.of_node,
phytium_ddma_of_xlate, ddma);
if (ret < 0) {
dev_err(&pdev->dev,
"phytium ddma of register failed %d\n", ret);
goto err_unregister;
}
platform_set_drvdata(pdev, ddma);
dev_info(ddma->dev, "phytium DDMA Controller registered\n");
return 0;
err_unregister:
dma_async_device_unregister(dma_dev);
out:
return ret;
}
static void phytium_ddma_chan_remove(struct phytium_ddma_chan *chan)
{
phytium_chan_irq_disable(chan);
phytium_chan_disable(chan);
if (chan->buf)
dma_free_coherent(chan_to_dev(chan), 4 * PAGE_SIZE, chan->buf,
chan->paddr);
tasklet_kill(&chan->vchan.task);
list_del(&chan->vchan.chan.device_node);
}
static int phytium_ddma_remove(struct platform_device *pdev)
{
struct phytium_ddma_device *ddma = platform_get_drvdata(pdev);
struct phytium_ddma_chan *chan = NULL;
int i = 0;
of_dma_controller_free(pdev->dev.of_node);
dma_async_device_unregister(&ddma->dma_dev);
for (i = 0; i < ddma->dma_channels; i++) {
chan = &ddma->chan[i];
phytium_ddma_chan_remove(chan);
}
phytium_ddma_irq_disable(ddma);
phytium_ddma_disable(ddma);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int phytium_ddma_suspend(struct device *dev)
{
struct phytium_ddma_device *ddma = dev_get_drvdata(dev);
int i = 0;
for (i = 0; i < ddma->dma_channels; i++) {
if (phytium_chan_is_running(&ddma->chan[i])) {
dev_warn(dev,
"suspend is prevented by channel %d\n", i);
return -EBUSY;
}
}
ddma->dma_reg.dma_chal_cfg0 =
phytium_ddma_ioread32(ddma, DMA_CHAL_CFG_L);
ddma->dma_reg.dma_chal_bind =
phytium_ddma_ioread32(ddma, DMA_CHAL_BIND);
ddma->dma_reg.dma_chal_cfg1 =
phytium_ddma_ioread32(ddma, DMA_CHAL_CFG_H);
for (i = 0; i < ddma->dma_channels; i++) {
struct phytium_ddma_chan *chan = &ddma->chan[i];
if (!chan->is_used)
continue;
ddma->dma_chal_reg[i].dma_chalx_ctl =
phytium_chan_ioread32(chan, DMA_CHALX_CTL);
ddma->dma_chal_reg[i].dma_chalx_timeout_cnt =
phytium_chan_ioread32(chan, DMA_CHALX_TIMEOUT_CNT);
}
phytium_ddma_irq_disable(ddma);
phytium_ddma_disable(ddma);
pm_runtime_force_suspend(dev);
return 0;
}
static int phytium_ddma_resume(struct device *dev)
{
struct phytium_ddma_device *ddma = dev_get_drvdata(dev);
u32 i = 0;
int ret = 0;
phytium_dma_hw_init(ddma);
phytium_ddma_iowrite32(ddma, DMA_CHAL_CFG_L,
ddma->dma_reg.dma_chal_cfg0);
phytium_ddma_iowrite32(ddma, DMA_CHAL_BIND,
ddma->dma_reg.dma_chal_bind);
phytium_ddma_iowrite32(ddma, DMA_CHAL_CFG_H,
ddma->dma_reg.dma_chal_cfg1);
for (i = 0; i < ddma->dma_channels; i++) {
struct phytium_ddma_chan *chan = &ddma->chan[i];
if (!chan->is_used)
continue;
phytium_chan_iowrite32(chan, DMA_CHALX_CTL,
ddma->dma_chal_reg[i].dma_chalx_ctl);
phytium_chan_iowrite32(chan, DMA_CHALX_TIMEOUT_CNT,
ddma->dma_chal_reg[i].dma_chalx_timeout_cnt);
}
ret = pm_runtime_force_resume(dev);
return ret;
}
#endif
static const struct dev_pm_ops phytium_ddma_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(phytium_ddma_suspend,
phytium_ddma_resume)
};
static const struct of_device_id phytium_dma_of_id_table[] = {
{ .compatible = "phytium,ddma" },
{}
};
MODULE_DEVICE_TABLE(of, phytium_dma_of_id_table);
static struct platform_driver phytium_driver = {
.probe = phytium_ddma_probe,
.remove = phytium_ddma_remove,
.driver = {
.name = "phytium-ddma",
.of_match_table = of_match_ptr(phytium_dma_of_id_table),
.pm = &phytium_ddma_pm_ops,
},
};
module_platform_driver(phytium_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Phytium DDMA Controller platform driver");
MODULE_AUTHOR("HuangJie <huangjie1663@phytium.com.cn>");

View File

@ -0,0 +1,164 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Phytium Device DDMA Controller driver.
*
* Copyright (c) 2023 Phytium Technology Co., Ltd.
*/
#ifndef _PHYTIUM_DDMAC_H
#define _PHYTIUM_DDMAC_H
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
#include "../virt-dma.h"
/* the number of physical channel */
#define DDMA_MAX_NR_PCHANNELS 8
#define DMAC_MAX_MASTERS 1
#define DMAC_MAX_BLK_SIZE PAGE_SIZE
#define CHAN_REG_LEN 0x40
#define DMA_REG_LEN 0x40
#define DMA_CTL 0x00
#define DMA_CHAL_CFG_L 0x04
#define DMA_CHAL_CFG_H 0x28
#define DMA_STAT 0x08
#define DMA_MASK_INT 0x0C
#define DMA_CHAL_BIND 0x20
#define DMA_GCAP 0x24
#define DMA_CHALX_DDR_UPADDR 0x00
#define DMA_CHALX_DDR_LWADDR 0x04
#define DMA_CHALX_DEV_ADDR 0x08
#define DMA_CHALX_TS 0x0C
#define DMA_CHALX_CRT_UPADDR 0x10
#define DMA_CHALX_CRT_LWADDR 0x14
#define DMA_CHALX_CTL 0x18
#define DMA_CHALX_STS 0x1C
#define DMA_CHALX_TIMEOUT_CNT 0x20
#define DMA_CHALX_TRANS_CNT 0x24
#define DMA_CTL_EN BIT(0)
#define DMA_CTL_SRST BIT(1)
#define DMA_CHAL_SEL(id, x) (min_t(unsigned int, x, 0x7F) << ((id) * 8))
#define DMA_CHAL_SEL_EN(id) BIT((id) * 8 + 7)
#define DMA_STAT_CHAL(id) BIT((id) * 4)
#define DMA_INT_EN BIT(31)
#define DMA_INT_CHAL_EN(id) BIT(id)
#define DMA_CHAL_EN BIT(0)
#define DMA_CHAL_SRST BIT(1)
#define DMA_CHAL_MODE BIT(2)
#define DMA_RX_REQ 1
#define DMA_TX_REQ 0
#define DMA_CHAL_TIMEOUT_EN BIT(31)
#define DMA_CHAL_TIMEOUT_CNT(x) min_t(unsigned int, x, 0xFFFFF)
#define DMA_TIMEOUT 10
/**
* struct phytium_ddma_sg_req - scatter-gatter list data info
* @len: number of bytes to transform
* @mem_addr_l: bus address low 32bit
* @mem_addr_h: bus address high 32bit
* @dev_addr: dma cousumer data reg addr
* @direction: dma transmit direction
*/
struct phytium_ddma_sg_req {
u32 len;
u32 mem_addr_l;
u32 mem_addr_h;
u32 dev_addr;
enum dma_transfer_direction direction;
};
/**
* struct phytium_ddma_desc - the struct holding info describing ddma request
* descriptor
* @vdesc: ddma request descriptor
* @num_sgs: the size of scatter-gatter list
* @sg_req: use to save scatter-gatter list info
*/
struct phytium_ddma_desc {
struct virt_dma_desc vdesc;
u32 num_sgs;
struct phytium_ddma_sg_req sg_req[];
};
/**
* struct phytium_ddma_chan - the struct holding info describing dma channel
* @vchan: virtual dma channel
* @base: the mapped register I/O of dma physical channel
* @id: the id of ddma physical channel
* @request_line: the request line of ddma channel
* @desc: the transform request descriptor
* @dma_config: config parameters for dma channel
* @busy: the channel busy flag, this flag set when channel is tansferring
* @is_used: the channel bind flag, this flag set when channel binded
* @next_sg: the index of next scatter-gatter
* @current_sg: use to save the current transfer scatter-gatter info
* @paddr: use to align data between dma provider and consumer
*/
struct phytium_ddma_chan {
struct virt_dma_chan vchan;
void __iomem *base;
u32 id;
u32 request_line;
struct phytium_ddma_desc *desc;
struct dma_slave_config dma_config;
bool busy;
bool is_used;
bool is_pasued;
u32 next_sg;
struct phytium_ddma_sg_req *current_sg;
dma_addr_t paddr;
char *buf;
};
struct global_reg {
u32 dma_chal_cfg0;
u32 dma_chal_bind;
u32 dma_chal_cfg1;
};
struct channel_reg {
u32 dma_chalx_ctl;
u32 dma_chalx_timeout_cnt;
};
/**
* struct phytium_ddma_device - the struct holding info describing DDMA device
* @dma_dev: an instance for struct dma_device
* @irq: the irq that DDMA using
* @base: the mapped register I/O base of this DDMA
* @core_clk: DDMA clock
* @dma_channels: the number of DDMA physical channels
* @chan: the phyical channels of DDMA
* @lock: spinlock to lock when set global registers
* @dma_reg: store global register value which need recover after resume
* @dma_chal_reg: store channel register value which need recover after resume
*/
struct phytium_ddma_device {
struct dma_device dma_dev;
struct device *dev;
int irq;
void __iomem *base;
struct clk *core_clk;
u32 dma_channels;
struct phytium_ddma_chan *chan;
spinlock_t lock;
struct global_reg dma_reg;
struct channel_reg dma_chal_reg[DDMA_MAX_NR_PCHANNELS];
};
#endif /* _PHYTIUM_DDMAC_H */

View File

@ -0,0 +1,485 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Phytium Pe220x EDAC (error detection and correction)
*
* Copyright (c) 2023 Phytium Technology Co., Ltd.
*/
#include <linux/ctype.h>
#include <linux/edac.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <ras/ras_event.h>
#include <linux/uaccess.h>
#include "edac_module.h"
#define EDAC_MOD_STR "phytium_edac"
/* register offset */
#define ERR_STATUS(n) (0x10 + ((n) * 64))
#define ERR_CTLR(n) (0x08 + ((n) * 64))
#define ERR_MISC0(n) (0x20 + ((n) * 64))
#define ERR_INJECT 0x7C
#define ERR_DEVID 0xFC8
#define ERR_GSR 0xE00
#define CTLR_ED BIT(0)
#define CTLR_UI BIT(2)
#define CTLR_CFI BIT(8)
#define MISC0_CEC(x) ((u64)(x) << 32)
#define ERR_STATUS_CLEAR GENMASK(31, 0)
#define CORRECTED_ERROR 0
#define UNCORRECTED_ERROR 1
#define MAX_ERR_GROUP 3
struct phytium_edac {
struct device *dev;
void __iomem **ras_base;
struct dentry *dfs;
struct edac_device_ctl_info *edac_dev;
};
struct ras_error_info {
u32 index;
u32 error_type;
const char *error_str;
};
/* error severity definition */
enum {
SEV_NO = 0x0,
SEV_CORRECTED = 0x1,
SEV_RECOVERABLE = 0x2,
SEV_PANIC = 0x3,
};
/* soc error record */
static const struct ras_error_info pe220x_ras_soc_error[] = {
{ 0, UNCORRECTED_ERROR, "lsd_nfc_ras_error" },
{ 1, UNCORRECTED_ERROR, "lsd_lpc_ras_long_wait_to" },
{ 2, UNCORRECTED_ERROR, "lsd_lpc_ras_short_wait_to" },
{ 3, UNCORRECTED_ERROR, "lsd_lpc_ras_sync_err" },
{ 4, UNCORRECTED_ERROR, "lsd_lbc_ras_err" },
{ 5, UNCORRECTED_ERROR, "usb3_err_0" },
{ 6, UNCORRECTED_ERROR, "usb3_err_1" },
{ 7, UNCORRECTED_ERROR, "gsd_gmu_mac0_asf_nonfatal_int" },
{ 8, UNCORRECTED_ERROR, "gsd_gmu_mac0_asf_fatal_int" },
{ 9, UNCORRECTED_ERROR, "gsd_gmu_mac0_asf_trans_to_err" },
{ 10, UNCORRECTED_ERROR, "gsd_gmu_mac0_asf_protocol_err" },
{ 11, UNCORRECTED_ERROR, "gsd_gmu_mac1_asf_nonfatal_int" },
{ 12, UNCORRECTED_ERROR, "gsd_gmu_mac1_asf_fatal_int" },
{ 13, UNCORRECTED_ERROR, "gsd_gmu_mac1_asf_trans_to_err" },
{ 14, UNCORRECTED_ERROR, "gsd_gmu_mac1_asf_protocol_err" },
{ 15, UNCORRECTED_ERROR, "gsd_gmu_mac2_asf_nonfatal_int" },
{ 16, UNCORRECTED_ERROR, "gsd_gmu_mac2_asf_fatal_int" },
{ 17, UNCORRECTED_ERROR, "gsd_gmu_mac2_asf_trans_to_err" },
{ 18, UNCORRECTED_ERROR, "gsd_gmu_mac2_asf_protocol_err" },
{ 19, UNCORRECTED_ERROR, "gsd_gmu_mac3_asf_nonfatal_int" },
{ 20, UNCORRECTED_ERROR, "gsd_gmu_mac3_asf_fatal_int" },
{ 21, UNCORRECTED_ERROR, "gsd_gmu_mac3_asf_trans_to_err" },
{ 22, UNCORRECTED_ERROR, "gsd_gmu_mac3_asf_protocol_err" },
{ 23, CORRECTED_ERROR, "dmu_ras_ecc_corrected_error" },
{ 24, UNCORRECTED_ERROR, "dmu_ras_ecc_uncorrected_error" },
{ 25, UNCORRECTED_ERROR, "cci_ras_nERRIRQ" },
{ 26, UNCORRECTED_ERROR, "smmu_tcu_ras_irpt" },
{ 27, UNCORRECTED_ERROR, "smmu_tbu0_ras_irpt" },
{ 28, UNCORRECTED_ERROR, "smmu_tbu1_ras_irpt" },
{ 29, UNCORRECTED_ERROR, "smmu_tbu2_ras_irpt" },
{ 30, UNCORRECTED_ERROR, "ocm_sram_ue" },
{ 31, CORRECTED_ERROR, "ocm_sram_ce" },
{ 32, UNCORRECTED_ERROR, "int_axim_err" },
{ 33, UNCORRECTED_ERROR, "int_fatal_error" },
{ 34, UNCORRECTED_ERROR, "nEXTERRIRQ_clust0" },
{ 35, UNCORRECTED_ERROR, "nINTERRIRQ_clust0" },
{ 36, UNCORRECTED_ERROR, "nEXTERRIRQ_clust1" },
{ 37, UNCORRECTED_ERROR, "nINTERRIRQ_clust1" },
{ 38, UNCORRECTED_ERROR, "nEXTERRIRQ_clust2" },
{ 39, UNCORRECTED_ERROR, "nINTERRIRQ_clust2" },
{ 40, UNCORRECTED_ERROR, "ams_ame0_ras_err" },
{ 41, UNCORRECTED_ERROR, "ams_ame1_ras_err" },
{ 42, UNCORRECTED_ERROR, "ams_amer_ras_err" },
{ 43, UNCORRECTED_ERROR, "ras_err_ame1" },
};
/* pcie controller error record */
static const struct ras_error_info pe220x_ras_peu_psu_error[] = {
{ 0, CORRECTED_ERROR, "pio_rd_addr_error" },
{ 1, UNCORRECTED_ERROR, "pio_wr_addr_error" },
{ 2, CORRECTED_ERROR, "pio_rd_timeout" },
{ 3, CORRECTED_ERROR, "pio_wr_timeout" },
{ 4, CORRECTED_ERROR, "axi_b_rsp_error" },
{ 5, CORRECTED_ERROR, "axi_r_rsp_error" },
};
static const struct ras_error_info pe220x_ras_peu_error[] = {
{ 0, CORRECTED_ERROR, "pio_rd_addr_error" },
{ 1, UNCORRECTED_ERROR, "pio_wr_addr_error" },
{ 2, CORRECTED_ERROR, "pio_rd_timeout" },
{ 3, CORRECTED_ERROR, "pio_wr_timeout" },
{ 4, CORRECTED_ERROR, "axi_b_rsp_error" },
{ 5, CORRECTED_ERROR, "axi_r_rsp_error" },
};
static const struct ras_error_info *pe220x_ras_error[] = {
pe220x_ras_soc_error, pe220x_ras_peu_psu_error, pe220x_ras_peu_error
};
static inline unsigned int get_error_num(const struct phytium_edac *edac,
int err_group)
{
unsigned int error_num = 0;
error_num = readl(edac->ras_base[err_group] + ERR_DEVID);
return error_num;
}
static inline void phytium_ras_setup(const struct phytium_edac *edac)
{
u64 val = 0;
unsigned int i = 0;
/*
* enable error report and generate interrupt for corrected error event
* first error record owned by node present the node configuration
*/
for (i = 0; i < MAX_ERR_GROUP; i++) {
val = readq(edac->ras_base[i] + ERR_CTLR(0));
val |= CTLR_ED | CTLR_UI | CTLR_CFI;
writeq(val, edac->ras_base[i] + ERR_CTLR(0));
}
}
static ssize_t phytium_edac_inject_ctrl_write(struct file *filp,
const char __user *buf,
size_t size, loff_t *ppos)
{
int ret = 0;
int res = 0;
unsigned int error_group = 0;
unsigned int error_id = 0;
unsigned int error_num = 0;
struct phytium_edac *edac = filp->private_data;
char str[255];
char *p_str = str;
char *tmp = NULL;
if (size > 255) {
ret = -EFAULT;
goto out;
}
if (copy_from_user(str, buf, size)) {
ret = -EFAULT;
goto out;
} else {
*ppos += size;
ret = size;
}
str[size] = '\0';
tmp = strsep(&p_str, ",");
if (!tmp)
goto out;
res = kstrtouint(tmp, 0, &error_group);
if (res || error_group >= MAX_ERR_GROUP) {
dev_err(edac->dev, "invalid error group parameters");
goto out;
}
res = kstrtouint(p_str, 0, &error_id);
if (res) {
dev_err(edac->dev, "invalid error id parameters");
goto out;
}
error_num = get_error_num(edac, error_group);
if (error_id >= error_num) {
dev_err(edac->dev, "invalid ras error id.\n");
goto out;
}
dev_dbg(edac->dev, "inject group%d, error_id: %d\n",
error_group, error_id);
if (pe220x_ras_error[error_group][error_id].error_type ==
CORRECTED_ERROR) {
writeq(MISC0_CEC(0xFF),
edac->ras_base[error_group] + ERR_MISC0(error_id));
}
writel(error_id, edac->ras_base[error_group] + ERR_INJECT);
out:
return ret;
}
static const struct file_operations phytium_edac_debug_inject_fops[] = {
{
.open = simple_open,
.write = phytium_edac_inject_ctrl_write,
.llseek = generic_file_llseek, },
{ }
};
static void phytium_edac_create_debugfs_nodes(struct phytium_edac *edac)
{
if (!IS_ENABLED(CONFIG_EDAC_DEBUG) || !edac->dfs) {
dev_info(edac->dev, "edac debug is disable");
return;
}
edac_debugfs_create_file("error_inject_ctrl", S_IWUSR, edac->dfs, edac,
&phytium_edac_debug_inject_fops[0]);
}
static int phytium_edac_device_add(struct phytium_edac *edac)
{
struct edac_device_ctl_info *edac_dev;
int res = 0;
edac_dev = edac_device_alloc_ctl_info(
sizeof(struct edac_device_ctl_info),
"ras", 1, "soc", 1, 0, NULL,
0, edac_device_alloc_index());
if (!edac_dev)
res = -ENOMEM;
edac_dev->dev = edac->dev;
edac_dev->mod_name = EDAC_MOD_STR;
edac_dev->ctl_name = "phytium ras";
edac_dev->dev_name = "soc";
phytium_edac_create_debugfs_nodes(edac);
res = edac_device_add_device(edac_dev);
if (res > 0) {
dev_err(edac->dev, "edac_device_add_device failed\n");
goto err_free;
}
edac->edac_dev = edac_dev;
dev_info(edac->dev, "phytium edac device registered\n");
return 0;
err_free:
edac_device_free_ctl_info(edac_dev);
return res;
}
static int phytium_edac_device_remove(struct phytium_edac *edac)
{
struct edac_device_ctl_info *edac_dev = edac->edac_dev;
debugfs_remove_recursive(edac->dfs);
edac_device_del_device(edac_dev->dev);
edac_device_free_ctl_info(edac_dev);
return 0;
}
static int get_error_id(struct phytium_edac *edac, int *error_id,
int *error_group)
{
unsigned int error_num = 0;
u64 error_bit = 0;
int ret = 0;
int i = 0;
int err_id = 0;
/* Iterate over the ras node to check error status */
for (i = 0; i < MAX_ERR_GROUP; i++) {
error_num = get_error_num(edac, i);
error_bit = readq(edac->ras_base[i] + ERR_GSR);
for (err_id = 0; err_id < error_num; err_id++) {
if (!(error_bit & BIT(err_id)))
continue;
else
break;
}
if (err_id < error_num) {
*error_id = err_id;
*error_group = i;
break;
}
}
if (i >= MAX_ERR_GROUP) {
ret = -1;
dev_warn(edac->dev, "no error detect.\n");
}
return ret;
}
static void phytium_edac_error_report(struct phytium_edac *edac,
const int error_id,
const int error_group)
{
const struct ras_error_info *err_info =
pe220x_ras_error[error_group];
if (err_info[error_id].error_type == UNCORRECTED_ERROR) {
edac_printk(KERN_CRIT, EDAC_MOD_STR, "uncorrected error: %s\n",
err_info[error_id].error_str);
edac_device_handle_ue(edac->edac_dev, 0, 0,
err_info[error_id].error_str);
/* Report the error via the trace interface */
if (IS_ENABLED(CONFIG_RAS))
trace_non_standard_event(&NULL_UUID_LE, &NULL_UUID_LE,
EDAC_MOD_STR, SEV_RECOVERABLE,
err_info[error_id].error_str,
strlen(err_info[error_id].error_str));
} else {
edac_printk(KERN_CRIT, EDAC_MOD_STR, "corrected error: %s\n",
err_info[error_id].error_str);
edac_device_handle_ce(edac->edac_dev, 0, 0,
err_info[error_id].error_str);
/* Report the error via the trace interface */
if (IS_ENABLED(CONFIG_RAS))
trace_non_standard_event(&NULL_UUID_LE, &NULL_UUID_LE,
EDAC_MOD_STR, SEV_CORRECTED,
err_info[error_id].error_str,
strlen(err_info[error_id].error_str));
}
}
/*
* clear error status and set correct error counter to 0xFE for trigger
* interrupt when next correct error event
*/
static void phytium_edac_clear_error_status(struct phytium_edac *edac,
const int error_id,
const int error_group)
{
writeq(MISC0_CEC(0XFE), edac->ras_base[error_group] +
ERR_MISC0(error_id));
writeq(GENMASK(31, 0), edac->ras_base[error_group] +
ERR_STATUS(error_id));
}
static irqreturn_t phytium_edac_isr(int irq, void *dev_id)
{
struct phytium_edac *edac = dev_id;
int ret = 0;
int error_group;
int error_id;
ret = get_error_id(edac, &error_id, &error_group);
if (ret < 0)
goto out;
phytium_edac_error_report(edac, error_id, error_group);
phytium_edac_clear_error_status(edac, error_id, error_group);
out:
return IRQ_HANDLED;
}
static int phytium_edac_probe(struct platform_device *pdev)
{
struct phytium_edac *edac;
struct resource *res;
int ret = 0;
int irq_cnt = 0;
int irq = 0;
int i = 0;
edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
if (!edac) {
ret = -ENOMEM;
goto out;
}
edac->dev = &pdev->dev;
platform_set_drvdata(pdev, edac);
edac->ras_base = devm_kcalloc(&pdev->dev, 3,
sizeof(*edac->ras_base), GFP_KERNEL);
if (!edac->ras_base) {
return -ENOMEM;
goto out;
}
for (i = 0; i < MAX_ERR_GROUP; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
edac->ras_base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(edac->ras_base[i])) {
dev_err(&pdev->dev, "no resource address\n");
ret = PTR_ERR(edac->ras_base[i]);
goto out;
}
}
edac->dfs = edac_debugfs_create_dir(EDAC_MOD_STR);
ret = phytium_edac_device_add(edac);
if (ret) {
dev_err(&pdev->dev, "can't add edac device");
goto out;
}
phytium_ras_setup(edac);
irq_cnt = platform_irq_count(pdev);
if (irq_cnt < 0) {
dev_err(&pdev->dev, "no irq resource\n");
ret = -EINVAL;
goto out;
}
for (i = 0; i < irq_cnt; i++) {
irq = platform_get_irq(pdev, i);
if (irq < 0) {
dev_err(&pdev->dev, "invalid irq resource\n");
ret = -EINVAL;
goto out;
}
ret = devm_request_irq(&pdev->dev, irq,
phytium_edac_isr, IRQF_SHARED,
EDAC_MOD_STR, edac);
if (ret) {
dev_err(&pdev->dev,
"could not request irq %d\n", irq);
goto out;
}
}
out:
return ret;
}
static int phytium_edac_remove(struct platform_device *pdev)
{
struct phytium_edac *edac = dev_get_drvdata(&pdev->dev);
phytium_edac_device_remove(edac);
return 0;
}
static const struct of_device_id phytium_edac_of_match[] = {
{ .compatible = "phytium,pe220x-edac" },
{},
};
MODULE_DEVICE_TABLE(of, phytium_edac_of_match);
static struct platform_driver phytium_edac_driver = {
.probe = phytium_edac_probe,
.remove = phytium_edac_remove,
.driver = {
.name = "phytium-edac",
.of_match_table = phytium_edac_of_match,
},
};
module_platform_driver(phytium_edac_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Huangjie <huangjie1663@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium Pe220x EDAC driver");

View File

@ -0,0 +1,363 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019-2023 Phytium Technology Co., Ltd.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include "gpio-phytium-core.h"
static int get_pin_location(struct phytium_gpio *gpio, unsigned int offset,
struct pin_loc *pl)
{
int ret;
if (offset < gpio->ngpio[0]) {
pl->port = 0;
pl->offset = offset;
ret = 0;
} else if (offset < (gpio->ngpio[0] + gpio->ngpio[1])) {
pl->port = 1;
pl->offset = offset - gpio->ngpio[0];
ret = 0;
} else {
ret = -EINVAL;
}
return ret;
}
static void phytium_gpio_toggle_trigger(struct phytium_gpio *gpio,
unsigned int offset)
{
struct gpio_chip *gc;
u32 pol;
int val;
/* Only port A can provide interrupt source */
if (offset >= gpio->ngpio[0])
return;
gc = &gpio->gc;
pol = readl(gpio->regs + GPIO_INT_POLARITY);
/* Just read the current value right out of the data register */
val = gc->get(gc, offset);
if (val)
pol &= ~BIT(offset);
else
pol |= BIT(offset);
writel(pol, gpio->regs + GPIO_INT_POLARITY);
}
int phytium_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct pin_loc loc;
void __iomem *dat;
if (get_pin_location(gpio, offset, &loc))
return -EINVAL;
dat = gpio->regs + GPIO_EXT_PORTA + (loc.port * GPIO_PORT_STRIDE);
return !!(readl(dat) & BIT(loc.offset));
}
EXPORT_SYMBOL_GPL(phytium_gpio_get);
void phytium_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct pin_loc loc;
void __iomem *dr;
unsigned long flags;
u32 mask;
if (get_pin_location(gpio, offset, &loc))
return;
dr = gpio->regs + GPIO_SWPORTA_DR + (loc.port * GPIO_PORT_STRIDE);
raw_spin_lock_irqsave(&gpio->lock, flags);
if (value)
mask = readl(dr) | BIT(loc.offset);
else
mask = readl(dr) & ~BIT(loc.offset);
writel(mask, dr);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
EXPORT_SYMBOL_GPL(phytium_gpio_set);
int phytium_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
{
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct pin_loc loc;
unsigned long flags;
void __iomem *ddr;
if (get_pin_location(gpio, offset, &loc))
return -EINVAL;
ddr = gpio->regs + GPIO_SWPORTA_DDR + (loc.port * GPIO_PORT_STRIDE);
raw_spin_lock_irqsave(&gpio->lock, flags);
writel(readl(ddr) & ~(BIT(loc.offset)), ddr);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(phytium_gpio_direction_input);
int phytium_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
int value)
{
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct pin_loc loc;
unsigned long flags;
void __iomem *ddr;
if (get_pin_location(gpio, offset, &loc))
return -EINVAL;
ddr = gpio->regs + GPIO_SWPORTA_DDR + (loc.port * GPIO_PORT_STRIDE);
raw_spin_lock_irqsave(&gpio->lock, flags);
writel(readl(ddr) | BIT(loc.offset), ddr);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
phytium_gpio_set(gc, offset, value);
return 0;
}
EXPORT_SYMBOL_GPL(phytium_gpio_direction_output);
void phytium_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
u32 val = BIT(irqd_to_hwirq(d));
raw_spin_lock(&gpio->lock);
writel(val, gpio->regs + GPIO_PORTA_EOI);
raw_spin_unlock(&gpio->lock);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_ack);
void phytium_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
u32 val;
/* Only port A can provide interrupt source */
if (irqd_to_hwirq(d) >= gpio->ngpio[0])
return;
raw_spin_lock(&gpio->lock);
val = readl(gpio->regs + GPIO_INTMASK);
val |= BIT(irqd_to_hwirq(d));
writel(val, gpio->regs + GPIO_INTMASK);
raw_spin_unlock(&gpio->lock);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_mask);
void phytium_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
u32 val;
/* Only port A can provide interrupt source */
if (irqd_to_hwirq(d) >= gpio->ngpio[0])
return;
raw_spin_lock(&gpio->lock);
val = readl(gpio->regs + GPIO_INTMASK);
val &= ~BIT(irqd_to_hwirq(d));
writel(val, gpio->regs + GPIO_INTMASK);
raw_spin_unlock(&gpio->lock);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_unmask);
int phytium_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
int hwirq = irqd_to_hwirq(d);
unsigned long flags, lvl, pol;
if (hwirq < 0 || hwirq >= gpio->ngpio[0])
return -EINVAL;
if ((flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
(flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) {
dev_err(gc->parent,
"trying to configure line %d for both level and edge detection, choose one!\n",
hwirq);
return -EINVAL;
}
raw_spin_lock_irqsave(&gpio->lock, flags);
lvl = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
pol = readl(gpio->regs + GPIO_INT_POLARITY);
switch (flow_type) {
case IRQ_TYPE_EDGE_BOTH:
lvl |= BIT(hwirq);
phytium_gpio_toggle_trigger(gpio, hwirq);
irq_set_handler_locked(d, handle_edge_irq);
dev_dbg(gc->parent, "line %d: IRQ on both edges\n", hwirq);
break;
case IRQ_TYPE_EDGE_RISING:
lvl |= BIT(hwirq);
pol |= BIT(hwirq);
irq_set_handler_locked(d, handle_edge_irq);
dev_dbg(gc->parent, "line %d: IRQ on RISING edge\n", hwirq);
break;
case IRQ_TYPE_EDGE_FALLING:
lvl |= BIT(hwirq);
pol &= ~BIT(hwirq);
irq_set_handler_locked(d, handle_edge_irq);
dev_dbg(gc->parent, "line %d: IRQ on FALLING edge\n", hwirq);
break;
case IRQ_TYPE_LEVEL_HIGH:
lvl &= ~BIT(hwirq);
pol |= BIT(hwirq);
irq_set_handler_locked(d, handle_level_irq);
dev_dbg(gc->parent, "line %d: IRQ on HIGH level\n", hwirq);
break;
case IRQ_TYPE_LEVEL_LOW:
lvl &= ~BIT(hwirq);
pol &= ~BIT(hwirq);
irq_set_handler_locked(d, handle_level_irq);
dev_dbg(gc->parent, "line %d: IRQ on LOW level\n", hwirq);
break;
}
writel(lvl, gpio->regs + GPIO_INTTYPE_LEVEL);
if (flow_type != IRQ_TYPE_EDGE_BOTH)
writel(pol, gpio->regs + GPIO_INT_POLARITY);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_set_type);
void phytium_gpio_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
unsigned long flags;
u32 val;
/* Only port A can provide interrupt source */
if (irqd_to_hwirq(d) >= gpio->ngpio[0])
return;
raw_spin_lock_irqsave(&gpio->lock, flags);
val = readl(gpio->regs + GPIO_INTEN);
val |= BIT(irqd_to_hwirq(d));
writel(val, gpio->regs + GPIO_INTEN);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_enable);
void phytium_gpio_irq_disable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
unsigned long flags;
u32 val;
/* Only port A can provide interrupt source */
if (irqd_to_hwirq(d) >= gpio->ngpio[0])
return;
raw_spin_lock_irqsave(&gpio->lock, flags);
val = readl(gpio->regs + GPIO_INTEN);
val &= ~BIT(irqd_to_hwirq(d));
writel(val, gpio->regs + GPIO_INTEN);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_disable);
void phytium_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
unsigned long pending;
int offset;
chained_irq_enter(irqchip, desc);
pending = readl(gpio->regs + GPIO_INTSTATUS);
if (pending) {
for_each_set_bit(offset, &pending, gpio->ngpio[0]) {
int gpio_irq = irq_find_mapping(gc->irq.domain,
offset);
generic_handle_irq(gpio_irq);
if ((irq_get_trigger_type(gpio_irq) &
IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
phytium_gpio_toggle_trigger(gpio, offset);
}
}
chained_irq_exit(irqchip, desc);
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_handler);
int phytium_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
struct phytium_gpio *gpio = gpiochip_get_data(gc);
struct pin_loc loc;
void __iomem *ddr;
if (get_pin_location(gpio, offset, &loc))
return -EINVAL;
ddr = gpio->regs + GPIO_SWPORTA_DDR + (loc.port * GPIO_PORT_STRIDE);
return !(readl(ddr) & BIT(loc.offset));
}
EXPORT_SYMBOL_GPL(phytium_gpio_get_direction);
#if CONFIG_SMP
int
phytium_gpio_irq_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force)
{
struct gpio_chip *chip_data = irq_data_get_irq_chip_data(d);
struct irq_chip *chip = irq_get_chip(*(chip_data->irq.parents));
struct irq_data *data = irq_get_irq_data(*(chip_data->irq.parents));
if (chip && chip->irq_set_affinity)
return chip->irq_set_affinity(data, mask_val, force);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(phytium_gpio_irq_set_affinity);
#endif
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Phytium GPIO Controller core");

View File

@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef _GPIO_PHYTIUM_H
#define _GPIO_PHYTIUM_H
#include <linux/gpio/driver.h>
#include <linux/spinlock.h>
#include "gpiolib.h"
#define GPIO_SWPORTA_DR 0x00 /* WR Port A Output Data Register */
#define GPIO_SWPORTA_DDR 0x04 /* WR Port A Data Direction Register */
#define GPIO_EXT_PORTA 0x08 /* RO Port A Input Data Register */
#define GPIO_SWPORTB_DR 0x0c /* WR Port B Output Data Register */
#define GPIO_SWPORTB_DDR 0x10 /* WR Port B Data Direction Register */
#define GPIO_EXT_PORTB 0x14 /* RO Port B Input Data Register */
#define GPIO_INTEN 0x18 /* WR Port A Interrput Enable Register */
#define GPIO_INTMASK 0x1c /* WR Port A Interrupt Mask Register */
#define GPIO_INTTYPE_LEVEL 0x20 /* WR Port A Interrupt Level Register */
#define GPIO_INT_POLARITY 0x24 /* WR Port A Interrupt Polarity Register */
#define GPIO_INTSTATUS 0x28 /* RO Port A Interrupt Status Register */
#define GPIO_RAW_INTSTATUS 0x2c /* RO Port A Raw Interrupt Status Register */
#define GPIO_LS_SYNC 0x30 /* WR Level-sensitive Synchronization Enable Register */
#define GPIO_DEBOUNCE 0x34 /* WR Debounce Enable Register */
#define GPIO_PORTA_EOI 0x38 /* WO Port A Clear Interrupt Register */
#define MAX_NPORTS 2
#define NGPIO_DEFAULT 8
#define NGPIO_MAX 32
#define GPIO_PORT_STRIDE (GPIO_EXT_PORTB - GPIO_EXT_PORTA)
struct pin_loc {
unsigned int port;
unsigned int offset;
};
#ifdef CONFIG_PM_SLEEP
struct phytium_gpio_ctx {
u32 swporta_dr;
u32 swporta_ddr;
u32 ext_porta;
u32 swportb_dr;
u32 swportb_ddr;
u32 ext_portb;
u32 inten;
u32 intmask;
u32 inttype_level;
u32 int_polarity;
u32 intstatus;
u32 raw_intstatus;
u32 ls_sync;
u32 debounce;
};
#endif
struct phytium_gpio {
raw_spinlock_t lock;
void __iomem *regs;
struct gpio_chip gc;
struct irq_chip irq_chip;
unsigned int ngpio[2];
int irq[32];
#ifdef CONFIG_PM_SLEEP
struct phytium_gpio_ctx ctx;
#endif
};
int phytium_gpio_get(struct gpio_chip *gc, unsigned int offset);
void phytium_gpio_set(struct gpio_chip *gc, unsigned int offset, int value);
int phytium_gpio_get_direction(struct gpio_chip *gc, unsigned int offset);
int phytium_gpio_direction_input(struct gpio_chip *gc, unsigned int offset);
int phytium_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value);
void phytium_gpio_irq_ack(struct irq_data *d);
void phytium_gpio_irq_mask(struct irq_data *d);
void phytium_gpio_irq_unmask(struct irq_data *d);
int phytium_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type);
void phytium_gpio_irq_enable(struct irq_data *d);
void phytium_gpio_irq_disable(struct irq_data *d);
void phytium_gpio_irq_handler(struct irq_desc *desc);
int phytium_gpio_irq_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force);
#endif

View File

@ -0,0 +1,187 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "gpio-phytium-core.h"
static int phytium_gpio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
struct phytium_gpio *gpio;
struct gpio_irq_chip *girq;
int err;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
err = pcim_enable_device(pdev);
if (err) {
dev_err(dev, "Failed to enable PCI device: err %d\n", err);
goto out;
}
err = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
if (err) {
dev_err(dev, "Failed to iomap PCI device: err %d\n", err);
goto out;
}
gpio->regs = pcim_iomap_table(pdev)[0];
if (!gpio->regs) {
dev_err(dev, "Cannot map PCI resource\n");
err = -ENOMEM;
goto out;
}
err = pci_enable_msi(pdev);
if (err < 0)
goto out;
pci_set_master(pdev);
gpio->irq[0] = pdev->irq;
if (gpio->irq[0] < 0)
dev_warn(dev, "no irq is found.\n");
/* There is only one group of Pins at the moment. */
gpio->ngpio[0] = NGPIO_MAX;
/* irq_chip support */
gpio->irq_chip.name = dev_name(dev);
gpio->irq_chip.irq_ack = phytium_gpio_irq_ack;
gpio->irq_chip.irq_mask = phytium_gpio_irq_mask;
gpio->irq_chip.irq_unmask = phytium_gpio_irq_unmask;
gpio->irq_chip.irq_set_type = phytium_gpio_irq_set_type;
gpio->irq_chip.irq_enable = phytium_gpio_irq_enable;
gpio->irq_chip.irq_disable = phytium_gpio_irq_disable;
raw_spin_lock_init(&gpio->lock);
gpio->gc.base = -1;
gpio->gc.get_direction = phytium_gpio_get_direction;
gpio->gc.direction_input = phytium_gpio_direction_input;
gpio->gc.direction_output = phytium_gpio_direction_output;
gpio->gc.get = phytium_gpio_get;
gpio->gc.set = phytium_gpio_set;
gpio->gc.ngpio = gpio->ngpio[0] + gpio->ngpio[1];
gpio->gc.label = dev_name(dev);
gpio->gc.parent = dev;
gpio->gc.owner = THIS_MODULE;
girq = &gpio->gc.irq;
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents), GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = gpio->irq[0];
girq->parent_handler = phytium_gpio_irq_handler;
girq->chip = &gpio->irq_chip;
err = devm_gpiochip_add_data(dev, &gpio->gc, gpio);
if (err)
goto out;
dev_info(dev, "Phytium PCI GPIO controller @%pa registered\n",
&gpio->regs);
pci_set_drvdata(pdev, gpio);
out:
return err;
}
static const struct pci_device_id phytium_gpio_pci_ids[] = {
{ PCI_DEVICE(0x1DB7, 0xDC31) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, phytium_gpio_pci_ids);
#ifdef CONFIG_PM_SLEEP
static int phytium_gpio_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct phytium_gpio *gpio = pci_get_drvdata(pdev);
unsigned long flags;
raw_spin_lock_irqsave(&gpio->lock, flags);
gpio->ctx.swporta_dr = readl(gpio->regs + GPIO_SWPORTA_DR);
gpio->ctx.swporta_ddr = readl(gpio->regs + GPIO_SWPORTA_DDR);
gpio->ctx.ext_porta = readl(gpio->regs + GPIO_EXT_PORTA);
gpio->ctx.swportb_dr = readl(gpio->regs + GPIO_SWPORTB_DR);
gpio->ctx.swportb_ddr = readl(gpio->regs + GPIO_SWPORTB_DDR);
gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB);
gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN);
gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK);
gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY);
gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
static int phytium_gpio_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct phytium_gpio *gpio = pci_get_drvdata(pdev);
unsigned long flags;
raw_spin_lock_irqsave(&gpio->lock, flags);
writel(gpio->ctx.swporta_dr, gpio->regs + GPIO_SWPORTA_DR);
writel(gpio->ctx.swporta_ddr, gpio->regs + GPIO_SWPORTA_DDR);
writel(gpio->ctx.ext_porta, gpio->regs + GPIO_EXT_PORTA);
writel(gpio->ctx.swportb_dr, gpio->regs + GPIO_SWPORTB_DR);
writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR);
writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB);
writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN);
writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK);
writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL);
writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY);
writel(gpio->ctx.debounce, gpio->regs + GPIO_DEBOUNCE);
writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(phytium_gpio_pci_pm_ops,
phytium_gpio_pci_suspend,
phytium_gpio_pci_resume);
static struct pci_driver phytium_gpio_pci_driver = {
.name = "gpio-phytium-pci",
.id_table = phytium_gpio_pci_ids,
.probe = phytium_gpio_pci_probe,
.driver = {
.pm = &phytium_gpio_pci_pm_ops,
},
};
module_pci_driver(phytium_gpio_pci_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Cheng Quan <chengquan@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium GPIO PCI Driver");

View File

@ -0,0 +1,204 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Support functions for Phytium GPIO
*
* Copyright (c) 2019-2023 Phytium Technology Co., Ltd.
*
* Derived from drivers/gpio/gpio-pl061.c
* Copyright (C) 2008, 2009 Provigent Ltd.
*/
#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include "gpio-phytium-core.h"
static const struct of_device_id phytium_gpio_of_match[] = {
{ .compatible = "phytium,gpio", },
{ }
};
MODULE_DEVICE_TABLE(of, phytium_gpio_of_match);
static const struct acpi_device_id phytium_gpio_acpi_match[] = {
{ "PHYT0001", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, phytium_gpio_acpi_match);
static int phytium_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct phytium_gpio *gpio;
struct gpio_irq_chip *girq;
struct fwnode_handle *fwnode;
int err, irq_count;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
if (!device_get_child_node_count(dev))
return -ENODEV;
device_for_each_child_node(dev, fwnode) {
int idx;
if (fwnode_property_read_u32(fwnode, "reg", &idx) ||
idx >= MAX_NPORTS) {
dev_err(dev, "missing/invalid port index\n");
fwnode_handle_put(fwnode);
return -EINVAL;
}
if (fwnode_property_read_u32(fwnode, "ngpios", &gpio->ngpio[idx]) &&
fwnode_property_read_u32(fwnode, "nr-gpios", &gpio->ngpio[idx])) {
dev_info(dev,
"failed to get number of gpios for Port%c\n",
idx ? 'B' : 'A');
gpio->ngpio[idx] = NGPIO_DEFAULT;
}
}
/* irq_chip support */
gpio->irq_chip.name = dev_name(dev);
gpio->irq_chip.irq_ack = phytium_gpio_irq_ack;
gpio->irq_chip.irq_mask = phytium_gpio_irq_mask;
gpio->irq_chip.irq_unmask = phytium_gpio_irq_unmask;
gpio->irq_chip.irq_set_type = phytium_gpio_irq_set_type;
gpio->irq_chip.irq_enable = phytium_gpio_irq_enable;
gpio->irq_chip.irq_disable = phytium_gpio_irq_disable;
#ifdef CONFIG_SMP
/* TODO: use irq_chip_set_affinity_parent instead? */
gpio->irq_chip.irq_set_affinity = phytium_gpio_irq_set_affinity;
#endif
raw_spin_lock_init(&gpio->lock);
gpio->gc.base = -1;
gpio->gc.get_direction = phytium_gpio_get_direction;
gpio->gc.direction_input = phytium_gpio_direction_input;
gpio->gc.direction_output = phytium_gpio_direction_output;
gpio->gc.get = phytium_gpio_get;
gpio->gc.set = phytium_gpio_set;
gpio->gc.ngpio = gpio->ngpio[0] + gpio->ngpio[1];
gpio->gc.label = dev_name(dev);
gpio->gc.parent = dev;
gpio->gc.owner = THIS_MODULE;
girq = &gpio->gc.irq;
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
for (irq_count = 0; irq_count < platform_irq_count(pdev); irq_count++) {
gpio->irq[irq_count] = -ENXIO;
gpio->irq[irq_count] = platform_get_irq(pdev, irq_count);
if (gpio->irq[irq_count] < 0) {
//dev_warn(dev, "no irq is found.\n");
break;
}
};
girq->num_parents = irq_count;
girq->parents = gpio->irq;
girq->parent_handler = phytium_gpio_irq_handler;
girq->chip = &gpio->irq_chip;
err = devm_gpiochip_add_data(dev, &gpio->gc, gpio);
if (err)
return err;
platform_set_drvdata(pdev, gpio);
dev_info(dev, "Phytium GPIO controller @%pa registered\n",
&res->start);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int phytium_gpio_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct phytium_gpio *gpio = platform_get_drvdata(pdev);
unsigned long flags;
raw_spin_lock_irqsave(&gpio->lock, flags);
gpio->ctx.swporta_dr = readl(gpio->regs + GPIO_SWPORTA_DR);
gpio->ctx.swporta_ddr = readl(gpio->regs + GPIO_SWPORTA_DDR);
gpio->ctx.ext_porta = readl(gpio->regs + GPIO_EXT_PORTA);
gpio->ctx.swportb_dr = readl(gpio->regs + GPIO_SWPORTB_DR);
gpio->ctx.swportb_ddr = readl(gpio->regs + GPIO_SWPORTB_DDR);
gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB);
gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN);
gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK);
gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY);
gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
static int phytium_gpio_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct phytium_gpio *gpio = platform_get_drvdata(pdev);
unsigned long flags;
raw_spin_lock_irqsave(&gpio->lock, flags);
writel(gpio->ctx.swporta_dr, gpio->regs + GPIO_SWPORTA_DR);
writel(gpio->ctx.swporta_ddr, gpio->regs + GPIO_SWPORTA_DDR);
writel(gpio->ctx.ext_porta, gpio->regs + GPIO_EXT_PORTA);
writel(gpio->ctx.swportb_dr, gpio->regs + GPIO_SWPORTB_DR);
writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR);
writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB);
writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN);
writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK);
writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL);
writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY);
writel(gpio->ctx.debounce, gpio->regs + GPIO_DEBOUNCE);
writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(phytium_gpio_pm_ops, phytium_gpio_suspend,
phytium_gpio_resume);
static struct platform_driver phytium_gpio_driver = {
.driver = {
.name = "gpio-phytium-platform",
.pm = &phytium_gpio_pm_ops,
.of_match_table = of_match_ptr(phytium_gpio_of_match),
.acpi_match_table = ACPI_PTR(phytium_gpio_acpi_match),
},
.probe = phytium_gpio_probe,
};
module_platform_driver(phytium_gpio_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Chen Baozi <chenbaozi@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium GPIO driver");

View File

@ -0,0 +1,302 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium SGPIO Driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/gpio/driver.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#define SGPIO_CTL0_REG 0x00
#define SGPIO_CTL0_REG_ENABLE BIT(0)
#define SGPIO_CTL0_REG_RX_DISABLE BIT(1)
#define SGPIO_CTL0_REG_L3_L0 GENMASK(11, 8)
#define SGPIO_CTL0_REG_CLK_DIV_NUM GENMASK(31, 12)
#define SGPIO_CTL1_REG 0x04
#define SGPIO_CTL1_REG_READY BIT(0)
#define SGPIO_CTL1_REG_W_UPDATA BIT(1)
#define SGPIO_CTL1_REG_OP_MODE BIT(2)
#define SGPIO_CTL1_REG_OP_STATE BIT(3)
#define SGPIO_CTL1_REG_BIT_NUM GENMASK(14, 8)
#define SGPIO_CTL1_REG_INTERVAL_TIMER GENMASK(31, 16)
#define SGPIO_SOFT_RESET_REG 0x08
#define SGPIO_SOFT_RESET_REG_MASK BIT(0)
#define SGPIO_IRQ_REG 0x0c
#define SGPIO_IRQ_REG_MASK BIT(0)
#define SGPIO_IRQ_M_REG 0x10
#define SGPIO_IRQ_M_REG_MASK BIT(0)
#define SGPIO_WDATA0_REG 0x14
#define SGPIO_WDATA_REG(x) (SGPIO_WDATA0_REG + ((x) == 2 ? 3 : (x))* 4) // 0x14, 0x18, 0x20
#define SGPIO_RDATA0_REG 0x24
#define SGPIO_RDATA_REG(x) (SGPIO_RDATA0_REG + (x) * 4)
#define DEFAULT_L3_L0 0
#define GPIO_GROUP(x) ((x) >> 6)
#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
struct phytium_sgpio {
struct gpio_chip gc;
void __iomem *regs;
unsigned int ngpios;
struct clk *pclk;
struct mutex lock;
struct completion completion;
};
static bool phytium_sgpio_is_input(unsigned int offset)
{
return !(offset % 2);
}
static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
{
struct phytium_sgpio *gpio = gpiochip_get_data(gc);
u32 reg;
int rc = 0;
if (phytium_sgpio_is_input(offset))
return -EINVAL;
reinit_completion(&gpio->completion);
/*
* Since this is an output, read the cached value from rdata,
* then update value.
*/
/* cached data from wdata? */
reg = readl(gpio->regs + SGPIO_WDATA_REG(GPIO_GROUP(offset)));
if (val)
reg |= GPIO_BIT(offset);
else
reg &= GPIO_BIT(offset);
writel(reg, gpio->regs + SGPIO_WDATA_REG(GPIO_GROUP(offset)));
/* Start transmission and wait for completion */
writel(readl(gpio->regs + SGPIO_CTL1_REG) | SGPIO_CTL1_REG_W_UPDATA,
gpio->regs + SGPIO_CTL1_REG);
if (!wait_for_completion_timeout(&gpio->completion, msecs_to_jiffies(1000)))
rc = -EINVAL;
return rc;
}
static int phytium_sgpio_direction_input(struct gpio_chip *gc, unsigned int offset)
{
return phytium_sgpio_is_input(offset) ? 0 : -EINVAL;
}
static int phytium_sgpio_direction_output(struct gpio_chip *gc, unsigned int offset, int val)
{
struct phytium_sgpio *gpio = gpiochip_get_data(gc);
int rc;
mutex_lock(&gpio->lock);
/*
* No special action is required for setting the direction; we'll
* error-out in sgpio_set_value if this isn't an output GPIO
*/
rc = sgpio_set_value(&gpio->gc, offset, val);
mutex_unlock(&gpio->lock);
return rc;
}
static int phytium_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
return !!phytium_sgpio_is_input(offset);
}
static int phytium_sgpio_get(struct gpio_chip *gc, unsigned int offset)
{
struct phytium_sgpio *gpio = gpiochip_get_data(gc);
int rc = 0;
u32 val, ctl0;
mutex_lock(&gpio->lock);
if (!phytium_sgpio_is_input(offset)) {
val = readl(gpio->regs + SGPIO_WDATA_REG(GPIO_GROUP(offset)));
rc = !!(val & GPIO_BIT(offset));
mutex_unlock(&gpio->lock);
return rc;
}
reinit_completion(&gpio->completion);
/* Enable Rx */
ctl0 = readl(gpio->regs + SGPIO_CTL0_REG);
writel(ctl0 & ~SGPIO_CTL0_REG_RX_DISABLE, gpio->regs + SGPIO_CTL0_REG);
/* Start reading transaction and wait for completion */
writel(readl(gpio->regs + SGPIO_CTL1_REG) | SGPIO_CTL1_REG_W_UPDATA,
gpio->regs + SGPIO_CTL1_REG);
if (!wait_for_completion_timeout(&gpio->completion, msecs_to_jiffies(1000))) {
rc = -EINVAL;
goto err;
}
val = readl(gpio->regs + SGPIO_RDATA_REG(GPIO_GROUP(offset)));
rc = !!(val & GPIO_BIT(offset));
err:
/* Disalbe Rx to hold the value */
writel(ctl0 | SGPIO_CTL0_REG_RX_DISABLE, gpio->regs + SGPIO_CTL0_REG);
mutex_unlock(&gpio->lock);
return rc;
}
static void phytium_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
{
struct phytium_sgpio *gpio = gpiochip_get_data(gc);
mutex_lock(&gpio->lock);
sgpio_set_value(gc, offset, val);
mutex_unlock(&gpio->lock);
}
static irqreturn_t phytium_sgpio_irq_handler(int irq, void *data)
{
struct phytium_sgpio *gpio = data;
if (!readl(gpio->regs + SGPIO_IRQ_REG))
return IRQ_NONE;
/* Clear the interrupt */
writel(0, gpio->regs + SGPIO_IRQ_REG);
/* Check if tx/rx has been done */
if (!(readl(gpio->regs + SGPIO_CTL1_REG) & SGPIO_CTL1_REG_OP_STATE))
complete(&gpio->completion);
return IRQ_HANDLED;
}
static int phytium_sgpio_probe(struct platform_device *pdev)
{
u32 pclk_freq, sclk_freq, clk_div;
struct phytium_sgpio *gpio;
struct resource *res;
struct device *dev = &pdev->dev;
int rc;
gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gpio->regs))
return PTR_ERR(gpio->regs);
if (devm_request_irq(dev, platform_get_irq(pdev, 0),
phytium_sgpio_irq_handler,
IRQF_SHARED, dev_name(dev), gpio)) {
dev_err(dev, "failed to request IRQ\n");
return -ENOENT;
}
rc = fwnode_property_read_u32(dev_fwnode(dev), "ngpios", &gpio->ngpios);
if (rc < 0) {
dev_err(dev, "Could not read ngpios property\n");
return -EINVAL;
} else if (gpio->ngpios % 32) {
dev_err(&pdev->dev, "Number of GPIOs not multiple of 32: %d\n",
gpio->ngpios);
return -EINVAL;
}
rc = fwnode_property_read_u32(dev_fwnode(dev), "bus-frequency", &sclk_freq);
if (rc < 0) {
dev_err(dev, "Could not read bus-frequency property\n");
return -EINVAL;
}
gpio->pclk = devm_clk_get(dev, NULL);
if (IS_ERR(gpio->pclk)) {
dev_err(dev, "Could not get the APB clock property\n");
return PTR_ERR(gpio->pclk);
}
rc = clk_prepare_enable(gpio->pclk);
if (rc) {
dev_err(dev, "failed to enable pclk: %d\n", rc);
return rc;
}
pclk_freq = clk_get_rate(gpio->pclk);
/*
* From the datasheet:
* (pclk / 2) / (clk_div + 1) = sclk
*/
if (sclk_freq == 0) {
dev_err(dev, "SCLK should not be 0\n");
return -EINVAL;
}
clk_div = (pclk_freq / (sclk_freq * 2)) - 1;
if (clk_div > (1 << 20) - 1) {
dev_err(dev, "clk_div is overflow\n");
return -EINVAL;
}
writel(FIELD_PREP(SGPIO_CTL0_REG_CLK_DIV_NUM, clk_div) |
FIELD_PREP(SGPIO_CTL0_REG_L3_L0, DEFAULT_L3_L0) |
SGPIO_CTL0_REG_RX_DISABLE | SGPIO_CTL0_REG_ENABLE,
gpio->regs + SGPIO_CTL0_REG);
writel(FIELD_PREP(SGPIO_CTL1_REG_BIT_NUM, gpio->ngpios) |
SGPIO_CTL1_REG_READY, gpio->regs + SGPIO_CTL1_REG);
mutex_init(&gpio->lock);
init_completion(&gpio->completion);
platform_set_drvdata(pdev, gpio);
gpio->gc.parent = dev;
gpio->gc.base = -1;
gpio->gc.ngpio = gpio->ngpios * 2;
gpio->gc.label = dev_name(dev);
gpio->gc.direction_input = phytium_sgpio_direction_input;
gpio->gc.direction_output = phytium_sgpio_direction_output;
gpio->gc.get_direction = phytium_sgpio_get_direction;
gpio->gc.get = phytium_sgpio_get;
gpio->gc.set = phytium_sgpio_set;
return devm_gpiochip_add_data(dev, &gpio->gc, gpio);
}
static const struct of_device_id phytium_sgpio_of_match[] = {
{ .compatible = "phytium,sgpio", },
{ }
};
MODULE_DEVICE_TABLE(of, phytium_sgpio_of_match);
static struct platform_driver phytium_sgpio_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(phytium_sgpio_of_match),
},
.probe = phytium_sgpio_probe,
};
module_platform_driver(phytium_sgpio_driver);
MODULE_AUTHOR("Chen Baozi <chenbaozi@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium SGPIO driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,7 @@
config DRM_PHYTIUM
tristate "DRM Support for Phytium Graphics Card"
depends on DRM
select DRM_KMS_HELPER
help
Choose this option if you have a phytium graphics card.
This driver provides kernel mode setting and buffer management to userspace.

View File

@ -0,0 +1,18 @@
phytium-dc-drm-y := phytium_display_drv.o \
phytium_plane.o \
phytium_crtc.o \
phytium_dp.o \
phytium_fb.o \
phytium_gem.o \
phytium_fbdev.o \
phytium_debugfs.o \
px210_dp.o \
phytium_panel.o \
px210_dc.o \
phytium_pci.o \
pe220x_dp.o \
pe220x_dc.o \
phytium_platform.o
obj-$(CONFIG_DRM_PHYTIUM) += phytium-dc-drm.o
CFLAGS_REMOVE_phytium_crtc.o += -mgeneral-regs-only

View File

@ -0,0 +1,255 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium Pe220x display controller DRM driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <asm/neon.h>
#include <linux/delay.h>
#include "phytium_display_drv.h"
#include "pe220x_reg.h"
#include "phytium_crtc.h"
#include "phytium_plane.h"
#include "phytium_fb.h"
#include "phytium_gem.h"
void pe220x_dc_hw_disable(struct drm_crtc *crtc);
static const unsigned int pe220x_primary_formats[] = {
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_ABGR2101010,
DRM_FORMAT_RGBA1010102,
DRM_FORMAT_BGRA1010102,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ABGR4444,
DRM_FORMAT_RGBA4444,
DRM_FORMAT_BGRA4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_XBGR4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_BGRX4444,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_RGBA5551,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_XBGR1555,
DRM_FORMAT_RGBX5551,
DRM_FORMAT_BGRX5551,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR565,
DRM_FORMAT_YUYV,
DRM_FORMAT_UYVY,
DRM_FORMAT_NV16,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
};
static uint64_t pe220x_primary_formats_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static uint64_t pe220x_cursor_formats_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static const unsigned int pe220x_cursor_formats[] = {
DRM_FORMAT_ARGB8888,
};
void pe220x_dc_hw_vram_init(struct phytium_display_private *priv, resource_size_t vram_addr,
resource_size_t vram_size)
{
uint32_t config;
uint32_t group_offset = priv->address_transform_base;
phytium_writel_reg(priv, (vram_addr & SRC_ADDR_MASK) >> SRC_ADDR_OFFSET,
group_offset, PE220X_DC_ADDRESS_TRANSFORM_SRC_ADDR);
phytium_writel_reg(priv, (vram_size >> SIZE_OFFSET) | ADDRESS_TRANSFORM_ENABLE,
group_offset, PE220X_DC_ADDRESS_TRANSFORM_SIZE);
config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_DST_ADDR);
phytium_writel_reg(priv, config, group_offset, PE220X_DC_ADDRESS_TRANSFORM_DST_ADDR);
}
void pe220x_dc_hw_config_pix_clock(struct drm_crtc *crtc, int clock)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
int ret = 0;
/* config pix clock */
phytium_writel_reg(priv, FLAG_REQUEST | CMD_PIXEL_CLOCK | (clock & PIXEL_CLOCK_MASK),
0, PE220X_DC_CMD_REGISTER(phys_pipe));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(phys_pipe),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to set pixel clock\n", __func__);
}
void pe220x_dc_hw_reset(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int config = 0;
int phys_pipe = phytium_crtc->phys_pipe;
/* disable pixel clock for bmc mode */
if (phys_pipe == 0)
pe220x_dc_hw_disable(crtc);
config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
config &= (~(DC0_CORE_RESET | DC1_CORE_RESET | AXI_RESET | AHB_RESET));
if (phys_pipe == 0) {
phytium_writel_reg(priv, config | DC0_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET | AHB_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
} else {
phytium_writel_reg(priv, config | DC1_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET | AHB_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
}
}
void pe220x_dc_hw_disable(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int config = 0;
int phys_pipe = phytium_crtc->phys_pipe;
/* clear framebuffer */
phytium_writel_reg(priv, CLEAR_VALUE_BLACK, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CLEARVALUE);
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
config |= FRAMEBUFFER_CLEAR;
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
/* disable cursor */
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
config = ((config & (~CURSOR_FORMAT_MASK)) | CURSOR_FORMAT_DISABLED);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
mdelay(20);
/* reset pix clock */
pe220x_dc_hw_config_pix_clock(crtc, 0);
if (phys_pipe == 0) {
config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
phytium_writel_reg(priv, config | DC0_CORE_RESET, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config & (~DC0_CORE_RESET), 0, PE220X_DC_CLOCK_CONTROL);
} else {
config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
phytium_writel_reg(priv, config | DC1_CORE_RESET, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config & (~DC1_CORE_RESET), 0, PE220X_DC_CLOCK_CONTROL);
}
udelay(20);
}
int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, int count)
{
int ret = 0;
if (mode_cmd->modifier[count] != DRM_FORMAT_MOD_LINEAR) {
DRM_ERROR("unsupported fb modifier 0x%llx\n", mode_cmd->modifier[count]);
ret = -EINVAL;
}
return ret;
}
void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count)
{
*format_modifiers = pe220x_primary_formats_modifiers;
*formats = pe220x_primary_formats;
*format_count = ARRAY_SIZE(pe220x_primary_formats);
}
void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count)
{
*format_modifiers = pe220x_cursor_formats_modifiers;
*formats = pe220x_cursor_formats;
*format_count = ARRAY_SIZE(pe220x_cursor_formats);
}
void pe220x_dc_hw_update_primary_hi_addr(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
int phys_pipe = phytium_plane->phys_pipe;
phytium_writel_reg(priv, (phytium_plane->iova[0] >> PREFIX_SHIFT) & PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_Y_HI_ADDRESS);
phytium_writel_reg(priv, (phytium_plane->iova[1] >> U_PREFIX_SHIFT) & U_PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_U_HI_ADDRESS);
phytium_writel_reg(priv, (phytium_plane->iova[2] >> V_PREFIX_SHIFT) & V_PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_V_HI_ADDRESS);
}
void pe220x_dc_hw_update_cursor_hi_addr(struct drm_plane *plane, uint64_t iova)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
int phys_pipe = phytium_plane->phys_pipe;
int config;
config = ((iova >> CURSOR_PREFIX_SHIFT) & CURSOR_PREFIX_MASK);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe], PE220X_DC_CURSOR_HI_ADDRESS);
}

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Phytium Pe220x display controller DRM driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PE220X_DC_H__
#define __PE220X_DC_H__
#define PE220X_DC_PIX_CLOCK_MAX (594000)
#define PE220X_DC_HDISPLAY_MAX 3840
#define PE220X_DC_VDISPLAY_MAX 2160
#define PE220X_DC_ADDRESS_MASK 0x7f
extern void pe220x_dc_hw_vram_init(struct phytium_display_private *priv,
resource_size_t vram_addr,
resource_size_t vram_size);
extern void pe220x_dc_hw_config_pix_clock(struct drm_crtc *crtc, int clock);
extern void pe220x_dc_hw_disable(struct drm_crtc *crtc);
extern int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, int count);
extern void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count);
extern void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count);
extern void pe220x_dc_hw_update_primary_hi_addr(struct drm_plane *plane);
extern void pe220x_dc_hw_update_cursor_hi_addr(struct drm_plane *plane, uint64_t iova);
void pe220x_dc_hw_reset(struct drm_crtc *crtc);
#endif /* __PE220X_DC_H__ */

View File

@ -0,0 +1,514 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium display port DRM driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include "phytium_display_drv.h"
#include "pe220x_reg.h"
#include "phytium_dp.h"
#include "pe220x_dp.h"
static uint8_t pe220x_dp_source_lane_count[2] = {1, 1};
/* [reg][ling_rate 1.62->8.1] */
static int vco_val[12][4] = {
{0x0509, 0x0509, 0x0509, 0x0509}, /* CP_PADJ */
{0x0f00, 0x0f00, 0x0f00, 0x0f00}, /* CP_IADJ */
{0x0F08, 0x0F08, 0x0F08, 0x0F08}, /* FILT_PADJ */
{0x0061, 0x006C, 0x006C, 0x0051}, /* INTDIV */
{0x3333, 0x0000, 0x0000, 0x0000}, /* FRACDIVL */
{0x0000, 0x0000, 0x0000, 0x0000}, /* FRACDIVH */
{0x0042, 0x0048, 0x0048, 0x0036}, /* HIGH_THR */
{0x0002, 0x0002, 0x0002, 0x0002}, /* PDIAG_CTRL */
{0x0c5e, 0x0c5e, 0x0c5e, 0x0c5e}, /* VCOCAL_PLLCNT_START */
{0x00c7, 0x00c7, 0x00c7, 0x00c7}, /* LOCK_PEFCNT */
{0x00c7, 0x00c7, 0x00c7, 0x00c7}, /* LOCK_PLLCNT_START */
{0x0005, 0x0005, 0x0005, 0x0005}, /* LOCK_PLLCNT_THR */
};
/* [link_rate][swing][emphasis] */
static int mgnfs_val[4][4][4] = {
/* 1.62Gbps */
{
{0x0026, 0x001f, 0x0012, 0x0000},
{0x0013, 0x0013, 0x0000, 0x0000},
{0x0006, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 2.7Gbps */
{
{0x0026, 0x001f, 0x0012, 0x0000},
{0x0013, 0x0013, 0x0000, 0x0000},
{0x0006, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 5.4Gbps */
{
{0x001f, 0x0013, 0x005, 0x0000},
{0x0018, 0x006, 0x0000, 0x0000},
{0x000c, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 8.1Gbps */
{
{0x0026, 0x0013, 0x005, 0x0000},
{0x0013, 0x006, 0x0000, 0x0000},
{0x0006, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
};
/* [link_rate][swing][emphasis] */
static int cpost_val[4][4][4] = {
/* 1.62Gbps */
{
{0x0000, 0x0014, 0x0020, 0x002a},
{0x0000, 0x0010, 0x001f, 0x0000},
{0x0000, 0x0013, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 2.7Gbps */
{
{0x0000, 0x0014, 0x0020, 0x002a},
{0x0000, 0x0010, 0x001f, 0x0000},
{0x0000, 0x0013, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 5.4Gbps */
{
{0x0005, 0x0014, 0x0022, 0x002e},
{0x0000, 0x0013, 0x0020, 0x0000},
{0x0000, 0x0013, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
/* 8.1Gbps */
{
{0x0000, 0x0014, 0x0022, 0x002e},
{0x0000, 0x0013, 0x0020, 0x0000},
{0x0000, 0x0013, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000},
},
};
static int pe220x_dp_hw_set_phy_lane_and_rate(struct phytium_dp_device *phytium_dp,
uint8_t link_lane_count, uint32_t link_rate)
{
int port = phytium_dp->port%2;
int i = 0, data, tmp, tmp1, index = 0, mask = 0;
int timeout = 500, ret = 0;
/* set pma powerdown */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (A3_POWERDOWN3 << (i * A3_POWERDOWN3_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA0_POWER(port), data);
/* lane pll disable */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++) {
data |= (PLL_EN << (i * PLL_EN_SHIFT));
mask |= (((1<<PLL_EN_SHIFT) - 1) << (i * PLL_EN_SHIFT));
}
data &= ~mask;
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL_EN(port), data);
/* pma pll disable */
data = CONTROL_ENABLE & (~CONTROL_ENABLE_MASK);
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA_CONTROL(port), data);
/* read pma pll disable state */
mdelay(2);
phytium_phy_readl(phytium_dp, PE220X_PHY_PMA_CONTROL2(port));
/* config link rate */
switch (link_rate) {
case 810000:
tmp = PLL_LINK_RATE_810000;
tmp1 = HSCLK_LINK_RATE_810000;
index = 3;
break;
case 540000:
tmp = PLL_LINK_RATE_540000;
tmp1 = HSCLK_LINK_RATE_540000;
index = 2;
break;
case 270000:
tmp = PLL_LINK_RATE_270000;
tmp1 = HSCLK_LINK_RATE_270000;
index = 1;
break;
case 162000:
tmp = PLL_LINK_RATE_162000;
tmp1 = HSCLK_LINK_RATE_162000;
index = 0;
break;
default:
DRM_ERROR("phytium dp rate(%d) not support\n", link_rate);
tmp = PLL_LINK_RATE_162000;
tmp1 = HSCLK_LINK_RATE_162000;
index = 0;
break;
}
/* config analog pll for link0 */
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_CLK_SEL(port), tmp);
phytium_phy_writel(phytium_dp, PE220X_PHY_HSCLK0_SEL(port), HSCLK_LINK_0);
phytium_phy_writel(phytium_dp, PE220X_PHY_HSCLK0_DIV(port), tmp1);
/* config digital pll for link0 */
phytium_phy_writel(phytium_dp, PE220X_PHY_PLLDRC0_CTRL(port), PLLDRC_LINK0);
/* common for all rate */
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_DSM_M0(port), PLL0_DSM_M0);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_VCOCAL_START(port),
PLL0_VCOCAL_START);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_VCOCAL_CTRL(port),
PLL0_VCOCAL_CTRL);
/* different for all rate */
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_CP_PADJ(port),
vco_val[0][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_CP_IADJ(port),
vco_val[1][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_CP_FILT_PADJ(port),
vco_val[2][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_INTDIV(port),
vco_val[3][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_FRACDIVL(port),
vco_val[4][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_FRACDIVH(port),
vco_val[5][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_HIGH_THR(port),
vco_val[6][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_PDIAG_CTRL(port),
vco_val[7][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_VCOCAL_PLLCNT_START(port),
vco_val[8][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_LOCK_PEFCNT(port),
vco_val[9][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_LOCK_PLLCNT_START(port),
vco_val[10][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_LOCK_PLLCNT_THR(port),
vco_val[11][index]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_PSC_A0(port),
PLL0_TX_PSC_A0);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_PSC_A2(port),
PLL0_TX_PSC_A2);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_PSC_A3(port),
PLL0_TX_PSC_A3);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_PSC_A0(port),
PLL0_RX_PSC_A0);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_PSC_A2(port),
PLL0_RX_PSC_A2);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_PSC_A3(port),
PLL0_RX_PSC_A3);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_PSC_CAL(port),
PLL0_RX_PSC_CAL);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_XCVR_CTRL(port),
PLL0_XCVR_CTRL);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_GCSM1_CTRL(port),
PLL0_RX_GCSM1_CTRL);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_GCSM2_CTRL(port),
PLL0_RX_GCSM2_CTRL);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_RX_PERGCSM_CTRL(port),
PLL0_RX_PERGCSM_CTRL);
/* pma pll enable */
data = CONTROL_ENABLE;
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA_CONTROL(port), data);
/* lane pll enable */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (PLL_EN << (i * PLL_EN_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL_EN(port), data);
/* set pma power active */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (A0_ACTIVE << (i * A0_ACTIVE_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA0_POWER(port), data);
mask = PLL0_LOCK_DONE;
do {
mdelay(1);
timeout--;
tmp = phytium_phy_readl(phytium_dp, PE220X_PHY_PMA_CONTROL2(port));
} while ((!(tmp & mask)) && timeout);
if (timeout == 0) {
DRM_ERROR("dp(%d) phy pll lock failed\n", port);
ret = -1;
}
udelay(1);
return ret;
}
static void pe220x_dp_hw_set_phy_lane_setting(struct phytium_dp_device *phytium_dp,
uint32_t link_rate, uint8_t train_set)
{
int port = phytium_dp->port % 3;
int voltage_swing = 0;
int pre_emphasis = 0, link_rate_index = 0;
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1:
voltage_swing = 1;
break;
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
voltage_swing = 2;
break;
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
voltage_swing = 3;
break;
default:
voltage_swing = 0;
break;
}
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
case DP_TRAIN_PRE_EMPH_LEVEL_1:
pre_emphasis = 1;
break;
case DP_TRAIN_PRE_EMPH_LEVEL_2:
pre_emphasis = 2;
break;
case DP_TRAIN_PRE_EMPH_LEVEL_3:
pre_emphasis = 3;
break;
default:
pre_emphasis = 0;
break;
}
switch (link_rate) {
case 810000:
link_rate_index = 3;
break;
case 540000:
link_rate_index = 2;
break;
case 270000:
link_rate_index = 1;
break;
case 162000:
link_rate_index = 0;
break;
default:
DRM_ERROR("phytium dp rate(%d) not support\n", link_rate);
link_rate_index = 2;
break;
}
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_DIAG_ACYA(port), LOCK);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_TXCC_CTRL(port), TX_TXCC_CTRL);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_DRV(port), TX_DRV);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_MGNFS(port),
mgnfs_val[link_rate_index][voltage_swing][pre_emphasis]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_CPOST(port),
cpost_val[link_rate_index][voltage_swing][pre_emphasis]);
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL0_TX_DIAG_ACYA(port), UNLOCK);
}
static int pe220x_dp_hw_init_phy(struct phytium_dp_device *phytium_dp)
{
int port = phytium_dp->port;
int i = 0, data, tmp, mask;
int timeout = 500, ret = 0;
phytium_phy_writel(phytium_dp, PE220X_PHY_APB_RESET(port), APB_RESET);
phytium_phy_writel(phytium_dp, PE220X_PHY_PIPE_RESET(port), RESET);
/* config lane to dp mode */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (LANE_BIT << (i * LANE_BIT_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_MODE(port), data);
/* pll clock enable */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (PLL_EN << (i * PLL_EN_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL_EN(port), data);
/* config input 20 bit */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (BIT_20 << (i * BIT_20_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA_WIDTH(port), data);
/* config lane active power state */
data = 0;
for (i = 0; i < phytium_dp->source_max_lane_count; i++)
data |= (A0_ACTIVE << (i * A0_ACTIVE_SHIFT));
phytium_phy_writel(phytium_dp, PE220X_PHY_PMA0_POWER(port), data);
/* link reset */
phytium_phy_writel(phytium_dp, PE220X_PHY_LINK_RESET(port), LINK_RESET);
phytium_phy_writel(phytium_dp, PE220X_PHY_SGMII_DPSEL_INIT(port), DP_SEL);
/* config single link */
phytium_phy_writel(phytium_dp, PE220X_PHY_PLL_CFG(port), SINGLE_LINK);
/* pipe reset */
phytium_phy_writel(phytium_dp, PE220X_PHY_PIPE_RESET(port), RESET_DEASSERT);
mask = PLL0_LOCK_DONE;
do {
mdelay(1);
timeout--;
tmp = phytium_phy_readl(phytium_dp, PE220X_PHY_PMA_CONTROL2(port));
} while ((!(tmp & mask)) && timeout);
if (timeout == 0) {
DRM_ERROR("reset dp(%d) phy failed\n", port);
ret = -1;
}
udelay(1);
return ret;
}
static void pe220x_dp_hw_poweron_panel(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
int ret = 0;
phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_ENABLE,
0, PE220X_DC_CMD_REGISTER(port));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to poweron panel\n", __func__);
}
static void pe220x_dp_hw_poweroff_panel(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
int ret = 0;
phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_DISABLE,
0, PE220X_DC_CMD_REGISTER(port));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to poweroff panel\n", __func__);
}
static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port, ret = 0;
phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_ENABLE,
0, PE220X_DC_CMD_REGISTER(port));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to enable backlight\n", __func__);
}
static void pe220x_dp_hw_disable_backlight(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
int ret = 0;
phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_DISABLE,
0, PE220X_DC_CMD_REGISTER(port));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to disable backlight\n", __func__);
}
static uint32_t pe220x_dp_hw_get_backlight(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int config;
uint32_t group_offset = priv->address_transform_base;
config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_BACKLIGHT_VALUE);
return ((config >> BACKLIGHT_VALUE_SHIFT) & BACKLIGHT_VALUE_MASK);
}
static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint32_t level)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
int config = 0;
int ret = 0;
if (level > PE220X_DP_BACKLIGHT_MAX) {
ret = -EINVAL;
goto out;
}
config = FLAG_REQUEST | CMD_BACKLIGHT | ((level & BACKLIGHT_MASK) << BACKLIGHT_SHIFT);
phytium_writel_reg(priv, config, 0, PE220X_DC_CMD_REGISTER(port));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to set backlight\n", __func__);
out:
return ret;
}
bool pe220x_dp_hw_spread_is_enable(struct phytium_dp_device *phytium_dp)
{
return false;
}
int pe220x_dp_hw_reset(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
uint32_t group_offset = priv->dp_reg_base[port];
phytium_writel_reg(priv, DP_RESET, group_offset, PE220X_DP_CONTROLLER_RESET);
udelay(500);
phytium_writel_reg(priv, AUX_CLK_DIVIDER_100, group_offset, PHYTIUM_DP_AUX_CLK_DIVIDER);
phytium_writel_reg(priv, SUPPORT_EDP_1_4, group_offset, PHYTIUM_EDP_CRC_ENABLE);
return 0;
}
uint8_t pe220x_dp_hw_get_source_lane_count(struct phytium_dp_device *phytium_dp)
{
return pe220x_dp_source_lane_count[phytium_dp->port];
}
static struct phytium_dp_func pe220x_dp_funcs = {
.dp_hw_get_source_lane_count = pe220x_dp_hw_get_source_lane_count,
.dp_hw_reset = pe220x_dp_hw_reset,
.dp_hw_spread_is_enable = pe220x_dp_hw_spread_is_enable,
.dp_hw_set_backlight = pe220x_dp_hw_set_backlight,
.dp_hw_get_backlight = pe220x_dp_hw_get_backlight,
.dp_hw_disable_backlight = pe220x_dp_hw_disable_backlight,
.dp_hw_enable_backlight = pe220x_dp_hw_enable_backlight,
.dp_hw_poweroff_panel = pe220x_dp_hw_poweroff_panel,
.dp_hw_poweron_panel = pe220x_dp_hw_poweron_panel,
.dp_hw_init_phy = pe220x_dp_hw_init_phy,
.dp_hw_set_phy_lane_setting = pe220x_dp_hw_set_phy_lane_setting,
.dp_hw_set_phy_lane_and_rate = pe220x_dp_hw_set_phy_lane_and_rate,
};
void pe220x_dp_func_register(struct phytium_dp_device *phytium_dp)
{
phytium_dp->funcs = &pe220x_dp_funcs;
}

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Phytium display port DRM driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PE220X_DP_H__
#define __PE220X_DP_H__
#define PE220X_DP_BACKLIGHT_MAX 100
void pe220x_dp_func_register(struct phytium_dp_device *phytium_dp);
#endif /* __PE220X_DP_H__ */

View File

@ -0,0 +1,209 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Phytium Pe220x display engine register
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PE220X_REG_H__
#define __PE220X_REG_H__
#include "phytium_reg.h"
/* dc register */
#define PE220X_DC_CLOCK_CONTROL 0x0000
#define DC1_CORE_RESET (1<<18)
#define DC0_CORE_RESET (1<<17)
#define AXI_RESET (1<<16)
#define AHB_RESET (1<<12)
#define PE220X_DC_CMD_REGISTER(pipe) (PE220X_DC_BASE(0) + 0x00F0 + 0x4*(pipe))
#define FLAG_REPLY (1<<31)
#define FLAG_REQUEST (1<<30)
#define CMD_PIXEL_CLOCK (0x0 << 28)
#define CMD_BACKLIGHT (0x1 << 28)
#define CMD_DC_DP_RESET (0x3 << 28)
#define BACKLIGHT_SHIFT 21
#define BACKLIGHT_MASK 0x7f
#define BACKLIGHT_MAX 100
#define BACKLIGHT_ENABLE (101 << BACKLIGHT_SHIFT)
#define BACKLIGHT_DISABLE (102 << BACKLIGHT_SHIFT)
#define PANEL_POWER_ENABLE (103 << BACKLIGHT_SHIFT)
#define PANEL_POWER_DISABLE (104 << BACKLIGHT_SHIFT)
#define PIXEL_CLOCK_MASK (0x1fffff)
#define PE220X_DC_FRAMEBUFFER_Y_HI_ADDRESS 0x1404
#define PREFIX_MASK 0xff
#define PREFIX_SHIFT 32
#define PE220X_DC_CURSOR_HI_ADDRESS 0x1490
#define CURSOR_PREFIX_MASK 0xff
#define CURSOR_PREFIX_SHIFT 32
#define PE220X_DC_FRAMEBUFFER_U_HI_ADDRESS 0x1534
#define U_PREFIX_MASK 0xff
#define U_PREFIX_SHIFT 32
#define PE220X_DC_FRAMEBUFFER_V_HI_ADDRESS 0x153c
#define V_PREFIX_MASK 0xff
#define V_PREFIX_SHIFT 32
/* dp register */
#define PE220X_DP_CONTROLLER_RESET 0x0850
#define DP_RESET 0x1
/* address transform register */
#define PE220X_DC_ADDRESS_TRANSFORM_SRC_ADDR 0x0
#define SRC_ADDR_OFFSET 22
#define SRC_ADDR_MASK 0xffffffffff
#define PE220X_DC_ADDRESS_TRANSFORM_SIZE 0x4
#define ADDRESS_TRANSFORM_ENABLE (0x1 << 31)
#define SIZE_OFFSET 22
#define PE220X_DC_ADDRESS_TRANSFORM_DST_ADDR 0x8
#define DST_ADDR_OFFSET 22
#define PE220X_DC_ADDRESS_TRANSFORM_DP_RESET_STATUS 0x48
#define DC_DP_RESET_STATUS(pipe) (1 << pipe)
#define DP_SPREAD_ENABLE(pipe) (0x8 << pipe)
#define PE220X_DC_ADDRESS_TRANSFORM_BACKLIGHT_VALUE 0x4c
#define BACKLIGHT_VALUE_MASK (0x7f)
#define BACKLIGHT_VALUE_SHIFT 16
/* phy register start */
#define PE220X_PHY_BASE(pipe) (0x100000*pipe)
#define PE220X_PHY_PIPE_RESET(pipe) (PE220X_PHY_BASE(pipe) + 0x40254)
#define RESET 0x0
#define RESET_DEASSERT 0x1
#define PE220X_PHY_MODE(pipe) (PE220X_PHY_BASE(pipe) + 0x40034)
#define LANE_BIT (0x3)
#define LANE_BIT_SHIFT 0x2
#define PE220X_PHY_LINK_CFG(pipe) (PE220X_PHY_BASE(pipe) + 0x40044)
#define LANE_MASTER 0x1
#define LANE_MASTER_SHIFT 1
#define PE220X_PHY_PLL_EN(pipe) (PE220X_PHY_BASE(pipe) + 0x40214)
#define PLL_EN 0x1
#define PLL_EN_SHIFT 1
#define PE220X_PHY_PMA_WIDTH(pipe) (PE220X_PHY_BASE(pipe) + 0x4021c)
#define BIT_20 0x5
#define BIT_20_SHIFT 4
#define PE220X_PHY_PLL_SOURCE_SEL(pipe) (PE220X_PHY_BASE(pipe) + 0x4004C)
#define PE220X_PHY_PMA0_POWER(pipe) (PE220X_PHY_BASE(pipe) + 0x402bc)
#define A0_ACTIVE 0x1
#define A0_ACTIVE_SHIFT 8
#define A3_POWERDOWN3 0x8
#define A3_POWERDOWN3_SHIFT 8
#define PE220X_PHY_LINK_RESET(pipe) (PE220X_PHY_BASE(pipe) + 0x40258)
#define LINK_RESET 0x1
#define LINK_RESET_MASK 0x1
#define LINTK_RESET_SHIFT 0x1
#define PE220X_PHY_SGMII_DPSEL_INIT(pipe) (PE220X_PHY_BASE(pipe) + 0x40260)
#define DP_SEL 0x1
#define PE220X_PHY_APB_RESET(pipe) (PE220X_PHY_BASE(pipe) + 0x40250)
#define APB_RESET 0x1
/* phy origin register */
#define PE220X_PHY_PLL_CFG(pipe) (PE220X_PHY_BASE(pipe) + 0x30038)
#define SINGLE_LINK 0x0
#define PE220X_PHY_PMA_CONTROL(pipe) (PE220X_PHY_BASE(pipe) + 0x3800c)
#define CONTROL_ENABLE 0x1
#define CONTROL_ENABLE_MASK 0x1
#define CONTROL_ENABLE_SHIFT 0x1
#define PE220X_PHY_PMA_CONTROL2(pipe) (PE220X_PHY_BASE(pipe) + 0x38004)
#define PLL0_LOCK_DONE (0x1 << 6)
#define PE220X_PHY_PLL0_CLK_SEL(pipe) (PE220X_PHY_BASE(pipe) + 0X684)
#define PLL_LINK_RATE_162000 0xf01
#define PLL_LINK_RATE_270000 0x701
#define PLL_LINK_RATE_540000 0x301
#define PLL_LINK_RATE_810000 0x200
#define PE220X_PHY_HSCLK0_SEL(pipe) (PE220X_PHY_BASE(pipe) + 0x18398)
#define HSCLK_LINK_0 0x0
#define HSCLK_LINK_1 0x1
#define PE220X_PHY_HSCLK0_DIV(pipe) (PE220X_PHY_BASE(pipe) + 0x1839c)
#define HSCLK_LINK_RATE_162000 0x2
#define HSCLK_LINK_RATE_270000 0x1
#define HSCLK_LINK_RATE_540000 0x0
#define HSCLK_LINK_RATE_810000 0x0
#define PE220X_PHY_PLLDRC0_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x18394)
#define PLLDRC_LINK0 0x1
#define PLLDRC_LINK1 0x9
#define PE220X_PHY_PLL0_DSM_M0(pipe) (PE220X_PHY_BASE(pipe) + 0x250)
#define PLL0_DSM_M0 0x4
#define PE220X_PHY_PLL0_VCOCAL_START(pipe) (PE220X_PHY_BASE(pipe) + 0x218)
#define PLL0_VCOCAL_START 0xc5e
#define PE220X_PHY_PLL0_VCOCAL_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x208)
#define PLL0_VCOCAL_CTRL 0x3
#define PE220X_PHY_PLL0_CP_PADJ(pipe) (PE220X_PHY_BASE(pipe) + 0x690)
#define PE220X_PHY_PLL0_CP_IADJ(pipe) (PE220X_PHY_BASE(pipe) + 0x694)
#define PE220X_PHY_PLL0_CP_FILT_PADJ(pipe) (PE220X_PHY_BASE(pipe) + 0x698)
#define PE220X_PHY_PLL0_INTDIV(pipe) (PE220X_PHY_BASE(pipe) + 0x240)
#define PE220X_PHY_PLL0_FRACDIVL(pipe) (PE220X_PHY_BASE(pipe) + 0x244)
#define PE220X_PHY_PLL0_FRACDIVH(pipe) (PE220X_PHY_BASE(pipe) + 0x248)
#define PE220X_PHY_PLL0_HIGH_THR(pipe) (PE220X_PHY_BASE(pipe) + 0x24c)
#define PE220X_PHY_PLL0_PDIAG_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x680)
#define PE220X_PHY_PLL0_VCOCAL_PLLCNT_START(pipe) (PE220X_PHY_BASE(pipe) + 0x220)
#define PE220X_PHY_PLL0_LOCK_PEFCNT(pipe) (PE220X_PHY_BASE(pipe) + 0x270)
#define PE220X_PHY_PLL0_LOCK_PLLCNT_START(pipe) (PE220X_PHY_BASE(pipe) + 0x278)
#define PE220X_PHY_PLL0_LOCK_PLLCNT_THR(pipe) (PE220X_PHY_BASE(pipe) + 0x27c)
#define PE220X_PHY_PLL0_TX_PSC_A0(pipe) (PE220X_PHY_BASE(pipe) + 0x18400)
#define PLL0_TX_PSC_A0 0xfb
#define PE220X_PHY_PLL0_TX_PSC_A2(pipe) (PE220X_PHY_BASE(pipe) + 0x18408)
#define PLL0_TX_PSC_A2 0x4aa
#define PE220X_PHY_PLL0_TX_PSC_A3(pipe) (PE220X_PHY_BASE(pipe) + 0x1840c)
#define PLL0_TX_PSC_A3 0x4aa
#define PE220X_PHY_PLL0_RX_PSC_A0(pipe) (PE220X_PHY_BASE(pipe) + 0x28000)
#define PLL0_RX_PSC_A0 0x0
#define PE220X_PHY_PLL0_RX_PSC_A2(pipe) (PE220X_PHY_BASE(pipe) + 0x28008)
#define PLL0_RX_PSC_A2 0x0
#define PE220X_PHY_PLL0_RX_PSC_A3(pipe) (PE220X_PHY_BASE(pipe) + 0x2800C)
#define PLL0_RX_PSC_A3 0x0
#define PE220X_PHY_PLL0_RX_PSC_CAL(pipe) (PE220X_PHY_BASE(pipe) + 0x28018)
#define PLL0_RX_PSC_CAL 0x0
#define PE220X_PHY_PLL0_XCVR_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x183a8)
#define PLL0_XCVR_CTRL 0xf
#define PE220X_PHY_PLL0_RX_GCSM1_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x28420)
#define PLL0_RX_GCSM1_CTRL 0x0
#define PE220X_PHY_PLL0_RX_GCSM2_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x28440)
#define PLL0_RX_GCSM2_CTRL 0x0
#define PE220X_PHY_PLL0_RX_PERGCSM_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x28460)
#define PLL0_RX_PERGCSM_CTRL 0x0
/* swing and emphasis */
#define PE220X_PHY_PLL0_TX_DIAG_ACYA(pipe) (PE220X_PHY_BASE(pipe) + 0x1879c)
#define LOCK 1
#define UNLOCK 0
#define PE220X_PHY_PLL0_TX_TXCC_CTRL(pipe) (PE220X_PHY_BASE(pipe) + 0x18100)
#define TX_TXCC_CTRL 0x8a4
#define PE220X_PHY_PLL0_TX_DRV(pipe) (PE220X_PHY_BASE(pipe) + 0x18318)
#define TX_DRV 0x3
#define PE220X_PHY_PLL0_TX_MGNFS(pipe) (PE220X_PHY_BASE(pipe) + 0x18140)
#define PE220X_PHY_PLL0_TX_CPOST(pipe) (PE220X_PHY_BASE(pipe) + 0x18130)
#endif /* __PE220X_REG_H__ */

View File

@ -0,0 +1,829 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <asm/neon.h>
#include <drm/drm_vblank.h>
#include "phytium_display_drv.h"
#include "phytium_crtc.h"
#include "phytium_plane.h"
#include "phytium_dp.h"
#include "px210_dc.h"
#include "pe220x_dc.h"
#include "phytium_reg.h"
#define MAXKERNELSIZE 9
#define SUBPIXELINDEXBITS 5
#define SUBPIXELCOUNT (1 << SUBPIXELINDEXBITS)
#define SUBPIXELLOADCOUNT (SUBPIXELCOUNT / 2 + 1)
#define WEIGHTSTATECOUNT (((SUBPIXELLOADCOUNT * MAXKERNELSIZE + 1) & ~1) / 2)
#define KERNELTABLESIZE (SUBPIXELLOADCOUNT * MAXKERNELSIZE * sizeof(uint16_t))
#define PHYALIGN(n, align) (((n) + ((align) - 1)) & ~((align) - 1))
#define KERNELSTATES (PHYALIGN(KERNELTABLESIZE + 4, 8))
#define PHYPI 3.14159265358979323846f
#define MATH_Add(X, Y) (float)((X) + (Y))
#define MATH_Multiply(X, Y) (float)((X) * (Y))
#define MATH_Divide(X, Y) (float)((X) / (Y))
#define MATH_DivideFromUInteger(X, Y) ((float)(X) / (float)(Y))
#define MATH_I2Float(X) (float)(X)
struct filter_blit_array {
uint8_t kernelSize;
uint32_t scaleFactor;
uint32_t *kernelStates;
};
static uint32_t dc_scaling_get_factor(uint32_t src_size, uint32_t dst_size)
{
uint32_t factor = 0;
factor = ((src_size - 1) << SCALE_FACTOR_SRC_OFFSET) / (dst_size - 1);
return factor;
}
static float dc_sint(float x)
{
const float B = 1.2732395477;
const float C = -0.4052847346;
const float P = 0.2310792853;
float y;
if (x < 0)
y = B*x - C*x*x;
else
y = B*x + C*x*x;
if (y < 0)
y = P * (y * (0 - y) - y) + y;
else
y = P * (y * y - y) + y;
return y;
}
static float dc_sinc_filter(float x, int radius)
{
float pit, pitd, f1, f2, result;
float f_radius = MATH_I2Float(radius);
if (x == 0.0f) {
result = 1.0f;
} else if ((x < -f_radius) || (x > f_radius)) {
result = 0.0f;
} else {
pit = MATH_Multiply(PHYPI, x);
pitd = MATH_Divide(pit, f_radius);
f1 = MATH_Divide(dc_sint(pit), pit);
f2 = MATH_Divide(dc_sint(pitd), pitd);
result = MATH_Multiply(f1, f2);
}
return result;
}
static int dc_calculate_sync_table(
uint8_t kernel_size,
uint32_t src_size,
uint32_t dst_size,
struct filter_blit_array *kernel_info)
{
uint32_t scale_factor;
float f_scale;
int kernel_half;
float f_subpixel_step;
float f_subpixel_offset;
uint32_t subpixel_pos;
int kernel_pos;
int padding;
uint16_t *kernel_array;
int range = 0;
do {
/* Compute the scale factor. */
scale_factor = dc_scaling_get_factor(src_size, dst_size);
/* Same kernel size and ratio as before? */
if ((kernel_info->kernelSize == kernel_size) &&
(kernel_info->scaleFactor == kernel_size)) {
break;
}
/* check the array */
if (kernel_info->kernelStates == NULL)
break;
/* Store new parameters. */
kernel_info->kernelSize = kernel_size;
kernel_info->scaleFactor = scale_factor;
/* Compute the scale factor. */
f_scale = MATH_DivideFromUInteger(dst_size, src_size);
/* Adjust the factor for magnification. */
if (f_scale > 1.0f)
f_scale = 1.0f;
/* Calculate the kernel half. */
kernel_half = (int) (kernel_info->kernelSize >> 1);
/* Calculate the subpixel step. */
f_subpixel_step = MATH_Divide(1.0f, MATH_I2Float(SUBPIXELCOUNT));
/* Init the subpixel offset. */
f_subpixel_offset = 0.5f;
/* Determine kernel padding size. */
padding = (MAXKERNELSIZE - kernel_info->kernelSize) / 2;
/* Set initial kernel array pointer. */
kernel_array = (uint16_t *) (kernel_info->kernelStates + 1);
/* Loop through each subpixel. */
for (subpixel_pos = 0; subpixel_pos < SUBPIXELLOADCOUNT; subpixel_pos++) {
/* Define a temporary set of weights. */
float fSubpixelSet[MAXKERNELSIZE];
/* Init the sum of all weights for the current subpixel. */
float fWeightSum = 0.0f;
uint16_t weightSum = 0;
short int adjustCount, adjustFrom;
short int adjustment;
/* Compute weights. */
for (kernel_pos = 0; kernel_pos < MAXKERNELSIZE; kernel_pos++) {
/* Determine the current index. */
int index = kernel_pos - padding;
/* Pad with zeros. */
if ((index < 0) || (index >= kernel_info->kernelSize)) {
fSubpixelSet[kernel_pos] = 0.0f;
} else {
if (kernel_info->kernelSize == 1) {
fSubpixelSet[kernel_pos] = 1.0f;
} else {
/* Compute the x position for filter function. */
float fX = MATH_Add(
MATH_I2Float(index - kernel_half),
f_subpixel_offset);
fX = MATH_Multiply(fX, f_scale);
/* Compute the weight. */
fSubpixelSet[kernel_pos] = dc_sinc_filter(fX,
kernel_half);
}
/* Update the sum of weights. */
fWeightSum = MATH_Add(fWeightSum,
fSubpixelSet[kernel_pos]);
}
}
/* Adjust weights so that the sum will be 1.0. */
for (kernel_pos = 0; kernel_pos < MAXKERNELSIZE; kernel_pos++) {
/* Normalize the current weight. */
float fWeight = MATH_Divide(fSubpixelSet[kernel_pos],
fWeightSum);
/* Convert the weight to fixed point and store in the table. */
if (fWeight == 0.0f)
kernel_array[kernel_pos] = 0x0000;
else if (fWeight >= 1.0f)
kernel_array[kernel_pos] = 0x4000;
else if (fWeight <= -1.0f)
kernel_array[kernel_pos] = 0xC000;
else
kernel_array[kernel_pos] =
(int16_t) MATH_Multiply(fWeight, 16384.0f);
weightSum += kernel_array[kernel_pos];
}
/* Adjust the fixed point coefficients. */
adjustCount = 0x4000 - weightSum;
if (adjustCount < 0) {
adjustCount = -adjustCount;
adjustment = -1;
} else {
adjustment = 1;
}
adjustFrom = (MAXKERNELSIZE - adjustCount) / 2;
for (kernel_pos = 0; kernel_pos < adjustCount; kernel_pos++) {
range = (MAXKERNELSIZE*subpixel_pos + adjustFrom + kernel_pos) *
sizeof(uint16_t);
if ((range >= 0) && (range < KERNELTABLESIZE))
kernel_array[adjustFrom + kernel_pos] += adjustment;
else
DRM_ERROR("%s failed\n", __func__);
}
kernel_array += MAXKERNELSIZE;
/* Advance to the next subpixel. */
f_subpixel_offset = MATH_Add(f_subpixel_offset, -f_subpixel_step);
}
} while (0);
return 0;
}
static void phytium_dc_scaling_config(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
uint32_t scale_factor_x, scale_factor_y, i;
uint32_t kernelStates[128];
struct filter_blit_array kernel_info_width;
void *tmp = NULL;
if (mode->hdisplay != mode->crtc_hdisplay || mode->vdisplay != mode->crtc_vdisplay) {
phytium_crtc->src_width = mode->hdisplay;
phytium_crtc->src_height = mode->vdisplay;
phytium_crtc->dst_width = mode->crtc_hdisplay;
phytium_crtc->dst_height = mode->crtc_vdisplay;
phytium_crtc->dst_x = (mode->crtc_hdisplay - phytium_crtc->dst_width) / 2;
phytium_crtc->dst_y = (mode->crtc_vdisplay - phytium_crtc->dst_height) / 2;
scale_factor_x = dc_scaling_get_factor(phytium_crtc->src_width,
phytium_crtc->dst_width);
scale_factor_y = dc_scaling_get_factor(phytium_crtc->src_height,
phytium_crtc->dst_height);
if (scale_factor_y > (SCALE_FACTOR_Y_MAX << SCALE_FACTOR_SRC_OFFSET))
scale_factor_y = (SCALE_FACTOR_Y_MAX << SCALE_FACTOR_SRC_OFFSET);
phytium_writel_reg(priv, scale_factor_x & SCALE_FACTOR_X_MASK,
group_offset, PHYTIUM_DC_FRAMEBUFFER_SCALE_FACTOR_X);
phytium_writel_reg(priv, scale_factor_y & SCALE_FACTOR_Y_MASK,
group_offset, PHYTIUM_DC_FRAMEBUFFER_SCALE_FACTOR_Y);
phytium_writel_reg(priv, FRAMEBUFFER_TAP,
group_offset, PHYTIUM_DC_FRAMEBUFFER_SCALECONFIG);
tmp = kmalloc(KERNELSTATES, GFP_KERNEL);
if (!tmp) {
DRM_ERROR("malloc %ld failed\n", KERNELSTATES);
return;
}
memset(&kernel_info_width, 0, sizeof(struct filter_blit_array));
kernel_info_width.kernelStates = tmp;
memset(kernel_info_width.kernelStates, 0, KERNELSTATES);
kernel_neon_begin();
dc_calculate_sync_table(FRAMEBUFFER_HORIZONTAL_FILTER_TAP,
phytium_crtc->src_width,
phytium_crtc->dst_width,
&kernel_info_width);
memset(kernelStates, 0, sizeof(kernelStates));
memcpy(kernelStates, kernel_info_width.kernelStates + 1, KERNELSTATES - 4);
kernel_neon_end();
phytium_writel_reg(priv, HORI_FILTER_INDEX,
group_offset, PHYTIUM_DC_FRAMEBUFFER_HORI_FILTER_INDEX);
for (i = 0; i < 128; i++) {
phytium_writel_reg(priv, kernelStates[i],
group_offset, PHYTIUM_DC_FRAMEBUFFER_HORI_FILTER);
}
memset(&kernel_info_width, 0, sizeof(struct filter_blit_array));
kernel_info_width.kernelStates = tmp;
memset(kernel_info_width.kernelStates, 0, KERNELSTATES);
kernel_neon_begin();
dc_calculate_sync_table(FRAMEBUFFER_FILTER_TAP, phytium_crtc->src_height,
phytium_crtc->dst_height, &kernel_info_width);
memset(kernelStates, 0, sizeof(kernelStates));
memcpy(kernelStates, kernel_info_width.kernelStates + 1, KERNELSTATES - 4);
kernel_neon_end();
phytium_writel_reg(priv, VERT_FILTER_INDEX,
group_offset, PHYTIUM_DC_FRAMEBUFFER_VERT_FILTER_INDEX);
for (i = 0; i < 128; i++)
phytium_writel_reg(priv, kernelStates[i],
group_offset, PHYTIUM_DC_FRAMEBUFFER_VERT_FILTER);
phytium_writel_reg(priv, INITIALOFFSET,
group_offset, PHYTIUM_DC_FRAMEBUFFER_INITIALOFFSET);
kfree(tmp);
phytium_crtc->scale_enable = true;
} else {
phytium_crtc->scale_enable = false;
}
}
static void phytium_crtc_gamma_set(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
uint32_t config = 0, data;
struct drm_crtc_state *state = crtc->state;
struct drm_color_lut *lut;
unsigned long flags;
uint32_t active_line = 0, timeout = 500;
int i;
if (state->gamma_lut) {
if (WARN((state->gamma_lut->length/sizeof(struct drm_color_lut) != GAMMA_INDEX_MAX),
"gamma size is not match\n"))
return;
lut = (struct drm_color_lut *)state->gamma_lut->data;
config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (config & FRAMEBUFFER_OUTPUT) {
struct drm_display_mode *mode = &state->adjusted_mode;
uint32_t frame_time;
uint32_t value_a, value_b;
frame_time = mode->crtc_vtotal * mode->crtc_htotal / mode->crtc_clock;
value_b = (frame_time - 2) * mode->crtc_vtotal;
local_irq_save(flags);
do {
active_line = phytium_readl_reg(priv, group_offset,
PHYTIUM_DC_LOCATION);
active_line = active_line >> LOVATION_Y_SHIFT;
value_a = (mode->crtc_vblank_end - mode->crtc_vblank_start +
active_line) * frame_time;
if (value_a < value_b)
break;
local_irq_restore(flags);
udelay(1000);
timeout--;
local_irq_save(flags);
} while (timeout);
if (timeout == 0)
DRM_ERROR("wait gamma active line timeout\n");
}
phytium_writel_reg(priv, 0, group_offset, PHYTIUM_DC_GAMMA_INDEX);
for (i = 0; i < GAMMA_INDEX_MAX; i++) {
data = ((lut[i].red >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT;
data |= (((lut[i].green >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT);
data |= (((lut[i].blue >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT);
phytium_writel_reg(priv, data, group_offset, PHYTIUM_DC_GAMMA_DATA);
}
if (config & FRAMEBUFFER_OUTPUT)
local_irq_restore(flags);
}
}
static void phytium_crtc_gamma_init(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
struct drm_crtc_state *state = crtc->state;
uint32_t config = 0, data;
uint16_t *red, *green, *blue;
unsigned long flags;
uint32_t active_line = 0, timeout = 500;
int i;
if (WARN((crtc->gamma_size != GAMMA_INDEX_MAX), "gamma size is not match\n"))
return;
red = crtc->gamma_store;
green = red + crtc->gamma_size;
blue = green + crtc->gamma_size;
config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (config & FRAMEBUFFER_OUTPUT) {
struct drm_display_mode *mode = &state->adjusted_mode;
uint32_t frame_time;
uint32_t value_a, value_b;
frame_time = mode->crtc_vtotal * mode->crtc_htotal / mode->crtc_clock;
value_b = (frame_time - 2) * mode->crtc_vtotal;
local_irq_save(flags);
do {
active_line = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_LOCATION);
active_line = active_line >> LOVATION_Y_SHIFT;
value_a = (mode->crtc_vblank_end - mode->crtc_vblank_start +
active_line) * frame_time;
if (value_a < value_b)
break;
local_irq_restore(flags);
udelay(1000);
timeout--;
local_irq_save(flags);
} while (timeout);
if (timeout == 0)
DRM_ERROR("wait gamma active line timeout\n");
}
phytium_writel_reg(priv, 0, group_offset, PHYTIUM_DC_GAMMA_INDEX);
for (i = 0; i < GAMMA_INDEX_MAX; i++) {
data = ((*red++ >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT;
data |= (((*green++ >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT);
data |= (((*blue++ >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT);
phytium_writel_reg(priv, data, group_offset, PHYTIUM_DC_GAMMA_DATA);
}
if (config & FRAMEBUFFER_OUTPUT)
local_irq_restore(flags);
}
static void phytium_crtc_destroy(struct drm_crtc *crtc)
{
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
drm_crtc_cleanup(crtc);
kfree(phytium_crtc);
}
struct drm_crtc_state *
phytium_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
{
struct phytium_crtc_state *phytium_crtc_state = NULL;
phytium_crtc_state = kmemdup(crtc->state, sizeof(*phytium_crtc_state),
GFP_KERNEL);
if (!phytium_crtc_state)
return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc,
&phytium_crtc_state->base);
return &phytium_crtc_state->base;
}
void
phytium_crtc_atomic_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct phytium_crtc_state *phytium_crtc_state =
to_phytium_crtc_state(state);
phytium_crtc_state = to_phytium_crtc_state(state);
__drm_atomic_helper_crtc_destroy_state(state);
kfree(phytium_crtc_state);
}
static int phytium_enable_vblank(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
phytium_writel_reg(priv, INT_ENABLE, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_INT_ENABLE);
return 0;
}
static void phytium_disable_vblank(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
phytium_writel_reg(priv, INT_DISABLE, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_INT_ENABLE);
}
static const struct drm_crtc_funcs phytium_crtc_funcs = {
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.destroy = phytium_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = phytium_crtc_atomic_duplicate_state,
.atomic_destroy_state = phytium_crtc_atomic_destroy_state,
.enable_vblank = phytium_enable_vblank,
.disable_vblank = phytium_disable_vblank,
};
static void
phytium_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct drm_atomic_state *state = old_state->state;
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct drm_connector_state *new_conn_state;
struct drm_connector *conn;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
int config = 0, i = 0;
for_each_new_connector_in_state(state, conn, new_conn_state, i) {
if (new_conn_state->crtc != crtc)
continue;
switch (conn->display_info.bpc) {
case 10:
phytium_crtc->bpc = DP_RGB101010;
break;
case 6:
phytium_crtc->bpc = DP_RGB666;
break;
default:
phytium_crtc->bpc = DP_RGB888;
break;
}
}
/* config pix clock */
phytium_crtc->dc_hw_config_pix_clock(crtc, mode->clock);
phytium_dc_scaling_config(crtc, old_state);
config = ((mode->crtc_hdisplay & HDISPLAY_END_MASK) << HDISPLAY_END_SHIFT)
| ((mode->crtc_htotal&HDISPLAY_TOTAL_MASK) << HDISPLAY_TOTAL_SHIFT);
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_HDISPLAY);
config = ((mode->crtc_hsync_start & HSYNC_START_MASK) << HSYNC_START_SHIFT)
| ((mode->crtc_hsync_end & HSYNC_END_MASK) << HSYNC_END_SHIFT)
| HSYNC_PULSE_ENABLED;
config |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : HSYNC_NEGATIVE;
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_HSYNC);
config = ((mode->crtc_vdisplay & VDISPLAY_END_MASK) << VDISPLAY_END_SHIFT)
| ((mode->crtc_vtotal & VDISPLAY_TOTAL_MASK) << VDISPLAY_TOTAL_SHIFT);
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_VDISPLAY);
config = ((mode->crtc_vsync_start & VSYNC_START_MASK) << VSYNC_START_SHIFT)
| ((mode->crtc_vsync_end & VSYNC_END_MASK) << VSYNC_END_SHIFT)
| VSYNC_PULSE_ENABLED;
config |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : VSYNC_NEGATIVE;
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_VSYNC);
config = PANEL_DATAENABLE_ENABLE | PANEL_DATA_ENABLE | PANEL_CLOCK_ENABLE;
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_PANEL_CONFIG);
config = phytium_crtc->bpc | OUTPUT_DP;
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_DP_CONFIG);
config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (crtc->state->active)
config |= FRAMEBUFFER_OUTPUT | FRAMEBUFFER_RESET;
else
config &= (~(FRAMEBUFFER_OUTPUT | FRAMEBUFFER_RESET));
if (phytium_crtc->scale_enable)
config |= FRAMEBUFFER_SCALE_ENABLE;
else
config &= (~FRAMEBUFFER_SCALE_ENABLE);
config |= FRAMEBUFFER_GAMMA_ENABLE;
if (crtc->state->gamma_lut)
phytium_crtc_gamma_set(crtc);
else
phytium_crtc_gamma_init(crtc);
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
drm_crtc_vblank_on(crtc);
}
static void
phytium_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
drm_crtc_vblank_off(crtc);
phytium_crtc->dc_hw_disable(crtc);
}
static void phytium_crtc_update_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,
const struct drm_display_mode *native_mode)
{
if (native_mode->clock == drm_mode->clock &&
native_mode->htotal == drm_mode->htotal &&
native_mode->vtotal == drm_mode->vtotal) {
drm_mode->crtc_hdisplay = native_mode->crtc_hdisplay;
drm_mode->crtc_vdisplay = native_mode->crtc_vdisplay;
drm_mode->crtc_clock = native_mode->crtc_clock;
drm_mode->crtc_hblank_start = native_mode->crtc_hblank_start;
drm_mode->crtc_hblank_end = native_mode->crtc_hblank_end;
drm_mode->crtc_hsync_start = native_mode->crtc_hsync_start;
drm_mode->crtc_hsync_end = native_mode->crtc_hsync_end;
drm_mode->crtc_htotal = native_mode->crtc_htotal;
drm_mode->crtc_hskew = native_mode->crtc_hskew;
drm_mode->crtc_vblank_start = native_mode->crtc_vblank_start;
drm_mode->crtc_vblank_end = native_mode->crtc_vblank_end;
drm_mode->crtc_vsync_start = native_mode->crtc_vsync_start;
drm_mode->crtc_vsync_end = native_mode->crtc_vsync_end;
drm_mode->crtc_vtotal = native_mode->crtc_vtotal;
}
}
static int
phytium_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
{
struct drm_atomic_state *state = crtc_state->state;
struct drm_plane_state *new_plane_state = NULL;
int ret = 0;
struct drm_connector *connector;
struct drm_connector_state *new_con_state;
uint32_t i;
struct phytium_dp_device *phytium_dp = NULL;
for_each_new_connector_in_state(state, connector, new_con_state, i) {
if (new_con_state->crtc == crtc) {
phytium_dp = connector_to_dp_device(connector);
break;
}
}
if (phytium_dp)
phytium_crtc_update_timing_for_drm_display_mode(&crtc_state->adjusted_mode,
&phytium_dp->native_mode);
new_plane_state = drm_atomic_get_new_plane_state(crtc_state->state,
crtc->primary);
if (crtc_state->enable && new_plane_state && !new_plane_state->crtc) {
ret = -EINVAL;
goto fail;
}
return 0;
fail:
return ret;
}
static void
phytium_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe, config;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (config & FRAMEBUFFER_RESET) {
phytium_writel_reg(priv, config | FRAMEBUFFER_VALID_PENDING,
group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
}
}
static void phytium_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
struct phytium_crtc_state *phytium_crtc_state = NULL;
int phys_pipe = phytium_crtc->phys_pipe, config;
uint32_t group_offset = priv->dc_reg_base[phys_pipe];
DRM_DEBUG_KMS("crtc->state active:%d enable:%d\n",
crtc->state->active, crtc->state->enable);
phytium_crtc_state = to_phytium_crtc_state(crtc->state);
if (crtc->state->color_mgmt_changed)
phytium_crtc_gamma_set(crtc);
config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
phytium_writel_reg(priv, config&(~FRAMEBUFFER_VALID_PENDING),
group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (crtc->state->event) {
DRM_DEBUG_KMS("vblank->refcount:%d\n",
atomic_read(&dev->vblank[0].refcount));
spin_lock_irq(&dev->event_lock);
if (drm_crtc_vblank_get(crtc) == 0)
drm_crtc_arm_vblank_event(crtc, crtc->state->event);
else
drm_crtc_send_vblank_event(crtc, crtc->state->event);
crtc->state->event = NULL;
spin_unlock_irq(&dev->event_lock);
}
}
static enum drm_mode_status
phytium_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
if (mode->crtc_clock > priv->info.crtc_clock_max)
return MODE_CLOCK_HIGH;
if (mode->hdisplay > priv->info.hdisplay_max)
return MODE_BAD_HVALUE;
if (mode->vdisplay > priv->info.vdisplay_max)
return MODE_BAD_VVALUE;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
return MODE_NO_INTERLACE;
return MODE_OK;
}
static const struct drm_crtc_helper_funcs phytium_crtc_helper_funcs = {
.mode_valid = phytium_crtc_mode_valid,
.atomic_check = phytium_crtc_atomic_check,
.atomic_begin = phytium_crtc_atomic_begin,
.atomic_flush = phytium_crtc_atomic_flush,
.atomic_enable = phytium_crtc_atomic_enable,
.atomic_disable = phytium_crtc_atomic_disable,
};
void phytium_crtc_resume(struct drm_device *drm_dev)
{
struct drm_crtc *crtc;
struct phytium_crtc *phytium_crtc = NULL;
drm_for_each_crtc(crtc, drm_dev) {
phytium_crtc = to_phytium_crtc(crtc);
if (phytium_crtc->dc_hw_reset)
phytium_crtc->dc_hw_reset(crtc);
phytium_crtc_gamma_init(crtc);
}
}
int phytium_crtc_init(struct drm_device *dev, int phys_pipe)
{
struct phytium_crtc *phytium_crtc;
struct phytium_crtc_state *phytium_crtc_state;
struct phytium_plane *phytium_primary_plane = NULL;
struct phytium_plane *phytium_cursor_plane = NULL;
struct phytium_display_private *priv = dev->dev_private;
int ret;
phytium_crtc = kzalloc(sizeof(*phytium_crtc), GFP_KERNEL);
if (!phytium_crtc) {
ret = -ENOMEM;
goto failed_malloc_crtc;
}
phytium_crtc_state = kzalloc(sizeof(*phytium_crtc_state), GFP_KERNEL);
if (!phytium_crtc_state) {
ret = -ENOMEM;
goto failed_malloc_crtc_state;
}
phytium_crtc_state->base.crtc = &phytium_crtc->base;
phytium_crtc->base.state = &phytium_crtc_state->base;
phytium_crtc->phys_pipe = phys_pipe;
if (IS_PX210(priv)) {
phytium_crtc->dc_hw_config_pix_clock = px210_dc_hw_config_pix_clock;
phytium_crtc->dc_hw_disable = px210_dc_hw_disable;
phytium_crtc->dc_hw_reset = NULL;
priv->dc_reg_base[phys_pipe] = PX210_DC_BASE(phys_pipe);
priv->dcreq_reg_base[phys_pipe] = PX210_DCREQ_BASE(phys_pipe);
priv->address_transform_base = PX210_ADDRESS_TRANSFORM_BASE;
} else if (IS_PE220X(priv)) {
phytium_crtc->dc_hw_config_pix_clock = pe220x_dc_hw_config_pix_clock;
phytium_crtc->dc_hw_disable = pe220x_dc_hw_disable;
phytium_crtc->dc_hw_reset = pe220x_dc_hw_reset;
priv->dc_reg_base[phys_pipe] = PE220X_DC_BASE(phys_pipe);
priv->dcreq_reg_base[phys_pipe] = 0x0;
priv->address_transform_base = PE220X_ADDRESS_TRANSFORM_BASE;
}
phytium_primary_plane = phytium_primary_plane_create(dev, phys_pipe);
if (IS_ERR(phytium_primary_plane)) {
ret = PTR_ERR(phytium_primary_plane);
DRM_ERROR("create primary plane failed, phys_pipe(%d)\n", phys_pipe);
goto failed_create_primary;
}
phytium_cursor_plane = phytium_cursor_plane_create(dev, phys_pipe);
if (IS_ERR(phytium_cursor_plane)) {
ret = PTR_ERR(phytium_cursor_plane);
DRM_ERROR("create cursor plane failed, phys_pipe(%d)\n", phys_pipe);
goto failed_create_cursor;
}
ret = drm_crtc_init_with_planes(dev, &phytium_crtc->base,
&phytium_primary_plane->base,
&phytium_cursor_plane->base,
&phytium_crtc_funcs,
"phys_pipe %d", phys_pipe);
if (ret) {
DRM_ERROR("init crtc with plane failed, phys_pipe(%d)\n", phys_pipe);
goto failed_crtc_init;
}
drm_crtc_helper_add(&phytium_crtc->base, &phytium_crtc_helper_funcs);
drm_crtc_vblank_reset(&phytium_crtc->base);
drm_mode_crtc_set_gamma_size(&phytium_crtc->base, GAMMA_INDEX_MAX);
drm_crtc_enable_color_mgmt(&phytium_crtc->base, 0, false, GAMMA_INDEX_MAX);
if (phytium_crtc->dc_hw_reset)
phytium_crtc->dc_hw_reset(&phytium_crtc->base);
return 0;
failed_crtc_init:
failed_create_cursor:
/* drm_mode_config_cleanup() will free any crtcs/planes already initialized */
failed_create_primary:
kfree(phytium_crtc_state);
failed_malloc_crtc_state:
kfree(phytium_crtc);
failed_malloc_crtc:
return ret;
}

View File

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_CRTC_H__
#define __PHYTIUM_CRTC_H__
struct phytium_crtc {
struct drm_crtc base;
int phys_pipe;
unsigned int bpc;
/* scale */
uint32_t src_width;
uint32_t src_height;
uint32_t dst_width;
uint32_t dst_height;
uint32_t dst_x;
uint32_t dst_y;
bool scale_enable;
bool reserve[3];
void (*dc_hw_config_pix_clock)(struct drm_crtc *crtc, int clock);
void (*dc_hw_disable)(struct drm_crtc *crtc);
void (*dc_hw_reset)(struct drm_crtc *crtc);
};
struct phytium_crtc_state {
struct drm_crtc_state base;
};
#define to_phytium_crtc(x) container_of(x, struct phytium_crtc, base)
#define to_phytium_crtc_state(x) container_of(x, struct phytium_crtc_state, base)
void phytium_crtc_resume(struct drm_device *drm_dev);
int phytium_crtc_init(struct drm_device *dev, int pipe);
#endif /* __PHYTIUM_CRTC_H__ */

View File

@ -0,0 +1,456 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <drm/drm_file.h>
#include "phytium_display_drv.h"
#include "phytium_dp.h"
#include "phytium_reg.h"
const char *const mem_state[PHYTIUM_MEM_STATE_TYPE_COUNT] = {
"Memory_Vram_Total",
"Memory_Vram_Alloc",
"Memory_System_Carveout_Total",
"Memory_System_Carveout_Alloc",
"Memory_System_Alloc",
};
static ssize_t
phytium_dp_register_write(struct file *filp,
const char __user *ubuf,
size_t len,
loff_t *ppos)
{
char tmp[16];
if (len >= sizeof(tmp))
return -EINVAL;
memset(tmp, 0, sizeof(tmp));
if (copy_from_user(tmp, ubuf, len))
return -EFAULT;
tmp[len] = '\0';
return len;
}
static int phytium_dp_register_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
struct drm_device *dev = phytium_dp->dev;
struct phytium_display_private *priv = dev->dev_private;
int port = phytium_dp->port;
uint32_t group_offset = priv->dp_reg_base[port];
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_M_VID,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_M_VID));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_N_VID,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_N_VID));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_TRANSFER_UNIT_SIZE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_TRANSFER_UNIT_SIZE));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_DATA_COUNT,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_DATA_COUNT));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_MAIN_LINK_HTOTAL,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_HTOTAL));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_MAIN_LINK_HRES,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_HRES));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_MAIN_LINK_HSWIDTH,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_HSWIDTH));
seq_printf(m, "addr:h0x%08x h0x%08x\n", PHYTIUM_DP_MAIN_LINK_HSTART,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_HSTART));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_VTOTAL,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_VTOTAL));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_VRES,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_VRES));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_VSWIDTH,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_VSWIDTH));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_VSTART,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_VSTART));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_POLARITY,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_POLARITY));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_MISC0,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_MISC0));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_MAIN_LINK_MISC1,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_MAIN_LINK_MISC1));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_USER_SYNC_POLARITY,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_USER_SYNC_POLARITY));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_VIDEO_STREAM_ENABLE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_VIDEO_STREAM_ENABLE));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SECONDARY_STREAM_ENABLE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SECONDARY_STREAM_ENABLE));
seq_puts(m, "audio:\n");
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_INPUT_SELECT,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_INPUT_SELECT));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_DIRECT_CLKDIV,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_DIRECT_CLKDIV));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CHANNEL_COUNT,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CHANNEL_COUNT));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CHANNEL_MAP,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CHANNEL_MAP));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_DATA_WINDOW,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_DATA_WINDOW));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CS_CATEGORY_CODE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CS_CATEGORY_CODE));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_MAUD,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_MAUD));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_NAUD,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_NAUD));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CLOCK_MODE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CLOCK_MODE));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CS_SOURCE_FORMAT,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CS_SOURCE_FORMAT));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CS_LENGTH_ORIG_FREQ,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CS_LENGTH_ORIG_FREQ));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_CS_FREQ_CLOCK_ACCURACY,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_CS_FREQ_CLOCK_ACCURACY));
seq_printf(m, "addr:h'0x%08x h'0x%08x\n", PHYTIUM_DP_SEC_AUDIO_ENABLE,
phytium_readl_reg(priv, group_offset, PHYTIUM_DP_SEC_AUDIO_ENABLE));
return 0;
}
static int phytium_dp_register_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_dp_register_show, inode->i_private);
}
static const struct file_operations phytium_dp_register_fops = {
.owner = THIS_MODULE,
.open = phytium_dp_register_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = phytium_dp_register_write,
};
static ssize_t
phytium_dp_trigger_train_fail_write(struct file *filp,
const char __user *ubuf,
size_t len,
loff_t *ppos)
{
struct seq_file *m = filp->private_data;
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
char tmp[16];
if (len >= sizeof(tmp))
return -EINVAL;
memset(tmp, 0, sizeof(tmp));
if (copy_from_user(tmp, ubuf, len))
return -EFAULT;
tmp[len] = '\0';
if (kstrtouint(tmp, 10, &phytium_dp->trigger_train_fail) != 0)
return -EINVAL;
return len;
}
static int phytium_dp_trigger_train_fail_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
seq_printf(m, "trigger_train_fail: %d\n", phytium_dp->trigger_train_fail);
seq_printf(m, "train_retry_count: %d\n", phytium_dp->train_retry_count);
return 0;
}
static int phytium_dp_trigger_train_fail_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_dp_trigger_train_fail_show, inode->i_private);
}
static const struct file_operations phytium_dp_trigger_train_fail_fops = {
.owner = THIS_MODULE,
.open = phytium_dp_trigger_train_fail_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = phytium_dp_trigger_train_fail_write,
};
static int phytium_edp_backlight_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
if (!phytium_dp->is_edp)
return -ENODEV;
mutex_lock(&phytium_dp->panel.panel_lock);
seq_printf(m, "backlight: %s\n", phytium_dp->panel.backlight_enabled?"enabled":"disabled");
mutex_unlock(&phytium_dp->panel.panel_lock);
return 0;
}
static int phytium_edp_backlight_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_edp_backlight_show, inode->i_private);
}
static const struct file_operations phytium_edp_backlight_fops = {
.owner = THIS_MODULE,
.open = phytium_edp_backlight_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int phytium_edp_power_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
if (!phytium_dp->is_edp)
return -ENODEV;
mutex_lock(&phytium_dp->panel.panel_lock);
seq_printf(m, "power: %s\n", phytium_dp->panel.power_enabled?"enabled":"disabled");
mutex_unlock(&phytium_dp->panel.panel_lock);
return 0;
}
static int phytium_edp_power_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_edp_power_show, inode->i_private);
}
static const struct file_operations phytium_edp_power_fops = {
.owner = THIS_MODULE,
.open = phytium_edp_power_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
struct dpcd_block {
/* DPCD dump start address. */
unsigned int offset;
/* DPCD dump end address, inclusive. If unset, .size will be used. */
unsigned int end;
/* DPCD dump size. Used if .end is unset. If unset, defaults to 1. */
size_t size;
/* Only valid for eDP. */
bool edp;
};
static const struct dpcd_block phytium_dpcd_debug[] = {
{ .offset = DP_DPCD_REV, .size = DP_RECEIVER_CAP_SIZE },
{ .offset = DP_PSR_SUPPORT, .end = DP_PSR_CAPS },
{ .offset = DP_DOWNSTREAM_PORT_0, .size = 16 },
{ .offset = DP_LINK_BW_SET, .end = DP_EDP_CONFIGURATION_SET },
{ .offset = DP_SINK_COUNT, .end = DP_ADJUST_REQUEST_LANE2_3 },
{ .offset = DP_SET_POWER },
{ .offset = DP_EDP_DPCD_REV },
{ .offset = DP_EDP_GENERAL_CAP_1, .end = DP_EDP_GENERAL_CAP_3 },
{ .offset = DP_EDP_DISPLAY_CONTROL_REGISTER, .end = DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB },
{ .offset = DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, .end = DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET },
{ .offset = DP_DEVICE_SERVICE_IRQ_VECTOR, .size = 1 },
{ .offset = DP_TEST_REQUEST, .end = DP_TEST_PATTERN },
};
static int phytium_dpcd_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
uint8_t buf[16], i;
ssize_t err;
if (connector->status != connector_status_connected)
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(phytium_dpcd_debug); i++) {
const struct dpcd_block *b = &phytium_dpcd_debug[i];
size_t size = b->end ? b->end - b->offset + 1 : (b->size ?: 1);
if (WARN_ON(size > sizeof(buf)))
continue;
err = drm_dp_dpcd_read(&phytium_dp->aux, b->offset, buf, size);
if (err <= 0) {
DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n",
size, b->offset, err);
continue;
}
seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf);
}
return 0;
}
static int phytium_dpcd_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_dpcd_show, inode->i_private);
}
static const struct file_operations phytium_dpcd_fops = {
.owner = THIS_MODULE,
.open = phytium_dpcd_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static ssize_t
phytium_dp_state_write(struct file *filp,
const char __user *ubuf,
size_t len,
loff_t *ppos)
{
char tmp[16];
if (len >= sizeof(tmp))
return -EINVAL;
memset(tmp, 0, sizeof(tmp));
if (copy_from_user(tmp, ubuf, len))
return -EFAULT;
tmp[len] = '\0';
return len;
}
static int phytium_dp_state_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
seq_printf(m, "port number: %d\n", phytium_dp->port);
seq_printf(m, "source_max_lane_count: %d\n", phytium_dp->source_max_lane_count);
seq_printf(m, "max_source_rates: %d\n",
phytium_dp->source_rates[phytium_dp->num_source_rates-1]);
if (connector->status == connector_status_connected) {
seq_printf(m, "sink_max_lane_count: %d\n", phytium_dp->sink_max_lane_count);
seq_printf(m, "max_sink_rates: %d\n",
phytium_dp->sink_rates[phytium_dp->num_sink_rates-1]);
seq_printf(m, "link_rate: %d\n", phytium_dp->link_rate);
seq_printf(m, "link_lane_count: %d\n", phytium_dp->link_lane_count);
seq_printf(m, "train_set[0]: %d\n", phytium_dp->train_set[0]);
seq_printf(m, "has_audio: %s\n", phytium_dp->has_audio?"yes":"no");
}
return 0;
}
static int phytium_dp_state_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_dp_state_show, inode->i_private);
}
static const struct file_operations phytium_dp_state_fops = {
.owner = THIS_MODULE,
.open = phytium_dp_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = phytium_dp_state_write,
};
static const struct phytium_debugfs_files {
const char *name;
const struct file_operations *fops;
} phytium_debugfs_connector_files[] = {
{"dp_state", &phytium_dp_state_fops},
{"dpcd", &phytium_dpcd_fops},
{"dp_register", &phytium_dp_register_fops},
{"dp_trigger_train_fail", &phytium_dp_trigger_train_fail_fops},
};
static const struct phytium_debugfs_files phytium_edp_debugfs_connector_files[] = {
{"edp_power", &phytium_edp_power_fops},
{"edp_backlight", &phytium_edp_backlight_fops},
};
int phytium_debugfs_connector_add(struct drm_connector *connector)
{
struct dentry *root = connector->debugfs_entry;
struct dentry *ent;
int i;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
if (!root)
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(phytium_debugfs_connector_files); i++) {
ent = debugfs_create_file(phytium_debugfs_connector_files[i].name,
0644,
root,
connector,
phytium_debugfs_connector_files[i].fops);
if (!ent)
return -ENOMEM;
}
if (phytium_dp->is_edp)
for (i = 0; i < ARRAY_SIZE(phytium_edp_debugfs_connector_files); i++) {
ent = debugfs_create_file(phytium_edp_debugfs_connector_files[i].name,
0644,
root,
connector,
phytium_edp_debugfs_connector_files[i].fops);
if (!ent)
return -ENOMEM;
}
return 0;
}
static int phytium_mem_state_show(struct seq_file *m, void *data)
{
struct phytium_display_private *priv = m->private;
uint8_t i;
for (i = 0; i < ARRAY_SIZE(mem_state); i++)
seq_printf(m, "%-34s %10lld\n", mem_state[i], priv->mem_state[i]);
return 0;
}
static int phytium_mem_state_open(struct inode *inode, struct file *file)
{
return single_open(file, phytium_mem_state_show, inode->i_private);
}
static const struct file_operations phytium_mem_state_fops = {
.owner = THIS_MODULE,
.open = phytium_mem_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static const struct phytium_debugfs_files phytium_debugfs_display_files[] = {
{"mem_state", &phytium_mem_state_fops},
};
int phytium_debugfs_display_register(struct phytium_display_private *priv)
{
struct drm_minor *minor = priv->dev->primary;
struct dentry *root = minor->debugfs_root;
struct dentry *ent;
if (!root)
return -ENODEV;
ent = debugfs_create_file(phytium_debugfs_display_files[0].name,
0644,
root,
priv,
phytium_debugfs_display_files[0].fops);
if (!ent)
return -ENOMEM;
return 0;
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_DEBUGFS_H__
#define __PHYTIUM_DEBUGFS_H__
int phytium_debugfs_connector_add(struct drm_connector *connector);
int phytium_debugfs_display_register(struct phytium_display_private *priv);
#endif /* __PHYTIUM_DEBUGFS_H__ */

View File

@ -0,0 +1,439 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_vblank.h>
#include <drm/drm_irq.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_drv.h>
#include <linux/atomic.h>
#include <drm/drm_atomic.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
#include "phytium_display_drv.h"
#include "phytium_plane.h"
#include "phytium_crtc.h"
#include "phytium_dp.h"
#include "phytium_gem.h"
#include "phytium_fb.h"
#include "phytium_fbdev.h"
#include "phytium_reg.h"
#include "phytium_pci.h"
#include "phytium_platform.h"
#include "phytium_debugfs.h"
int dc_fake_mode_enable;
module_param(dc_fake_mode_enable, int, 0644);
MODULE_PARM_DESC(dc_fake_mode_enable, "Enable DC fake mode (0-disabled; 1-enabled; default-0)");
int dc_fast_training_check = 1;
module_param(dc_fast_training_check, int, 0644);
MODULE_PARM_DESC(dc_fast_training_check, "Check dp fast training (0-disabled; 1-enabled; default-1)");
int num_source_rates = 4;
module_param(num_source_rates, int, 0644);
MODULE_PARM_DESC(num_source_rates, "set the source max rates (1-1.62Gbps; 2-2.7Gbps; 3-5.4Gbps; 4-8.1Gbps; default-4)");
int source_max_lane_count = 4;
module_param(source_max_lane_count, int, 0644);
MODULE_PARM_DESC(source_max_lane_count, "set the source lane count (1-1lane; 2-2lane; 4-4lane; default-4)");
int link_dynamic_adjust;
module_param(link_dynamic_adjust, int, 0644);
MODULE_PARM_DESC(link_dynamic_adjust, "dynamic select the train pamameter according to the display mode (0-disabled; 1-enabled; default-1)");
int phytium_wait_cmd_done(struct phytium_display_private *priv,
uint32_t register_offset,
uint32_t request_bit,
uint32_t reply_bit)
{
int timeout = 500, config = 0, ret = 0;
do {
mdelay(1);
timeout--;
config = phytium_readl_reg(priv, 0, register_offset);
} while ((!(config & reply_bit)) && timeout);
phytium_writel_reg(priv, config & (~request_bit), 0, register_offset);
if (timeout == 0) {
DRM_ERROR("wait cmd reply timeout\n");
ret = -EBUSY;
} else {
timeout = 500;
do {
mdelay(1);
timeout--;
config = phytium_readl_reg(priv, 0, register_offset);
} while ((config & reply_bit) && timeout);
if (timeout == 0) {
DRM_ERROR("clear cmd timeout\n");
ret = -EBUSY;
}
}
mdelay(5);
return ret;
}
static void phytium_irq_preinstall(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
int i, status;
for_each_pipe_masked(priv, i) {
status = phytium_readl_reg(priv, priv->dc_reg_base[i], PHYTIUM_DC_INT_STATUS);
phytium_writel_reg(priv, INT_DISABLE, priv->dc_reg_base[i], PHYTIUM_DC_INT_ENABLE);
}
}
static void phytium_irq_uninstall(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
int i, status;
for_each_pipe_masked(priv, i) {
status = phytium_readl_reg(priv, priv->dc_reg_base[i], PHYTIUM_DC_INT_STATUS);
phytium_writel_reg(priv, INT_DISABLE, priv->dc_reg_base[i], PHYTIUM_DC_INT_ENABLE);
}
}
static irqreturn_t phytium_display_irq_handler(int irq, void *data)
{
struct drm_device *dev = data;
struct phytium_display_private *priv = dev->dev_private;
bool enabled = 0;
int i = 0, virt_pipe = 0;
irqreturn_t ret = IRQ_NONE, ret1 = IRQ_NONE;
for_each_pipe_masked(priv, i) {
enabled = phytium_readl_reg(priv, priv->dc_reg_base[i], PHYTIUM_DC_INT_STATUS);
if (enabled & INT_STATUS) {
virt_pipe = phytium_get_virt_pipe(priv, i);
if (virt_pipe < 0)
return IRQ_NONE;
drm_handle_vblank(dev, virt_pipe);
ret = IRQ_HANDLED;
if (priv->dc_hw_clear_msi_irq)
priv->dc_hw_clear_msi_irq(priv, i);
}
}
ret1 = phytium_dp_hpd_irq_handler(priv);
if (ret == IRQ_HANDLED || ret1 == IRQ_HANDLED)
return IRQ_HANDLED;
return IRQ_NONE;
}
static const struct drm_mode_config_funcs phytium_mode_funcs = {
.fb_create = phytium_fb_create,
.output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
static void phytium_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
drm_atomic_helper_commit_modeset_disables(dev, state);
drm_atomic_helper_commit_planes(dev, state, false);
drm_atomic_helper_commit_modeset_enables(dev, state);
drm_atomic_helper_commit_hw_done(state);
drm_atomic_helper_wait_for_flip_done(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
}
static struct drm_mode_config_helper_funcs phytium_mode_config_helpers = {
.atomic_commit_tail = phytium_atomic_commit_tail,
};
static int phytium_modeset_init(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
int i = 0, ret;
drm_mode_config_init(dev);
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
dev->mode_config.max_width = 16384;
dev->mode_config.max_height = 16384;
dev->mode_config.cursor_width = 32;
dev->mode_config.cursor_height = 32;
dev->mode_config.preferred_depth = 24;
dev->mode_config.prefer_shadow = 1;
dev->mode_config.allow_fb_modifiers = true;
dev->mode_config.funcs = &phytium_mode_funcs;
dev->mode_config.helper_private = &phytium_mode_config_helpers;
for_each_pipe_masked(priv, i) {
ret = phytium_crtc_init(dev, i);
if (ret) {
DRM_ERROR("phytium_crtc_init(pipe %d) return failed\n", i);
goto failed_crtc_init;
}
}
for_each_pipe_masked(priv, i) {
ret = phytium_dp_init(dev, i);
if (ret) {
DRM_ERROR("phytium_dp_init(pipe %d) return failed\n", i);
goto failed_dp_init;
}
}
drm_mode_config_reset(dev);
return 0;
failed_dp_init:
failed_crtc_init:
drm_mode_config_cleanup(dev);
return ret;
}
int phytium_get_virt_pipe(struct phytium_display_private *priv, int phys_pipe)
{
int i = 0;
int virt_pipe = 0;
for_each_pipe_masked(priv, i) {
if (i != phys_pipe)
virt_pipe++;
else
return virt_pipe;
}
DRM_ERROR("%s %d failed\n", __func__, phys_pipe);
return -EINVAL;
}
int phytium_get_phys_pipe(struct phytium_display_private *priv, int virt_pipe)
{
int i = 0;
int tmp = 0;
for_each_pipe_masked(priv, i) {
if (tmp != virt_pipe)
tmp++;
else
return i;
}
DRM_ERROR("%s %d failed\n", __func__, virt_pipe);
return -EINVAL;
}
static int phytium_display_load(struct drm_device *dev, unsigned long flags)
{
struct phytium_display_private *priv = dev->dev_private;
int ret = 0;
ret = drm_vblank_init(dev, priv->info.num_pipes);
if (ret) {
DRM_ERROR("vblank init failed\n");
goto failed_vblank_init;
}
ret = phytium_modeset_init(dev);
if (ret) {
DRM_ERROR("phytium_modeset_init failed\n");
goto failed_modeset_init;
}
if (priv->support_memory_type & MEMORY_TYPE_VRAM)
priv->vram_hw_init(priv);
ret = drm_irq_install(dev, priv->irq);
if (ret) {
DRM_ERROR("install irq failed\n");
goto failed_irq_install;
}
ret = phytium_drm_fbdev_init(dev);
if (ret)
DRM_ERROR("failed to init dev\n");
phytium_debugfs_display_register(priv);
return ret;
failed_irq_install:
drm_mode_config_cleanup(dev);
failed_modeset_init:
failed_vblank_init:
return ret;
}
static void phytium_display_unload(struct drm_device *dev)
{
phytium_drm_fbdev_fini(dev);
drm_irq_uninstall(dev);
drm_mode_config_cleanup(dev);
}
static const struct drm_ioctl_desc phytium_ioctls[] = {
/* for test, none so far */
};
static const struct file_operations phytium_drm_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
.compat_ioctl = drm_compat_ioctl,
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
.mmap = phytium_gem_mmap,
};
struct drm_driver phytium_display_drm_driver = {
.driver_features = DRIVER_HAVE_IRQ |
DRIVER_MODESET |
DRIVER_ATOMIC |
DRIVER_GEM,
.load = phytium_display_load,
.unload = phytium_display_unload,
.lastclose = drm_fb_helper_lastclose,
.irq_handler = phytium_display_irq_handler,
.irq_preinstall = phytium_irq_preinstall,
.irq_uninstall = phytium_irq_uninstall,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = drm_gem_prime_export,
.gem_prime_import = drm_gem_prime_import,
.gem_prime_import_sg_table = phytium_gem_prime_import_sg_table,
.gem_prime_mmap = phytium_gem_prime_mmap,
.dumb_create = phytium_gem_dumb_create,
.dumb_destroy = phytium_gem_dumb_destroy,
.ioctls = phytium_ioctls,
.num_ioctls = ARRAY_SIZE(phytium_ioctls),
.fops = &phytium_drm_driver_fops,
.name = DRV_NAME,
.desc = DRV_DESC,
.date = DRV_DATE,
.major = DRV_MAJOR,
.minor = DRV_MINOR,
};
static void phytium_display_shutdown(struct drm_device *dev)
{
drm_atomic_helper_shutdown(dev);
}
static int phytium_display_pm_suspend(struct drm_device *dev)
{
struct drm_atomic_state *state;
struct phytium_display_private *priv = dev->dev_private;
int ret, ret1;
phytium_dp_hpd_irq_setup(dev, false);
cancel_work_sync(&priv->hotplug_work);
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
state = drm_atomic_helper_suspend(dev);
if (IS_ERR(state)) {
DRM_ERROR("drm_atomic_helper_suspend failed: %ld\n", PTR_ERR(state));
ret = PTR_ERR(state);
goto suspend_failed;
}
dev->mode_config.suspend_state = state;
ret = phytium_gem_suspend(dev);
if (ret) {
DRM_ERROR("phytium_gem_suspend failed: %d\n", ret);
goto gem_suspend_failed;
}
return 0;
gem_suspend_failed:
ret1 = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
if (ret1)
DRM_ERROR("Failed to resume (%d)\n", ret1);
dev->mode_config.suspend_state = NULL;
suspend_failed:
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
phytium_dp_hpd_irq_setup(dev, true);
return ret;
}
static int phytium_display_pm_resume(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
int ret = 0;
if (WARN_ON(!dev->mode_config.suspend_state))
return -EINVAL;
ret = phytium_dp_resume(dev);
if (ret)
return -EIO;
phytium_crtc_resume(dev);
phytium_gem_resume(dev);
if (priv->support_memory_type & MEMORY_TYPE_VRAM)
priv->vram_hw_init(priv);
ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
if (ret) {
DRM_ERROR("Failed to resume (%d)\n", ret);
return ret;
}
dev->mode_config.suspend_state = NULL;
drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
phytium_dp_hpd_irq_setup(dev, true);
return 0;
}
void phytium_display_private_init(struct phytium_display_private *priv, struct drm_device *dev)
{
INIT_LIST_HEAD(&priv->gem_list_head);
spin_lock_init(&priv->hotplug_irq_lock);
INIT_WORK(&priv->hotplug_work, phytium_dp_hpd_work_func);
memset(priv->mem_state, 0, sizeof(priv->mem_state));
priv->dev = dev;
priv->display_shutdown = phytium_display_shutdown;
priv->display_pm_suspend = phytium_display_pm_suspend;
priv->display_pm_resume = phytium_display_pm_resume;
}
static int __init phytium_display_init(void)
{
int ret = 0;
ret = platform_driver_register(&phytium_platform_driver);
if (ret)
return ret;
ret = pci_register_driver(&phytium_pci_driver);
return ret;
}
static void __exit phytium_display_exit(void)
{
pci_unregister_driver(&phytium_pci_driver);
platform_driver_unregister(&phytium_platform_driver);
}
module_init(phytium_display_init);
module_exit(phytium_display_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yang Xun <yangxun@phytium.com.cn>");
MODULE_AUTHOR("Shaojun Yang <yangshaojun@phytium.com.cn>");
MODULE_DESCRIPTION("Phytium Display Controller");

View File

@ -0,0 +1,178 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_DISPLAY_DRV_H__
#define __PHYTIUM_DISPLAY_DRV_H__
#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
#include <drm/drmP.h>
#endif
#include <drm/drm_print.h>
#include <drm/drm_fb_helper.h>
#define DEBUG_LOG 0
#define PHYTIUM_FORMAT_MAX_PLANE 3
#define DP_MAX_DOWNSTREAM_PORTS 0x10
#define DRV_NAME "dc"
#define DRV_DESC "phytium dc"
#define DRV_DATE "20201220"
#define DRV_MAJOR 1
#define DRV_MINOR 1
/* come from GPU */
#define DRM_FORMAT_MOD_VENDOR_PHYTIUM 0x92
/* dc:mode0 8x8 16bpp gpu: FBCDC_8X8_V10 */
#define DRM_FORMAT_MOD_PHYTIUM_TILE_MODE0_FBCDC fourcc_mod_code(PHYTIUM, 21)
/* dc:mode3 8x4 32bpp gpu: FBCDC_16X4_v10 */
#define DRM_FORMAT_MOD_PHYTIUM_TILE_MODE3_FBCDC fourcc_mod_code(PHYTIUM, 22)
#define PIPE_MASK_SHIFT 0x0
#define PIPE_MASK_MASK 0x7
#define EDP_MASK_SHIFT 0x3
#define EDP_MASK_MASK 0x7
enum phytium_platform {
PHYTIUM_PLATFORM_UNINITIALIZED = 0,
PHYTIUM_PLATFORM_PX210,
PHYTIUM_PLATFORM_PE220X,
};
enum phytium_mem_state_type {
PHYTIUM_MEM_VRAM_TOTAL = 0,
PHYTIUM_MEM_VRAM_ALLOC,
PHYTIUM_MEM_SYSTEM_CARVEOUT_TOTAL,
PHYTIUM_MEM_SYSTEM_CARVEOUT_ALLOC,
PHYTIUM_MEM_SYSTEM_UNIFIED_ALLOC,
PHYTIUM_MEM_STATE_TYPE_COUNT,
};
#define MEMORY_TYPE_VRAM 0x1
#define MEMORY_TYPE_SYSTEM_CARVEOUT 0x2
#define MEMORY_TYPE_SYSTEM_UNIFIED 0x4
#define IS_PLATFORM(priv, p) ((priv)->info.platform_mask & BIT(p))
#define IS_PX210(priv) IS_PLATFORM(priv, PHYTIUM_PLATFORM_PX210)
#define IS_PE220X(priv) IS_PLATFORM(priv, PHYTIUM_PLATFORM_PE220X)
struct phytium_device_info {
unsigned char platform_mask;
unsigned char pipe_mask;
unsigned char num_pipes;
unsigned char total_pipes;
unsigned char edp_mask;
unsigned int crtc_clock_max;
unsigned int hdisplay_max;
unsigned int vdisplay_max;
unsigned int backlight_max;
unsigned long address_mask;
};
struct phytium_display_private {
/* hw */
void __iomem *regs;
void __iomem *vram_addr;
struct phytium_device_info info;
char support_memory_type;
char reserve[3];
uint32_t dc_reg_base[3];
uint32_t dcreq_reg_base[3];
uint32_t dp_reg_base[3];
uint32_t address_transform_base;
uint32_t phy_access_base[3];
/* drm */
struct drm_device *dev;
int irq;
/* fb_dev */
struct drm_fb_helper fbdev_helper;
struct phytium_gem_object *fbdev_phytium_gem;
int save_reg[3];
struct list_head gem_list_head;
struct work_struct hotplug_work;
spinlock_t hotplug_irq_lock;
void (*vram_hw_init)(struct phytium_display_private *priv);
void (*display_shutdown)(struct drm_device *dev);
int (*display_pm_suspend)(struct drm_device *dev);
int (*display_pm_resume)(struct drm_device *dev);
void (*dc_hw_clear_msi_irq)(struct phytium_display_private *priv, uint32_t phys_pipe);
int (*dc_hw_fb_format_check)(const struct drm_mode_fb_cmd2 *mode_cmd, int count);
struct gen_pool *memory_pool;
resource_size_t pool_phys_addr;
resource_size_t pool_size;
void *pool_virt_addr;
uint64_t mem_state[PHYTIUM_MEM_STATE_TYPE_COUNT];
/* DMA info */
int dma_inited;
struct dma_chan *dma_chan;
};
static inline unsigned int
phytium_readl_reg(struct phytium_display_private *priv, uint32_t group_offset, uint32_t reg_offset)
{
unsigned int data;
data = readl(priv->regs + group_offset + reg_offset);
#if DEBUG_LOG
pr_info("Read 32'h%08x 32'h%08x\n", group_offset + reg_offset, data);
#endif
return data;
}
static inline void
phytium_writel_reg(struct phytium_display_private *priv, uint32_t data,
uint32_t group_offset, uint32_t reg_offset)
{
writel(data, priv->regs + group_offset + reg_offset);
#if DEBUG_LOG
pr_info("Write 32'h%08x 32'h%08x\n", group_offset + reg_offset, data);
#endif
}
static inline void
phytium_writeb_reg(struct phytium_display_private *priv, uint8_t data,
uint32_t group_offset, uint32_t reg_offset)
{
writeb(data, priv->regs + group_offset + reg_offset);
#if DEBUG_LOG
pr_info("Write 32'h%08x 8'h%08x\n", group_offset + reg_offset, data);
#endif
}
#define for_each_pipe(__dev_priv, __p) \
for ((__p) = 0; (__p) < __dev_priv->info.total_pipes; (__p)++)
#define for_each_pipe_masked(__dev_priv, __p) \
for ((__p) = 0; (__p) < __dev_priv->info.total_pipes; (__p)++) \
for_each_if((__dev_priv->info.pipe_mask) & BIT(__p))
int phytium_get_virt_pipe(struct phytium_display_private *priv, int phys_pipe);
int phytium_get_phys_pipe(struct phytium_display_private *priv, int virt_pipe);
int phytium_wait_cmd_done(struct phytium_display_private *priv,
uint32_t register_offset,
uint32_t request_bit,
uint32_t reply_bit);
void phytium_display_private_init(struct phytium_display_private *priv, struct drm_device *dev);
extern struct drm_driver phytium_display_drm_driver;
extern int dc_fake_mode_enable;
extern int dc_fast_training_check;
extern int num_source_rates;
extern int source_max_lane_count;
extern int link_dynamic_adjust;
#endif /* __PHYTIUM_DISPLAY_DRV_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,155 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_DP_H__
#define __PHYTIUM_DP_H__
#include <drm/drm_dp_helper.h>
#include <drm/drm_encoder.h>
#include <sound/hdmi-codec.h>
struct phytium_dp_device;
#include "phytium_panel.h"
struct audio_info {
int sample_rate;
int channels;
int sample_width;
};
struct dp_audio_n_m {
int sample_rate;
int link_rate;
u16 m;
u16 n;
};
struct phytium_dp_compliance {
unsigned long test_type;
uint32_t test_link_rate;
u8 test_lane_count;
bool test_active;
u8 reserve[2];
};
struct phytium_dp_func {
uint8_t (*dp_hw_get_source_lane_count)(struct phytium_dp_device *phytium_dp);
int (*dp_hw_reset)(struct phytium_dp_device *phytium_dp);
bool (*dp_hw_spread_is_enable)(struct phytium_dp_device *phytium_dp);
int (*dp_hw_set_backlight)(struct phytium_dp_device *phytium_dp, uint32_t level);
uint32_t (*dp_hw_get_backlight)(struct phytium_dp_device *phytium_dp);
void (*dp_hw_disable_backlight)(struct phytium_dp_device *phytium_dp);
void (*dp_hw_enable_backlight)(struct phytium_dp_device *phytium_dp);
void (*dp_hw_poweroff_panel)(struct phytium_dp_device *phytium_dp);
void (*dp_hw_poweron_panel)(struct phytium_dp_device *phytium_dp);
int (*dp_hw_init_phy)(struct phytium_dp_device *phytium_dp);
void (*dp_hw_set_phy_lane_setting)(struct phytium_dp_device *phytium_dp,
uint32_t link_rate, uint8_t train_set);
int (*dp_hw_set_phy_lane_and_rate)(struct phytium_dp_device *phytium_dp,
uint8_t link_lane_count,
uint32_t link_rate);
};
struct phytium_dp_hpd_state {
bool hpd_event_state;
bool hpd_irq_state;
bool hpd_raw_state;
bool hpd_irq_enable;
};
struct phytium_dp_device {
struct drm_device *dev;
struct drm_encoder encoder;
struct drm_connector connector;
int port;
struct drm_display_mode mode;
bool link_trained;
bool detect_done;
bool is_edp;
bool reserve0;
struct drm_dp_aux aux;
unsigned char dpcd[DP_RECEIVER_CAP_SIZE];
uint8_t edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
unsigned char downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
unsigned char sink_count;
int *source_rates;
int num_source_rates;
int sink_rates[DP_MAX_SUPPORTED_RATES];
int num_sink_rates;
int common_rates[DP_MAX_SUPPORTED_RATES];
int num_common_rates;
int source_max_lane_count;
int sink_max_lane_count;
int common_max_lane_count;
int max_link_rate;
int max_link_lane_count;
int link_rate;
int link_lane_count;
struct work_struct train_retry_work;
int train_retry_count;
uint32_t trigger_train_fail;
unsigned char train_set[4];
struct edid *edp_edid;
bool has_audio;
bool fast_train_support;
bool hw_spread_enable;
bool reserve[1];
struct platform_device *audio_pdev;
struct audio_info audio_info;
hdmi_codec_plugged_cb plugged_cb;
struct device *codec_dev;
struct phytium_dp_compliance compliance;
struct phytium_dp_func *funcs;
struct phytium_dp_hpd_state dp_hpd_state;
struct phytium_panel panel;
struct drm_display_mode native_mode;
};
union phytium_phy_tp {
struct {
/* DpcdPhyTestPatterns. This field is 2 bits for DP1.1
* and 3 bits for DP1.2.
*/
uint8_t PATTERN :3;
uint8_t RESERVED :5;
} bits;
uint8_t raw;
};
/* PHY test patterns
* The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248)
*/
enum phytium_dpcd_phy_tp {
PHYTIUM_PHY_TP_NONE = 0,
PHYTIUM_PHY_TP_D10_2,
PHYTIUM_PHY_TP_SYMBOL_ERROR,
PHYTIUM_PHY_TP_PRBS7,
PHYTIUM_PHY_TP_80BIT_CUSTOM,
PHYTIUM_PHY_TP_CP2520_1,
PHYTIUM_PHY_TP_CP2520_2,
PHYTIUM_PHY_TP_CP2520_3,
};
#define PHYTIUM_DP_AUDIO_ID (('P' << 24) + ('H' << 16) + ('Y' << 8))
#define encoder_to_dp_device(x) container_of(x, struct phytium_dp_device, encoder)
#define connector_to_dp_device(x) container_of(x, struct phytium_dp_device, connector)
#define panel_to_dp_device(x) container_of(x, struct phytium_dp_device, panel)
#define train_retry_to_dp_device(x) container_of(x, struct phytium_dp_device, train_retry_work)
void phytium_phy_writel(struct phytium_dp_device *phytium_dp, uint32_t address, uint32_t data);
uint32_t phytium_phy_readl(struct phytium_dp_device *phytium_dp, uint32_t address);
int phytium_dp_init(struct drm_device *dev, int pipe);
int phytium_dp_resume(struct drm_device *drm_dev);
void phytium_dp_hpd_irq_setup(struct drm_device *dev, bool enable);
irqreturn_t phytium_dp_hpd_irq_handler(struct phytium_display_private *priv);
void phytium_dp_hpd_work_func(struct work_struct *work);
const struct dp_audio_n_m *phytium_dp_audio_get_n_m(int link_rate, int sample_rate);
#endif /* __PHYTIUM_DP_H__ */

View File

@ -0,0 +1,143 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_gem.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_fourcc.h>
#include "phytium_display_drv.h"
#include "phytium_fb.h"
#include "phytium_gem.h"
static int
phytium_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file_priv,
unsigned int *handle)
{
struct phytium_framebuffer *phytium_fb = to_phytium_framebuffer(fb);
return drm_gem_handle_create(file_priv, &phytium_fb->phytium_gem_obj[0]->base, handle);
}
static void phytium_fb_destroy(struct drm_framebuffer *fb)
{
struct phytium_framebuffer *phytium_fb = to_phytium_framebuffer(fb);
int i, num_planes;
struct drm_gem_object *obj = NULL;
const struct drm_format_info *info;
info = drm_format_info(fb->format->format);
num_planes = info ? info->num_planes : 1;
for (i = 0; i < num_planes; i++) {
obj = &phytium_fb->phytium_gem_obj[i]->base;
if (obj)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
drm_gem_object_put(obj);
#else
drm_gem_object_unreference_unlocked(obj);
#endif
}
drm_framebuffer_cleanup(fb);
kfree(phytium_fb);
}
static struct drm_framebuffer_funcs viv_fb_funcs = {
.create_handle = phytium_fb_create_handle,
.destroy = phytium_fb_destroy,
};
struct phytium_framebuffer *
phytium_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
struct phytium_gem_object **phytium_gem_obj, unsigned int num_planes)
{
struct phytium_framebuffer *phytium_fb;
int ret = 0, i;
phytium_fb = kzalloc(sizeof(*phytium_fb), GFP_KERNEL);
if (!phytium_fb)
return ERR_PTR(-ENOMEM);
drm_helper_mode_fill_fb_struct(dev, &phytium_fb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &phytium_fb->base, &viv_fb_funcs);
if (ret) {
DRM_ERROR("Failed to initialize framebuffer: %d\n", ret);
kfree(phytium_fb);
return ERR_PTR(ret);
}
for (i = 0; i < num_planes; i++) {
phytium_fb->phytium_gem_obj[i] = phytium_gem_obj[i];
phytium_fb->base.obj[i] = &phytium_gem_obj[i]->base;
}
return phytium_fb;
}
struct drm_framebuffer *
phytium_fb_create(struct drm_device *dev, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
int ret = 0, i, num_planes;
struct drm_gem_object *obj;
unsigned int hsub, vsub, size;
struct phytium_gem_object *phytium_gem_obj[PHYTIUM_FORMAT_MAX_PLANE] = {0};
struct phytium_framebuffer *phytium_fb;
struct phytium_display_private *priv = dev->dev_private;
const struct drm_format_info *info;
info = drm_format_info(mode_cmd->pixel_format);
hsub = info ? info->hsub : 1;
vsub = info ? info->vsub : 1;
num_planes = info ? info->num_planes : 1;
num_planes = min(num_planes, PHYTIUM_FORMAT_MAX_PLANE);
for (i = 0; i < num_planes; i++) {
unsigned int height = mode_cmd->height / (i ? vsub : 1);
size = height * mode_cmd->pitches[i] + mode_cmd->offsets[i];
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
if (!obj) {
DRM_ERROR("Failed to lookup GEM object\n");
ret = -ENXIO;
goto error;
}
if (obj->size < size) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
drm_gem_object_put(obj);
#else
drm_gem_object_unreference_unlocked(obj);
#endif
ret = -EINVAL;
goto error;
}
phytium_gem_obj[i] = to_phytium_gem_obj(obj);
ret = priv->dc_hw_fb_format_check(mode_cmd, i);
if (ret < 0)
goto error;
}
phytium_fb = phytium_fb_alloc(dev, mode_cmd, phytium_gem_obj, i);
if (IS_ERR(phytium_fb)) {
DRM_DEBUG_KMS("phytium_fb_alloc failed\n");
ret = PTR_ERR(phytium_fb);
goto error;
}
return &phytium_fb->base;
error:
for (i--; i >= 0; i--)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
drm_gem_object_put(&phytium_gem_obj[i]->base);
#else
drm_gem_object_unreference_unlocked(&phytium_gem_obj[i]->base);
#endif
return ERR_PTR(ret);
}

View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_FB_H__
#define __PHYTIUM_FB_H__
#include <drm/drm_framebuffer.h>
struct phytium_framebuffer {
struct drm_framebuffer base;
struct phytium_gem_object *phytium_gem_obj[PHYTIUM_FORMAT_MAX_PLANE];
};
#define to_phytium_framebuffer(fb) container_of(fb, struct phytium_framebuffer, base)
struct phytium_framebuffer *phytium_fb_alloc(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct phytium_gem_object **phytium_gem_obj,
unsigned int num_planes);
struct drm_framebuffer *phytium_fb_create(struct drm_device *dev, struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd);
#endif /* __PHYTIUM_FB_H__ */

View File

@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fourcc.h>
#include "phytium_display_drv.h"
#include "phytium_gem.h"
#include "phytium_fb.h"
#define PHYTIUM_MAX_CONNECTOR 1
#define helper_to_drm_private(x) container_of(x, struct phytium_display_private, fbdev_helper)
static int phytium_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *helper = info->par;
struct phytium_display_private *priv = helper_to_drm_private(helper);
return phytium_gem_mmap_obj(&priv->fbdev_phytium_gem->base, vma);
}
static struct fb_ops phytium_fbdev_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_mmap = phytium_fbdev_mmap,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
};
static int
phytium_drm_fbdev_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes)
{
struct phytium_display_private *priv = helper_to_drm_private(helper);
struct drm_device *dev = helper->dev;
unsigned int bytes_per_pixel;
struct drm_mode_fb_cmd2 mode_cmd = {0};
struct phytium_framebuffer *phytium_fb = NULL;
struct fb_info *fbi = NULL;
struct drm_framebuffer *fb = NULL;
size_t size = 0;
int ret = 0;
unsigned long offset;
bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = ALIGN(sizes->surface_width * bytes_per_pixel, 128);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
size = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height);
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret < 0) {
DRM_ERROR("failed to get mutex lock\n");
return ret;
}
priv->fbdev_phytium_gem = phytium_gem_create_object(dev, size);
if (!priv->fbdev_phytium_gem) {
DRM_ERROR("failed to create gem object\n");
return -ENOMEM;
}
mutex_unlock(&dev->struct_mutex);
fbi = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(fbi)) {
DRM_DEV_ERROR(dev->dev, "Failed to create framebuffer info.");
ret = PTR_ERR(fbi);
goto out;
}
phytium_fb = phytium_fb_alloc(dev, &mode_cmd, &priv->fbdev_phytium_gem, 1);
if (IS_ERR(phytium_fb)) {
DRM_DEV_ERROR(dev->dev, "Failed to alloc DRM framebuffer.\n");
ret = PTR_ERR(phytium_fb);
goto out;
}
helper->fb = &(phytium_fb->base);
fbi->par = helper;
fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &phytium_fbdev_ops;
fb = helper->fb;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
#else
drm_fb_helper_fill_info(fbi, helper, sizes);
#endif
offset = fbi->var.xoffset * bytes_per_pixel;
offset += fbi->var.yoffset * fb->pitches[0];
dev->mode_config.fb_base = 0;
fbi->screen_base = priv->fbdev_phytium_gem->vaddr + offset;
fbi->screen_size = priv->fbdev_phytium_gem->base.size;
fbi->fix.smem_len = priv->fbdev_phytium_gem->base.size;
DRM_DEBUG_KMS("FB [%dx%d]-%d kvaddr=%pa offset=%ld size=%zu\n", fb->width, fb->height,
fb->format->depth, &priv->fbdev_phytium_gem->iova, offset, size);
fbi->skip_vt_switch = true;
return 0;
out:
phytium_gem_free_object(&priv->fbdev_phytium_gem->base);
return ret;
}
static const struct drm_fb_helper_funcs phytium_drm_fb_helper_funcs = {
.fb_probe = phytium_drm_fbdev_create,
};
int phytium_drm_fbdev_init(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
struct drm_fb_helper *helper;
int ret;
if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
return -EINVAL;
helper = &priv->fbdev_helper;
drm_fb_helper_prepare(dev, helper, &phytium_drm_fb_helper_funcs);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
ret = drm_fb_helper_init(dev, helper, PHYTIUM_MAX_CONNECTOR);
#else
ret = drm_fb_helper_init(dev, helper);
#endif
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "Failed to initialize drm fb helper -ret %d\n", ret);
return ret;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
ret = drm_fb_helper_single_add_all_connectors(helper);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "Failed to add connectors - %d/\n", ret);
goto err_drm_fb_helper_fini;
}
#endif
ret = drm_fb_helper_initial_config(helper, 32);
return ret;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
err_drm_fb_helper_fini:
drm_fb_helper_fini(helper);
return ret;
#endif
}
void phytium_drm_fbdev_fini(struct drm_device *dev)
{
struct phytium_display_private *priv = dev->dev_private;
struct drm_fb_helper *helper;
helper = &priv->fbdev_helper;
drm_fb_helper_unregister_fbi(helper);
if (helper->fb)
drm_framebuffer_put(helper->fb);
drm_fb_helper_fini(helper);
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef _PHYTIUM_FBDEV_H
#define _PHYTIUM_FBDEV_H
int phytium_drm_fbdev_init(struct drm_device *dev);
void phytium_drm_fbdev_fini(struct drm_device *dev);
#endif /* _PHYTIUM_FBDEV_H */

View File

@ -0,0 +1,535 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/dma-buf.h>
#include <linux/vmalloc.h>
#include <linux/version.h>
#include <linux/mm_types.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/genalloc.h>
#include <drm/drm_prime.h>
#include <linux/dmaengine.h>
#include <linux/completion.h>
#include "phytium_display_drv.h"
#include "phytium_gem.h"
#define VRAM_POOL_ALLOC_ORDER 12
int phytium_memory_pool_alloc(struct phytium_display_private *priv, void **pvaddr,
phys_addr_t *phys_addr, uint64_t size)
{
unsigned long vaddr;
vaddr = gen_pool_alloc(priv->memory_pool, size);
if (!vaddr)
return -ENOMEM;
*phys_addr = gen_pool_virt_to_phys(priv->memory_pool, vaddr);
*pvaddr = (void *)vaddr;
return 0;
}
void phytium_memory_pool_free(struct phytium_display_private *priv, void *vaddr, uint64_t size)
{
gen_pool_free(priv->memory_pool, (unsigned long)vaddr, size);
}
int phytium_memory_pool_init(struct device *dev, struct phytium_display_private *priv)
{
int ret = 0;
priv->memory_pool = gen_pool_create(VRAM_POOL_ALLOC_ORDER, -1);
if (priv->memory_pool == NULL) {
DRM_ERROR("fail to create memory pool\n");
ret = -1;
goto failed_create_pool;
}
ret = gen_pool_add_virt(priv->memory_pool, (unsigned long)priv->pool_virt_addr,
priv->pool_phys_addr, priv->pool_size, -1);
if (ret) {
DRM_ERROR("fail to add vram pool\n");
ret = -1;
goto failed_add_pool_virt;
}
return 0;
failed_add_pool_virt:
gen_pool_destroy(priv->memory_pool);
failed_create_pool:
return ret;
}
void phytium_memory_pool_fini(struct device *dev, struct phytium_display_private *priv)
{
gen_pool_destroy(priv->memory_pool);
}
struct sg_table *
phytium_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct phytium_gem_object *phytium_gem_obj = to_phytium_gem_obj(obj);
struct sg_table *sgt;
struct drm_device *dev = obj->dev;
int ret;
struct page *page = NULL;
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) {
DRM_DEBUG_KMS("malloc sgt fail\n");
return ERR_PTR(-ENOMEM);
}
if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) ||
(phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT)) {
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
if (ret) {
DRM_ERROR("failed to allocate sg\n");
goto sgt_free;
}
page = phys_to_page(phytium_gem_obj->phys_addr);
sg_set_page(sgt->sgl, page, PAGE_ALIGN(phytium_gem_obj->size), 0);
} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_UNIFIED) {
ret = dma_get_sgtable_attrs(dev->dev, sgt, phytium_gem_obj->vaddr,
phytium_gem_obj->iova, phytium_gem_obj->size,
DMA_ATTR_WRITE_COMBINE);
if (ret) {
DRM_ERROR("failed to allocate sgt, %d\n", ret);
goto sgt_free;
}
}
return sgt;
sgt_free:
kfree(sgt);
return ERR_PTR(ret);
}
struct drm_gem_object *
phytium_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach,
struct sg_table *sgt)
{
struct phytium_gem_object *phytium_gem_obj = NULL;
struct scatterlist *s;
dma_addr_t expected;
int ret, i;
phytium_gem_obj = kzalloc(sizeof(*phytium_gem_obj), GFP_KERNEL);
if (!phytium_gem_obj) {
DRM_ERROR("failed to allocate phytium_gem_obj\n");
ret = -ENOMEM;
goto failed_malloc;
}
ret = drm_gem_object_init(dev, &phytium_gem_obj->base, attach->dmabuf->size);
if (ret) {
DRM_ERROR("failed to initialize drm gem object: %d\n", ret);
goto failed_object_init;
}
expected = sg_dma_address(sgt->sgl);
for_each_sg(sgt->sgl, s, sgt->nents, i) {
if (sg_dma_address(s) != expected) {
DRM_ERROR("sg_table is not contiguous");
ret = -EINVAL;
goto failed_check_continue;
}
expected = sg_dma_address(s) + sg_dma_len(s);
}
phytium_gem_obj->iova = sg_dma_address(sgt->sgl);
phytium_gem_obj->sgt = sgt;
return &phytium_gem_obj->base;
failed_check_continue:
drm_gem_object_release(&phytium_gem_obj->base);
failed_object_init:
kfree(phytium_gem_obj);
failed_malloc:
return ERR_PTR(ret);
}
void *phytium_gem_prime_vmap(struct drm_gem_object *obj)
{
struct phytium_gem_object *phytium_obj = to_phytium_gem_obj(obj);
return phytium_obj->vaddr;
}
void phytium_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
{
return;
}
int phytium_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
int ret = 0;
ret = drm_gem_mmap_obj(obj, obj->size, vma);
if (ret < 0)
return ret;
return phytium_gem_mmap_obj(obj, vma);
}
static void phytium_dma_callback(void *callback_param)
{
struct completion *comp = callback_param;
complete(comp);
}
int phytium_dma_transfer(struct drm_device *drm_dev, int dev_to_mem, void *addr,
dma_addr_t iova, uint64_t size)
{
struct phytium_display_private *priv = drm_dev->dev_private;
struct dma_chan *dma_chan = priv->dma_chan;
struct sg_table st;
struct scatterlist *sgl;
int ret = 0, timeout;
uint32_t nents, i;
struct dma_slave_config cfg = {0};
struct dma_async_tx_descriptor *desc;
struct completion comp;
enum dma_data_direction dir;
size_t min = 0;
nents = DIV_ROUND_UP(size, PAGE_SIZE);
ret = sg_alloc_table(&st, nents, GFP_KERNEL);
if (ret) {
DRM_ERROR("failed to allocate sg_table\n");
ret = -ENOMEM;
goto failed_sg_alloc_table;
}
for_each_sg(st.sgl, sgl, st.nents, i) {
min = min_t(size_t, size, PAGE_SIZE - offset_in_page(addr));
sg_set_page(sgl, vmalloc_to_page(addr), min, offset_in_page(addr));
addr += min;
size -= min;
}
memset(&cfg, 0, sizeof(cfg));
if (dev_to_mem) {
cfg.direction = DMA_DEV_TO_MEM;
cfg.src_addr = iova;
cfg.dst_addr = 0;
dir = DMA_FROM_DEVICE;
} else {
cfg.direction = DMA_MEM_TO_DEV;
cfg.src_addr = 0;
cfg.dst_addr = iova;
dir = DMA_TO_DEVICE;
}
dmaengine_slave_config(dma_chan, &cfg);
nents = dma_map_sg(dma_chan->device->dev, st.sgl, st.nents, dir);
if (!nents) {
DRM_DEV_ERROR(drm_dev->dev, "failed to dma_map_sg for dmaengine\n");
ret = -EINVAL;
goto failed_dma_map_sg;
}
st.nents = nents;
dma_sync_sg_for_device(dma_chan->device->dev, st.sgl, st.nents, dir);
sgl = st.sgl;
desc = dmaengine_prep_slave_sg(dma_chan,
st.sgl,
st.nents,
cfg.direction,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
DRM_DEV_ERROR(drm_dev->dev, "failed to dmaengine_prep_slave_sg\n");
ret = -EINVAL;
goto failed_prep_slave_sg;
}
init_completion(&comp);
desc->callback = phytium_dma_callback;
desc->callback_param = &comp;
dmaengine_submit(desc);
dma_async_issue_pending(dma_chan);
timeout = wait_for_completion_timeout(&comp, 2 * HZ);
if (timeout == 0) {
DRM_DEV_ERROR(drm_dev->dev, "wait for dma callback timeout\n");
ret = -EIO;
}
dma_sync_sg_for_cpu(dma_chan->device->dev, st.sgl, st.nents, dir);
failed_prep_slave_sg:
dma_unmap_sg(dma_chan->device->dev, st.sgl, st.nents, dir);
failed_dma_map_sg:
sg_free_table(&st);
failed_sg_alloc_table:
return ret;
}
int phytium_gem_suspend(struct drm_device *drm_dev)
{
struct phytium_display_private *priv = drm_dev->dev_private;
struct phytium_gem_object *phytium_gem_obj = NULL;
int ret = 0;
list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
continue;
phytium_gem_obj->vaddr_save = vmalloc(phytium_gem_obj->size);
if (!phytium_gem_obj->vaddr_save)
goto malloc_failed;
if (priv->dma_inited)
ret = phytium_dma_transfer(drm_dev, 1, phytium_gem_obj->vaddr_save,
phytium_gem_obj->iova, phytium_gem_obj->size);
if ((!priv->dma_inited) || ret)
memcpy(phytium_gem_obj->vaddr_save, phytium_gem_obj->vaddr,
phytium_gem_obj->size);
}
return 0;
malloc_failed:
list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
continue;
if (phytium_gem_obj->vaddr_save) {
vfree(phytium_gem_obj->vaddr_save);
phytium_gem_obj->vaddr_save = NULL;
}
}
return -ENOMEM;
}
void phytium_gem_resume(struct drm_device *drm_dev)
{
struct phytium_display_private *priv = drm_dev->dev_private;
struct phytium_gem_object *phytium_gem_obj = NULL;
list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
continue;
memcpy(phytium_gem_obj->vaddr, phytium_gem_obj->vaddr_save, phytium_gem_obj->size);
vfree(phytium_gem_obj->vaddr_save);
phytium_gem_obj->vaddr_save = NULL;
}
}
void phytium_gem_free_object(struct drm_gem_object *obj)
{
struct phytium_gem_object *phytium_gem_obj = to_phytium_gem_obj(obj);
struct drm_device *dev = obj->dev;
struct phytium_display_private *priv = dev->dev_private;
uint64_t size = phytium_gem_obj->size;
DRM_DEBUG_KMS("free phytium_gem_obj iova:0x%pa size:0x%lx\n",
&phytium_gem_obj->iova, phytium_gem_obj->size);
if (phytium_gem_obj->vaddr) {
if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) {
phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size);
priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] -= size;
} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) {
dma_unmap_page(dev->dev, phytium_gem_obj->iova, size, DMA_TO_DEVICE);
phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size);
priv->mem_state[PHYTIUM_MEM_SYSTEM_CARVEOUT_ALLOC] -= size;
} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_UNIFIED) {
dma_free_attrs(dev->dev, size, phytium_gem_obj->vaddr,
phytium_gem_obj->iova, 0);
priv->mem_state[PHYTIUM_MEM_SYSTEM_UNIFIED_ALLOC] -= size;
}
list_del(&phytium_gem_obj->list);
} else if (obj->import_attach)
drm_prime_gem_destroy(obj, phytium_gem_obj->sgt);
drm_gem_object_release(obj);
kfree(phytium_gem_obj);
}
int phytium_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
int ret = 0;
struct phytium_gem_object *phytium_gem_obj = to_phytium_gem_obj(obj);
unsigned long pfn = PHYS_PFN(phytium_gem_obj->phys_addr);
/*
* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
* the whole buffer.
*/
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) {
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
ret = remap_pfn_range(vma, vma->vm_start, pfn,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) {
ret = remap_pfn_range(vma, vma->vm_start, pfn,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_UNIFIED) {
ret = dma_mmap_attrs(obj->dev->dev, vma, phytium_gem_obj->vaddr,
phytium_gem_obj->iova, vma->vm_end - vma->vm_start, 0);
}
if (ret)
drm_gem_vm_close(vma);
return ret;
}
int phytium_gem_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret = 0;
ret = drm_gem_mmap(filp, vma);
if (ret < 0)
return ret;
return phytium_gem_mmap_obj(vma->vm_private_data, vma);
}
int phytium_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, uint32_t handle)
{
return drm_gem_dumb_destroy(file, dev, handle);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
static const struct vm_operations_struct phytium_vm_ops = {
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
};
static const struct drm_gem_object_funcs phytium_drm_gem_object_funcs = {
.free = phytium_gem_free_object,
.get_sg_table = phytium_gem_prime_get_sg_table,
.vmap = phytium_gem_prime_vmap,
.vunmap = phytium_gem_prime_vunmap,
.vm_ops = &phytium_vm_ops,
};
#endif
struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, unsigned long size)
{
struct phytium_gem_object *phytium_gem_obj = NULL;
struct phytium_display_private *priv = dev->dev_private;
struct page *page = NULL;
int ret = 0;
phytium_gem_obj = kzalloc(sizeof(*phytium_gem_obj), GFP_KERNEL);
if (!phytium_gem_obj) {
DRM_ERROR("failed to allocate phytium_gem_obj\n");
ret = -ENOMEM;
goto error;
}
ret = drm_gem_object_init(dev, &phytium_gem_obj->base, size);
if (ret) {
DRM_ERROR("failed to initialize drm gem object: %d\n", ret);
goto failed_object_init;
}
if (priv->support_memory_type & MEMORY_TYPE_VRAM) {
ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr,
&phytium_gem_obj->phys_addr, size);
if (ret) {
DRM_ERROR("fail to allocate vram buffer with size %lx\n", size);
goto failed_dma_alloc;
}
phytium_gem_obj->iova = phytium_gem_obj->phys_addr;
phytium_gem_obj->memory_type = MEMORY_TYPE_VRAM;
priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] += size;
} else if (priv->support_memory_type & MEMORY_TYPE_SYSTEM_CARVEOUT) {
ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr,
&phytium_gem_obj->phys_addr, size);
if (ret) {
DRM_ERROR("fail to allocate carveout memory with size %lx\n", size);
goto failed_dma_alloc;
}
page = phys_to_page(phytium_gem_obj->phys_addr);
phytium_gem_obj->iova = dma_map_page(dev->dev, page, 0, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev->dev, phytium_gem_obj->iova)) {
DRM_ERROR("fail to dma map carveout memory with size %lx\n", size);
phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size);
ret = -ENOMEM;
goto failed_dma_alloc;
}
phytium_gem_obj->memory_type = MEMORY_TYPE_SYSTEM_CARVEOUT;
priv->mem_state[PHYTIUM_MEM_SYSTEM_CARVEOUT_ALLOC] += size;
} else if (priv->support_memory_type & MEMORY_TYPE_SYSTEM_UNIFIED) {
phytium_gem_obj->vaddr = dma_alloc_attrs(dev->dev, size, &phytium_gem_obj->iova,
GFP_KERNEL, 0);
if (!phytium_gem_obj->vaddr) {
DRM_ERROR("fail to allocate unified buffer with size %lx\n", size);
ret = -ENOMEM;
goto failed_dma_alloc;
}
phytium_gem_obj->memory_type = MEMORY_TYPE_SYSTEM_UNIFIED;
priv->mem_state[PHYTIUM_MEM_SYSTEM_UNIFIED_ALLOC] += size;
} else {
DRM_ERROR("fail to allocate buffer with size %lx\n", size);
ret = -ENOMEM;
goto failed_dma_alloc;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
phytium_gem_obj->base.funcs = &phytium_drm_gem_object_funcs;
#endif
phytium_gem_obj->size = size;
list_add_tail(&phytium_gem_obj->list, &priv->gem_list_head);
DRM_DEBUG_KMS("phytium_gem_obj iova:0x%pa size:0x%lx\n",
&phytium_gem_obj->iova, phytium_gem_obj->size);
return phytium_gem_obj;
failed_dma_alloc:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
drm_gem_object_put(&phytium_gem_obj->base);
#else
drm_gem_object_unreference_unlocked(&phytium_gem_obj->base);
#endif
return ERR_PTR(ret);
failed_object_init:
kfree(phytium_gem_obj);
error:
return ERR_PTR(ret);
}
int phytium_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
int size = 0;
struct phytium_gem_object *phytium_gem_obj = NULL;
int ret = 0;
args->pitch = ALIGN(args->width*DIV_ROUND_UP(args->bpp, 8), 128);
args->size = args->pitch * args->height;
size = PAGE_ALIGN(args->size);
phytium_gem_obj = phytium_gem_create_object(dev, size);
if (IS_ERR(phytium_gem_obj))
return PTR_ERR(phytium_gem_obj);
ret = drm_gem_handle_create(file, &phytium_gem_obj->base, &args->handle);
if (ret) {
DRM_ERROR("failed to drm_gem_handle_create\n");
goto failed_gem_handle;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
drm_gem_object_put(&phytium_gem_obj->base);
#else
drm_gem_object_unreference_unlocked(&phytium_gem_obj->base);
#endif
return 0;
failed_gem_handle:
phytium_gem_free_object(&phytium_gem_obj->base);
return ret;
}

View File

@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_GEM_H__
#define __PHYTIUM_GEM_H__
#include <drm/drm_gem.h>
struct phytium_gem_object {
struct drm_gem_object base;
phys_addr_t phys_addr;
dma_addr_t iova;
void *vaddr;
unsigned long size;
struct sg_table *sgt;
char memory_type;
char reserve[3];
struct list_head list;
void *vaddr_save;
};
#define to_phytium_gem_obj(obj) container_of(obj, struct phytium_gem_object, base)
int phytium_memory_pool_init(struct device *dev, struct phytium_display_private *priv);
void phytium_memory_pool_fini(struct device *dev, struct phytium_display_private *priv);
int phytium_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma);
int phytium_gem_mmap(struct file *filp, struct vm_area_struct *vma);
void phytium_gem_free_object(struct drm_gem_object *obj);
struct sg_table *phytium_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *phytium_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sgt);
void phytium_gem_free_object(struct drm_gem_object *obj);
int phytium_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, unsigned int handle);
struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, unsigned long size);
int phytium_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args);
void *phytium_gem_prime_vmap(struct drm_gem_object *obj);
void phytium_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
int phytium_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
int phytium_gem_suspend(struct drm_device *drm_dev);
void phytium_gem_resume(struct drm_device *drm_dev);
#endif /* __PHYTIUM_GEM_H__ */

View File

@ -0,0 +1,420 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_modes.h>
#include "phytium_display_drv.h"
#include "phytium_dp.h"
#include "phytium_panel.h"
static int
phytium_dp_aux_set_backlight(struct phytium_panel *panel, unsigned int level)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
unsigned char vals[2] = { 0x0 };
vals[0] = level;
if (phytium_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) {
vals[0] = (level & 0xFF00) >> 8;
vals[1] = (level & 0xFF);
}
if (drm_dp_dpcd_write(&phytium_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
vals, sizeof(vals)) < 0) {
DRM_DEBUG_KMS("Failed to write aux backlight level\n");
return -EIO;
}
return 0;
}
static unsigned int phytium_dp_aux_get_backlight(struct phytium_panel *panel)
{
unsigned char read_val[2] = { 0x0 };
unsigned char level = 0;
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
if (drm_dp_dpcd_read(&phytium_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
&read_val, sizeof(read_val)) < 0) {
DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
DP_EDP_BACKLIGHT_BRIGHTNESS_MSB);
return 0;
}
level = read_val[0];
if (phytium_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
level = (read_val[0] << 8 | read_val[1]);
return level;
}
static void set_aux_backlight_enable(struct phytium_panel *panel, bool enable)
{
u8 reg_val = 0;
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
if (!(phytium_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP))
return;
if (drm_dp_dpcd_readb(&phytium_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
&reg_val) < 0) {
DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
DP_EDP_DISPLAY_CONTROL_REGISTER);
return;
}
if (enable)
reg_val |= DP_EDP_BACKLIGHT_ENABLE;
else
reg_val &= ~(DP_EDP_BACKLIGHT_ENABLE);
if (drm_dp_dpcd_writeb(&phytium_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
reg_val) != 1) {
DRM_DEBUG_KMS("Failed to %s aux backlight\n",
enable ? "enable" : "disable");
}
}
static void phytium_dp_aux_enable_backlight(struct phytium_panel *panel)
{
unsigned char dpcd_buf, new_dpcd_buf, edp_backlight_mode;
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
if (drm_dp_dpcd_readb(&phytium_dp->aux,
DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf) != 1) {
DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
return;
}
new_dpcd_buf = dpcd_buf;
edp_backlight_mode = dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
switch (edp_backlight_mode) {
case DP_EDP_BACKLIGHT_CONTROL_MODE_PWM:
case DP_EDP_BACKLIGHT_CONTROL_MODE_PRESET:
case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT:
new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
break;
/* Do nothing when it is already DPCD mode */
case DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD:
default:
break;
}
if (new_dpcd_buf != dpcd_buf) {
if (drm_dp_dpcd_writeb(&phytium_dp->aux,
DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf) < 0) {
DRM_DEBUG_KMS("Failed to write aux backlight mode\n");
}
}
set_aux_backlight_enable(panel, true);
phytium_dp_aux_set_backlight(panel, panel->level);
}
static void phytium_dp_aux_disable_backlight(struct phytium_panel *panel)
{
set_aux_backlight_enable(panel, false);
}
static void phytium_dp_aux_setup_backlight(struct phytium_panel *panel)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
if (phytium_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
phytium_dp->panel.max = 0xFFFF;
else
phytium_dp->panel.max = 0xFF;
phytium_dp->panel.min = 0;
phytium_dp->panel.level = phytium_dp_aux_get_backlight(panel);
phytium_dp->panel.backlight_enabled = (phytium_dp->panel.level != 0);
}
static void phytium_dp_hw_poweron_panel(struct phytium_panel *panel)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
phytium_dp->funcs->dp_hw_poweron_panel(phytium_dp);
}
static void phytium_dp_hw_poweroff_panel(struct phytium_panel *panel)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
phytium_dp->funcs->dp_hw_poweroff_panel(phytium_dp);
}
static int
phytium_dp_hw_set_backlight(struct phytium_panel *panel, uint32_t level)
{
int ret;
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
ret = phytium_dp->funcs->dp_hw_set_backlight(phytium_dp, level);
return ret;
}
static uint32_t phytium_dp_hw_get_backlight(struct phytium_panel *panel)
{
uint32_t ret;
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
ret = phytium_dp->funcs->dp_hw_get_backlight(phytium_dp);
return ret;
}
static void phytium_dp_hw_enable_backlight(struct phytium_panel *panel)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
phytium_dp->funcs->dp_hw_set_backlight(phytium_dp, phytium_dp->panel.level);
phytium_dp->funcs->dp_hw_enable_backlight(phytium_dp);
}
static void phytium_dp_hw_disable_backlight(struct phytium_panel *panel)
{
struct phytium_dp_device *phytium_dp = panel_to_dp_device(panel);
phytium_dp->funcs->dp_hw_disable_backlight(phytium_dp);
}
static void phytium_dp_hw_setup_backlight(struct phytium_panel *panel)
{
struct drm_device *dev = panel->dev;
struct phytium_display_private *priv = dev->dev_private;
panel->max = priv->info.backlight_max;
panel->min = 0;
panel->level = phytium_dp_hw_get_backlight(panel);
}
void phytium_dp_panel_init_backlight_funcs(struct phytium_dp_device *phytium_dp)
{
if (phytium_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP &&
(phytium_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP) &&
!(phytium_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP)) {
DRM_DEBUG_KMS("AUX Backlight Control Supported!\n");
phytium_dp->panel.setup_backlight = phytium_dp_aux_setup_backlight;
phytium_dp->panel.enable_backlight = phytium_dp_aux_enable_backlight;
phytium_dp->panel.disable_backlight = phytium_dp_aux_disable_backlight;
phytium_dp->panel.set_backlight = phytium_dp_aux_set_backlight;
phytium_dp->panel.get_backlight = phytium_dp_aux_get_backlight;
} else {
DRM_DEBUG_KMS("SE Backlight Control Supported!\n");
phytium_dp->panel.setup_backlight = phytium_dp_hw_setup_backlight;
phytium_dp->panel.enable_backlight = phytium_dp_hw_enable_backlight;
phytium_dp->panel.disable_backlight = phytium_dp_hw_disable_backlight;
phytium_dp->panel.set_backlight = phytium_dp_hw_set_backlight;
phytium_dp->panel.get_backlight = phytium_dp_hw_get_backlight;
}
phytium_dp->panel.poweron = phytium_dp_hw_poweron_panel;
phytium_dp->panel.poweroff = phytium_dp_hw_poweroff_panel;
mutex_init(&phytium_dp->panel.panel_lock);
phytium_dp->panel.dev = phytium_dp->dev;
/* Upper limits from eDP 1.3 spec */
phytium_dp->panel.panel_power_up_delay = 210; /* t1_t3 */
phytium_dp->panel.backlight_on_delay = 50; /* t7 */
phytium_dp->panel.backlight_off_delay = 50;
phytium_dp->panel.panel_power_down_delay = 0; /* t10 */
phytium_dp->panel.panel_power_cycle_delay = 510; /* t11 + t12 */
}
void phytium_dp_panel_release_backlight_funcs(struct phytium_dp_device *phytium_dp)
{
phytium_dp->panel.setup_backlight = NULL;
phytium_dp->panel.enable_backlight = NULL;
phytium_dp->panel.disable_backlight = NULL;
phytium_dp->panel.set_backlight = NULL;
phytium_dp->panel.get_backlight = NULL;
phytium_dp->panel.poweron = NULL;
phytium_dp->panel.poweroff = NULL;
}
void phytium_panel_enable_backlight(struct phytium_panel *panel)
{
if (panel->enable_backlight) {
mutex_lock(&panel->panel_lock);
msleep(panel->backlight_on_delay);
panel->enable_backlight(panel);
panel->backlight_enabled = true;
mutex_unlock(&panel->panel_lock);
}
}
void phytium_panel_disable_backlight(struct phytium_panel *panel)
{
if (panel->disable_backlight) {
mutex_lock(&panel->panel_lock);
panel->disable_backlight(panel);
panel->backlight_enabled = false;
msleep(panel->backlight_off_delay);
mutex_unlock(&panel->panel_lock);
}
}
void phytium_panel_poweron(struct phytium_panel *panel)
{
if (panel->poweron) {
mutex_lock(&panel->panel_lock);
panel->poweron(panel);
panel->power_enabled = true;
msleep(panel->panel_power_up_delay);
mutex_unlock(&panel->panel_lock);
}
}
void phytium_panel_poweroff(struct phytium_panel *panel)
{
if (panel->poweroff) {
mutex_lock(&panel->panel_lock);
msleep(panel->panel_power_down_delay);
panel->poweroff(panel);
panel->power_enabled = false;
mutex_unlock(&panel->panel_lock);
}
}
static uint32_t phytium_scale(uint32_t source_val,
uint32_t source_min, uint32_t source_max,
uint32_t target_min, uint32_t target_max)
{
uint64_t target_val;
WARN_ON(source_min > source_max);
WARN_ON(target_min > target_max);
/* defensive */
source_val = clamp(source_val, source_min, source_max);
/* avoid overflows */
target_val = mul_u32_u32(source_val - source_min, target_max - target_min);
target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min);
target_val += target_min;
return target_val;
}
static inline uint32_t
phytium_scale_hw_to_user(struct phytium_panel *panel, uint32_t hw_level, uint32_t user_max)
{
return phytium_scale(hw_level, panel->min, panel->max,
0, user_max);
}
static inline uint32_t
phytium_scale_user_to_hw(struct phytium_panel *panel, u32 user_level, u32 user_max)
{
return phytium_scale(user_level, 0, user_max,
panel->min, panel->max);
}
static int phytium_backlight_device_update_status(struct backlight_device *bd)
{
struct phytium_panel *panel = bl_get_data(bd);
struct drm_device *dev = panel->dev;
uint32_t hw_level = 0;
int ret = 0;
DRM_DEBUG_KMS("updating phytium_backlight, brightness=%d/%d\n",
bd->props.brightness, bd->props.max_brightness);
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
hw_level = phytium_scale_user_to_hw(panel, bd->props.brightness, bd->props.max_brightness);
if ((panel->set_backlight) && (panel->backlight_enabled)) {
mutex_lock(&panel->panel_lock);
ret = panel->set_backlight(panel, hw_level);
panel->level = hw_level;
mutex_unlock(&panel->panel_lock);
}
drm_modeset_unlock(&dev->mode_config.connection_mutex);
return ret;
}
static int phytium_backlight_device_get_brightness(struct backlight_device *bd)
{
struct phytium_panel *panel = bl_get_data(bd);
struct drm_device *dev = panel->dev;
uint32_t hw_level = 0;
int ret;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
if (panel->get_backlight && panel->backlight_enabled) {
mutex_lock(&panel->panel_lock);
hw_level = panel->get_backlight(panel);
panel->level = hw_level;
mutex_unlock(&panel->panel_lock);
}
drm_modeset_unlock(&dev->mode_config.connection_mutex);
ret = phytium_scale_hw_to_user(panel, hw_level, bd->props.max_brightness);
DRM_DEBUG_KMS("get phytium_backlight, brightness=%d/%d\n",
ret, bd->props.max_brightness);
return ret;
}
static const struct backlight_ops phytium_backlight_device_ops = {
.update_status = phytium_backlight_device_update_status,
.get_brightness = phytium_backlight_device_get_brightness,
};
int phytium_edp_backlight_device_register(struct phytium_dp_device *phytium_dp)
{
struct backlight_properties props;
char bl_name[16];
if (phytium_dp->panel.setup_backlight) {
mutex_lock(&phytium_dp->panel.panel_lock);
phytium_dp->panel.setup_backlight(&phytium_dp->panel);
mutex_unlock(&phytium_dp->panel.panel_lock);
} else {
return -EINVAL;
}
memset(&props, 0, sizeof(props));
props.max_brightness = PHYTIUM_MAX_BL_LEVEL;
props.type = BACKLIGHT_RAW;
props.brightness = phytium_scale_hw_to_user(&phytium_dp->panel, phytium_dp->panel.level,
props.max_brightness);
snprintf(bl_name, sizeof(bl_name), "phytium_bl%d", phytium_dp->port);
phytium_dp->panel.bl_device =
backlight_device_register(bl_name,
phytium_dp->connector.kdev,
&phytium_dp->panel,
&phytium_backlight_device_ops,
&props);
if (IS_ERR(phytium_dp->panel.bl_device)) {
DRM_ERROR("Failed to register backlight: %ld\n",
PTR_ERR(phytium_dp->panel.bl_device));
phytium_dp->panel.bl_device = NULL;
return -ENODEV;
}
DRM_DEBUG_KMS("Connector %s backlight sysfs interface registered\n",
phytium_dp->connector.name);
return 0;
}
void phytium_edp_backlight_device_unregister(struct phytium_dp_device *phytium_dp)
{
if (phytium_dp->panel.bl_device) {
backlight_device_unregister(phytium_dp->panel.bl_device);
phytium_dp->panel.bl_device = NULL;
}
}

View File

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_PANEL_H__
#define __PHYTIUM_PANEL_H__
#include "phytium_dp.h"
#define PHYTIUM_MAX_BL_LEVEL 0xFF
struct phytium_panel {
struct drm_device *dev;
bool backlight_enabled;
bool power_enabled;
bool reserve1[2];
unsigned int min;
unsigned int level;
unsigned int max;
struct backlight_device *bl_device;
void (*setup_backlight)(struct phytium_panel *panel);
uint32_t (*get_backlight)(struct phytium_panel *panel);
int (*set_backlight)(struct phytium_panel *panel, uint32_t level);
void (*disable_backlight)(struct phytium_panel *panel);
void (*enable_backlight)(struct phytium_panel *panel);
void (*poweron)(struct phytium_panel *panel);
void (*poweroff)(struct phytium_panel *panel);
struct mutex panel_lock;
uint32_t panel_power_up_delay;
uint32_t backlight_on_delay;
uint32_t backlight_off_delay;
uint32_t panel_power_down_delay;
uint32_t panel_power_cycle_delay;
};
void phytium_dp_panel_init_backlight_funcs(struct phytium_dp_device *phytium_dp);
void phytium_panel_release_backlight_funcs(struct phytium_dp_device *phytium_dp);
int phytium_edp_backlight_device_register(struct phytium_dp_device *phytium_dp);
void phytium_edp_backlight_device_unregister(struct phytium_dp_device *phytium_dp);
void phytium_panel_enable_backlight(struct phytium_panel *panel);
void phytium_panel_disable_backlight(struct phytium_panel *panel);
void phytium_panel_poweron(struct phytium_panel *panel);
void phytium_panel_poweroff(struct phytium_panel *panel);
#endif /* __PHYTIUM_PANEL_H__ */

View File

@ -0,0 +1,388 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <linux/pci.h>
#include <drm/drm_drv.h>
#include <linux/dmaengine.h>
#include "phytium_display_drv.h"
#include "phytium_pci.h"
#include "phytium_dp.h"
#include "phytium_gem.h"
#include "px210_dc.h"
#include "px210_dp.h"
#include "pe220x_dc.h"
#include "pe220x_dp.h"
int dc_msi_enable;
module_param(dc_msi_enable, int, 0644);
MODULE_PARM_DESC(dc_msi_enable, "Enable DC msi interrupt (0-disabled; 1-enabled; default-0)");
void phytium_pci_vram_hw_init(struct phytium_display_private *priv)
{
struct phytium_pci_private *pci_priv = to_pci_priv(priv);
pci_priv->dc_hw_vram_init(priv, priv->pool_phys_addr, priv->pool_size);
}
int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *priv)
{
int ret = 0;
priv->pool_phys_addr = pci_resource_start(pdev, 2);
priv->pool_size = pci_resource_len(pdev, 2);
if ((priv->pool_phys_addr != 0) && (priv->pool_size != 0)) {
priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr,
priv->pool_size);
if (priv->pool_virt_addr == NULL) {
DRM_ERROR("pci vram ioremap fail, addr:0x%llx, size:0x%llx\n",
priv->pool_phys_addr, priv->pool_size);
ret = -EINVAL;
goto failed_ioremap;
}
ret = phytium_memory_pool_init(&pdev->dev, priv);
if (ret)
goto failed_init_memory_pool;
priv->mem_state[PHYTIUM_MEM_VRAM_TOTAL] = priv->pool_size;
priv->support_memory_type = MEMORY_TYPE_VRAM;
priv->vram_hw_init = phytium_pci_vram_hw_init;
} else {
DRM_DEBUG_KMS("not support vram\n");
priv->pool_virt_addr = NULL;
priv->mem_state[PHYTIUM_MEM_VRAM_TOTAL] = 0;
priv->support_memory_type = MEMORY_TYPE_SYSTEM_UNIFIED;
priv->vram_hw_init = NULL;
}
return 0;
failed_init_memory_pool:
devm_iounmap(&pdev->dev, priv->pool_virt_addr);
failed_ioremap:
return ret;
}
void phytium_pci_vram_fini(struct pci_dev *pdev, struct phytium_display_private *priv)
{
if (priv->support_memory_type == MEMORY_TYPE_VRAM) {
phytium_memory_pool_fini(&pdev->dev, priv);
devm_iounmap(&pdev->dev, priv->pool_virt_addr);
}
}
static bool phytium_pci_dma_chan_filter(struct dma_chan *chan, void *param)
{
struct phytium_dma_slave *s = param;
if (s->dma_dev != chan->device->dev)
return false;
if (s->chan_id == chan->chan_id)
return true;
else
return false;
}
int phytium_pci_dma_init(struct phytium_display_private *priv)
{
struct pci_dev *dma_dev, *gpu_dev;
struct drm_device *drm_dev = priv->dev;
dma_cap_mask_t mask;
struct phytium_dma_slave s;
int ret = 0;
u16 cmd;
/* check px210 gpu enable */
gpu_dev = pci_get_device(PCI_VENDOR_ID_PHYTIUM, 0xdc20, NULL);
if (!gpu_dev) {
DRM_INFO("failed to get gpu_dev\n");
ret = -ENODEV;
goto failed;
}
pci_read_config_word(gpu_dev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_MASTER)) {
DRM_INFO("gpu_dev master is disabled\n");
ret = -ENODEV;
goto failed;
}
dma_dev = pci_get_device(PCI_VENDOR_ID_PHYTIUM, 0xdc3c, NULL);
if (!dma_dev) {
DRM_INFO("failed to get dma_dev\n");
ret = -ENODEV;
goto failed;
}
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
s.dma_dev = &dma_dev->dev;
s.chan_id = 2;
priv->dma_chan = dma_request_channel(mask, phytium_pci_dma_chan_filter, &s);
if (!priv->dma_chan) {
DRM_DEV_ERROR(drm_dev->dev, "failed to request dma chan\n");
ret = -EBUSY;
goto failed;
}
priv->dma_inited = 1;
failed:
return ret;
}
void phytium_pci_dma_fini(struct phytium_display_private *priv)
{
if (priv->dma_inited)
dma_release_channel(priv->dma_chan);
priv->dma_inited = 0;
priv->dma_chan = NULL;
}
static struct phytium_display_private*
phytium_pci_private_init(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = NULL;
struct phytium_pci_private *pci_priv = NULL;
struct phytium_device_info *phytium_info = (struct phytium_device_info *)ent->driver_data;
int i = 0;
resource_size_t io_addr, io_size;
pci_priv = devm_kzalloc(&pdev->dev, sizeof(*pci_priv), GFP_KERNEL);
if (!pci_priv) {
DRM_ERROR("no memory to allocate for drm_display_private\n");
goto failed_malloc_priv;
}
memset(pci_priv, 0, sizeof(*pci_priv));
priv = &pci_priv->base;
phytium_display_private_init(priv, dev);
memcpy(&(priv->info), phytium_info, sizeof(struct phytium_device_info));
DRM_DEBUG_KMS("priv->info.num_pipes :%d\n", priv->info.num_pipes);
priv->info.pipe_mask = ((pdev->subsystem_device >> PIPE_MASK_SHIFT) & PIPE_MASK_MASK);
priv->info.edp_mask = ((pdev->subsystem_device >> EDP_MASK_SHIFT) & EDP_MASK_MASK);
priv->info.num_pipes = 0;
for_each_pipe_masked(priv, i)
priv->info.num_pipes++;
if (priv->info.num_pipes == 0) {
DRM_ERROR("num_pipes is zero, so exit init\n");
goto failed_init_numpipe;
}
io_addr = pci_resource_start(pdev, 0);
io_size = pci_resource_len(pdev, 0);
priv->regs = ioremap(io_addr, io_size);
if (priv->regs == NULL) {
DRM_ERROR("pci bar0 ioremap fail, addr:0x%llx, size:0x%llx\n", io_addr, io_size);
goto failed_ioremap;
}
priv->irq = pdev->irq;
if (IS_PX210(priv)) {
pci_priv->dc_hw_vram_init = px210_dc_hw_vram_init;
priv->dc_hw_clear_msi_irq = px210_dc_hw_clear_msi_irq;
priv->dc_hw_fb_format_check = px210_dc_hw_fb_format_check;
} else if (IS_PE220X(priv)) {
pci_priv->dc_hw_vram_init = pe220x_dc_hw_vram_init;
priv->dc_hw_clear_msi_irq = NULL;
priv->dc_hw_fb_format_check = pe220x_dc_hw_fb_format_check;
}
return priv;
failed_ioremap:
failed_init_numpipe:
devm_kfree(&pdev->dev, pci_priv);
failed_malloc_priv:
return NULL;
}
static void
phytium_pci_private_fini(struct pci_dev *pdev, struct phytium_display_private *priv)
{
struct phytium_pci_private *pci_priv = to_pci_priv(priv);
if (priv->regs)
iounmap(priv->regs);
devm_kfree(&pdev->dev, pci_priv);
}
static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct phytium_display_private *priv = NULL;
struct drm_device *dev = NULL;
int ret = 0;
dev = drm_dev_alloc(&phytium_display_drm_driver, &pdev->dev);
if (IS_ERR(dev)) {
DRM_ERROR("failed to allocate drm_device\n");
return PTR_ERR(dev);
}
dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
pci_set_master(pdev);
ret = pci_enable_device(pdev);
if (ret) {
DRM_ERROR("pci enbale device fail\n");
goto failed_enable_device;
}
if (dc_msi_enable) {
ret = pci_enable_msi(pdev);
if (ret)
DRM_ERROR("pci enbale msi fail\n");
}
dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
priv = phytium_pci_private_init(pdev, ent);
if (priv)
dev->dev_private = priv;
else
goto failed_pci_private_init;
ret = phytium_pci_vram_init(pdev, priv);
if (ret) {
DRM_ERROR("failed to init pci vram\n");
goto failed_pci_vram_init;
}
ret = drm_dev_register(dev, 0);
if (ret) {
DRM_ERROR("failed to register drm dev\n");
goto failed_register_drm;
}
phytium_dp_hpd_irq_setup(dev, true);
return 0;
failed_register_drm:
phytium_pci_vram_fini(pdev, priv);
failed_pci_vram_init:
phytium_pci_private_fini(pdev, priv);
failed_pci_private_init:
if (pdev->msi_enabled)
pci_disable_msi(pdev);
pci_disable_device(pdev);
failed_enable_device:
pci_set_drvdata(pdev, NULL);
drm_dev_put(dev);
return -1;
}
static void phytium_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = dev->dev_private;
phytium_dp_hpd_irq_setup(dev, false);
cancel_work_sync(&priv->hotplug_work);
drm_dev_unregister(dev);
phytium_pci_vram_fini(pdev, priv);
phytium_pci_private_fini(pdev, priv);
if (pdev->msi_enabled)
pci_disable_msi(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
drm_dev_put(dev);
}
static void phytium_pci_shutdown(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = dev->dev_private;
priv->display_shutdown(dev);
}
static int phytium_pci_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = drm_dev->dev_private;
int ret = 0;
if (IS_PX210(priv))
phytium_pci_dma_init(priv);
ret = priv->display_pm_suspend(drm_dev);
if (ret < 0)
goto out;
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
udelay(200);
out:
return ret;
}
static int phytium_pci_pm_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = drm_dev->dev_private;
int ret = 0;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret)
return ret;
pci_set_master(pdev);
ret = priv->display_pm_resume(drm_dev);
if (IS_PX210(priv))
phytium_pci_dma_fini(priv);
return ret;
}
static const struct dev_pm_ops phytium_pci_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(phytium_pci_pm_suspend, phytium_pci_pm_resume)
};
static const struct phytium_device_info px210_info = {
.platform_mask = BIT(PHYTIUM_PLATFORM_PX210),
.total_pipes = 3,
.crtc_clock_max = PX210_DC_PIX_CLOCK_MAX,
.hdisplay_max = PX210_DC_HDISPLAY_MAX,
.vdisplay_max = PX210_DC_VDISPLAY_MAX,
.address_mask = PX210_DC_ADDRESS_MASK,
.backlight_max = PX210_DP_BACKLIGHT_MAX,
};
static const struct phytium_device_info pe220x_info = {
.platform_mask = BIT(PHYTIUM_PLATFORM_PE220X),
.total_pipes = 2,
.crtc_clock_max = PE220X_DC_PIX_CLOCK_MAX,
.hdisplay_max = PE220X_DC_HDISPLAY_MAX,
.vdisplay_max = PE220X_DC_VDISPLAY_MAX,
.address_mask = PE220X_DC_ADDRESS_MASK,
.backlight_max = PE220X_DP_BACKLIGHT_MAX,
};
static const struct pci_device_id phytium_display_pci_ids[] = {
{ PCI_VDEVICE(PHYTIUM, 0xdc22), (kernel_ulong_t)&px210_info },
{ PCI_VDEVICE(PHYTIUM, 0xdc3e), (kernel_ulong_t)&pe220x_info },
{ /* End: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, phytium_display_pci_ids);
struct pci_driver phytium_pci_driver = {
.name = "phytium_display_pci",
.id_table = phytium_display_pci_ids,
.probe = phytium_pci_probe,
.remove = phytium_pci_remove,
.shutdown = phytium_pci_shutdown,
.driver.pm = &phytium_pci_pm_ops,
};

View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_PCI_H__
#define __PHYTIUM_PCI_H__
#include "phytium_display_drv.h"
struct phytium_pci_private {
struct phytium_display_private base;
void (*dc_hw_vram_init)(struct phytium_display_private *priv, resource_size_t vram_addr,
resource_size_t vram_size);
};
struct phytium_dma_slave {
struct device *dma_dev;
u32 chan_id;
};
#define to_pci_priv(priv) container_of(priv, struct phytium_pci_private, base)
extern struct pci_driver phytium_pci_driver;
#endif /* __PHYTIUM_PCI_H__ */

View File

@ -0,0 +1,683 @@
// SPDX-License-Identifier: GPL-2.0
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_fourcc.h>
#include <linux/dma-buf.h>
#include "phytium_display_drv.h"
#include "phytium_plane.h"
#include "phytium_fb.h"
#include "phytium_gem.h"
#include "phytium_crtc.h"
#include "px210_dc.h"
#include "pe220x_dc.h"
#include "phytium_reg.h"
#define PHYTIUM_CURS_W_SIZE 32
#define PHYTIUM_CURS_H_SIZE 32
void phytium_plane_destroy(struct drm_plane *plane)
{
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
drm_plane_cleanup(plane);
kfree(phytium_plane);
}
/**
* phytium_plane_atomic_get_property - fetch plane property value
* @plane: plane to fetch property for
* @state: state containing the property value
* @property: property to look up
* @val: pointer to write property value into
*
* The DRM core does not store shadow copies of properties for
* atomic-capable drivers. This entrypoint is used to fetch
* the current value of a driver-specific plane property.
*/
static int
phytium_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state,
struct drm_property *property,
uint64_t *val)
{
DRM_DEBUG_KMS("Unknown plane property [PROP:%d:%s]\n", property->base.id, property->name);
return -EINVAL;
}
/**
* phytium_plane_atomic_set_property - set plane property value
* @plane: plane to set property for
* @state: state to update property value in
* @property: property to set
* @val: value to set property to
*
* Writes the specified property value for a plane into the provided atomic
* state object.
*
* Returns 0 on success, -EINVAL on unrecognized properties
*/
int
phytium_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state,
struct drm_property *property,
uint64_t val)
{
DRM_DEBUG_KMS("Unknown plane property [PROP:%d:%s]\n", property->base.id, property->name);
return -EINVAL;
}
struct drm_plane_state *
phytium_plane_atomic_duplicate_state(struct drm_plane *plane)
{
struct drm_plane_state *state = NULL;
struct phytium_plane_state *phytium_state = NULL;
phytium_state = kmemdup(plane->state, sizeof(*phytium_state), GFP_KERNEL);
if (!phytium_state)
return NULL;
state = &phytium_state->base;
if (state->fb)
drm_framebuffer_get(state->fb);
state->fence = NULL;
state->commit = NULL;
return state;
}
void
phytium_plane_atomic_destroy_state(struct drm_plane *plane, struct drm_plane_state *state)
{
struct phytium_plane_state *phytium_state = to_phytium_plane_state(state);
__drm_atomic_helper_plane_destroy_state(state);
kfree(phytium_state);
}
static bool phytium_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format, uint64_t modifier)
{
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
if (modifier == DRM_FORMAT_MOD_PHYTIUM_TILE_MODE3_FBCDC) {
switch (format) {
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_BGRX8888:
return true;
default:
return false;
}
}
return false;
}
const struct drm_plane_funcs phytium_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = phytium_plane_destroy,
.reset = drm_atomic_helper_plane_reset,
.atomic_get_property = phytium_plane_atomic_get_property,
.atomic_set_property = phytium_plane_atomic_set_property,
.atomic_duplicate_state = phytium_plane_atomic_duplicate_state,
.atomic_destroy_state = phytium_plane_atomic_destroy_state,
.format_mod_supported = phytium_plane_format_mod_supported,
};
static int phytium_plane_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct dma_buf *dma_buf;
struct dma_fence *fence;
if (!state->fb)
return 0;
dma_buf = to_phytium_framebuffer(state->fb)->phytium_gem_obj[0]->base.dma_buf;
if (dma_buf) {
fence = dma_resv_get_excl_rcu(dma_buf->resv);
drm_atomic_set_fence_for_plane(state, fence);
}
return 0;
}
static int
phytium_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct drm_framebuffer *fb = state->fb;
struct drm_crtc *crtc = state->crtc;
struct drm_crtc_state *crtc_state;
int src_x, src_y, src_w, src_h;
unsigned long base_offset;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
if ((!fb) || (!crtc))
return 0;
crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
src_w = state->src_w >> 16;
src_h = state->src_h >> 16;
if (phytium_crtc->scale_enable)
return -EINVAL;
if ((src_w != PHYTIUM_CURS_W_SIZE) || (src_h != PHYTIUM_CURS_W_SIZE)) {
DRM_INFO("Invalid cursor size(%d, %d)\n", src_w, src_h);
return -EINVAL;
}
} else if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
src_x = state->src_x >> 16;
src_y = state->src_y >> 16;
src_w = state->src_w >> 16;
src_h = state->src_h >> 16;
base_offset = src_x * fb->format->cpp[0] + src_y*fb->pitches[0];
if (base_offset & (priv->info.address_mask)) {
DRM_ERROR("fb base address is not aligned by 0x%lx byte\n",
priv->info.address_mask);
return -EINVAL;
}
if (src_w != state->crtc_w || src_h != state->crtc_h) {
DRM_ERROR("scale not support: crtc_w(0x%x)/h(0x%x) src_w(0x%x)/h(0x%x)\n",
state->crtc_w, state->crtc_h, src_w, src_h);
return -EINVAL;
}
if ((state->crtc_x < 0) || (state->crtc_y < 0)) {
DRM_ERROR("crtc_x(0x%x)/y(0x%x) of drm plane state is invalid\n",
state->crtc_x, state->crtc_y);
return -EINVAL;
}
if ((state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay)
|| (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay)) {
DRM_ERROR("plane out of crtc region\n");
return -EINVAL;
}
}
return 0;
}
static void phytium_dc_get_plane_parameter(struct drm_plane *plane)
{
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
struct drm_framebuffer *fb = plane->state->fb;
struct phytium_framebuffer *phytium_fb = to_phytium_framebuffer(fb);
struct phytium_gem_object *phytium_gem_obj = NULL;
int i, num_planes = 0;
const struct drm_format_info *info;
info = drm_format_info(fb->format->format);
num_planes = info ? info->num_planes : 1;
for (i = 0; i < num_planes; i++) {
phytium_gem_obj = phytium_fb->phytium_gem_obj[i];
phytium_plane->iova[i] = phytium_gem_obj->iova + fb->offsets[i];
phytium_plane->size[i] = phytium_gem_obj->size - fb->offsets[i];
if (fb->modifier == DRM_FORMAT_MOD_PHYTIUM_TILE_MODE0_FBCDC)
phytium_plane->tiling[i] = FRAMEBUFFER_TILE_MODE0;
else if (fb->modifier == DRM_FORMAT_MOD_PHYTIUM_TILE_MODE3_FBCDC)
phytium_plane->tiling[i] = FRAMEBUFFER_TILE_MODE3;
else if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
phytium_plane->tiling[i] = FRAMEBUFFER_LINEAR;
else
phytium_plane->tiling[i] = FRAMEBUFFER_LINEAR;
if (i == 0) {
switch (fb->format->format) {
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_BGRA1010102:
phytium_plane->format = FRAMEBUFFER_FORMAT_ARGB2101010;
break;
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_BGRA8888:
phytium_plane->format = FRAMEBUFFER_FORMAT_ARGB8888;
break;
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_BGRX8888:
phytium_plane->format = FRAMEBUFFER_FORMAT_XRGB8888;
break;
case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_ABGR4444:
case DRM_FORMAT_RGBA4444:
case DRM_FORMAT_BGRA4444:
phytium_plane->format = FRAMEBUFFER_FORMAT_ARGB4444;
break;
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_XBGR4444:
case DRM_FORMAT_RGBX4444:
case DRM_FORMAT_BGRX4444:
phytium_plane->format = FRAMEBUFFER_FORMAT_XRGB4444;
break;
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_RGBA5551:
case DRM_FORMAT_BGRA5551:
phytium_plane->format = FRAMEBUFFER_FORMAT_ARGB1555;
break;
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_XBGR1555:
case DRM_FORMAT_RGBX5551:
case DRM_FORMAT_BGRX5551:
phytium_plane->format = FRAMEBUFFER_FORMAT_XRGB1555;
break;
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
phytium_plane->format = FRAMEBUFFER_FORMAT_RGB565;
break;
case DRM_FORMAT_YUYV:
phytium_plane->format = FRAMEBUFFER_FORMAT_YUYV;
break;
case DRM_FORMAT_UYVY:
phytium_plane->format = FRAMEBUFFER_FORMAT_UYVY;
break;
case DRM_FORMAT_NV16:
phytium_plane->format = FRAMEBUFFER_FORMAT_NV16;
break;
case DRM_FORMAT_NV12:
phytium_plane->format = FRAMEBUFFER_FORMAT_NV12;
break;
case DRM_FORMAT_NV21:
phytium_plane->format = FRAMEBUFFER_FORMAT_NV12;
break;
default:
DRM_ERROR("unsupported pixel format (format = %d)\n",
fb->format->format);
return;
}
switch (fb->format->format) {
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB4444:
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_RGB565:
phytium_plane->swizzle = FRAMEBUFFER_SWIZZLE_ARGB;
phytium_plane->uv_swizzle = FRAMEBUFFER_UVSWIZZLE_DISABLE;
break;
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR4444:
case DRM_FORMAT_XBGR4444:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_XBGR1555:
case DRM_FORMAT_BGR565:
phytium_plane->swizzle = FRAMEBUFFER_SWIZZLE_ABGR;
phytium_plane->uv_swizzle = FRAMEBUFFER_UVSWIZZLE_DISABLE;
break;
case DRM_FORMAT_RGBA1010102:
case DRM_FORMAT_RGBA8888:
case DRM_FORMAT_RGBX8888:
case DRM_FORMAT_RGBA4444:
case DRM_FORMAT_RGBX4444:
case DRM_FORMAT_RGBA5551:
case DRM_FORMAT_RGBX5551:
phytium_plane->swizzle = FRAMEBUFFER_SWIZZLE_RGBA;
phytium_plane->uv_swizzle = FRAMEBUFFER_UVSWIZZLE_DISABLE;
break;
case DRM_FORMAT_BGRA1010102:
case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_BGRX8888:
case DRM_FORMAT_BGRA4444:
case DRM_FORMAT_BGRX4444:
case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_BGRX5551:
phytium_plane->swizzle = FRAMEBUFFER_SWIZZLE_BGRA;
phytium_plane->uv_swizzle = FRAMEBUFFER_UVSWIZZLE_DISABLE;
break;
case DRM_FORMAT_YUYV:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV12:
phytium_plane->swizzle = FRAMEBUFFER_SWIZZLE_ARGB;
phytium_plane->uv_swizzle = FRAMEBUFFER_UVSWIZZLE_DISABLE;
break;
default:
DRM_ERROR("unsupported pixel format (format = %d)\n",
fb->format->format);
return;
}
}
}
}
static void phytium_dc_primary_plane_update(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
struct drm_framebuffer *fb = plane->state->fb;
int phys_pipe = phytium_plane->phys_pipe;
int src_x, src_y, crtc_x, crtc_y, crtc_w, crtc_h;
unsigned long base_offset;
int config;
src_x = plane->state->src_x >> 16;
src_y = plane->state->src_y >> 16;
crtc_x = plane->state->crtc_x;
crtc_y = plane->state->crtc_y;
crtc_w = plane->state->crtc_w;
crtc_h = plane->state->crtc_h;
if (phytium_plane->dc_hw_update_dcreq)
phytium_plane->dc_hw_update_dcreq(plane);
phytium_plane->dc_hw_update_primary_hi_addr(plane);
/* config dc */
/* Y */
base_offset = src_x * fb->format->cpp[0] + src_y*fb->pitches[0];
phytium_writel_reg(priv, (phytium_plane->iova[0] + base_offset) & ADDRESS_MASK,
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_Y_ADDRESS);
phytium_writel_reg(priv, ALIGN(fb->pitches[0], 128),
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_Y_STRIDE);
/* U */
phytium_writel_reg(priv, phytium_plane->iova[1] & 0xffffffff,
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_U_ADDRESS);
phytium_writel_reg(priv, ALIGN(fb->pitches[1], 128),
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_U_STRIDE);
/* V */
phytium_writel_reg(priv, phytium_plane->iova[2] & 0xffffffff,
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_V_ADDRESS);
phytium_writel_reg(priv, ALIGN(fb->pitches[2], 128),
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_V_STRIDE);
/* size */
phytium_writel_reg(priv, (crtc_w & WIDTH_MASK) | ((crtc_h&HEIGHT_MASK) << HEIGHT_SHIFT),
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_FRAMEBUFFER_SIZE);
/* config */
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
config &= ~(FRAMEBUFFER_FORMAT_MASK << FRAMEBUFFER_FORMAT_SHIFT);
config |= (phytium_plane->format << FRAMEBUFFER_FORMAT_SHIFT);
config &= ~(1 << FRAMEBUFFER_UVSWIZZLE_SHIFT);
config |= (phytium_plane->uv_swizzle << FRAMEBUFFER_UVSWIZZLE_SHIFT);
config &= ~(FRAMEBUFFER_SWIZZLE_MASK << FRAMEBUFFER_SWIZZLE_SHIFT);
config |= (phytium_plane->swizzle << FRAMEBUFFER_SWIZZLE_SHIFT);
config &= ~(FRAMEBUFFER_TILE_MODE_MASK << FRAMEBUFFER_TILE_MODE_SHIFT);
config |= (phytium_plane->tiling[0] << FRAMEBUFFER_TILE_MODE_SHIFT);
config &= (~FRAMEBUFFER_CLEAR);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
}
static void phytium_dc_cursor_plane_update(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
struct drm_framebuffer *fb = plane->state->fb;
int phys_pipe = phytium_plane->phys_pipe;
int config;
unsigned long iova;
phytium_plane->enable = 1;
phytium_plane->cursor_hot_x = fb->hot_x;
phytium_plane->cursor_hot_y = fb->hot_y;
phytium_plane->cursor_x = plane->state->crtc_x + fb->hot_x;
phytium_plane->cursor_y = plane->state->crtc_y + fb->hot_y;
if (phytium_plane->cursor_x < 0) {
phytium_plane->cursor_hot_x = plane->state->crtc_w - 1;
phytium_plane->cursor_x = plane->state->crtc_x + phytium_plane->cursor_hot_x;
}
if (phytium_plane->cursor_y < 0) {
phytium_plane->cursor_hot_y = plane->state->crtc_h - 1;
phytium_plane->cursor_y = plane->state->crtc_y + phytium_plane->cursor_hot_y;
}
config = CURSOR_FORMAT_ARGB8888 |
((phytium_plane->cursor_hot_y & CURSOR_HOT_Y_MASK) << CURSOR_HOT_Y_SHIFT) |
((phytium_plane->cursor_hot_x & CURSOR_HOT_X_MASK) << CURSOR_HOT_X_SHIFT);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
config = ((phytium_plane->cursor_x & CURSOR_X_MASK) << CURSOR_X_SHIFT) |
((phytium_plane->cursor_y & CURSOR_Y_MASK) << CURSOR_Y_SHIFT);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_CURSOR_LOCATION);
iova = phytium_plane->iova[0];
phytium_writel_reg(priv, iova & 0xffffffff, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_CURSOR_ADDRESS);
if (phytium_plane->dc_hw_update_cursor_hi_addr)
phytium_plane->dc_hw_update_cursor_hi_addr(plane, iova);
}
static void phytium_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct drm_framebuffer *fb, *old_fb;
DRM_DEBUG_KMS("update plane: type=%d\n", plane->type);
if (!plane->state->crtc || !plane->state->fb)
return;
fb = plane->state->fb;
old_fb = old_state->fb;
if (fb)
drm_framebuffer_get(fb);
if (old_fb)
drm_framebuffer_put(old_fb);
phytium_dc_get_plane_parameter(plane);
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
phytium_dc_primary_plane_update(plane);
else if (plane->type == DRM_PLANE_TYPE_CURSOR)
phytium_dc_cursor_plane_update(plane);
}
static void phytium_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
int phys_pipe = phytium_plane->phys_pipe;
int config;
struct drm_framebuffer *old_fb;
old_fb = old_state->fb;
if (old_fb)
drm_framebuffer_put(old_fb);
if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
phytium_writel_reg(priv, CLEAR_VALUE_RED, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CLEARVALUE);
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
config |= FRAMEBUFFER_CLEAR;
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
} else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
phytium_writel_reg(priv, CURSOR_FORMAT_DISABLED,
priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
}
}
const struct drm_plane_helper_funcs phytium_plane_helper_funcs = {
.prepare_fb = phytium_plane_prepare_fb,
.atomic_check = phytium_plane_atomic_check,
.atomic_update = phytium_plane_atomic_update,
.atomic_disable = phytium_plane_atomic_disable,
};
struct phytium_plane *phytium_primary_plane_create(struct drm_device *dev, int phys_pipe)
{
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = NULL;
struct phytium_plane_state *phytium_plane_state = NULL;
int ret = 0;
unsigned int flags = 0;
const uint32_t *formats = NULL;
uint32_t format_count;
const uint64_t *format_modifiers;
phytium_plane = kzalloc(sizeof(*phytium_plane), GFP_KERNEL);
if (!phytium_plane) {
ret = -ENOMEM;
goto failed_malloc_plane;
}
phytium_plane_state = kzalloc(sizeof(*phytium_plane_state), GFP_KERNEL);
if (!phytium_plane_state) {
ret = -ENOMEM;
goto failed_malloc_plane_state;
}
phytium_plane_state->base.plane = &phytium_plane->base;
phytium_plane_state->base.rotation = DRM_MODE_ROTATE_0;
phytium_plane->base.state = &phytium_plane_state->base;
phytium_plane->phys_pipe = phys_pipe;
if (IS_PX210(priv)) {
phytium_plane->dc_hw_plane_get_format = px210_dc_hw_plane_get_primary_format;
phytium_plane->dc_hw_update_dcreq = px210_dc_hw_update_dcreq;
phytium_plane->dc_hw_update_primary_hi_addr = px210_dc_hw_update_primary_hi_addr;
phytium_plane->dc_hw_update_cursor_hi_addr = NULL;
} else if (IS_PE220X(priv)) {
phytium_plane->dc_hw_plane_get_format = pe220x_dc_hw_plane_get_primary_format;
phytium_plane->dc_hw_update_dcreq = NULL;
phytium_plane->dc_hw_update_primary_hi_addr = pe220x_dc_hw_update_primary_hi_addr;
phytium_plane->dc_hw_update_cursor_hi_addr = NULL;
}
phytium_plane->dc_hw_plane_get_format(&format_modifiers, &formats, &format_count);
ret = drm_universal_plane_init(dev, &phytium_plane->base, 0x0,
&phytium_plane_funcs, formats,
format_count,
format_modifiers,
DRM_PLANE_TYPE_PRIMARY, "primary %d", phys_pipe);
if (ret)
goto failed_plane_init;
flags = DRM_MODE_ROTATE_0;
drm_plane_create_rotation_property(&phytium_plane->base, DRM_MODE_ROTATE_0, flags);
drm_plane_helper_add(&phytium_plane->base, &phytium_plane_helper_funcs);
return phytium_plane;
failed_plane_init:
kfree(phytium_plane_state);
failed_malloc_plane_state:
kfree(phytium_plane);
failed_malloc_plane:
return ERR_PTR(ret);
}
struct phytium_plane *phytium_cursor_plane_create(struct drm_device *dev, int phys_pipe)
{
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = NULL;
struct phytium_plane_state *phytium_plane_state = NULL;
int ret = 0;
unsigned int flags = 0;
const uint32_t *formats = NULL;
uint32_t format_count;
const uint64_t *format_modifiers;
phytium_plane = kzalloc(sizeof(*phytium_plane), GFP_KERNEL);
if (!phytium_plane) {
ret = -ENOMEM;
goto failed_malloc_plane;
}
phytium_plane_state = kzalloc(sizeof(*phytium_plane_state), GFP_KERNEL);
if (!phytium_plane_state) {
ret = -ENOMEM;
goto failed_malloc_plane_state;
}
phytium_plane_state->base.plane = &phytium_plane->base;
phytium_plane_state->base.rotation = DRM_MODE_ROTATE_0;
phytium_plane->base.state = &phytium_plane_state->base;
phytium_plane->phys_pipe = phys_pipe;
if (IS_PX210(priv)) {
phytium_plane->dc_hw_plane_get_format = px210_dc_hw_plane_get_cursor_format;
phytium_plane->dc_hw_update_dcreq = NULL;
phytium_plane->dc_hw_update_primary_hi_addr = NULL;
phytium_plane->dc_hw_update_cursor_hi_addr = NULL;
} else if (IS_PE220X(priv)) {
phytium_plane->dc_hw_plane_get_format = pe220x_dc_hw_plane_get_cursor_format;
phytium_plane->dc_hw_update_dcreq = NULL;
phytium_plane->dc_hw_update_primary_hi_addr = NULL;
phytium_plane->dc_hw_update_cursor_hi_addr = pe220x_dc_hw_update_cursor_hi_addr;
}
phytium_plane->dc_hw_plane_get_format(&format_modifiers, &formats, &format_count);
ret = drm_universal_plane_init(dev, &phytium_plane->base, 0x0,
&phytium_plane_funcs,
formats, format_count,
format_modifiers,
DRM_PLANE_TYPE_CURSOR, "cursor %d", phys_pipe);
if (ret)
goto failed_plane_init;
flags = DRM_MODE_ROTATE_0;
drm_plane_create_rotation_property(&phytium_plane->base, DRM_MODE_ROTATE_0, flags);
drm_plane_helper_add(&phytium_plane->base, &phytium_plane_helper_funcs);
return phytium_plane;
failed_plane_init:
kfree(phytium_plane_state);
failed_malloc_plane_state:
kfree(phytium_plane);
failed_malloc_plane:
return ERR_PTR(ret);
}

View File

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Phytium display drm driver
*
* Copyright (c) 2021-2023 Phytium Technology Co., Ltd.
*/
#ifndef __PHYTIUM_PLANE_H__
#define __PHYTIUM_PLANE_H__
struct phytium_plane {
struct drm_plane base;
int phys_pipe;
unsigned long iova[PHYTIUM_FORMAT_MAX_PLANE];
unsigned long size[PHYTIUM_FORMAT_MAX_PLANE];
unsigned int format;
unsigned int tiling[PHYTIUM_FORMAT_MAX_PLANE];
unsigned int swizzle;
unsigned int uv_swizzle;
unsigned int rot_angle;
/* only for cursor */
bool enable;
bool reserve[3];
int cursor_x;
int cursor_y;
int cursor_hot_x;
int cursor_hot_y;
void (*dc_hw_plane_get_format)(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count);
void (*dc_hw_update_dcreq)(struct drm_plane *plane);
void (*dc_hw_update_primary_hi_addr)(struct drm_plane *plane);
void (*dc_hw_update_cursor_hi_addr)(struct drm_plane *plane, uint64_t iova);
};
struct phytium_plane_state {
struct drm_plane_state base;
};
#define to_phytium_plane(x) container_of(x, struct phytium_plane, base)
#define to_phytium_plane_state(x) container_of(x, struct phytium_plane_state, base)
struct phytium_plane *phytium_primary_plane_create(struct drm_device *dev, int pipe);
struct phytium_plane *phytium_cursor_plane_create(struct drm_device *dev, int pipe);
#endif /* __PHYTIUM_PLANE_H__ */

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