Merge branch 'coolsnowwolf:master' into master

This commit is contained in:
mclk623 2025-11-14 12:53:29 +08:00 committed by GitHub
commit be88360baf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
169 changed files with 20335 additions and 1027 deletions

View File

@ -321,15 +321,14 @@ menu "Target Images"
depends on USES_BOOT_PART
default 8 if TARGET_apm821xx_sata
default 128 if TARGET_armsr
default 64 if TARGET_bcm27xx
default 64 if TARGET_bcm27xx || TARGET_x86 || TARGET_loongarch64
default 32 if TARGET_rockchip
default 16
config TARGET_ROOTFS_PARTSIZE
int "Root filesystem partition size (in MiB)"
depends on USES_ROOTFS_PART || TARGET_ROOTFS_EXT4FS
default 232 if TARGET_loongarch64
default 448 if TARGET_mediatek || TARGET_x86
default 448 if TARGET_mediatek || TARGET_x86 || TARGET_loongarch64
default 160
help
Select the root filesystem partition size.

View File

@ -81,7 +81,6 @@ define Build/Compile/Trusted-Firmware-A
$(if $(DTC),DTC="$(DTC)") \
PLAT=$(PLAT) \
BUILD_STRING="OpenWrt v$(PKG_VERSION)-$(PKG_RELEASE) ($(VARIANT))" \
$(if $(CONFIG_BINUTILS_VERSION_2_37)$(CONFIG_BINUTILS_VERSION_2_38),,LDFLAGS="-no-warn-rwx-segments") \
$(TFA_MAKE_FLAGS)
endef

View File

@ -9,13 +9,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=arm-trusted-firmware-mediatek
PKG_RELEASE:=2
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/mtk-openwrt/arm-trusted-firmware.git
PKG_SOURCE_DATE:=2024-01-17
PKG_SOURCE_VERSION:=bacca82a8cac369470df052a9d801a0ceb9b74ca
PKG_MIRROR_HASH:=d035c1b63a9bd71d752c90540361b66d290e7cf42dcca73259d0950af3569c79
PKG_SOURCE_DATE:=2025-07-11
PKG_SOURCE_VERSION:=78a0dfd927bb00ce973a1f8eb4079df0f755887a
PKG_MIRROR_HASH:=5604a9419f788f53448c48761dc50d3dc4bef3b3dbbc08a32cf2def253588171
PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
@ -33,6 +33,7 @@ define Trusted-Firmware-A/Default
BOARD_QFN:=
DRAM_USE_COMB:=
USE_UBI:=
SPIM_CTRL:=
endef
define Trusted-Firmware-A/mt7622-nor-1ddr
@ -285,6 +286,59 @@ define Trusted-Firmware-A/mt7986-spim-nand-ddr3
DDR_TYPE:=ddr3
endef
define Trusted-Firmware-A/mt7986-spim-nand-ubi-ddr3
NAME:=MediaTek MT7986 (SPI-NAND via SPIM using UBI, DDR3)
BOOT_DEVICE:=spim-nand
BUILD_SUBTARGET:=filogic
PLAT:=mt7986
DDR_TYPE:=ddr3
USE_UBI:=1
endef
define Trusted-Firmware-A/mt7987-emmc-comb
NAME:=MediaTek MT7987 (eMMC)
BOOT_DEVICE:=emmc
BUILD_SUBTARGET:=filogic
PLAT:=mt7987
DRAM_USE_COMB:=1
endef
define Trusted-Firmware-A/mt7987-nor-comb
NAME:=MediaTek MT7987 (NOR)
BOOT_DEVICE:=nor
BUILD_SUBTARGET:=filogic
PLAT:=mt7987
DRAM_USE_COMB:=1
endef
define Trusted-Firmware-A/mt7987-sdmmc-comb
NAME:=MediaTek MT7987 (SD card)
BOOT_DEVICE:=sdmmc
BUILD_SUBTARGET:=filogic
PLAT:=mt7987
DRAM_USE_COMB:=1
endef
define Trusted-Firmware-A/mt7987-spim-nand0-ubi-comb
NAME:=MediaTek MT7987 (SPI-NAND via SPIM, UBI)
BOOT_DEVICE:=spim-nand
BUILD_SUBTARGET:=filogic
PLAT:=mt7987
DRAM_USE_COMB:=1
USE_UBI:=1
SPIM_CTRL:=0
endef
define Trusted-Firmware-A/mt7987-spim-nand2-ubi-comb
NAME:=MediaTek MT7987 (SPI-NAND via SPIM, UBI)
BOOT_DEVICE:=spim-nand
BUILD_SUBTARGET:=filogic
PLAT:=mt7987
DRAM_USE_COMB:=1
USE_UBI:=1
SPIM_CTRL:=2
endef
define Trusted-Firmware-A/mt7988-nor-ddr3
NAME:=MediaTek MT7988 (SPI-NOR, DDR3)
BOOT_DEVICE:=nor
@ -423,6 +477,15 @@ define Trusted-Firmware-A/mt7988-spim-nand-ubi-comb
USE_UBI:=1
endef
define Trusted-Firmware-A/mt7988-spim-nand-ubi-ddr4
NAME:=MediaTek MT7988 (SPI-NAND via SPIM, DDR4)
BOOT_DEVICE:=spim-nand
BUILD_SUBTARGET:=filogic
PLAT:=mt7988
DDR_TYPE:=ddr4
USE_UBI:=1
endef
TFA_TARGETS:= \
mt7622-nor-1ddr \
mt7622-nor-2ddr \
@ -448,6 +511,7 @@ TFA_TARGETS:= \
mt7986-sdmmc-ddr3 \
mt7986-snand-ddr3 \
mt7986-spim-nand-ddr3 \
mt7986-spim-nand-ubi-ddr3 \
mt7986-emmc-ddr4 \
mt7986-nor-ddr4 \
mt7986-sdmmc-ddr4 \
@ -455,6 +519,11 @@ TFA_TARGETS:= \
mt7986-spim-nand-ddr4 \
mt7986-spim-nand-ubi-ddr4 \
mt7986-spim-nand-4k-ddr4 \
mt7987-emmc-comb \
mt7987-nor-comb \
mt7987-sdmmc-comb \
mt7987-spim-nand0-ubi-comb \
mt7987-spim-nand2-ubi-comb \
mt7988-emmc-ddr3 \
mt7988-nor-ddr3 \
mt7988-sdmmc-ddr3 \
@ -471,7 +540,8 @@ TFA_TARGETS:= \
mt7988-snand-comb \
mt7988-snand-ubi-comb \
mt7988-spim-nand-comb \
mt7988-spim-nand-ubi-comb
mt7988-spim-nand-ubi-comb \
mt7988-spim-nand-ubi-ddr4
TFA_MAKE_FLAGS += \
BOOT_DEVICE=$(BOOT_DEVICE) \
@ -484,6 +554,8 @@ TFA_MAKE_FLAGS += \
$(if $(DRAM_USE_COMB),DRAM_USE_COMB=1) \
$(if $(USE_UBI),UBI=1 $(if $(findstring mt7622,$(PLAT)),OVERRIDE_UBI_START_ADDR=0x80000)) \
$(if $(USE_UBI),UBI=1 $(if $(findstring mt7981,$(PLAT)),OVERRIDE_UBI_START_ADDR=0x100000)) \
$(if $(USE_UBI),UBI=1 $(if $(findstring mt7986,$(PLAT)),OVERRIDE_UBI_START_ADDR=0x200000)) \
$(if $(SPIM_CTRL),SPIM_CTRL=$(SPIM_CTRL)) \
all
define Package/trusted-firmware-a/install

View File

@ -0,0 +1,41 @@
From fd057aba83aea8458986e11c81dbb75a69468b84 Mon Sep 17 00:00:00 2001
From: Mikhail Zhilkin <csharper2005@gmail.com>
Date: Wed, 13 Aug 2025 22:46:54 +0300
Subject: arm-trusted-firmware-mediatek: add FudanMicro manufacturer
Add FudanMicro manufacturer.
Signed-off-by: Mikhail Zhilkin <csharper2005@gmail.com>
---
--- a/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c
+++ b/plat/mediatek/apsoc_common/drivers/spi_nand/mtk_spi_nand.c
@@ -21,6 +21,7 @@
#define SPI_NAND_MAX_ID_LEN 4U
#define DELAY_US_400MS 400000U
#define ETRON_ID 0xD5U
+#define FUDAN_ID 0xA1U
#define GIGADEVICE_ID 0xC8U
#define MACRONIX_ID 0xC2U
#define MICRON_ID 0x2CU
@@ -146,7 +147,8 @@ static int spi_nand_quad_enable(uint8_t
if (manufacturer_id != MACRONIX_ID &&
manufacturer_id != GIGADEVICE_ID &&
manufacturer_id != ETRON_ID &&
- manufacturer_id != FORESEE_ID) {
+ manufacturer_id != FORESEE_ID &&
+ manufacturer_id != FUDAN_ID) {
return 0;
}
@@ -543,6 +545,10 @@ static int spi_nand_check_pp(struct para
INFO("PP COPY %d CRC read: 0x%x, compute: 0x%x\n",
i, crc, crc_compute);
+ // FUDAN integrity CRC (bytes 254-255) is reversed
+ if (crc != crc_compute)
+ crc = htobe16(pp->integrity_crc);
+
if (crc != crc_compute) {
ret = -EBADMSG;
continue;

View File

@ -0,0 +1,128 @@
From e2e43103c00b5f7ccedbdbdece0f622cb420b4a5 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Fri, 3 Oct 2025 12:53:10 +0100
Subject: [PATCH] mt7987: make SPI controller configurable
Allow selecting the SPI controller used for SPIM-NAND or SPI-NOR boot
devices (either SPI0 or SPI2).
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
plat/mediatek/apsoc_common/Config.in | 1 +
plat/mediatek/mt7987/Config.in | 29 +++++++++++++++++++++
plat/mediatek/mt7987/bl2/bl2.mk | 12 +++++++++
plat/mediatek/mt7987/bl2/bl2_dev_spi_nand.c | 10 ++++++-
plat/mediatek/mt7987/platform.mk | 4 +--
5 files changed, 53 insertions(+), 3 deletions(-)
create mode 100644 plat/mediatek/mt7987/Config.in
--- a/plat/mediatek/apsoc_common/Config.in
+++ b/plat/mediatek/apsoc_common/Config.in
@@ -783,6 +783,7 @@ config ENABLE_BL31_RUNTIME_LOG
default 1
depends on _ENABLE_BL31_RUNTIME_LOG
+source "plat/mediatek/mt7987/Config.in"
source "plat/mediatek/mt7988/Config.in"
endmenu # Platform configurations
--- /dev/null
+++ b/plat/mediatek/mt7987/Config.in
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 2025 Daniel Golle <daniel@makrotopia.org>
+#
+# MT7987 platform-specific configurations
+#
+
+if _PLAT_MT7987
+
+choice
+ prompt "SPI controller"
+ depends on (_BOOT_DEVICE_SPIM_NAND || _BOOT_DEVICE_SPI_NOR)
+ default _SPIM_CTRL_0 if _BOOT_DEVICE_SPIM_NAND
+ default _SPIM_CTRL_2 if _BOOT_DEVICE_SPI_NOR
+
+ config _SPIM_CTRL_0
+ bool "0"
+
+ config _SPIM_CTRL_2
+ bool "2"
+
+endchoice
+
+config SPIM_CTRL
+ int
+ default 0 if _SPIM_CTRL_0
+ default 2 if _SPIM_CTRL_2
+
+endif # _PLAT_MT7987
--- a/plat/mediatek/mt7987/bl2/bl2.mk
+++ b/plat/mediatek/mt7987/bl2/bl2.mk
@@ -91,7 +91,11 @@ endif # END OF BOOT_DEVICE = ram
ifeq ($(BOOT_DEVICE),nor)
$(eval $(call BL2_BOOT_NOR))
BL2_SOURCES += $(MTK_PLAT_SOC)/bl2/bl2_dev_spi_nor.c
+ifeq ($(SPIM_CTRL),0)
+DTS_NAME := mt7987-spi0
+else
DTS_NAME := mt7987-spi2
+endif
endif # END OF BOOTDEVICE = nor
ifeq ($(BOOT_DEVICE),emmc)
@@ -112,10 +116,18 @@ ifeq ($(BOOT_DEVICE),spim-nand)
$(eval $(call BL2_BOOT_SPI_NAND,0,0))
BL2_SOURCES += $(MTK_PLAT_SOC)/bl2/bl2_dev_spi_nand.c
NAND_TYPE ?= spim:2k+64
+ifeq ($(SPIM_CTRL),2)
+DTS_NAME := mt7987-spi2
+else
DTS_NAME := mt7987-spi0
+endif
$(eval $(call BL2_BOOT_NAND_TYPE_CHECK,$(NAND_TYPE),spim:2k+64 spim:2k+128 spim:4k+256))
endif # END OF BOOTDEVICE = spim-nand
+ifneq ($(SPIM_CTRL),)
+BL2_CPPFLAGS += -DSPIM_CTRL=$(SPIM_CTRL)
+endif
+
ifeq ($(BROM_HEADER_TYPE),)
$(error BOOT_DEVICE has invalid value. Please re-check.)
endif
--- a/plat/mediatek/mt7987/bl2/bl2_dev_spi_nand.c
+++ b/plat/mediatek/mt7987/bl2/bl2_dev_spi_nand.c
@@ -12,10 +12,18 @@
#define MTK_QSPI_SRC_CLK CB_MPLL_D2
+#if SPIM_CTRL == 0
+#define SELECTED_SPIM SPIM0
+#elif SPIM_CTRL == 2
+#define SELECTED_SPIM SPIM2
+#else
+#error "Invalid SPI controller selection"
+#endif
+
uint32_t mtk_plat_get_qspi_src_clk(void)
{
/* config GPIO pinmux to spi mode */
- mtk_spi_gpio_init(SPIM0);
+ mtk_spi_gpio_init(SELECTED_SPIM);
/* select 208M clk */
mtk_spi_source_clock_select(MTK_QSPI_SRC_CLK);
--- a/plat/mediatek/mt7987/platform.mk
+++ b/plat/mediatek/mt7987/platform.mk
@@ -56,8 +56,8 @@ include make_helpers/dep.mk
$(call GEN_DEP_RULES,bl2,emicfg bl2_boot_ram bl2_boot_nand_nmbm bl2_dev_mmc bl2_plat_init bl2_plat_setup mt7987_gpio dtb)
$(call MAKE_DEP,bl2,emicfg,DDR4_4BG_MODE DRAM_DEBUG_LOG DDR3_FREQ_2133 DDR3_FREQ_1866 DDR4_FREQ_3200 DDR4_FREQ_2666)
-$(call MAKE_DEP,bl2,bl2_plat_init,BL2_COMPRESS)
-$(call MAKE_DEP,bl2,bl2_plat_setup,BOOT_DEVICE TRUSTED_BOARD_BOOT BL32_TZRAM_BASE BL32_TZRAM_SIZE BL32_LOAD_OFFSET)
+$(call MAKE_DEP,bl2,bl2_plat_init,BL2_COMPRESS SPIM_CTRL)
+$(call MAKE_DEP,bl2,bl2_plat_setup,BOOT_DEVICE TRUSTED_BOARD_BOOT BL32_TZRAM_BASE BL32_TZRAM_SIZE BL32_LOAD_OFFSET SPIM_CTRL)
$(call MAKE_DEP,bl2,bl2_dev_mmc,BOOT_DEVICE)
$(call MAKE_DEP,bl2,bl2_boot_ram,RAM_BOOT_DEBUGGER_HOOK RAM_BOOT_UART_DL)
$(call MAKE_DEP,bl2,bl2_boot_nand_nmbm,NMBM_MAX_RATIO NMBM_MAX_RESERVED_BLOCKS NMBM_DEFAULT_LOG_LEVEL)

View File

@ -0,0 +1,24 @@
From 0a09912eb336bee788443b919ea5b99b195f5a91 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 4 Oct 2025 22:13:49 +0100
Subject: [PATCH] hack: mt7987: mmc: use 4-bit bus-width for eMMC
The BananaPi R4 Lite has broken DAT5 signal of the MMC bus, which
results in 8-bit buswidth not working well for the eMMC.
Reduce to 4-bit buswidth fixes it (and makes all other boards with
eMMC a tiny bit slower to boot, but it's in the milliseconds).
---
plat/mediatek/mt7987/bl2/bl2_dev_mmc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/plat/mediatek/mt7987/bl2/bl2_dev_mmc.c
+++ b/plat/mediatek/mt7987/bl2/bl2_dev_mmc.c
@@ -74,7 +74,7 @@ static const struct mt7987_msdc_conf {
{
.base = MSDC0_BASE,
.top_base = MSDC0_TOP_BASE,
- .bus_width = MMC_BUS_WIDTH_8,
+ .bus_width = MMC_BUS_WIDTH_4,
.type = MMC_IS_EMMC,
.src_clk = 200000000,
.dev_comp = &mt7987_msdc_compat,

View File

@ -0,0 +1,27 @@
From 6725bb3c2aa9330f37a591e1e539badf67021b47 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 4 Oct 2025 23:59:54 +0100
Subject: [PATCH] hack: mt7987: bl2: move FIP offset to 0x100000
There is no use in allocating more than 2MB to the factory partition.
After all, even for WiFi 7 tri-band devices the calibration data is
still in the kilobytes range.
Move FIP offset to 0x100000 to not waste so much space on small NOR
flash.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
plat/mediatek/mt7987/bl2/bl2_dev_spi_nor.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/plat/mediatek/mt7987/bl2/bl2_dev_spi_nor.c
+++ b/plat/mediatek/mt7987/bl2/bl2_dev_spi_nor.c
@@ -7,7 +7,7 @@
#include <stdint.h>
#include <boot_spi.h>
-#define FIP_BASE 0x250000
+#define FIP_BASE 0x100000
#define FIP_SIZE 0x80000
#define MTK_QSPI_SRC_CLK CB_MPLL_D2

View File

@ -108,6 +108,7 @@ TFA_TARGETS:= \
udpu
TFA_MAKE_FLAGS += \
$(if $(CONFIG_BINUTILS_VERSION_2_37)$(CONFIG_BINUTILS_VERSION_2_38),,LDFLAGS="-no-warn-rwx-segments") \
CROSS_CM3=$(STAGING_DIR_IMAGE)/$(LINARO_NAME)-$(LINARO_RELEASE).$(LINARO_VERSION)/bin/arm-linux-gnueabi- \
BL33=$(STAGING_DIR_IMAGE)/$(UBOOT)-u-boot.bin \
MV_DDR_PATH=$(STAGING_DIR_IMAGE)/$(MV_DDR_NAME) \

View File

@ -46,6 +46,9 @@ TFA_TARGETS:= \
sunxi-h6 \
sunxi-h616
TFA_MAKE_FLAGS+= \
$(if $(CONFIG_BINUTILS_VERSION_2_37)$(CONFIG_BINUTILS_VERSION_2_38),,LDFLAGS="-no-warn-rwx-segments")
define Package/trusted-firmware-a/install
$(INSTALL_DIR) $(STAGING_DIR_IMAGE)
$(INSTALL_DATA) $(PKG_BUILD_DIR)/build/$(PLAT)/release/bl31.bin $(STAGING_DIR_IMAGE)/bl31_$(BUILD_VARIANT).bin

View File

@ -6,9 +6,11 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git
PKG_SOURCE_DATE:=2025-06-13
PKG_SOURCE_VERSION:=4810aacf3b1c5de99923b9a424a1f0e6341c6bca
PKG_MIRROR_HASH:=2e2fdf0578e39eb0be36cfd8e11de920c3e8446469dafee0ebbc580f272193a8
PKG_SOURCE_DATE:=2025-10-22
PKG_SOURCE_VERSION:=ec6831a43ff066c9873e7c41fd6f68354bb67b4a
PKG_MIRROR_HASH:=a9fbf572eb8c6dc2f40f167139d7ecdae8dbc86d29e519209ac482a76bcb0fe2
PKG_FLAGS:=nonshared
include $(INCLUDE_DIR)/package.mk
@ -37,15 +39,24 @@ ALLWIFIBOARDS:= \
edimax_cax1800 \
glinet_gl-ax1800 \
glinet_gl-axt1800 \
jdcloud_ax1800pro \
glinet_gl-b3000 \
jdcloud_re-cs-02 \
jdcloud_re-ss-01 \
linksys_homewrk \
linksys_mr5500 \
linksys_mr7350 \
linksys_mr7500 \
linksys_mx2000 \
linksys_mx4200 \
linksys_mx5300 \
linksys_mx5500 \
linksys_mx8500 \
netgear_lbr20 \
netgear_rax120v2 \
netgear_wax214 \
netgear_wax218 \
netgear_wax610 \
netgear_wax610y \
netgear_wax620 \
netgear_wax630 \
prpl_haze \
@ -58,6 +69,7 @@ ALLWIFIBOARDS:= \
xiaomi_ax6000 \
xiaomi_ax9000 \
xiaomi_rm1800 \
yuncore_ax830 \
yuncore_ax880 \
yuncore_fap650 \
zbtlink_zbt-z800ax \
@ -72,7 +84,7 @@ define Package/ipq-wifi-default
SUBMENU:=ath10k Board-Specific Overrides
SECTION:=firmware
CATEGORY:=Firmware
DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_qualcommax)
DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_qualcommax||TARGET_qualcommbe)
TITLE:=Custom Board
endef
@ -86,6 +98,11 @@ define ipq-wifi-install-ath11-one-to
$(INSTALL_DATA) $(1) $(2)/lib/firmware/ath11k/$(3)/board-2.bin
endef
define ipq-wifi-install-ath12-one-to
$(INSTALL_DIR) $(2)/lib/firmware/ath12k/$(3)/
$(INSTALL_DATA) $(1) $(2)/lib/firmware/ath12k/$(3)/board-2.bin
endef
define ipq-wifi-install-one
$(if $(filter $(suffix $(1)),.QCA4019 .qca4019),\
$(call ipq-wifi-install-one-to,$(1),$(2),QCA4019/hw1.0),\
@ -107,8 +124,10 @@ define ipq-wifi-install-one
$(call ipq-wifi-install-ath11-one-to,$(1),$(2),QCN6122/hw1.0),\
$(if $(filter $(suffix $(1)),.QCN9074 .qcn9074),\
$(call ipq-wifi-install-ath11-one-to,$(1),$(2),QCN9074/hw1.0),\
$(if $(filter $(suffix $(1)),.QCN9274 .qcn9274),\
$(call ipq-wifi-install-ath12-one-to,$(1),$(2),QCN9274/hw2.0),\
$(error Unrecognized board-file suffix '$(suffix $(1))' for '$(1)')\
))))))))))
)))))))))))
endef
# Blank line required at end of above define due to foreach context
@ -155,15 +174,24 @@ $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102))
$(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800))
$(eval $(call generate-ipq-wifi-package,glinet_gl-ax1800,GL.iNet GL-AX1800))
$(eval $(call generate-ipq-wifi-package,glinet_gl-axt1800,GL.iNet GL-AXT1800))
$(eval $(call generate-ipq-wifi-package,jdcloud_ax1800pro,JDCloud AX1800 Pro))
$(eval $(call generate-ipq-wifi-package,glinet_gl-b3000,GL.iNet GL-B3000))
$(eval $(call generate-ipq-wifi-package,jdcloud_re-cs-02,JDCloud RE-CS-02))
$(eval $(call generate-ipq-wifi-package,jdcloud_re-ss-01,JDCloud RE-SS-01))
$(eval $(call generate-ipq-wifi-package,linksys_homewrk,Linksys HomeWRK))
$(eval $(call generate-ipq-wifi-package,linksys_mr5500,Linksys MR5500))
$(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350))
$(eval $(call generate-ipq-wifi-package,linksys_mr7500,Linksys MR7500))
$(eval $(call generate-ipq-wifi-package,linksys_mx2000,Linksys MX2000))
$(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200))
$(eval $(call generate-ipq-wifi-package,linksys_mx5300,Linksys MX5300))
$(eval $(call generate-ipq-wifi-package,linksys_mx5500,Linksys MX5500))
$(eval $(call generate-ipq-wifi-package,linksys_mx8500,Linksys MX8500))
$(eval $(call generate-ipq-wifi-package,netgear_lbr20,Netgear LBR20))
$(eval $(call generate-ipq-wifi-package,netgear_rax120v2,Netgear RAX120v2))
$(eval $(call generate-ipq-wifi-package,netgear_wax214,Netgear WAX214))
$(eval $(call generate-ipq-wifi-package,netgear_wax218,Netgear WAX218))
$(eval $(call generate-ipq-wifi-package,netgear_wax610,Netgear WAX610))
$(eval $(call generate-ipq-wifi-package,netgear_wax610y,Netgear WAX610Y))
$(eval $(call generate-ipq-wifi-package,netgear_wax620,Netgear WAX620))
$(eval $(call generate-ipq-wifi-package,netgear_wax630,Netgear WAX630))
$(eval $(call generate-ipq-wifi-package,qihoo_360v6,Qihoo 360V6))
@ -176,6 +204,7 @@ $(eval $(call generate-ipq-wifi-package,xiaomi_ax3600,Xiaomi AX3600))
$(eval $(call generate-ipq-wifi-package,xiaomi_ax6000,Xiaomi AX6000))
$(eval $(call generate-ipq-wifi-package,xiaomi_ax9000,Xiaomi AX9000))
$(eval $(call generate-ipq-wifi-package,xiaomi_rm1800,Xiaomi RM1800))
$(eval $(call generate-ipq-wifi-package,yuncore_ax830,Yuncore AX830))
$(eval $(call generate-ipq-wifi-package,yuncore_ax880,Yuncore AX880))
$(eval $(call generate-ipq-wifi-package,yuncore_fap650,Yuncore FAP650))
$(eval $(call generate-ipq-wifi-package,zbtlink_zbt-z800ax,Zbtlink ZBT-Z800AX))

View File

@ -481,15 +481,14 @@ define KernelPackage/drm-amdgpu
DEPENDS:=@TARGET_x86 @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 \
+(LINUX_6_6||LINUX_6_12):kmod-drm-exec +(LINUX_6_6||LINUX_6_12):kmod-drm-suballoc-helper
+(LINUX_6_6||LINUX_6_12):kmod-drm-exec +(LINUX_6_6||LINUX_6_12):kmod-drm-suballoc-helper +kmod-drm-sched
KCONFIG:=CONFIG_DRM_AMDGPU \
CONFIG_DRM_AMDGPU_SI=y \
CONFIG_DRM_AMDGPU_CIK=y \
CONFIG_DRM_AMD_DC=y \
CONFIG_DEBUG_KERNEL_DC=n
FILES:=$(LINUX_DIR)/drivers/gpu/drm/amd/amdgpu/amdgpu.ko \
$(LINUX_DIR)/drivers/gpu/drm/amd/amdxcp/amdxcp.ko@ge6.5 \
$(LINUX_DIR)/drivers/gpu/drm/scheduler/gpu-sched.ko
$(LINUX_DIR)/drivers/gpu/drm/amd/amdxcp/amdxcp.ko@ge6.5
AUTOLOAD:=$(call AutoProbe,amdgpu)
endef
@ -754,6 +753,31 @@ endef
$(eval $(call KernelPackage,drm-nouveau))
define KernelPackage/drm-xe
SUBMENU:=$(VIDEO_MENU)
TITLE:=Intel Xe GPU drm support
DEPENDS:=@TARGET_x86 +kmod-drm-buddy +kmod-drm-ttm +kmod-drm-kms-helper +kmod-drm-i915 +i915-firmware \
+kmod-drm-display-helper +kmod-acpi-video \
+kmod-drm-exec +kmod-drm-suballoc-helper +kmod-drm-sched @LINUX_6_12
KCONFIG:= \
CONFIG_DRM_GPUVM \
CONFIG_DRM_SCHED \
CONFIG_DRM_XE
FILES:= \
$(LINUX_DIR)/drivers/gpu/drm/drm_gpuvm.ko \
$(LINUX_DIR)/drivers/gpu/drm/xe/xe.ko
AUTOLOAD:=$(call AutoProbe,gpu-sched drm_gpuvm xe)
endef
define KernelPackage/drm-xe/description
The drm/xe driver supports some future GFX cards with rendering, display,
compute and media. Support for currently available platforms like TGL, ADL,
DG2, etc is provided to prototype the driver.
endef
$(eval $(call KernelPackage,drm-xe))
#
# Video Capture
#

View File

@ -22,6 +22,13 @@ define Package/autocore-arm
VARIANT:=arm
endef
define Package/autocore-loongarch64
TITLE:=Loongarch64 auto core loadbalance script.
MAINTAINER:=LEAN
DEPENDS:=@loongarch64 +bc +ethtool +pciutils
VARIANT:=loongarch64
endef
define Package/autocore-x86
TITLE:=x86/x64 auto core loadbalance script.
MAINTAINER:=Lean
@ -33,6 +40,10 @@ define Package/autocore-arm/description
A luci autoconfig hotplug script.
endef
define Package/autocore-loongarch64/description
A luci autoconfig hotplug script.
endef
define Package/autocore-x86/description
A usb autoconfig hotplug script.
endef
@ -57,6 +68,19 @@ endif
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
endef
define Package/autocore-loongarch64/install
$(INSTALL_DIR) $(1)/etc
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/loongarch64/autocore $(1)/etc/init.d/autocore
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) ./files/loongarch64/sbin/cpuinfo $(1)/sbin/cpuinfo
$(INSTALL_BIN) ./files/loongarch64/sbin/tempinfo $(1)/sbin/tempinfo
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
endef
define Package/autocore-x86/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/x86/autocore $(1)/etc/init.d/autocore
@ -71,4 +95,5 @@ define Package/autocore-x86/install
endef
$(eval $(call BuildPackage,autocore-arm))
$(eval $(call BuildPackage,autocore-loongarch64))
$(eval $(call BuildPackage,autocore-x86))

View File

@ -0,0 +1,20 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2025 lean <coolsnowwolf@gmail.com>
START=99
start()
{
a=$(cat /proc/cpuinfo | grep 'Model Name' | cut -f2 -d: | head -n 1)
b=$(echo -n ' : ')
c=$(cat /proc/cpuinfo | grep 'core' | sort -u | wc -l)
d=$(echo -n 'C')
e=$(cat /proc/cpuinfo | grep 'global_id' | sort -u | wc -l)
f=$(echo -n 'T ')
g=$(cat /proc/cpuinfo | grep 'CPU Family' | cut -f2 -d: | head -n 1)
h=${g}' - '${a}${b}${c}${d}${e}${f}
mkdir -p /tmp/sysinfo
echo $h > /tmp/sysinfo/model
}

View File

@ -0,0 +1,5 @@
#!/bin/sh
MHz=`grep 'MHz' /proc/cpuinfo | cut -c13- |sed -n '1p'`
echo "$MHz MHz"

View File

@ -0,0 +1,45 @@
#!/usr/bin/lua
-- Copyright (C) 2022 ImmortalWrt.org
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local eth_info = {}
local ifname, stat
for ifname, stat in pairs(util.ubus("network.device", "status")) do
while true do
if (ifname:match("^(br-.+)$")) == ifname then
break
else
local status, speed, duplex
if(stat.speed ~= nil) then
status = stat.carrier and 1 or 0
if stat.speed:sub(1, 1) == "-" then
speed = " - "
else
speed = stat.speed:sub(1, -2) .. "Mb/s"
end
if stat.carrier and stat.speed:sub(-1) == "F" then
duplex = 1
else
duplex = 0
end
eth_info[#eth_info+1] = { name = ifname, status = status,
speed = speed, duplex = duplex }
end
break
end
end
end
table.sort(eth_info,
function(a, b)
return a.name < b.name
end)
print(jsonc.stringify(eth_info))

View File

@ -0,0 +1,5 @@
#!/bin/sh
TEMP=`awk '{printf("%.1f°C", $0 / 1000)}' "/sys/class/thermal/thermal_zone0/temp" 2>"/dev/null"`
echo "$TEMP "

View File

@ -12,9 +12,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git
PKG_SOURCE_DATE:=2022-10-31
PKG_SOURCE_VERSION:=23977554d9694d025eada50a5547e99ee1be7838
PKG_MIRROR_HASH:=e546fd57d0d0be6a51e2aeb5797febe8c89d2bba61b26c930ecb0616d5f6ace9
PKG_SOURCE_DATE:=2025-10-03
PKG_SOURCE_VERSION:=ebb92e6b339b88bbc6b76501b6603c52d4887ba1
PKG_MIRROR_HASH:=331155667553e4ee02cc027558af62e480fd4c863bda3e2a6ec327f38b933323
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=ISC

View File

@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=fstools
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git

View File

@ -0,0 +1,11 @@
--- a/libfstools/common.h
+++ b/libfstools/common.h
@@ -19,7 +19,7 @@
#include "libfstools.h"
#include "volume.h"
-#define F2FS_MINSIZE (100ULL * 1024ULL * 1024ULL)
+#define F2FS_MINSIZE (1024ULL * 1024ULL * 1024ULL)
int read_uint_from_file(char *dirname, char *filename, unsigned int *i);
char *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz);

View File

@ -60,7 +60,9 @@ CONFIG_BINFMT_MISC=y
CONFIG_BLK_DEV_BSGLIB=y
CONFIG_BLK_DEV_BSG_COMMON=y
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_BLK_DEV_INTEGRITY_T10=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_BLK_PM=y
@ -532,6 +534,13 @@ CONFIG_SCHED_INFO=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_THERMAL_PRESSURE=y
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_PROC_FS is not set
CONFIG_SCSI_SAS_ATTRS=y
CONFIG_SCSI_SAS_HOST_SMP=y
CONFIG_SCSI_SAS_LIBSAS=y
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
CONFIG_SERIAL_8250_FSL=y

View File

@ -13,7 +13,7 @@ Signed-off-by: Maxime Ripard <maxime@cerno.tech>
@@ -214,9 +214,9 @@ static void __init request_standard_reso
size_t res_size;
kernel_code.start = __pa_symbol(_stext);
kernel_code.start = __pa_symbol(_text);
- kernel_code.end = __pa_symbol(__init_begin - 1);
+ kernel_code.end = __pa_symbol(__init_begin) - 1;
kernel_data.start = __pa_symbol(_sdata);

View File

@ -18608,7 +18608,7 @@ Signed-off-by: j-schambacher <joerg@hifiberry.com>
}
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -869,8 +869,14 @@ static int usb_audio_probe(struct usb_in
@@ -875,8 +875,14 @@ static int usb_audio_probe(struct usb_in
if (ignore_ctl_error)
chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR;
@ -18626,7 +18626,7 @@ Signed-off-by: j-schambacher <joerg@hifiberry.com>
* For devices with more than one control interface, we assume the
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2360,6 +2360,8 @@ static const struct usb_audio_quirk_flag
@@ -2378,6 +2378,8 @@ static const struct usb_audio_quirk_flag
QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
QUIRK_FLAG_ALIGN_TRANSFER),

View File

@ -37,7 +37,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
{
u32 *buf;
@@ -3444,8 +3453,14 @@ static int lan78xx_bind(struct lan78xx_n
@@ -3464,8 +3473,14 @@ static int lan78xx_bind(struct lan78xx_n
if (DEFAULT_RX_CSUM_ENABLE)
dev->net->features |= NETIF_F_RXCSUM;

View File

@ -28,7 +28,7 @@ See: https://github.com/raspberrypi/linux/issues/2447
static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
{
u32 *buf;
@@ -4428,7 +4433,13 @@ static int lan78xx_probe(struct usb_inte
@@ -4448,7 +4453,13 @@ static int lan78xx_probe(struct usb_inte
if (ret < 0)
goto out4;

View File

@ -16,4 +16,4 @@ Subject: [PATCH] Patching lan78xx for SOF_TIMESTAMPING_TX_SOFTWARE support
+ .get_ts_info = ethtool_op_get_ts_info,
};
static void lan78xx_init_mac_address(struct lan78xx_net *dev)
static int lan78xx_init_mac_address(struct lan78xx_net *dev)

View File

@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2897,6 +2897,11 @@ static int lan78xx_reset(struct lan78xx_
@@ -2915,6 +2915,11 @@ static int lan78xx_reset(struct lan78xx_
int ret;
u32 buf;
u8 sig;
@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
ret = lan78xx_read_reg(dev, HW_CFG, &buf);
if (ret < 0)
@@ -2963,6 +2968,10 @@ static int lan78xx_reset(struct lan78xx_
@@ -2983,6 +2988,10 @@ static int lan78xx_reset(struct lan78xx_
buf |= HW_CFG_CLK125_EN_;
buf |= HW_CFG_REFCLK25_EN_;
@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
ret = lan78xx_write_reg(dev, HW_CFG, buf);
if (ret < 0)
return ret;
@@ -3065,6 +3074,9 @@ static int lan78xx_reset(struct lan78xx_
@@ -3085,6 +3094,9 @@ static int lan78xx_reset(struct lan78xx_
buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_;
}
}

View File

@ -14,7 +14,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1519,6 +1519,109 @@ static int xhci_check_ep0_maxpacket(stru
@@ -1515,6 +1515,109 @@ static int xhci_check_ep0_maxpacket(stru
}
/*
@ -124,7 +124,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
*/
@@ -5390,6 +5493,7 @@ static const struct hc_driver xhci_hc_dr
@@ -5386,6 +5489,7 @@ static const struct hc_driver xhci_hc_dr
.endpoint_reset = xhci_endpoint_reset,
.check_bandwidth = xhci_check_bandwidth,
.reset_bandwidth = xhci_reset_bandwidth,

View File

@ -19,7 +19,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1608,7 +1608,7 @@ static void xhci_fixup_endpoint(struct u
@@ -1604,7 +1604,7 @@ static void xhci_fixup_endpoint(struct u
return;
}
ctrl_ctx->add_flags = xhci_get_endpoint_flag_from_index(ep_index);

View File

@ -20,7 +20,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -4921,6 +4921,7 @@ static const struct {
@@ -4930,6 +4930,7 @@ static const struct {
*/
static int hci_dev_setup_sync(struct hci_dev *hdev)
{
@ -28,7 +28,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
int ret = 0;
bool invalid_bdaddr;
size_t i;
@@ -4949,7 +4950,8 @@ static int hci_dev_setup_sync(struct hci
@@ -4958,7 +4959,8 @@ static int hci_dev_setup_sync(struct hci
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
if (!ret) {
if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) &&

View File

@ -16,7 +16,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1206,6 +1206,9 @@ static int sc16is7xx_startup(struct uart
@@ -1196,6 +1196,9 @@ static int sc16is7xx_startup(struct uart
SC16IS7XX_IER_MSI_BIT;
sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);

View File

@ -53,7 +53,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
if (addr == 0) {
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1628,6 +1628,9 @@ struct xhci_hcd {
@@ -1631,6 +1631,9 @@ struct xhci_hcd {
#define XHCI_ETRON_HOST BIT_ULL(49)
#define XHCI_LIMIT_ENDPOINT_INTERVAL_9 BIT_ULL(50)

View File

@ -34,7 +34,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1397,6 +1397,7 @@ int xhci_endpoint_init(struct xhci_hcd *
@@ -1387,6 +1387,7 @@ int xhci_endpoint_init(struct xhci_hcd *
unsigned int ep_index;
struct xhci_ep_ctx *ep_ctx;
struct xhci_ring *ep_ring;
@ -42,7 +42,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
unsigned int max_packet;
enum xhci_ring_type ring_type;
u32 max_esit_payload;
@@ -1406,6 +1407,8 @@ int xhci_endpoint_init(struct xhci_hcd *
@@ -1396,6 +1397,8 @@ int xhci_endpoint_init(struct xhci_hcd *
unsigned int mult;
unsigned int avg_trb_len;
unsigned int err_count = 0;
@ -51,7 +51,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
@@ -1441,9 +1444,35 @@ int xhci_endpoint_init(struct xhci_hcd *
@@ -1431,9 +1434,35 @@ int xhci_endpoint_init(struct xhci_hcd *
mult = xhci_get_endpoint_mult(udev, ep);
max_packet = usb_endpoint_maxp(&ep->desc);
@ -100,7 +100,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1630,6 +1630,7 @@ struct xhci_hcd {
@@ -1633,6 +1633,7 @@ struct xhci_hcd {
/* Downstream VLI fixes */
#define XHCI_AVOID_DQ_ON_LINK BIT_ULL(56)

View File

@ -75,7 +75,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3664,6 +3664,48 @@ static int xhci_align_td(struct xhci_hcd
@@ -3661,6 +3661,48 @@ static int xhci_align_td(struct xhci_hcd
return 1;
}
@ -124,7 +124,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
/* This is very similar to what ehci-q.c qtd_fill() does */
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3818,6 +3860,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
@@ -3815,6 +3857,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
}
check_trb_math(urb, enqd_len);
@ -133,7 +133,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
start_cycle, start_trb);
return 0;
@@ -3966,6 +4010,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
@@ -3963,6 +4007,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
/* Event on completion */
field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state);
@ -144,7 +144,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
return 0;
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1631,6 +1631,7 @@ struct xhci_hcd {
@@ -1634,6 +1634,7 @@ struct xhci_hcd {
/* Downstream VLI fixes */
#define XHCI_AVOID_DQ_ON_LINK BIT_ULL(56)
#define XHCI_VLI_SS_BULK_OUT_BUG BIT_ULL(57)

View File

@ -21,7 +21,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1395,7 +1395,7 @@ struct urb_priv {
@@ -1398,7 +1398,7 @@ struct urb_priv {
};
/* Number of Event Ring segments to allocate, when amount is not specified. (spec allows 32k) */

View File

@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -2422,7 +2422,26 @@ static int lan78xx_phy_init(struct lan78
@@ -2440,7 +2440,26 @@ static int lan78xx_phy_init(struct lan78
mii_adv_to_linkmode_adv_t(fc, mii_adv);
linkmode_or(phydev->advertising, fc, phydev->advertising);

View File

@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -4921,7 +4921,8 @@ static const struct {
@@ -4930,7 +4930,8 @@ static const struct {
*/
static int hci_dev_setup_sync(struct hci_dev *hdev)
{

View File

@ -28,7 +28,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -715,6 +715,14 @@ void xhci_setup_streams_ep_input_ctx(str
@@ -705,6 +705,14 @@ void xhci_setup_streams_ep_input_ctx(str
ep_ctx->ep_info &= cpu_to_le32(~EP_MAXPSTREAMS_MASK);
ep_ctx->ep_info |= cpu_to_le32(EP_MAXPSTREAMS(max_primary_streams)
| EP_HAS_LSA);

View File

@ -18,7 +18,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2103,6 +2103,7 @@ static void nvme_free_host_mem(struct nv
@@ -2106,6 +2106,7 @@ static void nvme_free_host_mem(struct nv
dev->nr_host_mem_descs = 0;
}
@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
u32 chunk_size)
{
@@ -2171,9 +2172,11 @@ out:
@@ -2174,9 +2175,11 @@ out:
dev->host_mem_descs = NULL;
return -ENOMEM;
}
@ -38,7 +38,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
u64 min_chunk = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES);
u64 hmminds = max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2);
u64 chunk_size;
@@ -2186,6 +2189,7 @@ static int nvme_alloc_host_mem(struct nv
@@ -2189,6 +2192,7 @@ static int nvme_alloc_host_mem(struct nv
nvme_free_host_mem(dev);
}
}

View File

@ -17,7 +17,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -6887,6 +6887,39 @@ static int __init cgroup_disable(char *s
@@ -6916,6 +6916,39 @@ static int __init cgroup_disable(char *s
}
__setup("cgroup_disable=", cgroup_disable);

View File

@ -31,7 +31,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1478,7 +1478,7 @@ static int sc16is7xx_setup_mctrl_ports(s
@@ -1468,7 +1468,7 @@ static int sc16is7xx_setup_mctrl_ports(s
}
static const struct serial_rs485 sc16is7xx_rs485_supported = {

View File

@ -88,7 +88,7 @@ Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
/* Called when the last user of the media device exits. */
static void media_devnode_release(struct device *cd)
{
@@ -236,6 +239,7 @@ int __must_check media_devnode_register(
@@ -231,6 +234,7 @@ int __must_check media_devnode_register(
if (devnode->parent)
devnode->dev.parent = devnode->parent;
dev_set_name(&devnode->dev, "media%d", devnode->minor);
@ -96,7 +96,7 @@ Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
device_initialize(&devnode->dev);
/* Part 2: Initialize the character device */
@@ -313,6 +317,7 @@ static int __init media_devnode_init(voi
@@ -309,6 +313,7 @@ static int __init media_devnode_init(voi
static void __exit media_devnode_exit(void)
{

View File

@ -39,8 +39,8 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
+
static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
{
struct xhci_segment *seg = ring->first_seg;
@@ -4795,7 +4799,7 @@ static u16 xhci_calculate_u1_timeout(str
struct xhci_segment *seg;
@@ -4791,7 +4795,7 @@ static u16 xhci_calculate_u1_timeout(str
}
}
@ -49,7 +49,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
else
timeout_ns = udev->u1_params.sel;
@@ -4859,7 +4863,7 @@ static u16 xhci_calculate_u2_timeout(str
@@ -4855,7 +4859,7 @@ static u16 xhci_calculate_u2_timeout(str
}
}

View File

@ -0,0 +1,69 @@
From a6ba2dad0aa4f623ab0def8b6e6888ac00639055 Mon Sep 17 00:00:00 2001
From: Heiko Stuebner <heiko@sntech.de>
Date: Fri, 21 Feb 2025 00:41:40 +0100
Subject: [PATCH] drivers: base: component: add function to query the bound
status
The component helpers already expose the bound status in debugfs, but at
times it might be necessary to also check that state in the kernel and
act differently depending on the result.
For example the shutdown handler of a drm-driver might need to stop
a whole output pipeline if the drm device is up and running, but may
run into problems if that drm-device has never been set up before,
for example because the binding deferred.
So add a little helper that returns the bound status for a componet
device.
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20250220234141.2788785-2-heiko@sntech.de
---
drivers/base/component.c | 14 ++++++++++++++
include/linux/component.h | 4 +++-
2 files changed, 17 insertions(+), 1 deletion(-)
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -569,6 +569,20 @@ void component_master_del(struct device
}
EXPORT_SYMBOL_GPL(component_master_del);
+bool component_master_is_bound(struct device *parent,
+ const struct component_master_ops *ops)
+{
+ struct aggregate_device *adev;
+
+ guard(mutex)(&component_mutex);
+ adev = __aggregate_find(parent, ops);
+ if (!adev)
+ return 0;
+
+ return adev->bound;
+}
+EXPORT_SYMBOL_GPL(component_master_is_bound);
+
static void component_unbind(struct component *component,
struct aggregate_device *adev, void *data)
{
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -3,7 +3,7 @@
#define COMPONENT_H
#include <linux/stddef.h>
-
+#include <linux/types.h>
struct device;
@@ -90,6 +90,8 @@ int component_compare_dev_name(struct de
void component_master_del(struct device *,
const struct component_master_ops *);
+bool component_master_is_bound(struct device *parent,
+ const struct component_master_ops *ops);
struct component_match;

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
{
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
return nft_masq_ipv4_eval(expr, regs, pkt);
case NFPROTO_IPV6:
return nft_masq_ipv6_eval(expr, regs, pkt);

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
{
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
return nft_masq_ipv4_eval(expr, regs, pkt);
case NFPROTO_IPV6:
return nft_masq_ipv6_eval(expr, regs, pkt);

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
{
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
return nft_masq_ipv4_eval(expr, regs, pkt);
case NFPROTO_IPV6:
return nft_masq_ipv6_eval(expr, regs, pkt);

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
{
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
return nft_masq_ipv4_eval(expr, regs, pkt);
case NFPROTO_IPV6:
return nft_masq_ipv6_eval(expr, regs, pkt);

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb,
nft_hook(pkt),
&range,

View File

@ -0,0 +1,65 @@
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1477,12 +1477,14 @@ enum nft_tproxy_attributes {
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
* @NFTA_MASQ_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
* @NFTA_MASQ_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ * @NFTA_MASQ_REG_FULLCONE: fullcone NAT (NLA_U8)
*/
enum nft_masq_attributes {
NFTA_MASQ_UNSPEC,
NFTA_MASQ_FLAGS,
NFTA_MASQ_REG_PROTO_MIN,
NFTA_MASQ_REG_PROTO_MAX,
+ NFTA_MASQ_REG_FULLCONE,
__NFTA_MASQ_MAX
};
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -17,6 +17,7 @@ struct nft_masq {
u32 flags;
u8 sreg_proto_min;
u8 sreg_proto_max;
+ bool fullcone;
};
static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
@@ -24,6 +25,7 @@ static const struct nla_policy nft_masq_
NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NLA_U32 },
+ [NFTA_MASQ_REG_FULLCONE] = { .type = NLA_U8 },
};
static int nft_masq_validate(const struct nft_ctx *ctx,
@@ -51,6 +53,9 @@ static int nft_masq_init(const struct nf
if (tb[NFTA_MASQ_FLAGS])
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
+ if (tb[NFTA_MASQ_REG_FULLCONE])
+ priv->fullcone = nla_get_u8(tb[NFTA_MASQ_REG_FULLCONE]);
+
if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
&priv->sreg_proto_min, plen);
@@ -80,6 +85,9 @@ static int nft_masq_dump(struct sk_buff
nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
goto nla_put_failure;
+ if (priv->fullcone && nla_put_u8(skb, NFTA_MASQ_REG_FULLCONE, 1))
+ goto nla_put_failure;
+
if (priv->sreg_proto_min) {
if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
priv->sreg_proto_min) ||
@@ -112,6 +120,9 @@ static void nft_masq_eval(const struct n
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
+ if (priv->fullcone) {
+ range.min_addr.ip = 1;
+ }
regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb,
nft_hook(pkt),
&range,

View File

@ -544,7 +544,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ }
+
+ if (mtk_is_netsys_v3_or_greater(eth) && (mac->sgmii_pcs || mac->usxgmii_pcs)) {
+ mac->pextp = devm_of_phy_get(eth->dev, mac->of_node, NULL);
+ mac->pextp = devm_of_phy_optional_get(eth->dev, mac->of_node, NULL);
+ if (IS_ERR(mac->pextp)) {
+ if (PTR_ERR(mac->pextp) != -EPROBE_DEFER)
+ dev_err(eth->dev, "cannot get PHY, error %ld\n",

View File

@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
ARCH:=loongarch64
BOARD:=loongarch64
BOARDNAME:=Loongson LoongArch
FEATURES:=audio display ext4 pcie boot-part rootfs-part rtc usb targz
FEATURES:=squashfs audio display ext4 pcie boot-part rootfs-part rtc usb targz
SUBTARGETS:=generic
KERNEL_PATCHVER:=6.12
@ -18,6 +18,7 @@ KERNELNAME:=vmlinuz.efi dtbs
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
partx-utils blkid e2fsprogs grub2-efi-loongarch64 kmod-yt6801
partx-utils blkid e2fsprogs grub2-efi-loongarch64 kmod-yt6801 \
kmod-fs-ext4 kmod-fs-f2fs losetup mkf2fs f2fsck e2fsprogs autocore-loongarch64
$(eval $(call BuildTarget))

View File

@ -98,8 +98,8 @@
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-handle = <&phy0>;
phy-mode = "2500base-x";
phy-mode = "gmii";
phy-handle = <&int_gbe_phy>;
nvmem-cells = <&macaddr_factory_4 2>;
nvmem-cell-names = "mac-address";
@ -117,20 +117,13 @@
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
};
phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9461";
reg = <0>;
phy-mode = "gmii";
nvmem-cells = <&phy_calibration>;
nvmem-cell-names = "phy-cal-data";
};
phy6: ethernet-phy@6 {
phy1: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <6>;
reg = <1>;
reset-assert-us = <100000>;
reset-deassert-us = <100000>;
reset-gpios = <&pio 3 GPIO_ACTIVE_LOW>;
reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>;
realtek,led-link-select = <0x0 0xa7 0xa7>;
};
};
@ -247,7 +240,7 @@
port@5 {
reg = <5>;
label = "wan";
phy-handle = <&phy6>;
phy-handle = <&phy1>;
phy-mode = "2500base-x";
};

View File

@ -22,13 +22,6 @@ bananapi,bpi-r4-poe)
ucidef_set_led_netdev "lan2" "lan2" "mt7530-0:02:green:lan" "lan2" "link tx rx"
ucidef_set_led_netdev "lan3" "lan3" "mt7530-0:03:green:lan" "lan3" "link tx rx"
;;
hf,m7986r1*)
ucidef_set_led_netdev "led-1" "LAN1" "led-1" "lan1"
ucidef_set_led_netdev "led-2" "LAN2" "led-2" "lan2"
ucidef_set_led_netdev "led-3" "LAN3" "led-3" "lan3"
ucidef_set_led_netdev "led-4" "LAN4" "led-4" "lan4"
ucidef_set_led_netdev "led-5" "WWAN" "led-5" "usb0"
;;
glinet,gl-x3000|\
glinet,gl-xe3000)
ucidef_set_led_default "power" "POWER" "green:power" "1"
@ -40,6 +33,18 @@ glinet,gl-xe3000)
ucidef_set_led_netdev "wlan2g" "WLAN2G" "green:wifi2g" "phy0-ap0"
ucidef_set_led_netdev "wlan5g" "WLAN5G" "green:wifi5g" "phy1-ap0"
;;
hf,m7986r1*)
ucidef_set_led_netdev "led-1" "LAN1" "led-1" "lan1"
ucidef_set_led_netdev "led-2" "LAN2" "led-2" "lan2"
ucidef_set_led_netdev "led-3" "LAN3" "led-3" "lan3"
ucidef_set_led_netdev "led-4" "LAN4" "led-4" "lan4"
ucidef_set_led_netdev "led-5" "WWAN" "led-5" "usb0"
;;
huasifei,ws3006)
ucidef_set_led_netdev "lan3" "LAN3" "green:gbe" "eth1"
ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan"
ucidef_set_led_netdev "wlan" "WLAN" "green:wlan" "wlan1"
;;
imou,lc-hx3001|\
nokia,ea0326gmp)
ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan"

View File

@ -0,0 +1,36 @@
From 6e9ec5ade644eeb136c6b827d72fac80bf2c3817 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Date: Fri, 9 May 2025 13:22:14 +0800
Subject: [PATCH] net: pcs: mtk_lynxi add mt7987 support
Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
---
drivers/net/pcs/pcs-mtk-lynxi.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -413,9 +413,12 @@ static int mtk_pcs_lynxi_probe(struct pl
if (of_property_read_bool(np->parent, "mediatek,pnswap"))
flags |= MTK_SGMII_FLAG_PN_SWAP;
- mpcs->rstc = of_reset_control_get_shared(np->parent, NULL);
- if (IS_ERR(mpcs->rstc))
- return PTR_ERR(mpcs->rstc);
+ if (of_parse_phandle(np->parent, "resets", 0)) {
+ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL);
+ if (IS_ERR(mpcs->rstc))
+ return PTR_ERR(mpcs->rstc);
+ } else
+ mpcs->rstc = NULL;
reset_control_deassert(mpcs->rstc);
mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel");
@@ -462,6 +465,7 @@ static void mtk_pcs_lynxi_remove(struct
}
static const struct of_device_id mtk_pcs_lynxi_of_match[] = {
+ { .compatible = "mediatek,mt7987-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 },
{ .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 },
{ /* sentinel */ },
};

View File

@ -0,0 +1,89 @@
From be193994deca7cc3ca6ddedc6efd06182b032f21 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Date: Tue, 6 May 2025 12:53:37 +0800
Subject: [PATCH] net: pcs: mtk-lynxi: add phya tx rx clock path
In NETSYSv3.1, the SGMII hardware introduces a new clock path from PHYA.
Consequently, users can switch the SGMII PCS to this new clock source
for better performance on the MT7987.
Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
---
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -25,6 +25,7 @@
#define SGMSYS_PCS_CONTROL_1 0x0
#define SGMII_BMCR GENMASK(15, 0)
#define SGMII_BMSR GENMASK(31, 16)
+#define SGMII_REF_CK_SEL BIT(24)
#define SGMSYS_PCS_DEVICE_ID 0x4
#define SGMII_LYNXI_DEV_ID 0x4d544950
@@ -52,6 +53,8 @@
#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
#define SGMII_DUPLEX_HALF BIT(4)
#define SGMII_REMOTE_FAULT_DIS BIT(8)
+#define SGMII_TRXBUF_THR_MASK GENMASK(31, 16)
+#define SGMII_TRXBUF_THR(x) FIELD_PREP(SGMII_TRXBUF_THR_MASK, (x))
/* Register to reset SGMII design */
#define SGMSYS_RESERVED_0 0x34
@@ -166,7 +169,7 @@ static int mtk_pcs_lynxi_config(struct p
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
bool mode_changed = false, changed;
- unsigned int rgc3, sgm_mode, bmcr = 0;
+ unsigned int rgc3, sgm_mode, bmcr = 0, trxbuf_thr = 0x3112;
int advertise, link_timer;
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
@@ -193,6 +196,12 @@ static int mtk_pcs_lynxi_config(struct p
bmcr = BMCR_ANENABLE;
}
+ /* Configure SGMII PCS clock source */
+ if (mpcs->flags & MTK_SGMII_FLAG_PHYA_TRX_CK) {
+ bmcr |= SGMII_REF_CK_SEL;
+ trxbuf_thr = 0x2111;
+ }
+
if (mpcs->interface != interface) {
link_timer = phylink_get_link_timer_ns(interface);
if (link_timer < 0)
@@ -235,12 +244,14 @@ static int mtk_pcs_lynxi_config(struct p
/* Update the sgmsys mode register */
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_TRXBUF_THR_MASK |
SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
- SGMII_IF_MODE_SGMII, sgm_mode);
+ SGMII_IF_MODE_SGMII,
+ SGMII_TRXBUF_THR(trxbuf_thr) | sgm_mode);
/* Update the BMCR */
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- BMCR_ANENABLE, bmcr);
+ SGMII_REF_CK_SEL | BMCR_ANENABLE, bmcr);
/* Release PHYA power down state
* Only removing bit SGMII_PHYA_PWD isn't enough.
@@ -413,6 +424,9 @@ static int mtk_pcs_lynxi_probe(struct pl
if (of_property_read_bool(np->parent, "mediatek,pnswap"))
flags |= MTK_SGMII_FLAG_PN_SWAP;
+ if (of_property_read_bool(np->parent, "mediatek,phya_trx_ck"))
+ flags |= MTK_SGMII_FLAG_PHYA_TRX_CK;
+
if (of_parse_phandle(np->parent, "resets", 0)) {
mpcs->rstc = of_reset_control_get_shared(np->parent, NULL);
if (IS_ERR(mpcs->rstc))
--- a/include/linux/pcs/pcs-mtk-lynxi.h
+++ b/include/linux/pcs/pcs-mtk-lynxi.h
@@ -6,6 +6,7 @@
#include <linux/regmap.h>
#define MTK_SGMII_FLAG_PN_SWAP BIT(0)
+#define MTK_SGMII_FLAG_PHYA_TRX_CK BIT(2)
struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
struct regmap *regmap,
u32 ana_rgc3, u32 flags);

View File

@ -0,0 +1,325 @@
From 56973433cbea9f91f5f7eddebbc361ffc2bd6156 Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Date: Mon, 26 May 2025 13:20:42 +0800
Subject: [PATCH] net: ethernet: mtk_eth_soc: add mt7987 support
Without this patch, users are unable to bring up ETH driver on the
mt7987.
Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_path.c | 9 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 138 ++++++++++++++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 70 ++++++++--
3 files changed, 179 insertions(+), 38 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -106,13 +106,14 @@ static int set_mux_gmac2_gmac0_to_gephy(
return 0;
}
-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
+static int set_mux_u3_gmac23_to_qphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0, mask = 0, reg = 0;
bool updated = true;
switch (path) {
case MTK_ETH_PATH_GMAC2_SGMII:
+ case MTK_ETH_PATH_GMAC3_SGMII:
if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
reg = USB_PHY_SWITCH_REG;
val = SGMII_QPHY_SEL;
@@ -281,9 +282,9 @@ static const struct mtk_eth_muxc mtk_eth
.cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
.set_path = set_mux_gmac2_gmac0_to_gephy,
}, {
- .name = "mux_u3_gmac2_to_qphy",
- .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
- .set_path = set_mux_u3_gmac2_to_qphy,
+ .name = "mux_u3_gmac23_to_qphy",
+ .cap_bit = MTK_ETH_MUX_U3_GMAC23_TO_QPHY,
+ .set_path = set_mux_u3_gmac23_to_qphy,
}, {
.name = "mux_gmac2_to_2p5gphy",
.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -817,10 +817,16 @@ static void mtk_set_queue_speed(struct m
return;
val = MTK_QTX_SCH_MIN_RATE_EN |
- /* minimum: 10 Mbps */
- FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
- FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+ /* minimum: 10 Mbps */
+ if (mtk_is_netsys_v3_or_greater(eth) &&
+ (eth->soc->caps != MT7988_CAPS)) {
+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN_V3, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP_V3, 4);
+ } else {
+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4);
+ }
if (mtk_is_netsys_v1(eth))
val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
@@ -847,6 +853,30 @@ static void mtk_set_queue_speed(struct m
default:
break;
}
+ } else if (mtk_is_netsys_v3_or_greater(eth) &&
+ (eth->soc->caps != MT7988_CAPS)) {
+ switch (speed) {
+ case SPEED_10:
+ val |= MTK_QTX_SCH_MAX_RATE_EN_V3 |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN_V3, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP_V3, 4) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT_V3, 1);
+ break;
+ case SPEED_100:
+ val |= MTK_QTX_SCH_MAX_RATE_EN_V3 |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN_V3, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP_V3, 5) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT_V3, 1);
+ break;
+ case SPEED_1000:
+ val |= MTK_QTX_SCH_MAX_RATE_EN_V3 |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN_V3, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP_V3, 6) |
+ FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT_V3, 10);
+ break;
+ default:
+ break;
+ }
} else {
switch (speed) {
case SPEED_10:
@@ -935,7 +965,7 @@ static void mtk_xgdm_mac_link_up(struct
return;
/* Eliminate the interference(before link-up) caused by PHY noise */
- mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->id));
+ mtk_m32(mac->hw, XMAC_LOGIC_RST, 0, MTK_XMAC_LOGIC_RST(mac->hw, mac->id));
mdelay(20);
mtk_m32(mac->hw, XMAC_GLB_CNTCLR, XMAC_GLB_CNTCLR, MTK_XMAC_CNT_CTRL(mac->id));
@@ -2901,10 +2931,16 @@ static int mtk_tx_alloc(struct mtk_eth *
mtk_w32(eth, val, soc->reg_map->qdma.qtx_cfg + ofs);
val = MTK_QTX_SCH_MIN_RATE_EN |
- /* minimum: 10 Mbps */
- FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
- FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
+ /* minimum: 10 Mbps */
+ if (mtk_is_netsys_v3_or_greater(eth) &&
+ (eth->soc->caps != MT7988_CAPS)) {
+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN_V3, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP_V3, 4);
+ } else {
+ val |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
+ FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4);
+ }
if (mtk_is_netsys_v1(eth))
val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
@@ -5873,6 +5909,36 @@ static const struct mtk_soc_data mt7986_
},
};
+static const struct mtk_soc_data mt7987_data = {
+ .reg_map = &mt7988_reg_map,
+ .ana_rgc3 = 0x128,
+ .caps = MT7987_CAPS,
+ .hw_features = MTK_HW_FEATURES,
+ .required_clks = MT7987_CLKS_BITMAP,
+ .required_pctl = false,
+ .version = 3,
+ .offload_version = 2,
+ .ppe_num = 2,
+ .hash_offset = 4,
+ .has_accounting = true,
+ .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
+ .tx = {
+ DESC_SIZE(struct mtk_tx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ .dma_size = MTK_DMA_SIZE(2K),
+ .fq_dma_size = MTK_DMA_SIZE(4K),
+ },
+ .rx = {
+ DESC_SIZE(struct mtk_rx_dma_v2),
+ .irq_done_mask = MTK_RX_DONE_INT_V2,
+ .dma_l4_valid = RX_DMA_L4_VALID_V2,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ .dma_size = MTK_DMA_SIZE(2K),
+ },
+};
+
static const struct mtk_soc_data mt7988_data = {
.reg_map = &mt7988_reg_map,
.ana_rgc3 = 0x128,
@@ -5934,6 +6000,7 @@ const struct of_device_id of_mtk_match[]
{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data },
{ .compatible = "mediatek,mt7981-eth", .data = &mt7981_data },
{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data },
+ { .compatible = "mediatek,mt7987-eth", .data = &mt7987_data },
{ .compatible = "mediatek,mt7988-eth", .data = &mt7988_data },
{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data },
{},
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -262,6 +262,13 @@
#define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4)
#define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0)
+#define MTK_QTX_SCH_MAX_RATE_EN_V3 BIT(26)
+#define MTK_QTX_SCH_MIN_RATE_MAN_V3 GENMASK(25, 19)
+#define MTK_QTX_SCH_MIN_RATE_EXP_V3 GENMASK(18, 16)
+#define MTK_QTX_SCH_MAX_RATE_WEIGHT_V3 GENMASK(15, 10)
+#define MTK_QTX_SCH_MAX_RATE_MAN_V3 GENMASK(9, 3)
+#define MTK_QTX_SCH_MAX_RATE_EXP_V3 GENMASK(2, 0)
+
/* QDMA TX Scheduler Rate Control Register */
#define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15)
@@ -536,9 +543,23 @@
#define XMAC_MCR_FORCE_RX_FC BIT(4)
/* XFI Mac logic reset registers */
-#define MTK_XMAC_LOGIC_RST(x) (MTK_XMAC_BASE(x) + 0x10)
+#define MTK_XMAC_LOGIC_RST(eth, x) (MTK_XMAC_BASE(x) + \
+ (MTK_HAS_CAPS((eth)->soc->caps, MTK_XGMAC_V2) ? \
+ 0x820 : 0x10))
#define XMAC_LOGIC_RST BIT(0)
+/* XFI Mac status force registers */
+#define MTK_XMAC_STS(x) (MTK_XMAC_MCR(x) + 0x14)
+
+/* XFI Mac status force registers */
+#define MTK_XMAC_STS_FRC(x) (MTK_XMAC_MCR(x) + 0x18)
+#define XMAC_FORCE_RX_FC_MODE BIT(13)
+#define XMAC_FORCE_TX_FC_MODE BIT(12)
+#define XMAC_FORCE_LINK_MODE BIT(8)
+#define XMAC_FORCE_RX_FC BIT(5)
+#define XMAC_FORCE_TX_FC BIT(4)
+#define XMAC_FORCE_LINK BIT(0)
+
/* XFI Mac count global control */
#define MTK_XMAC_CNT_CTRL(x) (MTK_XMAC_BASE(x) + 0x100)
#define XMAC_GLB_CNTCLR BIT(0)
@@ -834,6 +855,17 @@ enum mtk_clks_map {
BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
BIT_ULL(MTK_CLK_SGMII2_CDR_FB))
+#define MT7987_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP1) | \
+ BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP3) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL))
#define MT7988_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \
BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \
BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \
@@ -990,12 +1022,14 @@ enum mkt_eth_capabilities {
MTK_RSTCTRL_PPE2_BIT,
MTK_U3_COPHY_V2_BIT,
MTK_SRAM_BIT,
+ MTK_XGMAC_BIT,
+ MTK_XGMAC_V2_BIT,
MTK_36BIT_DMA_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT,
- MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
+ MTK_ETH_MUX_U3_GMAC23_TO_QPHY_BIT,
MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT,
MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
@@ -1037,14 +1071,16 @@ enum mkt_eth_capabilities {
#define MTK_RSTCTRL_PPE2 BIT_ULL(MTK_RSTCTRL_PPE2_BIT)
#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
#define MTK_SRAM BIT_ULL(MTK_SRAM_BIT)
+#define MTK_XGMAC BIT_ULL(MTK_XGMAC_BIT)
+#define MTK_XGMAC_V2 BIT_ULL(MTK_XGMAC_V2_BIT)
#define MTK_36BIT_DMA BIT_ULL(MTK_36BIT_DMA_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
#define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \
BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
-#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
- BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
+#define MTK_ETH_MUX_U3_GMAC23_TO_QPHY \
+ BIT_ULL(MTK_ETH_MUX_U3_GMAC23_TO_QPHY_BIT)
#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY \
BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT)
#define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
@@ -1076,12 +1112,13 @@ enum mkt_eth_capabilities {
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
-#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY)
+#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY | MTK_XGMAC)
+#define MTK_GMAC2_2P5GPHY_V2 (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY | MTK_XGMAC_V2)
#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
#define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
-#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
-#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII)
-#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII)
+#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII | MTK_XGMAC)
+#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII | MTK_XGMAC)
+#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII | MTK_XGMAC)
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -1091,9 +1128,9 @@ enum mkt_eth_capabilities {
#define MTK_MUX_GMAC2_GMAC0_TO_GEPHY \
(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY | MTK_MUX | MTK_INFRA)
-/* 0: U3 -> QPHY, 1: GMAC2 -> QPHY */
-#define MTK_MUX_U3_GMAC2_TO_QPHY \
- (MTK_ETH_MUX_U3_GMAC2_TO_QPHY | MTK_MUX | MTK_INFRA)
+/* 0: U3 -> QPHY, 1: GMACx -> QPHY where x is 2 or 3 */
+#define MTK_MUX_U3_GMAC23_TO_QPHY \
+ (MTK_ETH_MUX_U3_GMAC23_TO_QPHY | MTK_MUX | MTK_INFRA)
/* 2: GMAC1 -> SGMII, 3: GMAC2 -> SGMII */
#define MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
@@ -1133,18 +1170,24 @@ enum mkt_eth_capabilities {
#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
- MTK_MUX_U3_GMAC2_TO_QPHY | \
+ MTK_MUX_U3_GMAC23_TO_QPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
- MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
+ MTK_MUX_U3_GMAC23_TO_QPHY | MTK_U3_COPHY_V2 | \
MTK_RSTCTRL_PPE1 | MTK_SRAM)
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_RSTCTRL_PPE1 | MTK_SRAM)
+#define MT7987_CAPS (MTK_36BIT_DMA | MTK_GMAC1_SGMII | \
+ MTK_GMAC2_2P5GPHY_V2 | MTK_GMAC2_SGMII | MTK_GMAC3_SGMII | \
+ MTK_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \
+ MTK_MUX_U3_GMAC23_TO_QPHY | MTK_U3_COPHY_V2 | \
+ MTK_QDMA | MTK_RSTCTRL_PPE1)
+
#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \
MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \
MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \

View File

@ -0,0 +1,79 @@
From 5ef0b04d30efff8f171e30bfbe876c00e3b9036a Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Date: Fri, 9 May 2025 09:49:04 +0800
Subject: [PATCH] net: ethernet: mtk_eth_soc: revise hardware configuration for
mt7987
Change hardware configuration for the MT7987.
- Enable PSE drop mechanism when the WDMA Rx ring full
- Enable PSE no-drop mechanism for packets from the WDMA Tx
Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 +++++++++++++--------
1 file changed, 31 insertions(+), 18 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4445,27 +4445,40 @@ static int mtk_hw_init(struct mtk_eth *e
mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) | PSE_DUMMY_WORK_GDM(2) |
PSE_DUMMY_WORK_GDM(3) | DUMMY_PAGE_THR, PSE_DUMY_REQ);
- /* PSE free buffer drop threshold */
- mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
-
- /* PSE should not drop port8, port9 and port13 packets from
- * WDMA Tx
- */
- mtk_w32(eth, 0x00002300, PSE_DROP_CFG);
-
- /* PSE should drop packets to port8, port9 and port13 on WDMA Rx
- * ring full
- */
- mtk_w32(eth, 0x00002300, PSE_PPE_DROP(0));
- mtk_w32(eth, 0x00002300, PSE_PPE_DROP(1));
- mtk_w32(eth, 0x00002300, PSE_PPE_DROP(2));
-
- /* GDM and CDM Threshold */
- mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES);
- mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
-
- /* Disable GDM1 RX CRC stripping */
- mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, MTK_GDMA_FWD_CFG(0));
+ if (eth->soc->caps == MT7988_CAPS) {
+ /* PSE free buffer drop threshold */
+ mtk_w32(eth, 0x00600009, PSE_IQ_REV(8));
+
+ /* PSE should not drop port8, port9 and port13 packets
+ * from WDMA Tx
+ */
+ mtk_w32(eth, 0x00002300, PSE_DROP_CFG);
+
+ /* PSE should drop packets to port8, port9 and port13
+ * on WDMA Rx ring full
+ */
+ mtk_w32(eth, 0x00002300, PSE_PPE_DROP(0));
+ mtk_w32(eth, 0x00002300, PSE_PPE_DROP(1));
+ mtk_w32(eth, 0x00002300, PSE_PPE_DROP(2));
+
+ /* GDM and CDM Threshold */
+ mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES);
+ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+ } else if (eth->soc->caps == MT7987_CAPS) {
+ /* PSE should not drop port8 packets from WDMA Tx */
+ mtk_w32(eth, 0x00000100, PSE_DROP_CFG);
+
+ /* PSE should drop packets to port8 on WDMA Rx ring
+ * full
+ */
+ mtk_w32(eth, 0x00000100, PSE_PPE_DROP(0));
+ mtk_w32(eth, 0x00000100, PSE_PPE_DROP(1));
+ }
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_ESW)) {
+ /* Disable GDM1 RX CRC stripping */
+ mtk_m32(eth, MTK_GDMA_STRP_CRC, 0, MTK_GDMA_FWD_CFG(0));
+ }
/* PSE GDM3 MIB counter has incorrect hw default values,
* so the driver ought to read clear the values beforehand

View File

@ -0,0 +1,397 @@
--- a/drivers/net/phy/mediatek/mtk-2p5ge.c
+++ b/drivers/net/phy/mediatek/mtk-2p5ge.c
@@ -12,13 +12,77 @@
#include "mtk.h"
+#define MTK_2P5GPHY_ID_MT7987 (0x00339c91)
#define MTK_2P5GPHY_ID_MT7988 (0x00339c11)
+#define MT7987_2P5GE_PMB_FW "mediatek/mt7987/i2p5ge-phy-pmb.bin"
+#define MT7987_2P5GE_PMB_FW_SIZE (0x18000)
+#define MT7987_2P5GE_DSPBITTB \
+ "mediatek/mt7987/i2p5ge-phy-DSPBitTb.bin"
+#define MT7987_2P5GE_DSPBITTB_SIZE (0x7000)
+
#define MT7988_2P5GE_PMB_FW "mediatek/mt7988/i2p5ge-phy-pmb.bin"
#define MT7988_2P5GE_PMB_FW_SIZE (0x20000)
+
+#define MTK_2P5GPHY_PMD_REG_BASE (0x0f010000)
+#define MTK_2P5GPHY_PMD_REG_LEN (0x210)
+#define DO_NOT_RESET (0x28)
+#define DO_NOT_RESET_XBZ BIT(0)
+#define DO_NOT_RESET_PMA BIT(3)
+#define DO_NOT_RESET_RX BIT(5)
+#define FNPLL_PWR_CTRL1 (0x208)
+#define RG_SPEED_MASK GENMASK(3, 0)
+#define RG_SPEED_2500 BIT(3)
+#define RG_SPEED_100 BIT(0)
+#define FNPLL_PWR_CTRL_STATUS (0x20c)
+#define RG_STABLE_MASK GENMASK(3, 0)
+#define RG_SPEED_2500_STABLE BIT(3)
+#define RG_SPEED_100_STABLE BIT(0)
+
+#define MTK_2P5GPHY_XBZ_PCS_REG_BASE (0x0f030000)
+#define MTK_2P5GPHY_XBZ_PCS_REG_LEN (0x844)
+#define PHY_CTRL_CONFIG (0x200)
+#define PMU_WP (0x800)
+#define WRITE_PROTECT_KEY (0xCAFEF00D)
+#define PMU_PMA_AUTO_CFG (0x820)
+#define POWER_ON_AUTO_MODE BIT(16)
+#define PMU_AUTO_MODE_EN BIT(0)
+#define PMU_PMA_STATUS (0x840)
+#define CLK_IS_DISABLED BIT(3)
+
+#define MTK_2P5GPHY_XBZ_PMA_RX_BASE (0x0f080000)
+#define MTK_2P5GPHY_XBZ_PMA_RX_LEN (0x5228)
+#define SMEM_WDAT0 (0x5000)
+#define SMEM_WDAT1 (0x5004)
+#define SMEM_WDAT2 (0x5008)
+#define SMEM_WDAT3 (0x500c)
+#define SMEM_CTRL (0x5024)
+#define SMEM_HW_RDATA_ZERO BIT(24)
+#define SMEM_ADDR_REF_ADDR (0x502c)
+#define CM_CTRL_P01 (0x5100)
+#define CM_CTRL_P23 (0x5124)
+#define DM_CTRL_P01 (0x5200)
+#define DM_CTRL_P23 (0x5224)
+
+#define MTK_2P5GPHY_CHIP_SCU_BASE (0x0f0cf800)
+#define MTK_2P5GPHY_CHIP_SCU_LEN (0x12c)
+#define SYS_SW_RESET (0x128)
+#define RESET_RST_CNT BIT(0)
+
+#define MTK_2P5GPHY_MCU_CSR_BASE (0x0f0f0000)
+#define MTK_2P5GPHY_MCU_CSR_LEN (0x20)
#define MD32_EN_CFG (0x18)
#define MD32_EN BIT(0)
+#define MTK_2P5GPHY_PMB_FW_BASE (0x0f100000)
+//#define MTK_2P5GPHY_PMB_FW_LEN MT7988_2P5GE_PMB_FW_SIZE
+
+#define MTK_2P5GPHY_APB_BASE (0x11c30000)
+#define MTK_2P5GPHY_APB_LEN (0x9c)
+#define SW_RESET (0x94)
+#define MD32_RESTART_EN_CLEAR BIT(9)
+
+
#define BASE100T_STATUS_EXTEND (0x10)
#define BASE1000T_STATUS_EXTEND (0x11)
#define EXTEND_CTRL_AND_STATUS (0x16)
@@ -31,6 +95,14 @@
#define MTK_PHY_LPI_PCS_DSP_CTRL (0x121)
#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
+#define MTK_PHY_LINK_STATUS_RELATED (0x147)
+#define MTK_PHY_BYPASS_LINK_STATUS_OK BIT(4)
+#define MTK_PHY_FORCE_LINK_STATUS_HCD BIT(3)
+
+#define MTK_PHY_AN_FORCE_SPEED_REG (0x313)
+#define MTK_PHY_MASTER_FORCE_SPEED_SEL_EN BIT(7)
+#define MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK GENMASK(6, 0)
+
#define MTK_PHY_HOST_CMD1 0x800e
#define MTK_PHY_HOST_CMD2 0x800f
/* Registers on Token Ring debug nodes */
@@ -48,7 +120,249 @@ enum {
PHY_AUX_SPD_2500,
};
-static int mt798x_2p5ge_phy_load_fw(struct phy_device *phydev)
+static int mt7987_2p5ge_phy_load_fw(struct phy_device *phydev)
+{
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ void __iomem *xbz_pcs_reg_base;
+ void __iomem *xbz_pma_rx_base;
+ void __iomem *chip_scu_base;
+ void __iomem *pmd_reg_base;
+ void __iomem *mcu_csr_base;
+ const struct firmware *fw;
+ void __iomem *apb_base;
+ void __iomem *pmb_addr;
+ int ret, i;
+ u32 reg;
+
+ if (priv->fw_loaded)
+ return 0;
+
+ apb_base = ioremap(MTK_2P5GPHY_APB_BASE,
+ MTK_2P5GPHY_APB_LEN);
+ if (!apb_base)
+ return -ENOMEM;
+
+ pmd_reg_base = ioremap(MTK_2P5GPHY_PMD_REG_BASE,
+ MTK_2P5GPHY_PMD_REG_LEN);
+ if (!pmd_reg_base) {
+ ret = -ENOMEM;
+ goto free_apb;
+ }
+
+ xbz_pcs_reg_base = ioremap(MTK_2P5GPHY_XBZ_PCS_REG_BASE,
+ MTK_2P5GPHY_XBZ_PCS_REG_LEN);
+ if (!xbz_pcs_reg_base) {
+ ret = -ENOMEM;
+ goto free_pmd;
+ }
+
+ xbz_pma_rx_base = ioremap(MTK_2P5GPHY_XBZ_PMA_RX_BASE,
+ MTK_2P5GPHY_XBZ_PMA_RX_LEN);
+ if (!xbz_pma_rx_base) {
+ ret = -ENOMEM;
+ goto free_pcs;
+ }
+
+ chip_scu_base = ioremap(MTK_2P5GPHY_CHIP_SCU_BASE,
+ MTK_2P5GPHY_CHIP_SCU_LEN);
+ if (!chip_scu_base) {
+ ret = -ENOMEM;
+ goto free_pma;
+ }
+
+ mcu_csr_base = ioremap(MTK_2P5GPHY_MCU_CSR_BASE,
+ MTK_2P5GPHY_MCU_CSR_LEN);
+ if (!mcu_csr_base) {
+ ret = -ENOMEM;
+ goto free_chip_scu;
+ }
+
+ pmb_addr = ioremap(MTK_2P5GPHY_PMB_FW_BASE, MT7987_2P5GE_PMB_FW_SIZE);
+ if (!pmb_addr) {
+ return -ENOMEM;
+ goto free_mcu_csr;
+ }
+
+ ret = request_firmware(&fw, MT7987_2P5GE_PMB_FW, dev);
+ if (ret) {
+ dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+ MT7987_2P5GE_PMB_FW, ret);
+ goto free_pmb_addr;
+ }
+
+ if (fw->size != MT7987_2P5GE_PMB_FW_SIZE) {
+ dev_err(dev, "PMb firmware size 0x%zx != 0x%x\n",
+ fw->size, MT7987_2P5GE_PMB_FW_SIZE);
+ ret = -EINVAL;
+ goto release_fw;
+ }
+
+ /* Force 2.5Gphy back to AN state */
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
+ usleep_range(5000, 6000);
+ phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
+
+ reg = readw(apb_base + SW_RESET);
+ writew(reg & ~MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
+ writew(reg | MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
+ writew(reg & ~MD32_RESTART_EN_CLEAR, apb_base + SW_RESET);
+
+ reg = readw(mcu_csr_base + MD32_EN_CFG);
+ writew(reg & ~MD32_EN, mcu_csr_base + MD32_EN_CFG);
+
+ for (i = 0; i < MT7987_2P5GE_PMB_FW_SIZE - 1; i += 4)
+ writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
+ dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
+ be16_to_cpu(*((__be16 *)(fw->data +
+ MT7987_2P5GE_PMB_FW_SIZE - 8))),
+ *(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 6),
+ *(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 5),
+ *(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 2),
+ *(fw->data + MT7987_2P5GE_PMB_FW_SIZE - 1));
+ release_firmware(fw);
+
+ /* Enable 100Mbps module clock. */
+ writel(FIELD_PREP(RG_SPEED_MASK, RG_SPEED_100),
+ pmd_reg_base + FNPLL_PWR_CTRL1);
+
+ /* Check if 100Mbps module clock is ready. */
+ ret = readl_poll_timeout(pmd_reg_base + FNPLL_PWR_CTRL_STATUS, reg,
+ reg & RG_SPEED_100_STABLE, 1, 10000);
+ if (ret)
+ dev_err(dev, "Fail to enable 100Mbps module clock: %d\n", ret);
+
+ /* Enable 2.5Gbps module clock. */
+ writel(FIELD_PREP(RG_SPEED_MASK, RG_SPEED_2500),
+ pmd_reg_base + FNPLL_PWR_CTRL1);
+
+ /* Check if 2.5Gbps module clock is ready. */
+ ret = readl_poll_timeout(pmd_reg_base + FNPLL_PWR_CTRL_STATUS, reg,
+ reg & RG_SPEED_2500_STABLE, 1, 10000);
+
+ if (ret)
+ dev_err(dev, "Fail to enable 2.5Gbps module clock: %d\n", ret);
+
+ /* Disable AN */
+ phy_clear_bits(phydev, MII_BMCR, BMCR_ANENABLE);
+
+ /* Force to run at 2.5G speed */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_AN_FORCE_SPEED_REG,
+ MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK,
+ MTK_PHY_MASTER_FORCE_SPEED_SEL_EN |
+ FIELD_PREP(MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK, 0x1b));
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_RELATED,
+ MTK_PHY_BYPASS_LINK_STATUS_OK |
+ MTK_PHY_FORCE_LINK_STATUS_HCD);
+
+ /* Set xbz, pma and rx as "do not reset" in order to input DSP code. */
+ reg = readl(pmd_reg_base + DO_NOT_RESET);
+ reg |= DO_NOT_RESET_XBZ | DO_NOT_RESET_PMA | DO_NOT_RESET_RX;
+ writel(reg, pmd_reg_base + DO_NOT_RESET);
+
+ reg = readl(chip_scu_base + SYS_SW_RESET);
+ writel(reg & ~RESET_RST_CNT, chip_scu_base + SYS_SW_RESET);
+
+ writel(WRITE_PROTECT_KEY, xbz_pcs_reg_base + PMU_WP);
+
+ reg = readl(xbz_pcs_reg_base + PMU_PMA_AUTO_CFG);
+ reg |= PMU_AUTO_MODE_EN | POWER_ON_AUTO_MODE;
+ writel(reg, xbz_pcs_reg_base + PMU_PMA_AUTO_CFG);
+
+ /* Check if clock in auto mode is disabled. */
+ ret = readl_poll_timeout(xbz_pcs_reg_base + PMU_PMA_STATUS, reg,
+ (reg & CLK_IS_DISABLED) == 0x0, 1, 100000);
+ if (ret)
+ dev_err(dev, "Clock isn't disabled in auto mode: %d\n", ret);
+
+ reg = readl(xbz_pma_rx_base + SMEM_CTRL);
+ writel(reg | SMEM_HW_RDATA_ZERO, xbz_pma_rx_base + SMEM_CTRL);
+
+ reg = readl(xbz_pcs_reg_base + PHY_CTRL_CONFIG);
+ writel(reg | BIT(16), xbz_pcs_reg_base + PHY_CTRL_CONFIG);
+
+ /* Initialize data memory */
+ reg = readl(xbz_pma_rx_base + DM_CTRL_P01);
+ writel(reg | BIT(28), xbz_pma_rx_base + DM_CTRL_P01);
+ reg = readl(xbz_pma_rx_base + DM_CTRL_P23);
+ writel(reg | BIT(28), xbz_pma_rx_base + DM_CTRL_P23);
+
+ /* Initialize coefficient memory */
+ reg = readl(xbz_pma_rx_base + CM_CTRL_P01);
+ writel(reg | BIT(28), xbz_pma_rx_base + CM_CTRL_P01);
+ reg = readl(xbz_pma_rx_base + CM_CTRL_P23);
+ writel(reg | BIT(28), xbz_pma_rx_base + CM_CTRL_P23);
+
+ /* Initilize PM offset */
+ writel(0, xbz_pma_rx_base + SMEM_ADDR_REF_ADDR);
+
+ ret = request_firmware(&fw, MT7987_2P5GE_DSPBITTB, dev);
+ if (ret) {
+ dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+ MT7987_2P5GE_DSPBITTB, ret);
+ goto free_pmb_addr;
+ }
+ if (fw->size != MT7987_2P5GE_DSPBITTB_SIZE) {
+ dev_err(dev, "DSPBITTB size 0x%zx != 0x%x\n",
+ fw->size, MT7987_2P5GE_DSPBITTB_SIZE);
+ ret = -EINVAL;
+ goto release_fw;
+ }
+
+ for (i = 0; i < fw->size - 1; i += 16) {
+ writel(*((uint32_t *)(fw->data + i)),
+ xbz_pma_rx_base + SMEM_WDAT0);
+ writel(*((uint32_t *)(fw->data + i + 0x4)),
+ xbz_pma_rx_base + SMEM_WDAT1);
+ writel(*((uint32_t *)(fw->data + i + 0x8)),
+ xbz_pma_rx_base + SMEM_WDAT2);
+ writel(*((uint32_t *)(fw->data + i + 0xc)),
+ xbz_pma_rx_base + SMEM_WDAT3);
+ }
+
+ reg = readl(xbz_pma_rx_base + DM_CTRL_P01);
+ writel(reg & ~BIT(28), xbz_pma_rx_base + DM_CTRL_P01);
+
+ reg = readl(xbz_pma_rx_base + DM_CTRL_P23);
+ writel(reg & ~BIT(28), xbz_pma_rx_base + DM_CTRL_P23);
+
+ reg = readl(xbz_pma_rx_base + CM_CTRL_P01);
+ writel(reg & ~BIT(28), xbz_pma_rx_base + CM_CTRL_P01);
+
+ reg = readl(xbz_pma_rx_base + CM_CTRL_P23);
+ writel(reg & ~BIT(28), xbz_pma_rx_base + CM_CTRL_P23);
+
+ reg = readw(mcu_csr_base + MD32_EN_CFG);
+ writew(reg | MD32_EN, mcu_csr_base + MD32_EN_CFG);
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
+ /* We need a delay here to stabilize initialization of MCU */
+ usleep_range(7000, 8000);
+ dev_info(dev, "Firmware loading/trigger ok.\n");
+
+ priv->fw_loaded = true;
+
+release_fw:
+ release_firmware(fw);
+free_pmb_addr:
+ iounmap(pmb_addr);
+free_mcu_csr:
+ iounmap(mcu_csr_base);
+free_chip_scu:
+ iounmap(chip_scu_base);
+free_pma:
+ iounmap(xbz_pma_rx_base);
+free_pcs:
+ iounmap(xbz_pcs_reg_base);
+free_pmd:
+ iounmap(pmd_reg_base);
+free_apb:
+ iounmap(apb_base);
+
+ return ret;
+}
+
+static int mt7988_2p5ge_phy_load_fw(struct phy_device *phydev)
{
struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
void __iomem *mcu_csr_base, *pmb_addr;
@@ -135,7 +449,20 @@ static int mt798x_2p5ge_phy_config_init(
if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL)
return -ENODEV;
- ret = mt798x_2p5ge_phy_load_fw(phydev);
+ switch (phydev->drv->phy_id) {
+ case MTK_2P5GPHY_ID_MT7987:
+ ret = mt7987_2p5ge_phy_load_fw(phydev);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED_ON_POLARITY);
+ break;
+ case MTK_2P5GPHY_ID_MT7988:
+ ret = mt7988_2p5ge_phy_load_fw(phydev);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED_ON_POLARITY);
+ break;
+ default:
+ return -EINVAL;
+ }
if (ret < 0)
return ret;
@@ -293,6 +620,7 @@ static int mt798x_2p5ge_phy_probe(struct
return -ENOMEM;
switch (phydev->drv->phy_id) {
+ case MTK_2P5GPHY_ID_MT7987:
case MTK_2P5GPHY_ID_MT7988:
/* The original hardware only sets MDIO_DEVS_PMAPMD */
phydev->c45_ids.mmds_present |= MDIO_DEVS_PCS |
@@ -312,6 +640,20 @@ static int mt798x_2p5ge_phy_probe(struct
static struct phy_driver mtk_2p5gephy_driver[] = {
{
+ PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7987),
+ .name = "MediaTek MT7987 2.5GbE PHY",
+ .probe = mt798x_2p5ge_phy_probe,
+ .config_init = mt798x_2p5ge_phy_config_init,
+ .config_aneg = mt798x_2p5ge_phy_config_aneg,
+ .get_features = mt798x_2p5ge_phy_get_features,
+ .read_status = mt798x_2p5ge_phy_read_status,
+ .get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_phy_read_page,
+ .write_page = mtk_phy_write_page,
+ },
+ {
PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7988),
.name = "MediaTek MT7988 2.5GbE PHY",
.probe = mt798x_2p5ge_phy_probe,

View File

@ -0,0 +1,148 @@
From: Chad Monroe <chad@monroe.io>
Date: Mon, 01 Sep 2025 06:42:10 -0700
Subject: [PATCH] thermal/drivers/mediatek/lvts_thermal: Add irq_enable
support.
Allow interrupt support to be disabled as some SoCs don't support it.
Signed-off-by: Chad Monroe <chad@monroe.io>
---
drivers/thermal/mediatek/lvts_thermal.c | 33 ++++++++++++++++------
1 file changed, 25 insertions(+), 8 deletions(-)
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -127,6 +127,7 @@ struct lvts_data {
const struct lvts_ctrl_data *lvts_ctrl;
const u32 *conn_cmd;
const u32 *init_cmd;
+ bool irq_enable;
int num_lvts_ctrl;
int num_conn_cmd;
int num_init_cmd;
@@ -408,6 +409,10 @@ static int lvts_set_trips(struct thermal
lvts_ctrl->high_thresh = high;
lvts_ctrl->low_thresh = low;
}
+
+ if (!lvts_data->irq_enable)
+ return 0;
+
lvts_update_irq_mask(lvts_ctrl);
if (!should_update_thresh)
@@ -921,6 +926,8 @@ static void lvts_write_config(struct lvt
static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl)
{
+ const struct lvts_data *lvts_data = lvts_ctrl->lvts_data;
+
/*
* LVTS_PROTCTL : Thermal Protection Sensor Selection
*
@@ -954,7 +961,8 @@ static int lvts_irq_init(struct lvts_ctr
* The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS
* register, except we set the bits to enable the interrupt.
*/
- writel(0, LVTS_MONINT(lvts_ctrl->base));
+ if (lvts_data->irq_enable)
+ writel(0, LVTS_MONINT(lvts_ctrl->base));
return 0;
}
@@ -1338,9 +1346,11 @@ static int lvts_probe(struct platform_de
if (IS_ERR(lvts_td->reset))
return dev_err_probe(dev, PTR_ERR(lvts_td->reset), "Failed to get reset control\n");
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+ if (lvts_data->irq_enable) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ }
golden_temp_offset = lvts_data->temp_offset;
@@ -1352,10 +1362,12 @@ static int lvts_probe(struct platform_de
* At this point the LVTS is initialized and enabled. We can
* safely enable the interrupt.
*/
- ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler,
- IRQF_ONESHOT, dev_name(dev), lvts_td);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to request interrupt\n");
+ if (lvts_data->irq_enable) {
+ ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler,
+ IRQF_ONESHOT, dev_name(dev), lvts_td);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request interrupt\n");
+ }
platform_set_drvdata(pdev, lvts_td);
@@ -1754,6 +1766,7 @@ static const struct lvts_ctrl_data mt819
};
static const struct lvts_data mt7988_lvts_ap_data = {
+ .irq_enable = true,
.lvts_ctrl = mt7988_lvts_ap_data_ctrl,
.conn_cmd = mt7988_conn_cmds,
.init_cmd = mt7988_init_cmds,
@@ -1766,6 +1779,7 @@ static const struct lvts_data mt7988_lvt
};
static const struct lvts_data mt8186_lvts_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8186_lvts_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1779,6 +1793,7 @@ static const struct lvts_data mt8186_lvt
};
static const struct lvts_data mt8188_lvts_mcu_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8188_lvts_mcu_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1792,6 +1807,7 @@ static const struct lvts_data mt8188_lvt
};
static const struct lvts_data mt8188_lvts_ap_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8188_lvts_ap_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1805,6 +1821,7 @@ static const struct lvts_data mt8188_lvt
};
static const struct lvts_data mt8192_lvts_mcu_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8192_lvts_mcu_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1818,6 +1835,7 @@ static const struct lvts_data mt8192_lvt
};
static const struct lvts_data mt8192_lvts_ap_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8192_lvts_ap_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1831,6 +1849,7 @@ static const struct lvts_data mt8192_lvt
};
static const struct lvts_data mt8195_lvts_mcu_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8195_lvts_mcu_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,
@@ -1844,6 +1863,7 @@ static const struct lvts_data mt8195_lvt
};
static const struct lvts_data mt8195_lvts_ap_data = {
+ .irq_enable = true,
.lvts_ctrl = mt8195_lvts_ap_data_ctrl,
.conn_cmd = default_conn_cmds,
.init_cmd = default_init_cmds,

View File

@ -0,0 +1,106 @@
From: Chad Monroe <chad@monroe.io>
Date: Mon, 01 Sep 2025 06:44:04 -0700
Subject: [PATCH] thermal/drivers/mediatek/lvts_thermal: Add MT7987 support
Add support for Mediatek MT7987 LVTS. Based patch[1] from vendor SDK.
1: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/742007e189ffcc95783924cea1150f574b6eb71e
Signed-off-by: Chad Monroe <chad@monroe.io>
---
drivers/thermal/mediatek/lvts_thermal.c | 36 ++++++++++
include/dt-bindings/thermal/mediatek,lvts-thermal.h | 3
2 files changed, 39 insertions(+)
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -87,6 +87,8 @@
#define LVTS_COEFF_B_MT8195 250460
#define LVTS_COEFF_A_MT7988 -204650
#define LVTS_COEFF_B_MT7988 204650
+#define LVTS_COEFF_A_MT7987 -204650
+#define LVTS_COEFF_B_MT7987 204650
#define LVTS_MSR_IMMEDIATE_MODE 0
#define LVTS_MSR_FILTERED_MODE 1
@@ -1385,6 +1387,19 @@ static void lvts_remove(struct platform_
lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false);
}
+static const struct lvts_ctrl_data mt7987_lvts_ap_data_ctrl[] = {
+ {
+ .lvts_sensor = {
+ { .dt_id = MT7987_CPU,
+ .cal_offsets = { 0x04, 0x05, 0x06 } },
+ { .dt_id = MT7987_ETH2P5G,
+ .cal_offsets = { 0x08, 0x09, 0x0a } },
+ },
+ VALID_SENSOR_MAP(1, 1, 0, 0),
+ .offset = 0x0,
+ },
+};
+
static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = {
{
.lvts_sensor = {
@@ -1455,6 +1470,7 @@ static int lvts_resume(struct device *de
}
static const u32 default_conn_cmds[] = { 0xC103FFFF, 0xC502FF55 };
+static const u32 mt7987_conn_cmds[] = { 0xC103FFFF, 0xC502FC55 };
static const u32 mt7988_conn_cmds[] = { 0xC103FFFF, 0xC502FC55 };
/*
@@ -1467,6 +1483,12 @@ static const u32 default_init_cmds[] = {
0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1
};
+static const u32 mt7987_init_cmds[] = {
+ 0xC1030300, 0xC1030420, 0xC1030500, 0xC10307A6, 0xC10308C7,
+ 0xC103098D, 0xC1030C7C, 0xC1030AA8, 0xC10308CE, 0xC10308C7,
+ 0xC1030B04, 0xC1030E01, 0xC10306B8
+};
+
static const u32 mt7988_init_cmds[] = {
0xC1030300, 0xC1030420, 0xC1030500, 0xC10307A6, 0xC1030CFC,
0xC1030A8C, 0xC103098D, 0xC10308F1, 0xC1030B04, 0xC1030E01,
@@ -1765,6 +1787,19 @@ static const struct lvts_ctrl_data mt819
}
};
+static const struct lvts_data mt7987_lvts_ap_data = {
+ .irq_enable = false,
+ .lvts_ctrl = mt7987_lvts_ap_data_ctrl,
+ .conn_cmd = mt7987_conn_cmds,
+ .init_cmd = mt7987_init_cmds,
+ .num_lvts_ctrl = ARRAY_SIZE(mt7987_lvts_ap_data_ctrl),
+ .num_conn_cmd = ARRAY_SIZE(mt7987_conn_cmds),
+ .num_init_cmd = ARRAY_SIZE(mt7987_init_cmds),
+ .temp_factor = LVTS_COEFF_A_MT7987,
+ .temp_offset = LVTS_COEFF_B_MT7987,
+ .gt_calib_bit_offset = 24,
+};
+
static const struct lvts_data mt7988_lvts_ap_data = {
.irq_enable = true,
.lvts_ctrl = mt7988_lvts_ap_data_ctrl,
@@ -1877,6 +1912,7 @@ static const struct lvts_data mt8195_lvt
};
static const struct of_device_id lvts_of_match[] = {
+ { .compatible = "mediatek,mt7987-lvts-ap", .data = &mt7987_lvts_ap_data },
{ .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data },
{ .compatible = "mediatek,mt8186-lvts", .data = &mt8186_lvts_data },
{ .compatible = "mediatek,mt8188-lvts-mcu", .data = &mt8188_lvts_mcu_data },
--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h
+++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h
@@ -7,6 +7,9 @@
#ifndef __MEDIATEK_LVTS_DT_H
#define __MEDIATEK_LVTS_DT_H
+#define MT7987_CPU 0
+#define MT7987_ETH2P5G 1
+
#define MT7988_CPU_0 0
#define MT7988_CPU_1 1
#define MT7988_ETH2P5G_0 2

View File

@ -212,6 +212,7 @@
&wifi {
status = "okay";
qcom,ath11k-calibration-variant = "JDC-AX1800-Pro";
qcom,ath11k-calibration-variant = "JDC-RE-SS-01";
qcom,ath11k-fw-memory-mode = <1>;
};

View File

@ -143,15 +143,17 @@
perst-gpio = <&tlmm 53 GPIO_ACTIVE_LOW>;
status = "okay";
bridge@0,0 {
reg = <0x00000000 0 0 0 0>;
pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
#address-cells = <3>;
#size-cells = <2>;
ranges;
wifi@1,0 {
wifi@0,0 {
compatible = "pci17cb,1104";
reg = <0x00010000 0 0 0 0>;
qcom,ath11k-calibration-variant = "JDC-RE-CS-02";
};
};
};
@ -288,5 +290,6 @@
&wifi {
status = "okay";
qcom,ath11k-calibration-variant = "JDC-AX6600";
qcom,ath11k-calibration-variant = "JDC-RE-CS-02";
};

View File

@ -52,7 +52,7 @@ define Device/jdcloud_re-cs-02
BLOCKSIZE := 64k
KERNEL_SIZE := 6144k
DEVICE_DTS_CONFIG := config@cp03-c3
DEVICE_PACKAGES := ipq-wifi-jdcloud_re-cs-02 kmod-ath11k-pci ath11k-firmware-qcn9074
DEVICE_PACKAGES := ath11k-firmware-qcn9074 ipq-wifi-jdcloud_re-cs-02 kmod-ath11k-pci
endef
TARGET_DEVICES += jdcloud_re-cs-02
@ -78,7 +78,7 @@ define Device/jdcloud_re-ss-01
BLOCKSIZE := 64k
KERNEL_SIZE := 6144k
DEVICE_DTS_CONFIG := config@cp03-c2
DEVICE_PACKAGES := ipq-wifi-jdcloud_ax1800pro
DEVICE_PACKAGES := ipq-wifi-jdcloud_re-ss-01
endef
TARGET_DEVICES += jdcloud_re-ss-01

View File

@ -404,6 +404,7 @@ CONFIG_MFD_CORE=y
CONFIG_MFD_RK8XX=y
CONFIG_MFD_RK8XX_I2C=y
CONFIG_MFD_RK8XX_SPI=y
CONFIG_MFD_ROCKCHIP_MFPWM=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
@ -587,6 +588,7 @@ CONFIG_ROCKCHIP_MBOX=y
CONFIG_ROCKCHIP_MFPWM=y
CONFIG_ROCKCHIP_PHY=y
CONFIG_ROCKCHIP_PM_DOMAINS=y
CONFIG_ROCKCHIP_PWM_CAPTURE=y
CONFIG_ROCKCHIP_THERMAL=y
CONFIG_ROCKCHIP_TIMER=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y

View File

@ -0,0 +1,71 @@
From f2dbca169790ea1e436ffdd9ef37d7c3a4401c46 Mon Sep 17 00:00:00 2001
From: Andy Yan <andy.yan@rock-chips.com>
Date: Fri, 20 Sep 2024 17:36:28 +0800
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Don't request
RST_PHY/RST_ROPLL/RST_LCPLL
RST_PHY/RST_ROPLL/RST_LCPLL are used for debug only on rk3588,
and they are not exported on rk3576, no need to request it in
driver.
Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
Link: https://lore.kernel.org/r/20240920093629.7410-1-andyshrk@163.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -257,13 +257,10 @@ struct ropll_config {
};
enum rk_hdptx_reset {
- RST_PHY = 0,
- RST_APB,
+ RST_APB = 0,
RST_INIT,
RST_CMN,
RST_LANE,
- RST_ROPLL,
- RST_LCPLL,
RST_MAX
};
@@ -679,11 +676,6 @@ static void rk_hdptx_phy_disable(struct
{
u32 val;
- /* reset phy and apb, or phy locked flag may keep 1 */
- reset_control_assert(hdptx->rsts[RST_PHY].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_PHY].rstc);
-
reset_control_assert(hdptx->rsts[RST_APB].rstc);
usleep_range(20, 30);
reset_control_deassert(hdptx->rsts[RST_APB].rstc);
@@ -804,10 +796,6 @@ static int rk_hdptx_ropll_tmds_cmn_confi
rk_hdptx_pre_power_up(hdptx);
- reset_control_assert(hdptx->rsts[RST_ROPLL].rstc);
- usleep_range(20, 30);
- reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc);
-
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq);
@@ -1130,13 +1118,10 @@ static int rk_hdptx_phy_probe(struct pla
return dev_err_probe(dev, PTR_ERR(hdptx->regmap),
"Failed to init regmap\n");
- hdptx->rsts[RST_PHY].id = "phy";
hdptx->rsts[RST_APB].id = "apb";
hdptx->rsts[RST_INIT].id = "init";
hdptx->rsts[RST_CMN].id = "cmn";
hdptx->rsts[RST_LANE].id = "lane";
- hdptx->rsts[RST_ROPLL].id = "ropll";
- hdptx->rsts[RST_LCPLL].id = "lcpll";
ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts);
if (ret)

View File

@ -0,0 +1,42 @@
From c8f7d65cac565cacf0420acf8b54c855dd7b4484 Mon Sep 17 00:00:00 2001
From: Heiko Stuebner <heiko.stuebner@cherry.de>
Date: Fri, 6 Dec 2024 11:34:00 +0100
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: annotate regmap
register-callback
The variant of the driver in the vendor-tree contained those handy
comments in the regmap register callback. Having the different ranges
describe what they are looks helpful.
Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20241206103401.1780416-2-heiko@sntech.de
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -574,13 +574,13 @@ static const struct reg_sequence rk_hdtp
static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case 0x0000 ... 0x029c:
- case 0x0400 ... 0x04a4:
- case 0x0800 ... 0x08a4:
- case 0x0c00 ... 0x0cb4:
- case 0x1000 ... 0x10b4:
- case 0x1400 ... 0x14b4:
- case 0x1800 ... 0x18b4:
+ case 0x0000 ... 0x029c: /* CMN Register */
+ case 0x0400 ... 0x04a4: /* Sideband Register */
+ case 0x0800 ... 0x08a4: /* Lane Top Register */
+ case 0x0c00 ... 0x0cb4: /* Lane 0 Register */
+ case 0x1000 ... 0x10b4: /* Lane 1 Register */
+ case 0x1400 ... 0x14b4: /* Lane 2 Register */
+ case 0x1800 ... 0x18b4: /* Lane 3 Register */
return true;
}

View File

@ -0,0 +1,37 @@
From f706024107204cb0b640bac35ea47e7b91b8c71f Mon Sep 17 00:00:00 2001
From: Damon Ding <damon.ding@rock-chips.com>
Date: Wed, 5 Feb 2025 18:51:55 +0800
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Supplement some register
names with their full version
Complete the register names of CMN_REG(0081) and CMN_REG(0087) to their
full version, and it can help to better match the datasheet.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20250205105157.580060-3-damon.ding@rock-chips.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -82,14 +82,14 @@
#define ROPLL_SSC_EN BIT(0)
/* CMN_REG(0081) */
#define OVRD_PLL_CD_CLK_EN BIT(8)
-#define PLL_CD_HSCLK_EAST_EN BIT(0)
+#define ANA_PLL_CD_HSCLK_EAST_EN BIT(0)
/* CMN_REG(0086) */
#define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4)
#define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1)
#define PLL_PCG_CLK_EN BIT(0)
/* CMN_REG(0087) */
-#define PLL_FRL_MODE_EN BIT(3)
-#define PLL_TX_HS_CLK_EN BIT(2)
+#define ANA_PLL_FRL_MODE_EN BIT(3)
+#define ANA_PLL_TX_HS_CLK_EN BIT(2)
/* CMN_REG(0089) */
#define LCPLL_ALONE_MODE BIT(1)
/* CMN_REG(0097) */

View File

@ -0,0 +1,170 @@
From 2dc8224e3758c5d6387786ea1d74d2d510149b1a Mon Sep 17 00:00:00 2001
From: Damon Ding <damon.ding@rock-chips.com>
Date: Wed, 5 Feb 2025 18:51:56 +0800
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add the '_MASK' suffix to
all registers
Adding the '_MASK' suffix to all registers in order to ensures consistency
in the naming convention for register macros throughout the file.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20250205105157.580060-4-damon.ding@rock-chips.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 88 +++++++++----------
1 file changed, 44 insertions(+), 44 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -50,60 +50,60 @@
#define LCPLL_PI_EN_MASK BIT(5)
#define LCPLL_100M_CLK_EN_MASK BIT(0)
/* CMN_REG(0025) */
-#define LCPLL_PMS_IQDIV_RSTN BIT(4)
+#define LCPLL_PMS_IQDIV_RSTN_MASK BIT(4)
/* CMN_REG(0028) */
-#define LCPLL_SDC_FRAC_EN BIT(2)
-#define LCPLL_SDC_FRAC_RSTN BIT(0)
+#define LCPLL_SDC_FRAC_EN_MASK BIT(2)
+#define LCPLL_SDC_FRAC_RSTN_MASK BIT(0)
/* CMN_REG(002d) */
#define LCPLL_SDC_N_MASK GENMASK(3, 1)
/* CMN_REG(002e) */
#define LCPLL_SDC_NUMBERATOR_MASK GENMASK(5, 0)
/* CMN_REG(002f) */
#define LCPLL_SDC_DENOMINATOR_MASK GENMASK(7, 2)
-#define LCPLL_SDC_NDIV_RSTN BIT(0)
+#define LCPLL_SDC_NDIV_RSTN_MASK BIT(0)
/* CMN_REG(003d) */
-#define ROPLL_LCVCO_EN BIT(4)
+#define ROPLL_LCVCO_EN_MASK BIT(4)
/* CMN_REG(004e) */
-#define ROPLL_PI_EN BIT(5)
+#define ROPLL_PI_EN_MASK BIT(5)
/* CMN_REG(005c) */
-#define ROPLL_PMS_IQDIV_RSTN BIT(5)
+#define ROPLL_PMS_IQDIV_RSTN_MASK BIT(5)
/* CMN_REG(005e) */
#define ROPLL_SDM_EN_MASK BIT(6)
-#define ROPLL_SDM_FRAC_EN_RBR BIT(3)
-#define ROPLL_SDM_FRAC_EN_HBR BIT(2)
-#define ROPLL_SDM_FRAC_EN_HBR2 BIT(1)
-#define ROPLL_SDM_FRAC_EN_HBR3 BIT(0)
+#define ROPLL_SDC_FRAC_EN_RBR_MASK BIT(3)
+#define ROPLL_SDC_FRAC_EN_HBR_MASK BIT(2)
+#define ROPLL_SDC_FRAC_EN_HBR2_MASK BIT(1)
+#define ROPLL_SDM_FRAC_EN_HBR3_MASK BIT(0)
/* CMN_REG(0064) */
#define ROPLL_SDM_NUM_SIGN_RBR_MASK BIT(3)
/* CMN_REG(0069) */
#define ROPLL_SDC_N_RBR_MASK GENMASK(2, 0)
/* CMN_REG(0074) */
-#define ROPLL_SDC_NDIV_RSTN BIT(2)
-#define ROPLL_SSC_EN BIT(0)
+#define ROPLL_SDC_NDIV_RSTN_MASK BIT(2)
+#define ROPLL_SSC_EN_MASK BIT(0)
/* CMN_REG(0081) */
-#define OVRD_PLL_CD_CLK_EN BIT(8)
-#define ANA_PLL_CD_HSCLK_EAST_EN BIT(0)
+#define OVRD_PLL_CD_CLK_EN_MASK BIT(8)
+#define ANA_PLL_CD_HSCLK_EAST_EN_MASK BIT(0)
/* CMN_REG(0086) */
#define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4)
#define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1)
-#define PLL_PCG_CLK_EN BIT(0)
+#define PLL_PCG_CLK_EN_MASK BIT(0)
/* CMN_REG(0087) */
-#define ANA_PLL_FRL_MODE_EN BIT(3)
-#define ANA_PLL_TX_HS_CLK_EN BIT(2)
+#define ANA_PLL_FRL_MODE_EN_MASK BIT(3)
+#define ANA_PLL_TX_HS_CLK_EN_MASK BIT(2)
/* CMN_REG(0089) */
-#define LCPLL_ALONE_MODE BIT(1)
+#define LCPLL_ALONE_MODE_MASK BIT(1)
/* CMN_REG(0097) */
-#define DIG_CLK_SEL BIT(1)
+#define DIG_CLK_SEL_MASK BIT(1)
#define LCPLL_REF BIT(1)
#define ROPLL_REF 0
/* CMN_REG(0099) */
-#define CMN_ROPLL_ALONE_MODE BIT(2)
+#define CMN_ROPLL_ALONE_MODE_MASK BIT(2)
#define ROPLL_ALONE_MODE BIT(2)
/* CMN_REG(009a) */
-#define HS_SPEED_SEL BIT(0)
+#define HS_SPEED_SEL_MASK BIT(0)
#define DIV_10_CLOCK BIT(0)
/* CMN_REG(009b) */
-#define IS_SPEED_SEL BIT(4)
+#define LS_SPEED_SEL_MASK BIT(4)
#define LINK_SYMBOL_CLOCK BIT(4)
#define LINK_SYMBOL_CLOCK1_2 0
@@ -161,36 +161,36 @@
#define SB_READY_MASK BIT(4)
/* LNTOP_REG(0200) */
-#define PROTOCOL_SEL BIT(2)
+#define PROTOCOL_SEL_MASK BIT(2)
#define HDMI_MODE BIT(2)
#define HDMI_TMDS_FRL_SEL BIT(1)
/* LNTOP_REG(0206) */
-#define DATA_BUS_SEL BIT(0)
+#define DATA_BUS_WIDTH_SEL_MASK BIT(0)
#define DATA_BUS_36_40 BIT(0)
/* LNTOP_REG(0207) */
-#define LANE_EN 0xf
+#define LANE_EN_MASK 0xf
#define ALL_LANE_EN 0xf
/* LANE_REG(0312) */
-#define LN0_TX_SER_RATE_SEL_RBR BIT(5)
-#define LN0_TX_SER_RATE_SEL_HBR BIT(4)
-#define LN0_TX_SER_RATE_SEL_HBR2 BIT(3)
-#define LN0_TX_SER_RATE_SEL_HBR3 BIT(2)
+#define LN0_TX_SER_RATE_SEL_RBR_MASK BIT(5)
+#define LN0_TX_SER_RATE_SEL_HBR_MASK BIT(4)
+#define LN0_TX_SER_RATE_SEL_HBR2_MASK BIT(3)
+#define LN0_TX_SER_RATE_SEL_HBR3_MASK BIT(2)
/* LANE_REG(0412) */
-#define LN1_TX_SER_RATE_SEL_RBR BIT(5)
-#define LN1_TX_SER_RATE_SEL_HBR BIT(4)
-#define LN1_TX_SER_RATE_SEL_HBR2 BIT(3)
-#define LN1_TX_SER_RATE_SEL_HBR3 BIT(2)
+#define LN1_TX_SER_RATE_SEL_RBR_MASK BIT(5)
+#define LN1_TX_SER_RATE_SEL_HBR_MASK BIT(4)
+#define LN1_TX_SER_RATE_SEL_HBR2_MASK BIT(3)
+#define LN1_TX_SER_RATE_SEL_HBR3_MASK BIT(2)
/* LANE_REG(0512) */
-#define LN2_TX_SER_RATE_SEL_RBR BIT(5)
-#define LN2_TX_SER_RATE_SEL_HBR BIT(4)
-#define LN2_TX_SER_RATE_SEL_HBR2 BIT(3)
-#define LN2_TX_SER_RATE_SEL_HBR3 BIT(2)
+#define LN2_TX_SER_RATE_SEL_RBR_MASK BIT(5)
+#define LN2_TX_SER_RATE_SEL_HBR_MASK BIT(4)
+#define LN2_TX_SER_RATE_SEL_HBR2_MASK BIT(3)
+#define LN2_TX_SER_RATE_SEL_HBR3_MASK BIT(2)
/* LANE_REG(0612) */
-#define LN3_TX_SER_RATE_SEL_RBR BIT(5)
-#define LN3_TX_SER_RATE_SEL_HBR BIT(4)
-#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3)
-#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2)
+#define LN3_TX_SER_RATE_SEL_RBR_MASK BIT(5)
+#define LN3_TX_SER_RATE_SEL_HBR_MASK BIT(4)
+#define LN3_TX_SER_RATE_SEL_HBR2_MASK BIT(3)
+#define LN3_TX_SER_RATE_SEL_HBR3_MASK BIT(2)
#define HDMI14_MAX_RATE 340000000
#define HDMI20_MAX_RATE 600000000
@@ -825,8 +825,8 @@ static int rk_hdptx_ropll_tmds_cmn_confi
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
- regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN,
- PLL_PCG_CLK_EN);
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
+ FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
ret = rk_hdptx_post_enable_pll(hdptx);
if (!ret)

View File

@ -0,0 +1,49 @@
From 4a8463ae8d871ccd491d48a371a6789eb7378243 Mon Sep 17 00:00:00 2001
From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Date: Thu, 6 Mar 2025 20:29:23 +0100
Subject: [PATCH] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
Despite the compatible already being listed in the bindings, the PHY
driver never gained explicit support for it. This is especially a
problem because the explicitly listed PHY addresses need to be specified
for each SoC.
To solve this, add the compatible, and a PHY config, with the address
gleaned from rk3576.dtsi.
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -2022,6 +2022,13 @@ static const struct dev_pm_ops rk_hdptx_
rk_hdptx_phy_runtime_resume, NULL)
};
+static const struct rk_hdptx_phy_cfg rk3576_hdptx_phy_cfgs = {
+ .num_phys = 1,
+ .phy_ids = {
+ 0x2b000000,
+ },
+};
+
static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = {
.num_phys = 2,
.phy_ids = {
@@ -2032,6 +2039,10 @@ static const struct rk_hdptx_phy_cfg rk3
static const struct of_device_id rk_hdptx_phy_of_match[] = {
{
+ .compatible = "rockchip,rk3576-hdptx-phy",
+ .data = &rk3576_hdptx_phy_cfgs
+ },
+ {
.compatible = "rockchip,rk3588-hdptx-phy",
.data = &rk3588_hdptx_phy_cfgs
},

View File

@ -0,0 +1,83 @@
From 10ed34d6eaaf86e301a8f2dd190d26dfbc9799bd Mon Sep 17 00:00:00 2001
From: Sandor Yu <Sandor.yu@nxp.com>
Date: Tue, 18 Mar 2025 14:35:35 +0200
Subject: [PATCH] phy: Add HDMI configuration options
Allow HDMI PHYs to be configured through the generic
functions through a custom structure added to the generic union.
The parameters added here are based on HDMI PHY
implementation practices. The current set of parameters
should cover the potential users.
Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
Link: https://lore.kernel.org/r/d1cff6c03ec3732d2244022029245ab2d954d997.1734340233.git.Sandor.yu@nxp.com
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-1-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
include/linux/phy/phy-hdmi.h | 19 +++++++++++++++++++
include/linux/phy/phy.h | 7 ++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 include/linux/phy/phy-hdmi.h
--- /dev/null
+++ b/include/linux/phy/phy-hdmi.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2022,2024 NXP
+ */
+
+#ifndef __PHY_HDMI_H_
+#define __PHY_HDMI_H_
+
+/**
+ * struct phy_configure_opts_hdmi - HDMI configuration set
+ * @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ *
+ * This structure is used to represent the configuration state of a HDMI phy.
+ */
+struct phy_configure_opts_hdmi {
+ unsigned long long tmds_char_rate;
+};
+
+#endif /* __PHY_HDMI_H_ */
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -17,6 +17,7 @@
#include <linux/regulator/consumer.h>
#include <linux/phy/phy-dp.h>
+#include <linux/phy/phy-hdmi.h>
#include <linux/phy/phy-lvds.h>
#include <linux/phy/phy-mipi-dphy.h>
@@ -42,7 +43,8 @@ enum phy_mode {
PHY_MODE_MIPI_DPHY,
PHY_MODE_SATA,
PHY_MODE_LVDS,
- PHY_MODE_DP
+ PHY_MODE_DP,
+ PHY_MODE_HDMI,
};
enum phy_media {
@@ -60,11 +62,14 @@ enum phy_media {
* the DisplayPort protocol.
* @lvds: Configuration set applicable for phys supporting
* the LVDS phy mode.
+ * @hdmi: Configuration set applicable for phys supporting
+ * the HDMI phy mode.
*/
union phy_configure_opts {
struct phy_configure_opts_mipi_dphy mipi_dphy;
struct phy_configure_opts_dp dp;
struct phy_configure_opts_lvds lvds;
+ struct phy_configure_opts_hdmi hdmi;
};
/**

View File

@ -0,0 +1,33 @@
From 3bb9286f4ece6acbc1fbaa9f192a82645d30efbf Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:36 +0200
Subject: [PATCH] phy: hdmi: Add color depth configuration
Extend the HDMI configuration options to allow managing bits per color
channel. This is required by some PHY drivers such as
rockchip-samsung-hdptx.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-2-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
include/linux/phy/phy-hdmi.h | 2 ++
1 file changed, 2 insertions(+)
--- a/include/linux/phy/phy-hdmi.h
+++ b/include/linux/phy/phy-hdmi.h
@@ -9,11 +9,13 @@
/**
* struct phy_configure_opts_hdmi - HDMI configuration set
* @tmds_char_rate: HDMI TMDS Character Rate in Hertz.
+ * @bpc: Bits per color channel.
*
* This structure is used to represent the configuration state of a HDMI phy.
*/
struct phy_configure_opts_hdmi {
unsigned long long tmds_char_rate;
+ unsigned int bpc;
};
#endif /* __PHY_HDMI_H_ */

View File

@ -0,0 +1,56 @@
From 6218c3fd6702a5bc4ab323fed25714cde127684c Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:39 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Drop unused struct lcpll_config
This is just a leftover from downstream support for HDMI 2.1.
Remove the unused struct for now.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-5-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -------------------
1 file changed, 31 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -329,37 +329,6 @@ enum dp_link_rate {
DP_BW_HBR2,
};
-struct lcpll_config {
- u32 bit_rate;
- u8 lcvco_mode_en;
- u8 pi_en;
- u8 clk_en_100m;
- u8 pms_mdiv;
- u8 pms_mdiv_afc;
- u8 pms_pdiv;
- u8 pms_refdiv;
- u8 pms_sdiv;
- u8 pi_cdiv_rstn;
- u8 pi_cdiv_sel;
- u8 sdm_en;
- u8 sdm_rstn;
- u8 sdc_frac_en;
- u8 sdc_rstn;
- u8 sdm_deno;
- u8 sdm_num_sign;
- u8 sdm_num;
- u8 sdc_n;
- u8 sdc_n2;
- u8 sdc_num;
- u8 sdc_deno;
- u8 sdc_ndiv_rstn;
- u8 ssc_en;
- u8 ssc_fm_dev;
- u8 ssc_fm_freq;
- u8 ssc_clk_div_sel;
- u8 cd_tx_ser_rate_sel;
-};
-
struct ropll_config {
u32 bit_rate;
u8 pms_mdiv;

View File

@ -0,0 +1,26 @@
From bcd61d182618c6a77d0841fcdc3333e125725360 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:40 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Drop unused phy_cfg driver data
There is no usage of phy_cfg in the upstream driver data, nor in the
downstream one, hence remove it.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-6-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -397,7 +397,6 @@ struct rk_hdptx_phy {
int phy_id;
struct phy *phy;
- struct phy_config *phy_cfg;
struct clk_bulk_data *clks;
int nr_clks;
struct reset_control_bulk_data rsts[RST_MAX];

View File

@ -0,0 +1,61 @@
From bacf2fe750dab6bc7ed50556aaadd3ab107fc643 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:41 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Drop superfluous cfgs driver
data
The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
but it is only used during probe() in order to setup ->phy_id.
Use a probe() local variable to store device match data and remove the
now unnecessary member from struct rk_hdptx_phy.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-7-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -392,10 +392,7 @@ struct rk_hdptx_phy {
struct regmap *regmap;
struct regmap *grf;
- /* PHY const config */
- const struct rk_hdptx_phy_cfg *cfgs;
int phy_id;
-
struct phy *phy;
struct clk_bulk_data *clks;
int nr_clks;
@@ -1896,6 +1893,7 @@ static int rk_hdptx_phy_runtime_resume(s
static int rk_hdptx_phy_probe(struct platform_device *pdev)
{
+ const struct rk_hdptx_phy_cfg *cfgs;
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct rk_hdptx_phy *hdptx;
@@ -1914,14 +1912,14 @@ static int rk_hdptx_phy_probe(struct pla
return dev_err_probe(dev, PTR_ERR(regs),
"Failed to ioremap resource\n");
- hdptx->cfgs = device_get_match_data(dev);
- if (!hdptx->cfgs)
+ cfgs = device_get_match_data(dev);
+ if (!cfgs)
return dev_err_probe(dev, -EINVAL, "missing match data\n");
/* find the phy-id from the io address */
hdptx->phy_id = -ENODEV;
- for (id = 0; id < hdptx->cfgs->num_phys; id++) {
- if (res->start == hdptx->cfgs->phy_ids[id]) {
+ for (id = 0; id < cfgs->num_phys; id++) {
+ if (res->start == cfgs->phy_ids[id]) {
hdptx->phy_id = id;
break;
}

View File

@ -0,0 +1,240 @@
From 0edf9d2bb9b4ba7566dfdc7605883e04575129d9 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:42 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit conversion
overhead
The ropll_tmds_cfg table used to identify the configuration params for
the supported rates expects the search key, i.e. bit_rate member of
struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
Hz). This requires multiple conversions between these units being
performed at runtime.
Improve implementation clarity and efficiency by consistently using the
Hz unit throughout driver's internal data structures and functions.
Also rename the rather misleading struct member.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-8-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++----------
1 file changed, 39 insertions(+), 40 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -330,7 +330,7 @@ enum dp_link_rate {
};
struct ropll_config {
- u32 bit_rate;
+ unsigned long long rate;
u8 pms_mdiv;
u8 pms_mdiv_afc;
u8 pms_pdiv;
@@ -410,47 +410,47 @@ struct rk_hdptx_phy {
};
static const struct ropll_config ropll_tmds_cfg[] = {
- { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 594000000ULL, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 371250000ULL, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 297000000ULL, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
+ { 162000000ULL, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 185625000ULL, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
+ { 154000000ULL, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
+ { 148500000ULL, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
+ { 146250000ULL, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
+ { 119000000ULL, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
+ { 106500000ULL, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ { 108000000ULL, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
+ { 85500000ULL, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
+ { 83500000ULL, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 92812500ULL, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ { 74250000ULL, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
+ { 65000000ULL, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 502500, 84, 84, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 11, 1, 4, 5,
+ { 50250000ULL, 84, 84, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 11, 1, 4, 5,
4, 11, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
+ { 33750000ULL, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ { 40000000ULL, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ { 27000000ULL, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
- { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
+ { 25175000ULL, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
};
@@ -896,10 +896,10 @@ static void rk_hdptx_phy_disable(struct
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
-static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
+static bool rk_hdptx_phy_clk_pll_calc(unsigned long long rate,
struct ropll_config *cfg)
{
- const unsigned int fout = data_rate / 2, fref = 24000;
+ const unsigned int fout = div_u64(rate, 200), fref = 24000;
unsigned long k = 0, lc, k_sub, lc_sub;
unsigned int fvco, sdc;
u32 mdiv, sdiv, n = 8;
@@ -969,14 +969,14 @@ static bool rk_hdptx_phy_clk_pll_calc(un
}
static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
- unsigned int rate)
+ unsigned long long rate)
{
const struct ropll_config *cfg = NULL;
struct ropll_config rc = {0};
int ret, i;
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
- if (rate == ropll_tmds_cfg[i].bit_rate) {
+ if (rate == ropll_tmds_cfg[i].rate) {
cfg = &ropll_tmds_cfg[i];
break;
}
@@ -990,8 +990,8 @@ static int rk_hdptx_ropll_tmds_cmn_confi
}
}
- dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
- cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
+ dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
+ __func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
rk_hdptx_pre_power_up(hdptx);
@@ -1030,19 +1030,19 @@ static int rk_hdptx_ropll_tmds_cmn_confi
ret = rk_hdptx_post_enable_pll(hdptx);
if (!ret)
- hdptx->rate = rate * 100;
+ hdptx->rate = rate;
return ret;
}
static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
- unsigned int rate)
+ unsigned long long rate)
{
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
- if (rate > HDMI14_MAX_RATE / 100) {
+ if (rate > HDMI14_MAX_RATE) {
/* For 1/40 bitrate clk */
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
} else {
@@ -1095,7 +1095,7 @@ static void rk_hdptx_dp_reset(struct rk_
}
static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
- unsigned int rate)
+ unsigned long long rate)
{
enum phy_mode mode = phy_get_mode(hdptx->phy);
u32 status;
@@ -1413,8 +1413,8 @@ static int rk_hdptx_dp_aux_init(struct r
static int rk_hdptx_phy_power_on(struct phy *phy)
{
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
- int bus_width = phy_get_bus_width(hdptx->phy);
enum phy_mode mode = phy_get_mode(phy);
+ unsigned long long rate;
int ret, lane;
/*
@@ -1422,10 +1422,10 @@ static int rk_hdptx_phy_power_on(struct
* from the HDMI bridge driver until phy_configure_opts_hdmi
* becomes available in the PHY API.
*/
- unsigned int rate = bus_width & 0xfffffff;
+ rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+ rate *= 100;
- dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
- __func__, bus_width, rate);
+ dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, rate);
ret = rk_hdptx_phy_consumer_get(hdptx, rate);
if (ret)
@@ -1787,7 +1787,7 @@ static int rk_hdptx_phy_clk_prepare(stru
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
+ return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
}
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1808,18 +1808,17 @@ static unsigned long rk_hdptx_phy_clk_re
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- u32 bit_rate = rate / 100;
int i;
if (rate > HDMI20_MAX_RATE)
return rate;
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
- if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+ if (rate == ropll_tmds_cfg[i].rate)
break;
if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
- !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+ !rk_hdptx_phy_clk_pll_calc(rate, NULL))
return -EINVAL;
return rate;
@@ -1830,7 +1829,7 @@ static int rk_hdptx_phy_clk_set_rate(str
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
}
static const struct clk_ops hdptx_phy_clk_ops = {

View File

@ -0,0 +1,131 @@
From c871a311edf0ebb1b934946a84a6c532cac0c035 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:43 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Setup TMDS char rate via
phy_configure_opts_hdmi
The current workaround to setup the TMDS character rate relies on the
unconventional usage of phy_set_bus_width().
Make use of the recently introduced HDMI PHY configuration API to
properly handle the setup. The workaround will be dropped as soon as
the switch has been completed on both ends.
Rename rk_hdptx_phy_verify_config() to rk_hdptx_phy_verify_dp_config()
and introduce the rk_hdptx_phy_verify_hdmi_config() helper to check the
HDMI parameters during phy_configure().
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-9-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 64 ++++++++++++++-----
1 file changed, 47 insertions(+), 17 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -394,6 +394,7 @@ struct rk_hdptx_phy {
int phy_id;
struct phy *phy;
+ struct phy_configure_opts_hdmi hdmi_cfg;
struct clk_bulk_data *clks;
int nr_clks;
struct reset_control_bulk_data rsts[RST_MAX];
@@ -1414,20 +1415,24 @@ static int rk_hdptx_phy_power_on(struct
{
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
enum phy_mode mode = phy_get_mode(phy);
- unsigned long long rate;
int ret, lane;
- /*
- * FIXME: Temporary workaround to pass pixel_clk_rate
- * from the HDMI bridge driver until phy_configure_opts_hdmi
- * becomes available in the PHY API.
- */
- rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
- rate *= 100;
+ if (mode != PHY_MODE_DP) {
+ if (!hdptx->hdmi_cfg.tmds_char_rate) {
+ /*
+ * FIXME: Temporary workaround to setup TMDS char rate
+ * from the RK DW HDMI QP bridge driver.
+ * Will be removed as soon the switch to the HDMI PHY
+ * configuration API has been completed on both ends.
+ */
+ hdptx->hdmi_cfg.tmds_char_rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
+ hdptx->hdmi_cfg.tmds_char_rate *= 100;
+ }
- dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, rate);
+ dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+ }
- ret = rk_hdptx_phy_consumer_get(hdptx, rate);
+ ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
if (ret)
return ret;
@@ -1458,7 +1463,7 @@ static int rk_hdptx_phy_power_on(struct
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
}
@@ -1473,8 +1478,27 @@ static int rk_hdptx_phy_power_off(struct
return rk_hdptx_phy_consumer_put(hdptx, false);
}
-static int rk_hdptx_phy_verify_config(struct rk_hdptx_phy *hdptx,
- struct phy_configure_opts_dp *dp)
+static int rk_hdptx_phy_verify_hdmi_config(struct rk_hdptx_phy *hdptx,
+ struct phy_configure_opts_hdmi *hdmi)
+{
+ int i;
+
+ if (!hdmi->tmds_char_rate || hdmi->tmds_char_rate > HDMI20_MAX_RATE)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+ if (hdmi->tmds_char_rate == ropll_tmds_cfg[i].rate)
+ break;
+
+ if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
+ !rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int rk_hdptx_phy_verify_dp_config(struct rk_hdptx_phy *hdptx,
+ struct phy_configure_opts_dp *dp)
{
int i;
@@ -1734,12 +1758,18 @@ static int rk_hdptx_phy_configure(struct
enum phy_mode mode = phy_get_mode(phy);
int ret;
- if (mode != PHY_MODE_DP)
- return 0;
+ if (mode != PHY_MODE_DP) {
+ ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+ if (ret)
+ dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
+ else
+ hdptx->hdmi_cfg = opts->hdmi;
+ return ret;
+ }
- ret = rk_hdptx_phy_verify_config(hdptx, &opts->dp);
+ ret = rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
if (ret) {
- dev_err(hdptx->dev, "invalid params for phy configure\n");
+ dev_err(hdptx->dev, "invalid dp params for phy configure\n");
return ret;
}

View File

@ -0,0 +1,42 @@
From 2392050a2cb94ff3397949e109e4b9f0285ee085 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:44 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Provide config params
validation support
Implement the phy_ops.validate() callback to allow checking the PHY
configuration parameters without actually applying them.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-10-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1801,10 +1801,22 @@ static int rk_hdptx_phy_configure(struct
return 0;
}
+static int rk_hdptx_phy_validate(struct phy *phy, enum phy_mode mode,
+ int submode, union phy_configure_opts *opts)
+{
+ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+
+ if (mode != PHY_MODE_DP)
+ return rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
+
+ return rk_hdptx_phy_verify_dp_config(hdptx, &opts->dp);
+}
+
static const struct phy_ops rk_hdptx_phy_ops = {
.power_on = rk_hdptx_phy_power_on,
.power_off = rk_hdptx_phy_power_off,
.configure = rk_hdptx_phy_configure,
+ .validate = rk_hdptx_phy_validate,
.owner = THIS_MODULE,
};

View File

@ -0,0 +1,129 @@
From 6efbd0f46dd8ae1d2b91b41d98c2800c60ab1f5e Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:45 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Restrict altering TMDS char
rate via CCF
Although, in theory, the clock provider functionality could be enabled
as a standalone driver feature, in practice it is unlikely that it would
be ever needed separately from the common PHY related features, i.e.
making use of the PHY PLL as an alternative and more accurate clock
source for display modes handling. Which means the PLL will be always
programmed according to the TMDS char rate set via the HDMI PHY
configuration API.
Currently it's possible to freely adjust the rate via the clock API as
well, that is through clk_set_rate(). Making the clock read-only is not
feasible since we need to ensure any rate update done via the PHY
configuration API has been actually programmed into the hardware before
CCF accesses it. This would be normally done during phy_ops.power_on()
or clk_ops.prepare() callbacks, but it might happen that the former gets
fired too late and the latter only once, hence we need to keep handle it
via clk_ops.set_rate() as a fallback approach.
Prevent changing the TMDS character rate via CCF by letting
rk_hdptx_phy_clk_round_rate() always return the value set via
phy_configure(). To avoid breaking existing users, i.e. RK DW HDMI QP
bridge driver, until the switch to the HDMI PHY config based approach is
completed, introduce a temporary exception to the rule, toggled via the
new ->restrict_rate_change flag, which indicates whether phy_configure()
has been called or not.
Additionally, revert any unlikely rate change that might have occurred
between the calls to ->round_rate() and ->set_rate().
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-11-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 52 ++++++++++++++-----
1 file changed, 40 insertions(+), 12 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -402,6 +402,7 @@ struct rk_hdptx_phy {
/* clk provider */
struct clk_hw hw;
unsigned long rate;
+ bool restrict_rate_change;
atomic_t usage_count;
@@ -1760,10 +1761,12 @@ static int rk_hdptx_phy_configure(struct
if (mode != PHY_MODE_DP) {
ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &opts->hdmi);
- if (ret)
+ if (ret) {
dev_err(hdptx->dev, "invalid hdmi params for phy configure\n");
- else
+ } else {
hdptx->hdmi_cfg = opts->hdmi;
+ hdptx->restrict_rate_change = true;
+ }
return ret;
}
@@ -1850,20 +1853,31 @@ static unsigned long rk_hdptx_phy_clk_re
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- int i;
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- if (rate > HDMI20_MAX_RATE)
- return rate;
+ /*
+ * FIXME: Temporarily allow altering TMDS char rate via CCF.
+ * To be dropped as soon as the RK DW HDMI QP bridge driver
+ * switches to make use of phy_configure().
+ */
+ if (!hdptx->restrict_rate_change && rate != hdptx->hdmi_cfg.tmds_char_rate) {
+ struct phy_configure_opts_hdmi hdmi = {
+ .tmds_char_rate = rate,
+ };
+ int ret = rk_hdptx_phy_verify_hdmi_config(hdptx, &hdmi);
- for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
- if (rate == ropll_tmds_cfg[i].rate)
- break;
+ if (ret)
+ return ret;
- if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
- !rk_hdptx_phy_clk_pll_calc(rate, NULL))
- return -EINVAL;
+ hdptx->hdmi_cfg = hdmi;
+ }
- return rate;
+ /*
+ * The TMDS char rate shall be adjusted via phy_configure() only,
+ * hence ensure rk_hdptx_phy_clk_set_rate() won't be invoked with
+ * a different rate argument.
+ */
+ return hdptx->hdmi_cfg.tmds_char_rate;
}
static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1871,6 +1885,20 @@ static int rk_hdptx_phy_clk_set_rate(str
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+ /* Revert any unlikely TMDS char rate change since round_rate() */
+ if (hdptx->hdmi_cfg.tmds_char_rate != rate) {
+ dev_warn(hdptx->dev, "Reverting unexpected rate change from %lu to %llu\n",
+ rate, hdptx->hdmi_cfg.tmds_char_rate);
+ hdptx->hdmi_cfg.tmds_char_rate = rate;
+ }
+
+ /*
+ * The TMDS char rate would be normally programmed in HW during
+ * phy_ops.power_on() or clk_ops.prepare() callbacks, but it might
+ * happen that the former gets fired too late, i.e. after this call,
+ * while the latter being executed only once, i.e. when clock remains
+ * in the prepared state during rate changes.
+ */
return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
}

View File

@ -0,0 +1,58 @@
From 37f335dbfd028c008d0a7940ca5a270d1e2f6b81 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:46 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Rename ambiguous
rk_hdptx_phy->rate
The main purpose of the ->rate member of struct rk_hdptx_phy is to
implement rk_hdptx_phy_clk_recalc_rate() by providing the actual rate
programmed in hardware. Hence the current naming is too generic and
rather ambiguous.
Improve clarity by renaming ->rate to ->hw_rate.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-12-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -401,7 +401,7 @@ struct rk_hdptx_phy {
/* clk provider */
struct clk_hw hw;
- unsigned long rate;
+ unsigned long hw_rate;
bool restrict_rate_change;
atomic_t usage_count;
@@ -1032,7 +1032,7 @@ static int rk_hdptx_ropll_tmds_cmn_confi
ret = rk_hdptx_post_enable_pll(hdptx);
if (!ret)
- hdptx->rate = rate;
+ hdptx->hw_rate = rate;
return ret;
}
@@ -1832,7 +1832,7 @@ static int rk_hdptx_phy_clk_prepare(stru
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
+ return rk_hdptx_phy_consumer_get(hdptx, hdptx->hw_rate);
}
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1847,7 +1847,7 @@ static unsigned long rk_hdptx_phy_clk_re
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- return hdptx->rate;
+ return hdptx->hw_rate;
}
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,

View File

@ -0,0 +1,147 @@
From 45b14bdcf4acfd483d9890396197c35c23821124 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:47 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Optimize internal rate handling
Drop the rate parameter from a bunch of internal helpers and, instead,
make better use of the newly introduced ->hdmi_cfg.tmds_char_rate driver
data.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Acked-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-13-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 47 +++++++++----------
1 file changed, 23 insertions(+), 24 deletions(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -970,31 +970,34 @@ static bool rk_hdptx_phy_clk_pll_calc(un
return true;
}
-static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
- unsigned long long rate)
+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx)
{
const struct ropll_config *cfg = NULL;
struct ropll_config rc = {0};
int ret, i;
+ if (!hdptx->hdmi_cfg.tmds_char_rate)
+ return 0;
+
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
- if (rate == ropll_tmds_cfg[i].rate) {
+ if (hdptx->hdmi_cfg.tmds_char_rate == ropll_tmds_cfg[i].rate) {
cfg = &ropll_tmds_cfg[i];
break;
}
if (!cfg) {
- if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
- cfg = &rc;
- } else {
- dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+ if (!rk_hdptx_phy_clk_pll_calc(hdptx->hdmi_cfg.tmds_char_rate, &rc)) {
+ dev_err(hdptx->dev, "%s cannot find pll cfg for rate=%llu\n",
+ __func__, hdptx->hdmi_cfg.tmds_char_rate);
return -EINVAL;
}
+
+ cfg = &rc;
}
dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
- __func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
- cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
+ __func__, hdptx->hdmi_cfg.tmds_char_rate, cfg->pms_mdiv, cfg->pms_sdiv + 1,
+ cfg->sdm_en, cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
rk_hdptx_pre_power_up(hdptx);
@@ -1032,19 +1035,18 @@ static int rk_hdptx_ropll_tmds_cmn_confi
ret = rk_hdptx_post_enable_pll(hdptx);
if (!ret)
- hdptx->hw_rate = rate;
+ hdptx->hw_rate = hdptx->hdmi_cfg.tmds_char_rate;
return ret;
}
-static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
- unsigned long long rate)
+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx)
{
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
- if (rate > HDMI14_MAX_RATE) {
+ if (hdptx->hdmi_cfg.tmds_char_rate > HDMI14_MAX_RATE) {
/* For 1/40 bitrate clk */
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
} else {
@@ -1096,8 +1098,7 @@ static void rk_hdptx_dp_reset(struct rk_
HDPTX_I_BGR_EN << 16 | FIELD_PREP(HDPTX_I_BGR_EN, 0x0));
}
-static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
- unsigned long long rate)
+static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx)
{
enum phy_mode mode = phy_get_mode(hdptx->phy);
u32 status;
@@ -1116,11 +1117,9 @@ static int rk_hdptx_phy_consumer_get(str
if (mode == PHY_MODE_DP) {
rk_hdptx_dp_reset(hdptx);
} else {
- if (rate) {
- ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
- if (ret)
- goto dec_usage;
- }
+ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx);
+ if (ret)
+ goto dec_usage;
}
return 0;
@@ -1433,7 +1432,7 @@ static int rk_hdptx_phy_power_on(struct
dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
}
- ret = rk_hdptx_phy_consumer_get(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+ ret = rk_hdptx_phy_consumer_get(hdptx);
if (ret)
return ret;
@@ -1464,7 +1463,7 @@ static int rk_hdptx_phy_power_on(struct
regmap_write(hdptx->grf, GRF_HDPTX_CON0,
HDPTX_MODE_SEL << 16 | FIELD_PREP(HDPTX_MODE_SEL, 0x0));
- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, hdptx->hdmi_cfg.tmds_char_rate);
+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx);
if (ret)
rk_hdptx_phy_consumer_put(hdptx, true);
}
@@ -1832,7 +1831,7 @@ static int rk_hdptx_phy_clk_prepare(stru
{
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
- return rk_hdptx_phy_consumer_get(hdptx, hdptx->hw_rate);
+ return rk_hdptx_phy_consumer_get(hdptx);
}
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
@@ -1899,7 +1898,7 @@ static int rk_hdptx_phy_clk_set_rate(str
* while the latter being executed only once, i.e. when clock remains
* in the prepared state during rate changes.
*/
- return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
+ return rk_hdptx_ropll_tmds_cmn_config(hdptx);
}
static const struct clk_ops hdptx_phy_clk_ops = {

View File

@ -0,0 +1,76 @@
From 9d0ec51d7c227c3ae837e22832eaed219e25f126 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 18 Mar 2025 14:35:48 +0200
Subject: [PATCH] phy: rockchip: samsung-hdptx: Add high color depth management
Add support for 8-bit, 10-bit, 12-bit and 16-bit color depth setup.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Reviewed-by: Dmitry Baryshkov <dmtiry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-14-8cb1678e7663@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 23 ++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1030,6 +1030,9 @@ static int rk_hdptx_ropll_tmds_cmn_confi
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, (hdptx->hdmi_cfg.bpc - 8) >> 1));
+
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
@@ -1429,7 +1432,8 @@ static int rk_hdptx_phy_power_on(struct
hdptx->hdmi_cfg.tmds_char_rate *= 100;
}
- dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, hdptx->hdmi_cfg.tmds_char_rate);
+ dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+ hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
}
ret = rk_hdptx_phy_consumer_get(hdptx);
@@ -1494,6 +1498,19 @@ static int rk_hdptx_phy_verify_hdmi_conf
!rk_hdptx_phy_clk_pll_calc(hdmi->tmds_char_rate, NULL))
return -EINVAL;
+ if (!hdmi->bpc)
+ hdmi->bpc = 8;
+
+ switch (hdmi->bpc) {
+ case 8:
+ case 10:
+ case 12:
+ case 16:
+ break;
+ default:
+ return -EINVAL;
+ };
+
return 0;
}
@@ -1766,6 +1783,9 @@ static int rk_hdptx_phy_configure(struct
hdptx->hdmi_cfg = opts->hdmi;
hdptx->restrict_rate_change = true;
}
+
+ dev_dbg(hdptx->dev, "%s rate=%llu bpc=%u\n", __func__,
+ hdptx->hdmi_cfg.tmds_char_rate, hdptx->hdmi_cfg.bpc);
return ret;
}
@@ -1974,6 +1994,7 @@ static int rk_hdptx_phy_probe(struct pla
return -ENOMEM;
hdptx->dev = dev;
+ hdptx->hdmi_cfg.bpc = 8;
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs))

View File

@ -0,0 +1,68 @@
From f855146263b14abadd8d5bd0e280e54fbab3bd18 Mon Sep 17 00:00:00 2001
From: Damon Ding <damon.ding@rock-chips.com>
Date: Mon, 10 Mar 2025 18:41:10 +0800
Subject: [PATCH] dt-bindings: display: rockchip: analogix-dp: Add support for
RK3588
Compared with RK3288/RK3399, the HBR2 link rate support is the main
improvement of RK3588 eDP TX controller, and there are also two
independent eDP display interfaces on RK3588 Soc.
The newly added 'apb' reset is to ensure the APB bus of eDP controller
works well on the RK3588 SoC.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Link: https://lore.kernel.org/r/20250310104114.2608063-10-damon.ding@rock-chips.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../rockchip/rockchip,analogix-dp.yaml | 22 +++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,analogix-dp.yaml
@@ -15,6 +15,7 @@ properties:
enum:
- rockchip,rk3288-dp
- rockchip,rk3399-edp
+ - rockchip,rk3588-edp
clocks:
minItems: 2
@@ -31,10 +32,14 @@ properties:
maxItems: 1
resets:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
reset-names:
- const: dp
+ minItems: 1
+ items:
+ - const: dp
+ - const: apb
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -52,6 +57,19 @@ required:
allOf:
- $ref: /schemas/display/bridge/analogix,dp.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3588-edp
+ then:
+ properties:
+ resets:
+ minItems: 2
+ reset-names:
+ minItems: 2
+
unevaluatedProperties: false
examples:

View File

@ -0,0 +1,92 @@
From 3303a206ae7474b2f8a5d17d8df9de08bac16ca5 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 8 Sep 2024 14:54:58 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Filter modes based on hdmiphy_clk
RK3228 and RK3328 clock rate is being validated against a mpll config
table intended for a Synopsys phy, and not the used inno-hdmi-phy.
Instead get a reference to the hdmiphy clk and validate rates against
it to enable use of HDMI2.0 modes, e.g. 4K@60Hz, on RK3228 and RK3328.
For Synopsis phy the max_tmds_clock validation is sufficient.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Tested-by: Diederik de Haas <didi.debian@cknow.org> # Rock64
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-2-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 35 ++++++++++-----------
1 file changed, 17 insertions(+), 18 deletions(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -76,6 +76,7 @@ struct rockchip_hdmi {
struct rockchip_encoder encoder;
const struct rockchip_hdmi_chip_data *chip_data;
const struct dw_hdmi_plat_data *plat_data;
+ struct clk *hdmiphy_clk;
struct clk *ref_clk;
struct clk *grf_clk;
struct dw_hdmi *hdmi;
@@ -251,10 +252,7 @@ dw_hdmi_rockchip_mode_valid(struct dw_hd
const struct drm_display_mode *mode)
{
struct rockchip_hdmi *hdmi = data;
- const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
int pclk = mode->clock * 1000;
- bool exact_match = hdmi->plat_data->phy_force_vendor;
- int i;
if (hdmi->chip_data->max_tmds_clock &&
mode->clock > hdmi->chip_data->max_tmds_clock)
@@ -263,26 +261,18 @@ dw_hdmi_rockchip_mode_valid(struct dw_hd
if (hdmi->ref_clk) {
int rpclk = clk_round_rate(hdmi->ref_clk, pclk);
- if (abs(rpclk - pclk) > pclk / 1000)
+ if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
return MODE_NOCLOCK;
}
- for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
- /*
- * For vendor specific phys force an exact match of the pixelclock
- * to preserve the original behaviour of the driver.
- */
- if (exact_match && pclk == mpll_cfg[i].mpixelclock)
- return MODE_OK;
- /*
- * The Synopsys phy can work with pixelclocks up to the value given
- * in the corresponding mpll_cfg entry.
- */
- if (!exact_match && pclk <= mpll_cfg[i].mpixelclock)
- return MODE_OK;
+ if (hdmi->hdmiphy_clk) {
+ int rpclk = clk_round_rate(hdmi->hdmiphy_clk, pclk);
+
+ if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000)
+ return MODE_NOCLOCK;
}
- return MODE_BAD;
+ return MODE_OK;
}
static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
@@ -607,6 +597,15 @@ static int dw_hdmi_rockchip_bind(struct
return ret;
}
+ if (hdmi->phy) {
+ struct of_phandle_args clkspec;
+
+ clkspec.np = hdmi->phy->dev.of_node;
+ hdmi->hdmiphy_clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(hdmi->hdmiphy_clk))
+ hdmi->hdmiphy_clk = NULL;
+ }
+
if (hdmi->chip_data == &rk3568_chip_data) {
regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |

View File

@ -0,0 +1,53 @@
From 6e94e2871eb706a17692acf7ef85ecf2789f6433 Mon Sep 17 00:00:00 2001
From: Yakir Yang <ykk@rock-chips.com>
Date: Sun, 8 Sep 2024 14:54:59 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Adjust cklvl & txlvl for RF/EMI
Dut to the high HDMI signal voltage driver, Mickey have meet
a serious RF/EMI problem, so we decided to reduce HDMI signal
voltage to a proper value.
The default params for phy is cklvl = 20 & txlvl = 13 (RF/EMI failed)
ck: lvl = 13, term=100, vlo = 2.71, vhi=3.14, vswing = 0.43
tx: lvl = 20, term=100, vlo = 2.81, vhi=3.16, vswing = 0.35
1. We decided to reduce voltage value to lower, but VSwing still
keep high, RF/EMI have been improved but still failed.
ck: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50
tx: lvl = 6, term=100, vlo = 2.61, vhi=3.11, vswing = 0.50
2. We try to keep voltage value and vswing both lower, then RF/EMI
test all passed ;)
ck: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
tx: lvl = 11, term= 66, vlo = 2.68, vhi=3.09, vswing = 0.40
When we back to run HDMI different test and single-end test, we see
different test passed, but signle-end test failed. The oscilloscope
show that simgle-end clock's VL value is 1.78v (which remind LowLimit
should not lower then 2.6v).
3. That's to say there are some different between PHY document and
measure value. And according to experiment 2 results, we need to
higher clock voltage and lower data voltage, then we can keep RF/EMI
satisfied and single-end & differen test passed.
ck: lvl = 9, term=100, vlo = 2.65, vhi=3.12, vswing = 0.47
tx: lvl = 16, term=100, vlo = 2.75, vhi=3.15, vswing = 0.39
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-3-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -202,7 +202,7 @@ static const struct dw_hdmi_curr_ctrl ro
static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
/*pixelclk symbol term vlev*/
{ 74250000, 0x8009, 0x0004, 0x0272},
- { 148500000, 0x802b, 0x0004, 0x028d},
+ { 165000000, 0x802b, 0x0004, 0x0209},
{ 297000000, 0x8039, 0x0005, 0x028d},
{ ~0UL, 0x0000, 0x0000, 0x0000}
};

View File

@ -0,0 +1,25 @@
From b60c86d305f46483d3ed0743e9ec97a76addcabc Mon Sep 17 00:00:00 2001
From: Nickey Yang <nickey.yang@rock-chips.com>
Date: Sun, 8 Sep 2024 14:55:00 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Add phy_config for 594Mhz pixel clock
Add phy_config for 594Mhz pixel clock used for HDMI2.0 display modes.
Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-4-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -204,6 +204,7 @@ static const struct dw_hdmi_phy_config r
{ 74250000, 0x8009, 0x0004, 0x0272},
{ 165000000, 0x802b, 0x0004, 0x0209},
{ 297000000, 0x8039, 0x0005, 0x028d},
+ { 594000000, 0x8039, 0x0000, 0x019d},
{ ~0UL, 0x0000, 0x0000, 0x0000}
};

View File

@ -0,0 +1,46 @@
From 7d324630f3515bd6e11cadeb1d748bd74ecc9664 Mon Sep 17 00:00:00 2001
From: Douglas Anderson <dianders@chromium.org>
Date: Sun, 8 Sep 2024 14:55:01 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Set cur_ctr to 0 always
Jitter was improved by lowering the MPLL bandwidth to account for high
frequency noise in the rk3288 PLL. In each case MPLL bandwidth was
lowered only enough to get us a comfortable margin. We believe that
lowering the bandwidth like this is safe given sufficient testing.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-5-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -179,23 +179,9 @@ static const struct dw_hdmi_mpll_config
static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
/* pixelclk bpp8 bpp10 bpp12 */
{
- 40000000, { 0x0018, 0x0018, 0x0018 },
- }, {
- 65000000, { 0x0028, 0x0028, 0x0028 },
- }, {
- 66000000, { 0x0038, 0x0038, 0x0038 },
- }, {
- 74250000, { 0x0028, 0x0038, 0x0038 },
- }, {
- 83500000, { 0x0028, 0x0038, 0x0038 },
- }, {
- 146250000, { 0x0038, 0x0038, 0x0038 },
- }, {
- 148500000, { 0x0000, 0x0038, 0x0038 },
- }, {
600000000, { 0x0000, 0x0000, 0x0000 },
}, {
- ~0UL, { 0x0000, 0x0000, 0x0000},
+ ~0UL, { 0x0000, 0x0000, 0x0000 },
}
};

View File

@ -0,0 +1,173 @@
From 7595c7ef17ffe70d0f4fdda01f87f105a12de66b Mon Sep 17 00:00:00 2001
From: Douglas Anderson <dianders@chromium.org>
Date: Sun, 8 Sep 2024 14:55:02 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Use auto-generated tables
The previous tables for mpll_cfg and curr_ctrl were created using the
20-pages of example settings provided by the PHY vendor. Those
example settings weren't particularly dense, so there were places
where we were guessing what the settings would be for 10-bit and
12-bit (not that we use those anyway). It was also always a lot of
extra work every time we wanted to add a new clock rate since we had
to cross-reference several tables.
In <https://crrev.com/c/285855> I've gone through the work to figure
out how to generate this table automatically. Let's now use the
automatically generated table and then we'll never need to look at it
again.
We only support 8-bit mode right now and only support a small number
of clock rates and I've verified that the only 8-bit rate that was
affected was 148.5. That mode appears to have been wrong in the old
table.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-6-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 104 ++++++++++----------
1 file changed, 53 insertions(+), 51 deletions(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -92,74 +92,70 @@ static struct rockchip_hdmi *to_rockchip
static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
{
- 27000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 30666000, {
+ { 0x00b3, 0x0000 },
+ { 0x2153, 0x0000 },
+ { 0x40f3, 0x0000 },
},
}, {
- 36000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 36800000, {
+ { 0x00b3, 0x0000 },
+ { 0x2153, 0x0000 },
+ { 0x40a2, 0x0001 },
},
}, {
- 40000000, {
- { 0x00b3, 0x0000},
- { 0x2153, 0x0000},
- { 0x40f3, 0x0000}
+ 46000000, {
+ { 0x00b3, 0x0000 },
+ { 0x2142, 0x0001 },
+ { 0x40a2, 0x0001 },
},
}, {
- 54000000, {
- { 0x0072, 0x0001},
- { 0x2142, 0x0001},
- { 0x40a2, 0x0001},
+ 61333000, {
+ { 0x0072, 0x0001 },
+ { 0x2142, 0x0001 },
+ { 0x40a2, 0x0001 },
},
}, {
- 65000000, {
- { 0x0072, 0x0001},
- { 0x2142, 0x0001},
- { 0x40a2, 0x0001},
+ 73600000, {
+ { 0x0072, 0x0001 },
+ { 0x2142, 0x0001 },
+ { 0x4061, 0x0002 },
},
}, {
- 66000000, {
- { 0x013e, 0x0003},
- { 0x217e, 0x0002},
- { 0x4061, 0x0002}
+ 92000000, {
+ { 0x0072, 0x0001 },
+ { 0x2145, 0x0002 },
+ { 0x4061, 0x0002 },
},
}, {
- 74250000, {
- { 0x0072, 0x0001},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 122666000, {
+ { 0x0051, 0x0002 },
+ { 0x2145, 0x0002 },
+ { 0x4061, 0x0002 },
},
}, {
- 83500000, {
- { 0x0072, 0x0001},
+ 147200000, {
+ { 0x0051, 0x0002 },
+ { 0x2145, 0x0002 },
+ { 0x4064, 0x0003 },
},
}, {
- 108000000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 184000000, {
+ { 0x0051, 0x0002 },
+ { 0x214c, 0x0003 },
+ { 0x4064, 0x0003 },
},
}, {
- 106500000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
- },
- }, {
- 146250000, {
- { 0x0051, 0x0002},
- { 0x2145, 0x0002},
- { 0x4061, 0x0002}
+ 226666000, {
+ { 0x0040, 0x0003 },
+ { 0x214c, 0x0003 },
+ { 0x4064, 0x0003 },
},
}, {
- 148500000, {
- { 0x0051, 0x0003},
- { 0x214c, 0x0003},
- { 0x4064, 0x0003}
+ 272000000, {
+ { 0x0040, 0x0003 },
+ { 0x214c, 0x0003 },
+ { 0x5a64, 0x0003 },
},
}, {
340000000, {
@@ -168,10 +164,16 @@ static const struct dw_hdmi_mpll_config
{ 0x5a64, 0x0003 },
},
}, {
+ 600000000, {
+ { 0x1a40, 0x0003 },
+ { 0x3b4c, 0x0003 },
+ { 0x5a64, 0x0003 },
+ },
+ }, {
~0UL, {
- { 0x00a0, 0x000a },
- { 0x2001, 0x000f },
- { 0x4002, 0x000f },
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
+ { 0x0000, 0x0000 },
},
}
};

View File

@ -0,0 +1,37 @@
From 28f0ae48e7fdbd6cdcf3972c8d8686a529ae1ede Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 8 Sep 2024 14:55:03 +0000
Subject: [PATCH] drm/rockchip: dw_hdmi: Enable 4K@60Hz mode on RK3399 and
RK356x
Use a maximum TMDS clock rate limit of 594MHz to enable use of HDMI2.0
modes, e.g. 4K@60Hz, on RK3399 and RK3568.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Tested-by: Diederik de Haas <didi.debian@cknow.org> # Quartz64 Model B
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-7-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -481,7 +481,7 @@ static struct rockchip_hdmi_chip_data rk
.lcdsel_grf_reg = RK3399_GRF_SOC_CON20,
.lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL),
.lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL),
- .max_tmds_clock = 340000,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
@@ -495,7 +495,7 @@ static const struct dw_hdmi_plat_data rk
static struct rockchip_hdmi_chip_data rk3568_chip_data = {
.lcdsel_grf_reg = -1,
- .max_tmds_clock = 340000,
+ .max_tmds_clock = 594000,
};
static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {

View File

@ -0,0 +1,59 @@
From 0c4558a1bc2df9b6e6fb311de9cab192b0943426 Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
Date: Sun, 8 Sep 2024 14:55:04 +0000
Subject: [PATCH] drm/rockchip: Load crtc devices in preferred order
On RK3399 the VOPL is loaded before VOPB and get registered as crtc-0.
However, on RK3288 and PX30 VOPB is gets registered as crtc-0 instead of
VOPL.
With VOPL registered as crtc-0 the kernel kms client is not able to
enable 4K display modes for console use on RK3399.
Load VOPB before VOPL to help kernel kms client make use of 4K display
modes for console use on RK3399.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240908145511.3331451-8-jonas@kwiboo.se
---
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 23 +++++++++++++++++++++
1 file changed, 23 insertions(+)
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -358,11 +358,34 @@ static void rockchip_drm_match_remove(st
device_link_del(link);
}
+/* list of preferred vop devices */
+static const char *const rockchip_drm_match_preferred[] = {
+ "rockchip,rk3399-vop-big",
+ NULL,
+};
+
static struct component_match *rockchip_drm_match_add(struct device *dev)
{
struct component_match *match = NULL;
+ struct device_node *port;
int i;
+ /* add preferred vop device match before adding driver device matches */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (of_device_is_available(port->parent) &&
+ of_device_compatible_match(port->parent,
+ rockchip_drm_match_preferred))
+ drm_of_component_match_add(dev, &match,
+ component_compare_of,
+ port->parent);
+
+ of_node_put(port);
+ }
+
for (i = 0; i < num_rockchip_sub_drivers; i++) {
struct platform_driver *drv = rockchip_sub_drivers[i];
struct device *p = NULL, *d;

View File

@ -0,0 +1,63 @@
From 905df8f19e1a7042ddeae1e39d0920b60dfe8c0d Mon Sep 17 00:00:00 2001
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: Tue, 24 Sep 2024 09:12:35 +0200
Subject: [PATCH] drm/rockchip: Run DRM default client setup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Call drm_client_setup() to run the kernel's default client setup
for DRM. Set fbdev_probe in struct drm_driver, so that the client
setup can start the common fbdev client.
v5:
- select DRM_CLIENT_SELECTION
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Sandy Huang <hjc@rock-chips.com>
Cc: "Heiko St¡§1bner" <heiko@sntech.de>
Cc: Andy Yan <andy.yan@rock-chips.com>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240924071734.98201-38-tzimmermann@suse.de
---
drivers/gpu/drm/rockchip/Kconfig | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -2,6 +2,7 @@
config DRM_ROCKCHIP
tristate "DRM Support for Rockchip"
depends on DRM && ROCKCHIP_IOMMU
+ select DRM_CLIENT_SELECTION
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_PANEL
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -17,6 +17,7 @@
#include <linux/iommu.h>
#include <drm/drm_aperture.h>
+#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
@@ -195,7 +196,7 @@ static int rockchip_drm_bind(struct devi
if (ret)
goto err_kms_helper_poll_fini;
- drm_fbdev_dma_setup(drm_dev, 0);
+ drm_client_setup(drm_dev, NULL);
return 0;
err_kms_helper_poll_fini:
@@ -230,6 +231,7 @@ static const struct drm_driver rockchip_
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
.dumb_create = rockchip_gem_dumb_create,
.gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
+ DRM_FBDEV_DMA_DRIVER_OPS,
.fops = &rockchip_drm_driver_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,

View File

@ -0,0 +1,511 @@
From 128a9bf8ace290d86d2805c06f3b0e4cfab75de0 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Wed, 16 Oct 2024 23:06:53 +0300
Subject: [PATCH] drm/rockchip: Add basic RK3588 HDMI output support
The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
Samsung IP block.
Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
without audio, CEC or any of the HDMI 2.1 specific features.
Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241016-b4-rk3588-bridge-upstream-v10-3-87ef92a6d14e@collabora.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
drivers/gpu/drm/rockchip/Kconfig | 9 +
drivers/gpu/drm/rockchip/Makefile | 1 +
.../gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 424 ++++++++++++++++++
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +
drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 +
5 files changed, 437 insertions(+)
create mode 100644 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -9,6 +9,7 @@ config DRM_ROCKCHIP
select VIDEOMODE_HELPERS
select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
+ select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
@@ -64,6 +65,14 @@ config ROCKCHIP_DW_HDMI
enable HDMI on RK3288 or RK3399 based SoC, you should select
this option.
+config ROCKCHIP_DW_HDMI_QP
+ bool "Rockchip specific extensions for Synopsys DW HDMI QP"
+ select DRM_BRIDGE_CONNECTOR
+ help
+ This selects support for Rockchip SoC specific extensions
+ for the Synopsys DesignWare HDMI QP driver. If you want to
+ enable HDMI on RK3588 based SoC, you should select this option.
+
config ROCKCHIP_DW_MIPI_DSI
bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
select GENERIC_PHY_MIPI_DPHY
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -11,6 +11,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += ro
rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Collabora Ltd.
+ *
+ * Author: Algea Cao <algea.cao@rock-chips.com>
+ * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+
+#include <drm/bridge/dw_hdmi_qp.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "rockchip_drm_drv.h"
+
+#define RK3588_GRF_SOC_CON2 0x0308
+#define RK3588_HDMI0_HPD_INT_MSK BIT(13)
+#define RK3588_HDMI0_HPD_INT_CLR BIT(12)
+#define RK3588_GRF_SOC_CON7 0x031c
+#define RK3588_SET_HPD_PATH_MASK GENMASK(13, 12)
+#define RK3588_GRF_SOC_STATUS1 0x0384
+#define RK3588_HDMI0_LEVEL_INT BIT(16)
+#define RK3588_GRF_VO1_CON3 0x000c
+#define RK3588_SCLIN_MASK BIT(9)
+#define RK3588_SDAIN_MASK BIT(10)
+#define RK3588_MODE_MASK BIT(11)
+#define RK3588_I2S_SEL_MASK BIT(13)
+#define RK3588_GRF_VO1_CON9 0x0024
+#define RK3588_HDMI0_GRANT_SEL BIT(10)
+
+#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16)
+#define HOTPLUG_DEBOUNCE_MS 150
+
+struct rockchip_hdmi_qp {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regmap *vo_regmap;
+ struct rockchip_encoder encoder;
+ struct clk *ref_clk;
+ struct dw_hdmi_qp *hdmi;
+ struct phy *phy;
+ struct gpio_desc *enable_gpio;
+ struct delayed_work hpd_work;
+};
+
+static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
+{
+ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
+
+ return container_of(rkencoder, struct rockchip_hdmi_qp, encoder);
+}
+
+static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
+{
+ struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
+ struct drm_crtc *crtc = encoder->crtc;
+ unsigned long long rate;
+
+ /* Unconditionally switch to TMDS as FRL is not yet supported */
+ gpiod_set_value(hdmi->enable_gpio, 1);
+
+ if (crtc && crtc->state) {
+ rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode,
+ 8, HDMI_COLORSPACE_RGB);
+ clk_set_rate(hdmi->ref_clk, rate);
+ /*
+ * FIXME: Temporary workaround to pass pixel clock rate
+ * to the PHY driver until phy_configure_opts_hdmi
+ * becomes available in the PHY API. See also the related
+ * comment in rk_hdptx_phy_power_on() from
+ * drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+ */
+ phy_set_bus_width(hdmi->phy, rate / 100);
+ }
+}
+
+static int
+dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+ s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+ s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+
+ return 0;
+}
+
+static const struct
+drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = {
+ .enable = dw_hdmi_qp_rockchip_encoder_enable,
+ .atomic_check = dw_hdmi_qp_rockchip_encoder_atomic_check,
+};
+
+static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+ return phy_power_on(hdmi->phy);
+}
+
+static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi,
+ void *data)
+{
+ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+ phy_power_off(hdmi->phy);
+}
+
+static enum drm_connector_status
+dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+ u32 val;
+
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
+
+ return val & RK3588_HDMI0_LEVEL_INT ?
+ connector_status_connected : connector_status_disconnected;
+}
+
+static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+ struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+ regmap_write(hdmi->regmap,
+ RK3588_GRF_SOC_CON2,
+ HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
+ RK3588_HDMI0_HPD_INT_CLR |
+ RK3588_HDMI0_HPD_INT_MSK));
+}
+
+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
+ .init = dw_hdmi_qp_rk3588_phy_init,
+ .disable = dw_hdmi_qp_rk3588_phy_disable,
+ .read_hpd = dw_hdmi_qp_rk3588_read_hpd,
+ .setup_hpd = dw_hdmi_qp_rk3588_setup_hpd,
+};
+
+static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
+{
+ struct rockchip_hdmi_qp *hdmi = container_of(work,
+ struct rockchip_hdmi_qp,
+ hpd_work.work);
+ struct drm_device *drm = hdmi->encoder.encoder.dev;
+ bool changed;
+
+ if (drm) {
+ changed = drm_helper_hpd_irq_event(drm);
+ if (changed)
+ drm_dbg(hdmi, "connector status changed\n");
+ }
+}
+
+static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id)
+{
+ struct rockchip_hdmi_qp *hdmi = dev_id;
+ u32 intr_stat, val;
+
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
+
+ if (intr_stat) {
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK,
+ RK3588_HDMI0_HPD_INT_MSK);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+ return IRQ_WAKE_THREAD;
+ }
+
+ return IRQ_NONE;
+}
+
+static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id)
+{
+ struct rockchip_hdmi_qp *hdmi = dev_id;
+ u32 intr_stat, val;
+
+ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
+ if (!intr_stat)
+ return IRQ_NONE;
+
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
+ RK3588_HDMI0_HPD_INT_CLR);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+ mod_delayed_work(system_wq, &hdmi->hpd_work,
+ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
+
+ val |= HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+ return IRQ_HANDLED;
+}
+
+static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
+ { .compatible = "rockchip,rk3588-dw-hdmi-qp",
+ .data = &rk3588_hdmi_phy_ops },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
+
+static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ static const char * const clk_names[] = {
+ "pclk", "earc", "aud", "hdp", "hclk_vo1",
+ "ref" /* keep "ref" last */
+ };
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dw_hdmi_qp_plat_data plat_data;
+ struct drm_device *drm = data;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ struct rockchip_hdmi_qp *hdmi;
+ struct clk *clk;
+ int ret, irq, i;
+ u32 val;
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ plat_data.phy_ops = of_device_get_match_data(dev);
+ if (!plat_data.phy_ops)
+ return -ENODEV;
+
+ plat_data.phy_data = hdmi;
+ hdmi->dev = &pdev->dev;
+
+ encoder = &hdmi->encoder.encoder;
+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+
+ rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder,
+ dev->of_node, 0, 0);
+ /*
+ * If we failed to find the CRTC(s) which this encoder is
+ * supposed to be connected to, it's because the CRTC has
+ * not been registered yet. Defer probing, and hope that
+ * the required CRTC is added later.
+ */
+ if (encoder->possible_crtcs == 0)
+ return -EPROBE_DEFER;
+
+ hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,grf");
+ if (IS_ERR(hdmi->regmap)) {
+ drm_err(hdmi, "Unable to get rockchip,grf\n");
+ return PTR_ERR(hdmi->regmap);
+ }
+
+ hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,vo-grf");
+ if (IS_ERR(hdmi->vo_regmap)) {
+ drm_err(hdmi, "Unable to get rockchip,vo-grf\n");
+ return PTR_ERR(hdmi->vo_regmap);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
+ clk = devm_clk_get_enabled(hdmi->dev, clk_names[i]);
+
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ if (ret != -EPROBE_DEFER)
+ drm_err(hdmi, "Failed to get %s clock: %d\n",
+ clk_names[i], ret);
+ return ret;
+ }
+ }
+ hdmi->ref_clk = clk;
+
+ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(hdmi->enable_gpio)) {
+ ret = PTR_ERR(hdmi->enable_gpio);
+ drm_err(hdmi, "Failed to request enable GPIO: %d\n", ret);
+ return ret;
+ }
+
+ hdmi->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
+ if (IS_ERR(hdmi->phy)) {
+ ret = PTR_ERR(hdmi->phy);
+ if (ret != -EPROBE_DEFER)
+ drm_err(hdmi, "failed to get phy: %d\n", ret);
+ return ret;
+ }
+
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
+ regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON3, val);
+
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
+ RK3588_SET_HPD_PATH_MASK);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
+ RK3588_HDMI0_GRANT_SEL);
+ regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+
+ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+ INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work);
+
+ plat_data.main_irq = platform_get_irq_byname(pdev, "main");
+ if (plat_data.main_irq < 0)
+ return plat_data.main_irq;
+
+ irq = platform_get_irq_byname(pdev, "hpd");
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(hdmi->dev, irq,
+ dw_hdmi_qp_rk3588_hardirq,
+ dw_hdmi_qp_rk3588_irq,
+ IRQF_SHARED, "dw-hdmi-qp-hpd",
+ hdmi);
+ if (ret)
+ return ret;
+
+ drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs);
+ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+
+ platform_set_drvdata(pdev, hdmi);
+
+ hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data);
+ if (IS_ERR(hdmi->hdmi)) {
+ ret = PTR_ERR(hdmi->hdmi);
+ drm_encoder_cleanup(encoder);
+ return ret;
+ }
+
+ connector = drm_bridge_connector_init(drm, encoder);
+ if (IS_ERR(connector)) {
+ ret = PTR_ERR(connector);
+ drm_err(hdmi, "failed to init bridge connector: %d\n", ret);
+ return ret;
+ }
+
+ return drm_connector_attach_encoder(connector, encoder);
+}
+
+static void dw_hdmi_qp_rockchip_unbind(struct device *dev,
+ struct device *master,
+ void *data)
+{
+ struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&hdmi->hpd_work);
+
+ drm_encoder_cleanup(&hdmi->encoder.encoder);
+}
+
+static const struct component_ops dw_hdmi_qp_rockchip_ops = {
+ .bind = dw_hdmi_qp_rockchip_bind,
+ .unbind = dw_hdmi_qp_rockchip_unbind,
+};
+
+static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
+}
+
+static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
+}
+
+static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
+{
+ struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+ u32 val;
+
+ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
+ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
+ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
+ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
+ regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON3, val);
+
+ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
+ RK3588_SET_HPD_PATH_MASK);
+ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+
+ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
+ RK3588_HDMI0_GRANT_SEL);
+ regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+
+ dw_hdmi_qp_resume(dev, hdmi->hdmi);
+
+ if (hdmi->encoder.encoder.dev)
+ drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
+};
+
+struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
+ .probe = dw_hdmi_qp_rockchip_probe,
+ .remove = dw_hdmi_qp_rockchip_remove,
+ .driver = {
+ .name = "dwhdmiqp-rockchip",
+ .pm = &dw_hdmi_qp_rockchip_pm,
+ .of_match_table = dw_hdmi_qp_rockchip_dt_ids,
+ },
+};
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -532,6 +532,8 @@ static int __init rockchip_drm_init(void
ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
CONFIG_ROCKCHIP_DW_HDMI);
+ ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
+ CONFIG_ROCKCHIP_DW_HDMI_QP);
ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver,
CONFIG_ROCKCHIP_DW_MIPI_DSI);
ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -88,6 +88,7 @@ int rockchip_drm_encoder_set_crtc_endpoi
int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
extern struct platform_driver cdn_dp_driver;
extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
+extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
extern struct platform_driver dw_mipi_dsi_rockchip_driver;
extern struct platform_driver inno_hdmi_driver;
extern struct platform_driver rockchip_dp_driver;

View File

@ -0,0 +1,334 @@
From 4f537776340dab2b680a4d8554567f6884240d0b Mon Sep 17 00:00:00 2001
From: Piotr Zalewski <pZ010001011111@proton.me>
Date: Fri, 1 Nov 2024 19:01:17 +0000
Subject: [PATCH] rockchip/drm: vop2: add support for gamma LUT
Add support for gamma LUT in VOP2 driver. The implementation was inspired
by one found in VOP1 driver. Blue and red channels in gamma LUT register
write were swapped with respect to how gamma LUT values are written in
VOP1. Gamma LUT port selection was added before the write of new gamma LUT
table.
If the current SoC is rk356x, check if no other CRTC has gamma LUT enabled
in atomic_check (only one video port can use gamma LUT at a time) and
disable gamma LUT before the LUT table write.
If the current SoC isn't rk356x, "seamless" gamma lut update is performed
similarly to how it was done in the case of RK3399 in VOP1[1]. In seamless
update gamma LUT disable before the write isn't necessary, check if no
other CRTC has gamma LUT enabled is also not necessary, different register
is being used to select gamma LUT port[2] and after setting DSP_LUT_EN bit,
GAMMA_UPDATE_EN bit is set[3].
Gamma size is set and drm color management is enabled for each video port's
CRTC except ones which have no associated device.
Patch was tested on RK3566 (Pinetab2). When using userspace tools
which set eg. constant color temperature no issues were noticed. When
using userspace tools which adjust eg. color temperature the slight screen
flicker is visible probably because of gamma LUT disable needed in the
case of RK356x before gamma LUT write.
Compare behaviour of eg.:
```
gammastep -O 3000
```
To eg.:
```
gammastep -l 53:23 -t 6000:3000
```
In latter case color temperature is slowly adjusted at the beginning which
causes screen to slighly flicker. Then it adjusts every few seconds which
also causes slight screen flicker.
[1] https://lists.infradead.org/pipermail/linux-rockchip/2021-October/028132.html
[2] https://lore.kernel.org/linux-rockchip/48249708-8c05-40d2-a5d8-23de960c5a77@rock-chips.com/
[3] https://github.com/radxa/kernel/blob/linux-6.1-stan-rkr1/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c#L3437
Helped-by: Daniel Stone <daniel@fooishbar.org>
Helped-by: Dragan Simic <dsimic@manjaro.org>
Helped-by: Diederik de Haas <didi.debian@cknow.org>
Helped-by: Andy Yan <andy.yan@rock-chips.com>
Signed-off-by: Piotr Zalewski <pZ010001011111@proton.me>
Reviewed-by: Andy Yan <andyshrk@163.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20241101185545.559090-3-pZ010001011111@proton.me
---
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 186 +++++++++++++++++++
drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 5 +
2 files changed, 191 insertions(+)
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -281,6 +281,15 @@ static u32 vop2_readl(struct vop2 *vop2,
return val;
}
+static u32 vop2_vp_read(struct vop2_video_port *vp, u32 offset)
+{
+ u32 val;
+
+ regmap_read(vp->vop2->map, vp->data->offset + offset, &val);
+
+ return val;
+}
+
static void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v)
{
regmap_field_write(win->reg[reg], v);
@@ -1020,6 +1029,67 @@ static void vop2_disable(struct vop2 *vo
clk_disable_unprepare(vop2->hclk);
}
+static bool vop2_vp_dsp_lut_is_enabled(struct vop2_video_port *vp)
+{
+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL);
+
+ return dsp_ctrl & RK3568_VP_DSP_CTRL__DSP_LUT_EN;
+}
+
+static void vop2_vp_dsp_lut_disable(struct vop2_video_port *vp)
+{
+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL);
+
+ dsp_ctrl &= ~RK3568_VP_DSP_CTRL__DSP_LUT_EN;
+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
+}
+
+static bool vop2_vp_dsp_lut_poll_disabled(struct vop2_video_port *vp)
+{
+ u32 dsp_ctrl;
+ int ret = readx_poll_timeout(vop2_vp_dsp_lut_is_enabled, vp, dsp_ctrl,
+ !dsp_ctrl, 5, 30 * 1000);
+ if (ret) {
+ drm_err(vp->vop2->drm, "display LUT RAM enable timeout!\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void vop2_vp_dsp_lut_enable(struct vop2_video_port *vp)
+{
+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL);
+
+ dsp_ctrl |= RK3568_VP_DSP_CTRL__DSP_LUT_EN;
+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
+}
+
+static void vop2_vp_dsp_lut_update_enable(struct vop2_video_port *vp)
+{
+ u32 dsp_ctrl = vop2_vp_read(vp, RK3568_VP_DSP_CTRL);
+
+ dsp_ctrl |= RK3588_VP_DSP_CTRL__GAMMA_UPDATE_EN;
+ vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
+}
+
+static inline bool vop2_supports_seamless_gamma_lut_update(struct vop2 *vop2)
+{
+ return (vop2->data->soc_id != 3566 && vop2->data->soc_id != 3568);
+}
+
+static bool vop2_gamma_lut_in_use(struct vop2 *vop2, struct vop2_video_port *vp)
+{
+ const int nr_vps = vop2->data->nr_vps;
+ int gamma_en_vp_id;
+
+ for (gamma_en_vp_id = 0; gamma_en_vp_id < nr_vps; gamma_en_vp_id++)
+ if (vop2_vp_dsp_lut_is_enabled(&vop2->vps[gamma_en_vp_id]))
+ break;
+
+ return gamma_en_vp_id != nr_vps && gamma_en_vp_id != vp->id;
+}
+
static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1511,6 +1581,77 @@ static bool vop2_crtc_mode_fixup(struct
return true;
}
+static void vop2_crtc_write_gamma_lut(struct vop2 *vop2, struct drm_crtc *crtc)
+{
+ const struct vop2_video_port *vp = to_vop2_video_port(crtc);
+ const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id];
+ struct drm_color_lut *lut = crtc->state->gamma_lut->data;
+ unsigned int i, bpc = ilog2(vp_data->gamma_lut_len);
+ u32 word;
+
+ for (i = 0; i < crtc->gamma_size; i++) {
+ word = (drm_color_lut_extract(lut[i].blue, bpc) << (2 * bpc)) |
+ (drm_color_lut_extract(lut[i].green, bpc) << bpc) |
+ drm_color_lut_extract(lut[i].red, bpc);
+
+ writel(word, vop2->lut_regs + i * 4);
+ }
+}
+
+static void vop2_crtc_atomic_set_gamma_seamless(struct vop2 *vop2,
+ struct vop2_video_port *vp,
+ struct drm_crtc *crtc)
+{
+ vop2_writel(vop2, RK3568_LUT_PORT_SEL,
+ FIELD_PREP(RK3588_LUT_PORT_SEL__GAMMA_AHB_WRITE_SEL, vp->id));
+ vop2_vp_dsp_lut_enable(vp);
+ vop2_crtc_write_gamma_lut(vop2, crtc);
+ vop2_vp_dsp_lut_update_enable(vp);
+}
+
+static void vop2_crtc_atomic_set_gamma_rk356x(struct vop2 *vop2,
+ struct vop2_video_port *vp,
+ struct drm_crtc *crtc)
+{
+ vop2_vp_dsp_lut_disable(vp);
+ vop2_cfg_done(vp);
+ if (!vop2_vp_dsp_lut_poll_disabled(vp))
+ return;
+
+ vop2_writel(vop2, RK3568_LUT_PORT_SEL, vp->id);
+ vop2_crtc_write_gamma_lut(vop2, crtc);
+ vop2_vp_dsp_lut_enable(vp);
+}
+
+static void vop2_crtc_atomic_try_set_gamma(struct vop2 *vop2,
+ struct vop2_video_port *vp,
+ struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ if (!vop2->lut_regs || !crtc_state->color_mgmt_changed)
+ return;
+
+ if (!crtc_state->gamma_lut) {
+ vop2_vp_dsp_lut_disable(vp);
+ return;
+ }
+
+ if (vop2_supports_seamless_gamma_lut_update(vop2))
+ vop2_crtc_atomic_set_gamma_seamless(vop2, vp, crtc);
+ else
+ vop2_crtc_atomic_set_gamma_rk356x(vop2, vp, crtc);
+}
+
+static inline void vop2_crtc_atomic_try_set_gamma_locked(struct vop2 *vop2,
+ struct vop2_video_port *vp,
+ struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ vop2_lock(vop2);
+ vop2_crtc_atomic_try_set_gamma(vop2, vp, crtc, crtc_state);
+ vop2_unlock(vop2);
+}
+
static void vop2_dither_setup(struct drm_crtc *crtc, u32 *dsp_ctrl)
{
struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
@@ -2107,11 +2248,40 @@ static void vop2_crtc_atomic_enable(stru
vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
+ vop2_crtc_atomic_try_set_gamma(vop2, vp, crtc, crtc_state);
+
drm_crtc_vblank_on(crtc);
vop2_unlock(vop2);
}
+static int vop2_crtc_atomic_check_gamma(struct vop2_video_port *vp,
+ struct drm_crtc *crtc,
+ struct drm_atomic_state *state,
+ struct drm_crtc_state *crtc_state)
+{
+ struct vop2 *vop2 = vp->vop2;
+ unsigned int len;
+
+ if (!vp->vop2->lut_regs || !crtc_state->color_mgmt_changed ||
+ !crtc_state->gamma_lut)
+ return 0;
+
+ len = drm_color_lut_size(crtc_state->gamma_lut);
+ if (len != crtc->gamma_size) {
+ drm_dbg(vop2->drm, "Invalid LUT size; got %d, expected %d\n",
+ len, crtc->gamma_size);
+ return -EINVAL;
+ }
+
+ if (!vop2_supports_seamless_gamma_lut_update(vop2) && vop2_gamma_lut_in_use(vop2, vp)) {
+ drm_info(vop2->drm, "Gamma LUT can be enabled for only one CRTC at a time\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -2119,6 +2289,11 @@ static int vop2_crtc_atomic_check(struct
struct drm_plane *plane;
int nplanes = 0;
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ int ret;
+
+ ret = vop2_crtc_atomic_check_gamma(vp, crtc, state, crtc_state);
+ if (ret)
+ return ret;
drm_atomic_crtc_state_for_each_plane(plane, crtc_state)
nplanes++;
@@ -2582,7 +2757,13 @@ static void vop2_crtc_atomic_begin(struc
static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct vop2_video_port *vp = to_vop2_video_port(crtc);
+ struct vop2 *vop2 = vp->vop2;
+
+ /* In case of modeset, gamma lut update already happened in atomic enable */
+ if (!drm_atomic_crtc_needs_modeset(crtc_state))
+ vop2_crtc_atomic_try_set_gamma_locked(vop2, vp, crtc, crtc_state);
vop2_post_config(crtc);
@@ -2885,7 +3066,12 @@ static int vop2_create_crtcs(struct vop2
}
drm_crtc_helper_add(&vp->crtc, &vop2_crtc_helper_funcs);
+ if (vop2->lut_regs) {
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+ drm_mode_crtc_set_gamma_size(&vp->crtc, vp_data->gamma_lut_len);
+ drm_crtc_enable_color_mgmt(&vp->crtc, 0, false, vp_data->gamma_lut_len);
+ }
init_completion(&vp->dsp_hold_completion);
}
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
@@ -404,6 +404,7 @@ enum dst_factor_mode {
#define RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN BIT(15)
#define RK3568_VP_DSP_CTRL__STANDBY BIT(31)
+#define RK3568_VP_DSP_CTRL__DSP_LUT_EN BIT(28)
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_MODE BIT(20)
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL GENMASK(19, 18)
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17)
@@ -418,6 +419,8 @@ enum dst_factor_mode {
#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4)
#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0)
+#define RK3588_VP_DSP_CTRL__GAMMA_UPDATE_EN BIT(22)
+
#define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV GENMASK(3, 2)
#define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV GENMASK(1, 0)
@@ -470,6 +473,8 @@ enum dst_factor_mode {
#define RK3588_DSP_IF_POL__DP1_PIN_POL GENMASK(14, 12)
#define RK3588_DSP_IF_POL__DP0_PIN_POL GENMASK(10, 8)
+#define RK3588_LUT_PORT_SEL__GAMMA_AHB_WRITE_SEL GENMASK(13, 12)
+
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5)
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4)

View File

@ -0,0 +1,28 @@
From 86caee745e4506528801d9542db54e7b4c4d834b Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 21 Jun 2024 22:17:55 +0200
Subject: [PATCH] drm/rockchip: analogix_dp: allow to work without panel
When the DP output is routed to a external connector there is no
need for a fixed panel, as the panel may be detected via EDID on
the AUX channel. Allow to continue probing if no panel reference
is present.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20240621201755.500271-1-l.stach@pengutronix.de
---
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -386,7 +386,7 @@ static int rockchip_dp_probe(struct plat
return -ENODEV;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
- if (ret < 0)
+ if (ret < 0 && ret != -ENODEV)
return ret;
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);

View File

@ -0,0 +1,32 @@
From 4b64b4a81fcd51f570c046cf904aef19ec756d45 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Fri, 18 Oct 2024 15:10:10 +0000
Subject: [PATCH] drm/rockchip: avoid 64-bit division
Dividing a 64-bit integer prevents building this for 32-bit targets:
ERROR: modpost: "__aeabi_uldivmod" [drivers/gpu/drm/rockchip/rockchipdrm.ko] undefined!
As this function is not performance criticial, just Use the div_u64() helper.
Fixes: 128a9bf8ace2 ("drm/rockchip: Add basic RK3588 HDMI output support")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/20241018151016.3496613-1-arnd@kernel.org
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
---
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -82,7 +82,7 @@ static void dw_hdmi_qp_rockchip_encoder_
* comment in rk_hdptx_phy_power_on() from
* drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
*/
- phy_set_bus_width(hdmi->phy, rate / 100);
+ phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
}
}

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