Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2025-02-06 17:21:06 +08:00
commit fa59b42f0d
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
147 changed files with 19921 additions and 475 deletions

View File

@ -7,11 +7,11 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=imx-bootlets
PKG_VERSION:=10.05.02
PKG_VERSION:=10.12.01
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://trabant.uid0.hu/openwrt/
PKG_HASH:=09ecd81a64db5166a235932146faf08d0689bfc7ac04ac9fcc3a5bd809fba74a
PKG_HASH:=f7c98cbc41e15184cad61c56115e840e34ac3ebb4a162fadeea905e5038fd65b
PKG_FLAGS:=nonshared
@ -37,7 +37,7 @@ define Package/imx-bootlets/install
$(INSTALL_BIN) $(PKG_BUILD_DIR)/boot_prep/boot_prep $(STAGING_DIR)/boot_prep
$(INSTALL_BIN) $(PKG_BUILD_DIR)/linux_prep/output-target/linux_prep $(STAGING_DIR)/linux_prep
$(INSTALL_BIN) $(PKG_BUILD_DIR)/power_prep/power_prep $(STAGING_DIR)/power_prep
$(INSTALL_BIN) $(PKG_BUILD_DIR)/linux_prebuilt.db $(STAGING_DIR)/linux_prebuilt.db
$(INSTALL_BIN) $(PKG_BUILD_DIR)/linux_ivt.bd $(STAGING_DIR)/linux_ivt.bd
endef
$(eval $(call BuildPackage,imx-bootlets))

View File

@ -1,18 +1,22 @@
--- a/Makefile
+++ b/Makefile
@@ -32,10 +32,11 @@ ifeq "$(DFT_IMAGE)" "$(wildcard $(DFT_IM
sed -i 's,[^ *]image.*;,\timage="$(DFT_UBOOT)";,' uboot.db
elftosb2 -z -c ./uboot.db -o i$(ARCH)_uboot.sb
@@ -37,13 +37,13 @@ ifeq "$(DFT_IMAGE)" "$(wildcard $(DFT_IM
elftosb -z -c ./uboot.bd -o i$(ARCH)_uboot.sb
elftosb -z -f imx28 -c ./uboot_ivt.bd -o i$(ARCH)_ivt_uboot.sb
else
- @echo "by using the pre-built kernel"
- elftosb2 -z -c ./linux_prebuilt.db -o i$(ARCH)_linux.sb
- @echo "generating U-Boot boot stream image"
- elftosb2 -z -c ./uboot_prebuilt.db -o i$(ARCH)_uboot.sb
- elftosb -z -c ./linux.bd -o i$(ARCH)_linux.sb
- elftosb -z -f imx28 -c ./linux_ivt.bd -o i$(ARCH)_ivt_linux.sb
+ @echo "... not generating any image for now."
+ #@echo "by using the pre-built kernel"
+ #elftosb2 -z -c ./linux_prebuilt.db -o i$(ARCH)_linux.sb
+ #elftosb -z -c ./linux.bd -o i$(ARCH)_linux.sb
+ #elftosb -z -f imx28 -c ./linux_ivt.bd -o i$(ARCH)_ivt_linux.sb
- @echo "generating U-Boot boot stream image"
- elftosb -z -c ./uboot.bd -o i$(ARCH)_uboot.sb
- elftosb -z -f imx28 -c ./uboot_ivt.bd -o i$(ARCH)_ivt_uboot.sb
+ #@echo "generating U-Boot boot stream image"
+ #elftosb2 -z -c ./uboot_prebuilt.db -o i$(ARCH)_uboot.sb
+ #elftosb -z -c ./uboot.bd -o i$(ARCH)_uboot.sb
+ #elftosb -z -f imx28 -c ./uboot_ivt.bd -o i$(ARCH)_ivt_uboot.sb
endif
#@echo "generating kernel bootstream file sd_mmc_bootstream.raw"
#Please use cfimager to burn xxx_linux.sb. The below way will no

View File

@ -1,5 +1,5 @@
--- a/linux_prebuilt.db
+++ b/linux_prebuilt.db
--- a/linux_ivt.bd
+++ b/linux_ivt.bd
@@ -4,10 +4,10 @@ options {
flags = 0x01;
}
@ -7,11 +7,11 @@
- power_prep="./power_prep/power_prep";
- sdram_prep="./boot_prep/boot_prep";
- linux_prep="./linux_prep/output-target/linux_prep";
- zImage = "./zImage";
- zImage="./zImage";
+ power_prep="./power_prep";
+ sdram_prep="./boot_prep";
+ linux_prep="./linux_prep";
+ zImage = "./zImage_dtb";
+ zImage="./zImage_dtb";
}
section (0) {

View File

@ -121,7 +121,7 @@
all: build_prep gen_bootstream
@@ -94,6 +97,8 @@ distclean: clean
@@ -101,6 +104,8 @@ distclean: clean
clean:
-rm -rf *.sb
rm -f sd_mmc_bootstream.raw
@ -130,14 +130,3 @@
$(MAKE) -C linux_prep clean ARCH=$(ARCH)
$(MAKE) -C boot_prep clean ARCH=$(ARCH)
$(MAKE) -C power_prep clean ARCH=$(ARCH)
--- a/uboot.db
+++ b/uboot.db
@@ -3,7 +3,7 @@
sources {
power_prep="./power_prep/power_prep";
sdram_prep="./boot_prep/boot_prep";
- image="/home/b18647/repos/ltib_latest/rootfs/boot/u-boot";
+ image="../boot/u-boot";
}
section (0) {

View File

@ -0,0 +1,11 @@
--- a/linux_prep/core/cmdlines.S
+++ b/linux_prep/core/cmdlines.S
@@ -14,7 +14,7 @@
#define CMDLINES_FILE "output-target/command_lines_stripped.txt"
#endif
- .section .cmdlines, #alloc
+ .section .cmdlines, "a"
.globl cmdlines_start
cmdlines_start:
.incbin CMDLINES_FILE

View File

@ -0,0 +1,22 @@
[ -e /etc/config/ubootenv ] && exit 0
touch /etc/config/ubootenv
. /lib/uboot-envtools.sh
. /lib/functions.sh
board=$(board_name)
case "$board" in
linksys,mx2000|\
linksys,mx5500)
idx="$(find_mtd_index u_env)"
[ -n "$idx" ] && \
ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000"
;;
esac
config_load ubootenv
config_foreach ubootenv_add_app_config
exit 0

View File

@ -25,6 +25,21 @@ include $(INCLUDE_DIR)/package.mk
RSTRIP:=:
STRIP:=:
ATH11K_LEGACY_FW_NAME:=ath11k-legacy-firmware
ATH11K_LEGACY_FW_DATE:=2024-03-14
ATH11K_LEGACY_FW_RELEASE:=795809c7
ATH11K_LEGACY_FW_SUBDIR:=$(ATH11K_LEGACY_FW_NAME)-$(ATH11K_LEGACY_FW_DATE)~$(ATH11K_LEGACY_FW_RELEASE)
ATH11K_LEGACY_FW_SOURCE=$(ATH11K_LEGACY_FW_SUBDIR).tar.zst
define Download/$(ATH11K_LEGACY_FW_NAME)
FILE:=$(ATH11K_LEGACY_FW_SOURCE)
PROTO:=git
URL:=https://github.com/quic/upstream-wifi-fw.git
SOURCE_VERSION:=795809c7041582bd51bdfaa1f548b916ae8d4382
MIRROR_HASH:=e042024b6762a5b4fe56f1a5bf8870df2e7abcca90ec22103cd46a609bee7cec
SUBDIR:=$(ATH11K_LEGACY_FW_SUBDIR)
endef
define Package/ath11k-firmware-default
SECTION:=firmware
CATEGORY:=Firmware
@ -32,6 +47,11 @@ define Package/ath11k-firmware-default
DEPENDS:=
endef
define Package/ath11k-firmware-ipq5018
$(Package/ath11k-firmware-default)
TITLE:=IPQ5018 ath11k firmware
endef
define Package/ath11k-firmware-ipq6018
$(Package/ath11k-firmware-default)
TITLE:=IPQ6018 ath11k firmware
@ -42,15 +62,43 @@ $(Package/ath11k-firmware-default)
TITLE:=IPQ8074 ath11k firmware
endef
define Package/ath11k-firmware-qcn6122
$(Package/ath11k-firmware-default)
TITLE:=QCN6122 ath11k firmware
DEPENDS:=ath11k-firmware-ipq5018
endef
define Package/ath11k-firmware-qcn9074
$(Package/ath11k-firmware-default)
TITLE:=QCN9074 ath11k firmware
endef
define Build/Clean
$(call Build/Clean/Default,)
rm -rf \
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)
endef
define Build/Prepare
$(eval $(call Download,ath11k-legacy-firmware))
$(call Build/Prepare/Default,)
$(TAR) -C $(BUILD_DIR) -xf $(DL_DIR)/$(ATH11K_LEGACY_FW_SOURCE)
endef
define Build/Compile
endef
define Package/ath11k-firmware-ipq5018/install
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ5018/hw1.0
$(INSTALL_DATA) \
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)/ath11k-firmware/IPQ5018_QCN6122_QCN6122/hw1.0/2.7.0.1/WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1/*.* \
$(1)/lib/firmware/ath11k/IPQ5018/hw1.0/
endef
define Package/ath11k-firmware-ipq6018/install
$(INSTALL_DIR) $(1)/lib/firmware/IPQ6018
$(INSTALL_DATA) \
@ -65,6 +113,13 @@ define Package/ath11k-firmware-ipq8074/install
$(1)/lib/firmware/IPQ8074/
endef
define Package/ath11k-firmware-qcn6122/install
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN6122/hw1.0
$(INSTALL_DATA) \
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)/ath11k-firmware/IPQ5018_QCN6122_QCN6122/hw1.0/2.7.0.1/WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1/qcn6122/* \
$(1)/lib/firmware/ath11k/QCN6122/hw1.0/
endef
define Package/ath11k-firmware-qcn9074/install
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0
$(INSTALL_DATA) \
@ -74,6 +129,8 @@ define Package/ath11k-firmware-qcn9074/install
$(PKG_BUILD_DIR)/QCN9074/hw1.0/board-2.bin $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin
endef
$(eval $(call BuildPackage,ath11k-firmware-ipq5018))
$(eval $(call BuildPackage,ath11k-firmware-ipq6018))
$(eval $(call BuildPackage,ath11k-firmware-ipq8074))
$(eval $(call BuildPackage,ath11k-firmware-qcn6122))
$(eval $(call BuildPackage,ath11k-firmware-qcn9074))

View File

@ -39,8 +39,10 @@ ALLWIFIBOARDS:= \
edimax_cax1800 \
linksys_homewrk \
linksys_mr7350 \
linksys_mx2000 \
linksys_mx4200 \
linksys_mx5300 \
linksys_mx5500 \
linksys_mx8500 \
linksys_whw03 \
netgear_lbr20 \
@ -102,14 +104,18 @@ define ipq-wifi-install-one
$(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/hw1.0),\
$(if $(filter $(suffix $(1)),.QCA99X0 .qca99x0),\
$(call ipq-wifi-install-one-to,$(1),$(2),QCA99X0/hw2.0),\
$(if $(filter $(suffix $(1)),.IPQ5018 .ipq5018),\
$(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ5018/hw1.0),\
$(if $(filter $(suffix $(1)),.IPQ6018 .ipq6018),\
$(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ6018/hw1.0),\
$(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074),\
$(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ8074/hw2.0),\
$(if $(filter $(suffix $(1)),.QCN6122 .qcn6122),\
$(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),\
$(error Unrecognized board-file suffix '$(suffix $(1))' for '$(1)')\
))))))))
))))))))))
endef
# Blank line required at end of above define due to foreach context
@ -171,8 +177,10 @@ $(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,linksys_homewrk,Linksys HomeWRK))
$(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350))
$(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,linksys_whw03,Linksys WHW03))
$(eval $(call generate-ipq-wifi-package,netgear_lbr20,Netgear LBR20))

View File

@ -637,6 +637,65 @@ endef
$(eval $(call KernelPackage,dsa-qca8k))
define KernelPackage/dsa-realtek
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Realtek common module RTL83xx DSA switch family
DEPENDS:=+kmod-dsa +kmod-phy-realtek +kmod-regmap-core @!TARGET_x86 @!TARGET_bcm47xx @!TARGET_uml
KCONFIG:= \
CONFIG_NET_DSA_REALTEK \
CONFIG_NET_DSA_REALTEK_MDIO=y \
CONFIG_NET_DSA_REALTEK_SMI=y
FILES:= $(LINUX_DIR)/drivers/net/dsa/realtek/realtek_dsa.ko
endef
define KernelPackage/dsa-realtek/description
Common kernel module for Realtek RTL83xx DSA switch family
endef
$(eval $(call KernelPackage,dsa-realtek))
define KernelPackage/dsa-rtl8366rb
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Realtek RTL8365MB switch DSA support
DEPENDS:=+kmod-dsa-realtek @!TARGET_x86 @!TARGET_bcm47xx @!TARGET_uml
KCONFIG:= \
CONFIG_NET_DSA_REALTEK_RTL8366RB \
CONFIG_NET_DSA_TAG_RTL4_A
FILES:= \
$(LINUX_DIR)/drivers/net/dsa/realtek/rtl8366.ko \
$(LINUX_DIR)/net/dsa/tag_rtl4_a.ko
AUTOLOAD:=$(call AutoLoad,42,rtl8366,1)
endef
define KernelPackage/dsa-rtl8366rb/description
DSA based kernel modules for the Realtek RTL8366RB switch family
endef
$(eval $(call KernelPackage,dsa-rtl8366rb))
define KernelPackage/dsa-rtl8365mb
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Realtek RTL8365MB switch DSA support
DEPENDS:=+kmod-dsa-realtek @!TARGET_x86 @!TARGET_bcm47xx @!TARGET_uml
KCONFIG:= \
CONFIG_NET_DSA_REALTEK_RTL8365MB \
CONFIG_NET_DSA_TAG_RTL8_4
FILES:= \
$(LINUX_DIR)/drivers/net/dsa/realtek/rtl8365mb.ko \
$(LINUX_DIR)/net/dsa/tag_rtl8_4.ko
AUTOLOAD:=$(call AutoLoad,42,rtl8365mb,1)
endef
define KernelPackage/dsa-rtl8365mb/description
DSA based kernel modules for the Realtek RTL8365MB switch family
endef
$(eval $(call KernelPackage,dsa-rtl8365mb))
define KernelPackage/swconfig
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=switch configuration API

View File

@ -0,0 +1,62 @@
From 824dde8652815aa67b4e2bf2d8a9455a8ef82b8f Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Thu, 29 Jun 2023 06:12:45 +0000
Subject: [PATCH] wifi: ath11k: Support setting bdf-addr and caldb-addr via DT
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/net/wireless/ath/ath11k/qmi.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2028,6 +2028,7 @@ static int ath11k_qmi_assign_target_mem_
struct device_node *hremote_node = NULL;
struct resource res;
u32 host_ddr_sz;
+ u32 addr;
int i, idx, ret;
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
@@ -2067,7 +2068,9 @@ static int ath11k_qmi_assign_target_mem_
idx++;
break;
case BDF_MEM_REGION_TYPE:
- ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
+ if(of_property_read_u32(dev->of_node, "qcom,bdf-addr", &addr))
+ addr = ab->hw_params.bdf_addr;
+ ab->qmi.target_mem[idx].paddr = addr;
ab->qmi.target_mem[idx].vaddr = NULL;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
@@ -2089,8 +2092,9 @@ static int ath11k_qmi_assign_target_mem_
if (!ab->qmi.target_mem[idx].iaddr)
return -EIO;
} else {
- ab->qmi.target_mem[idx].paddr =
- ATH11K_QMI_CALDB_ADDRESS;
+ if(of_property_read_u32(dev->of_node, "qcom,caldb-addr", &addr))
+ addr = ATH11K_QMI_CALDB_ADDRESS;
+ ab->qmi.target_mem[idx].paddr = addr;
}
} else {
ab->qmi.target_mem[idx].paddr = 0;
@@ -2292,6 +2296,7 @@ static int ath11k_qmi_load_file_target_m
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
struct qmi_txn txn;
const u8 *temp = data;
+ u32 addr;
void __iomem *bdf_addr = NULL;
int ret = 0;
u32 remaining = len;
@@ -2303,7 +2308,9 @@ static int ath11k_qmi_load_file_target_m
memset(&resp, 0, sizeof(resp));
if (ab->hw_params.fixed_bdf_addr) {
- bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size);
+ if(of_property_read_u32(ab->dev->of_node, "qcom,bdf-addr", &addr))
+ addr = ab->hw_params.bdf_addr;
+ bdf_addr = ioremap(addr, ab->hw_params.fw.board_size);
if (!bdf_addr) {
ath11k_warn(ab, "qmi ioremap error for bdf_addr\n");
ret = -EIO;

View File

@ -0,0 +1,153 @@
From: Ziyang Huang <hzyitc@outlook.com>
Date: Thu, 2 May 2024 00:14:31 +0800
Subject: [PATCH] wifi: ath11k: fix remapped ce accessing issue on 64bit OS
On 64bit OS, when ab->mem_ce is lower than or 4G far away from ab->mem,
u32 is not enough to store the offsets, which makes ath11k_ahb_read32()
and ath11k_ahb_write32() access incorrect address and causes Data Abort
Exception.
Let's use the high bits of offsets to decide where to access, which is
similar as ath11k_pci_get_window_start() done. In the future, we can merge
these functions for unified regs accessing.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -198,12 +198,18 @@ static const struct ath11k_pci_ops ath11
static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
{
- return ioread32(ab->mem + offset);
+ if ((offset & ATH11K_REG_TYPE_MASK) == ATH11K_REG_TYPE_CE)
+ return ioread32(ab->mem_ce + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset));
+ else
+ return ioread32(ab->mem + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset));
}
static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
{
- iowrite32(value, ab->mem + offset);
+ if ((offset & ATH11K_REG_TYPE_MASK) == ATH11K_REG_TYPE_CE)
+ iowrite32(value, ab->mem_ce + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset));
+ else
+ iowrite32(value, ab->mem + FIELD_GET(ATH11K_REG_OFFSET_MASK, offset));
}
static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
@@ -275,9 +281,9 @@ static void ath11k_ahb_ce_irq_enable(str
const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr;
u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
- ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab);
- ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab);
- ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab);
+ ie1_reg_addr = ce_ie_addr->ie1_reg_addr;
+ ie2_reg_addr = ce_ie_addr->ie2_reg_addr;
+ ie3_reg_addr = ce_ie_addr->ie3_reg_addr;
ce_attr = &ab->hw_params.host_ce_config[ce_id];
if (ce_attr->src_nentries)
@@ -296,9 +302,9 @@ static void ath11k_ahb_ce_irq_disable(st
const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr;
u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
- ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab);
- ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab);
- ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab);
+ ie1_reg_addr = ce_ie_addr->ie1_reg_addr;
+ ie2_reg_addr = ce_ie_addr->ie2_reg_addr;
+ ie3_reg_addr = ce_ie_addr->ie3_reg_addr;
ce_attr = &ab->hw_params.host_ce_config[ce_id];
if (ce_attr->src_nentries)
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1247,20 +1247,16 @@ static int ath11k_hal_srng_create_config
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
s = &hal->srng_config[HAL_CE_SRC];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB +
- ATH11K_CE_OFFSET(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP +
- ATH11K_CE_OFFSET(ab);
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
s = &hal->srng_config[HAL_CE_DST];
- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB +
- ATH11K_CE_OFFSET(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP +
- ATH11K_CE_OFFSET(ab);
+ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
@@ -1268,9 +1264,8 @@ static int ath11k_hal_srng_create_config
s = &hal->srng_config[HAL_CE_DST_STATUS];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
- HAL_CE_DST_STATUS_RING_BASE_LSB + ATH11K_CE_OFFSET(ab);
- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP +
- ATH11K_CE_OFFSET(ab);
+ HAL_CE_DST_STATUS_RING_BASE_LSB;
+ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2268,9 +2268,9 @@ const struct ce_ie_addr ath11k_ce_ie_add
};
const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018 = {
- .ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
- .ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
- .ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+ .ie1_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+ .ie2_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+ .ie3_reg_addr = ATH11K_REG_TYPE_CE + CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
};
const struct ce_remap ath11k_ce_remap_ipq5018 = {
@@ -2801,13 +2801,13 @@ const struct ath11k_hw_regs ipq5018_regs
.hal_reo_status_hp = 0x00003070,
/* WCSS relative address */
- .hal_seq_wcss_umac_ce0_src_reg = 0x08400000
+ .hal_seq_wcss_umac_ce0_src_reg = ATH11K_REG_TYPE_CE + 0x08400000
- HAL_IPQ5018_CE_WFSS_REG_BASE,
- .hal_seq_wcss_umac_ce0_dst_reg = 0x08401000
+ .hal_seq_wcss_umac_ce0_dst_reg = ATH11K_REG_TYPE_CE + 0x08401000
- HAL_IPQ5018_CE_WFSS_REG_BASE,
- .hal_seq_wcss_umac_ce1_src_reg = 0x08402000
+ .hal_seq_wcss_umac_ce1_src_reg = ATH11K_REG_TYPE_CE + 0x08402000
- HAL_IPQ5018_CE_WFSS_REG_BASE,
- .hal_seq_wcss_umac_ce1_dst_reg = 0x08403000
+ .hal_seq_wcss_umac_ce1_dst_reg = ATH11K_REG_TYPE_CE + 0x08403000
- HAL_IPQ5018_CE_WFSS_REG_BASE,
/* WBM Idle address */
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -81,7 +81,12 @@
#define ATH11K_M3_FILE "m3.bin"
#define ATH11K_REGDB_FILE_NAME "regdb.bin"
-#define ATH11K_CE_OFFSET(ab) (ab->mem_ce - ab->mem)
+#define ATH11K_REG_TYPE_MASK GENMASK(31, 28)
+#define ATH11K_REG_TYPE(x) FIELD_PREP_CONST(ATH11K_REG_TYPE_MASK, x)
+#define ATH11K_REG_TYPE_NORMAL ATH11K_REG_TYPE(0)
+#define ATH11K_REG_TYPE_DP ATH11K_REG_TYPE(1)
+#define ATH11K_REG_TYPE_CE ATH11K_REG_TYPE(2)
+#define ATH11K_REG_OFFSET_MASK GENMASK(27, 0)
enum ath11k_hw_rate_cck {
ATH11K_HW_RATE_CCK_LP_11M = 0,

View File

@ -0,0 +1,115 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: add hw params for QCN6122
Add QCN6122 platform support.
QCN6122 is a PCIe based solution that is attached to and enumerated
by the WPSS (Wireless Processor SubSystem) Q6 processor.
Though it is a PCIe device, since it is not attached to APSS processor
(Application Processor SubSystem), APSS will be unaware of such a decice
and hence it is registered to the APSS processor as a platform device(AHB).
Because of this hybrid nature, it is called as a hybrid bus device.
As such, QCN6122 is a hybrid bus type device and follows the same codepath
as for WCN6750.
This is a heavily simplified version of below downstream patch:
Download from https://git.codelinaro.org/clo/qsdk/oss/system/feeds/wlan-open/-/blob/NHSS.QSDK.12.4.5.r2/mac80211/patches/232-ath11k-qcn6122-support.patch
Co-developed-by: George Moussalem <george.moussalem@outlook.com>
Signed-off-by: Sowmiya Sree Elavalagan <ssreeela@codeaurora.org>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -809,6 +809,67 @@ static struct ath11k_hw_params ath11k_hw
.support_fw_mac_sequence = true,
.support_dual_stations = true,
},
+ {
+ .hw_rev = ATH11K_HW_QCN6122_HW10,
+ .name = "qcn6122 hw1.0",
+ .fw = {
+ .dir = "QCN6122/hw1.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ },
+ .hal_params = &ath11k_hw_hal_params_ipq8074,
+ .max_radios = MAX_RADIOS_5018,
+ .bdf_addr = 0x4D200000,
+ .hw_ops = &ipq5018_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
+ .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122,
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT),
+ .spectral = {
+ .fft_sz = 2,
+ .fft_pad_sz = 0,
+ .summary_pad_sz = 16,
+ .fft_hdr_len = 24,
+ .max_fft_bins = 1024,
+ },
+ .credit_flow = false,
+ .max_tx_ring = 1,
+ .supports_monitor = true,
+ .supports_shadow_regs = false,
+ .idle_ps = false,
+ .supports_suspend = false,
+ .host_ce_config = ath11k_host_ce_config_qcn9074,
+ .ce_count = CE_CNT_5018,
+ .target_ce_config = ath11k_target_ce_config_wlan_ipq5018,
+ .target_ce_count = TARGET_CE_CNT_5018,
+ .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018,
+ .svc_to_ce_map_len = SVC_CE_MAP_LEN_5018,
+ .single_pdev_only = false,
+ .rxdma1_enable = true,
+ .num_rxdma_per_pdev = RXDMA_PER_PDEV_5018,
+ .rx_mac_buf_ring = false,
+ .vdev_start_delay = false,
+ .htt_peer_map_v2 = true,
+ .coldboot_cal_mm = true,
+ .coldboot_cal_ftm = true,
+ .cbcal_restart_fw = true,
+ .fix_l1ss = true,
+ .alloc_cacheable_memory = true,
+ .m3_fw_support = false,
+ .fixed_bdf_addr = true,
+ .fixed_mem_region = true,
+ .static_window_map = true,
+ .hybrid_bus_type = true,
+ .fw_mem_mode = 1,
+ .supports_sta_ps = false,
+ .dbr_debug_support = true,
+ .bios_sar_capa = NULL,
+ .fixed_fw_mem = false,
+ .support_off_channel_tx = false,
+ .tcl_ring_retry = true,
+ .tx_ring_size = DP_TCL_DATA_RING_SIZE,
+ },
};
static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -148,6 +148,7 @@ enum ath11k_hw_rev {
ATH11K_HW_WCN6750_HW10,
ATH11K_HW_IPQ5018_HW10,
ATH11K_HW_QCA2066_HW21,
+ ATH11K_HW_QCN6122_HW10,
};
enum ath11k_firmware_mode {
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -22,6 +22,7 @@
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074 0x02
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074 0x07
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750 0x03
+#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122 0x40
#define ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 32
#define ATH11K_QMI_RESP_LEN_MAX 8192
#define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 52

View File

@ -0,0 +1,114 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: add hal regs for QCN6122
Add HAL changes required to support QCN6122. Offsets are similar to those of
WCN6750 but QCN6122 does not use the hal_shadow_base_addr, so add platform
specific ath11k_hw_regs and register them in hw params.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -822,6 +822,7 @@ static struct ath11k_hw_params ath11k_hw
.bdf_addr = 0x4D200000,
.hw_ops = &ipq5018_ops,
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
+ .regs = &qcn6122_regs,
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122,
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2822,6 +2822,81 @@ const struct ath11k_hw_regs ipq5018_regs
.hal_wbm1_release_ring_base_lsb = 0x0000097c,
};
+const struct ath11k_hw_regs qcn6122_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .hal_tcl1_ring_base_lsb = 0x00000694,
+ .hal_tcl1_ring_base_msb = 0x00000698,
+ .hal_tcl1_ring_id = 0x0000069c,
+ .hal_tcl1_ring_misc = 0x000006a4,
+ .hal_tcl1_ring_tp_addr_lsb = 0x000006b0,
+ .hal_tcl1_ring_tp_addr_msb = 0x000006b4,
+ .hal_tcl1_ring_consumer_int_setup_ix0 = 0x000006c4,
+ .hal_tcl1_ring_consumer_int_setup_ix1 = 0x000006c8,
+ .hal_tcl1_ring_msi1_base_lsb = 0x000006dc,
+ .hal_tcl1_ring_msi1_base_msb = 0x000006e0,
+ .hal_tcl1_ring_msi1_data = 0x000006e4,
+ .hal_tcl2_ring_base_lsb = 0x000006ec,
+ .hal_tcl_ring_base_lsb = 0x0000079c,
+
+ /* TCL STATUS ring address */
+ .hal_tcl_status_ring_base_lsb = 0x000008a4,
+
+ /* REO2SW(x) R0 ring configuration address */
+ .hal_reo1_ring_base_lsb = 0x000001ec,
+ .hal_reo1_ring_base_msb = 0x000001f0,
+ .hal_reo1_ring_id = 0x000001f4,
+ .hal_reo1_ring_misc = 0x000001fc,
+ .hal_reo1_ring_hp_addr_lsb = 0x00000200,
+ .hal_reo1_ring_hp_addr_msb = 0x00000204,
+ .hal_reo1_ring_producer_int_setup = 0x00000210,
+ .hal_reo1_ring_msi1_base_lsb = 0x00000234,
+ .hal_reo1_ring_msi1_base_msb = 0x00000238,
+ .hal_reo1_ring_msi1_data = 0x0000023c,
+ .hal_reo2_ring_base_lsb = 0x00000244,
+ .hal_reo1_aging_thresh_ix_0 = 0x00000564,
+ .hal_reo1_aging_thresh_ix_1 = 0x00000568,
+ .hal_reo1_aging_thresh_ix_2 = 0x0000056c,
+ .hal_reo1_aging_thresh_ix_3 = 0x00000570,
+
+ /* REO2SW(x) R2 ring pointers (head/tail) address */
+ .hal_reo1_ring_hp = 0x00003028,
+ .hal_reo1_ring_tp = 0x0000302c,
+ .hal_reo2_ring_hp = 0x00003030,
+
+ /* REO2TCL R0 ring configuration address */
+ .hal_reo_tcl_ring_base_lsb = 0x000003fc,
+ .hal_reo_tcl_ring_hp = 0x00003058,
+
+ /* SW2REO ring address */
+ .hal_sw2reo_ring_base_lsb = 0x0000013c,
+ .hal_sw2reo_ring_hp = 0x00003018,
+
+ /* REO CMD ring address */
+ .hal_reo_cmd_ring_base_lsb = 0x000000e4,
+ .hal_reo_cmd_ring_hp = 0x00003010,
+
+ /* REO status address */
+ .hal_reo_status_ring_base_lsb = 0x00000504,
+ .hal_reo_status_hp = 0x00003070,
+
+ /* WCSS relative address */
+ .hal_seq_wcss_umac_ce0_src_reg = 0x01b80000,
+ .hal_seq_wcss_umac_ce0_dst_reg = 0x01b81000,
+ .hal_seq_wcss_umac_ce1_src_reg = 0x01b82000,
+ .hal_seq_wcss_umac_ce1_dst_reg = 0x01b83000,
+
+ /* WBM Idle address */
+ .hal_wbm_idle_link_ring_base_lsb = 0x00000874,
+ .hal_wbm_idle_link_ring_misc = 0x00000884,
+
+ /* SW2WBM release address */
+ .hal_wbm_release_ring_base_lsb = 0x000001ec,
+
+ /* WBM2SW release address */
+ .hal_wbm0_release_ring_base_lsb = 0x00000924,
+ .hal_wbm1_release_ring_base_lsb = 0x0000097c,
+};
+
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -425,6 +425,7 @@ extern const struct ath11k_hw_regs qcn90
extern const struct ath11k_hw_regs wcn6855_regs;
extern const struct ath11k_hw_regs wcn6750_regs;
extern const struct ath11k_hw_regs ipq5018_regs;
+extern const struct ath11k_hw_regs qcn6122_regs;
static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type)
{

View File

@ -0,0 +1,74 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: add hw ring mask for QCN6122
Add ring mask for QCN6122 and register them in hw params.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -821,6 +821,7 @@ static struct ath11k_hw_params ath11k_hw
.max_radios = MAX_RADIOS_5018,
.bdf_addr = 0x4D200000,
.hw_ops = &ipq5018_ops,
+ .ring_mask = &ath11k_hw_ring_mask_qcn6122,
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
.regs = &qcn6122_regs,
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN6122,
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2070,6 +2070,43 @@ const struct ath11k_hw_ring_mask ath11k_
},
};
+const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn6122 = {
+ .tx = {
+ ATH11K_TX_RING_MASK_0,
+ ATH11K_TX_RING_MASK_1,
+ ATH11K_TX_RING_MASK_2,
+ },
+ .rx_mon_status = {
+ 0, 0, 0,
+ ATH11K_RX_MON_STATUS_RING_MASK_0,
+ },
+ .rx = {
+ 0, 0, 0, 0,
+ ATH11K_RX_RING_MASK_0,
+ ATH11K_RX_RING_MASK_1,
+ ATH11K_RX_RING_MASK_2,
+ ATH11K_RX_RING_MASK_3,
+ },
+ .rx_err = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ ATH11K_RX_ERR_RING_MASK_0,
+ },
+ .rx_wbm_rel = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ ATH11K_RX_WBM_REL_RING_MASK_0,
+ },
+ .reo_status = {
+ 0, 0, 0,
+ ATH11K_REO_STATUS_RING_MASK_0,
+ },
+ .rxdma2host = {
+ ATH11K_RXDMA2HOST_RING_MASK_0,
+ },
+ .host2rxdma = {
+ ATH11K_HOST2RXDMA_RING_MASK_0,
+ },
+};
+
/* Target firmware's Copy Engine configuration for IPQ5018 */
const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[] = {
/* CE0: host->target HTC control and raw streams */
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -289,6 +289,7 @@ extern const struct ath11k_hw_ring_mask
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074;
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750;
+extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn6122;
extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074;
extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;

View File

@ -0,0 +1,102 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: update hif and pci ops for QCN6122
Add HIF and PCI ops for QCN6122. QCN6122 by default uses DP window 3.
However, this is configurable, so let's introduce a function to do that and
follow the existing register access code for (hybrid)AHB devices and use
DP window 1.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -768,6 +768,18 @@ static int ath11k_ahb_hif_resume(struct
return 0;
}
+static void ath11k_ahb_config_static_window_qcn6122(struct ath11k_base *ab)
+{
+ u32 umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);
+ u32 ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);
+ u32 window;
+
+ window = (umac_window) | (ce_window << 6);
+
+ iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,
+ ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);
+}
+
static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = {
.start = ath11k_ahb_start,
.stop = ath11k_ahb_stop,
@@ -800,6 +812,24 @@ static const struct ath11k_hif_ops ath11
.ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq,
};
+static const struct ath11k_hif_ops ath11k_ahb_hif_ops_qcn6122 = {
+ .start = ath11k_pcic_start,
+ .stop = ath11k_pcic_stop,
+ .read32 = ath11k_pcic_read32,
+ .write32 = ath11k_pcic_write32,
+ .read = NULL,
+ .irq_enable = ath11k_pcic_ext_irq_enable,
+ .irq_disable = ath11k_pcic_ext_irq_disable,
+ .get_msi_address = ath11k_pcic_get_msi_address,
+ .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment,
+ .map_service_to_pipe = ath11k_pcic_map_service_to_pipe,
+ .power_down = ath11k_ahb_power_down,
+ .power_up = ath11k_ahb_power_up,
+ .ce_irq_enable = ath11k_pci_enable_ce_irqs_except_wake_irq,
+ .ce_irq_disable = ath11k_pci_disable_ce_irqs_except_wake_irq,
+ .config_static_window = ath11k_ahb_config_static_window_qcn6122,
+};
+
static int ath11k_core_get_rproc(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
@@ -1144,6 +1174,10 @@ static int ath11k_ahb_probe(struct platf
hif_ops = &ath11k_ahb_hif_ops_wcn6750;
pci_ops = &ath11k_ahb_pci_ops_wcn6750;
break;
+ case ATH11K_HW_QCN6122_HW10:
+ hif_ops = &ath11k_ahb_hif_ops_qcn6122;
+ pci_ops = &ath11k_ahb_pci_ops_wcn6750;
+ break;
default:
dev_err(&pdev->dev, "unsupported device type %d\n", hw_rev);
return -EOPNOTSUPP;
--- a/drivers/net/wireless/ath/ath11k/hif.h
+++ b/drivers/net/wireless/ath/ath11k/hif.h
@@ -31,6 +31,7 @@ struct ath11k_hif_ops {
void (*ce_irq_enable)(struct ath11k_base *ab);
void (*ce_irq_disable)(struct ath11k_base *ab);
void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx);
+ void (*config_static_window)(struct ath11k_base *ab);
};
static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab)
@@ -146,4 +147,12 @@ static inline void ath11k_get_ce_msi_idx
*msi_data_idx = ce_id;
}
+static inline void ath11k_hif_config_static_window(struct ath11k_base *ab)
+{
+ if (!ab->hw_params.static_window_map || !ab->hif.ops->config_static_window)
+ return;
+
+ ab->hif.ops->config_static_window(ab);
+}
+
#endif /* _HIF_H_ */
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2184,6 +2184,8 @@ static int ath11k_qmi_request_device_inf
ab->mem = bar_addr_va;
ab->mem_len = resp.bar_size;
+ ath11k_hif_config_static_window(ab);
+
return 0;
out:
return ret;

View File

@ -0,0 +1,110 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: add multipd support for QCN6122
IPQ5018/QCN6122 platforms use multi PD (protection domains) to avoid having
one instance of the running Q6 firmware crashing resulting in crashing the
others. See below patch for more info:
https://lore.kernel.org/all/20231110091939.3025413-1-quic_mmanikan@quicinc.com/
The IPQ5018 platform can have multiple (2) QCN6122 wifi cards. To differentiate
the two, the PD instance number (1 or 2) is added to the QMI service instance
ID, which the QCN6122 firmware also expects. IPQ5018 is always the first PD, so
the QCN6122 cards should be the second or third.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -435,6 +435,7 @@ static void ath11k_ahb_init_qmi_ce_confi
cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
+ ab->qmi.service_ins_id += ab->userpd_id;
}
static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
@@ -1118,6 +1119,27 @@ err_unregister:
return ret;
}
+static int ath11k_get_userpd_id(struct device *dev)
+{
+ int ret;
+ int userpd_id = 0;
+ const char *subsys_name;
+
+ ret = of_property_read_string(dev->of_node,
+ "qcom,userpd-subsys-name",
+ &subsys_name);
+ if (ret)
+ return 0;
+
+ if (strcmp(subsys_name, "q6v5_wcss_userpd2") == 0)
+ userpd_id = ATH11K_QCN6122_USERPD_2;
+ else if (strcmp(subsys_name, "q6v5_wcss_userpd3") == 0)
+ userpd_id = ATH11K_QCN6122_USERPD_3;
+ dev_info(dev, "Multipd architecture - userpd: %d\n", userpd_id + 1);
+
+ return userpd_id;
+}
+
static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
{
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
@@ -1159,7 +1181,7 @@ static int ath11k_ahb_probe(struct platf
const struct ath11k_hif_ops *hif_ops;
const struct ath11k_pci_ops *pci_ops;
enum ath11k_hw_rev hw_rev;
- int ret;
+ int ret, userpd_id;
hw_rev = (uintptr_t)device_get_match_data(&pdev->dev);
@@ -1183,6 +1205,7 @@ static int ath11k_ahb_probe(struct platf
return -EOPNOTSUPP;
}
+ userpd_id = ath11k_get_userpd_id(&pdev->dev);
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
@@ -1199,6 +1222,7 @@ static int ath11k_ahb_probe(struct platf
ab->hif.ops = hif_ops;
ab->pdev = pdev;
ab->hw_rev = hw_rev;
+ ab->userpd_id = userpd_id;
ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
platform_set_drvdata(pdev, ab);
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -45,6 +45,9 @@
#define ATH11K_INVALID_HW_MAC_ID 0xFF
#define ATH11K_CONNECTION_LOSS_HZ (3 * HZ)
+#define ATH11K_QCN6122_USERPD_2 1
+#define ATH11K_QCN6122_USERPD_3 2
+
/* SMBIOS type containing Board Data File Name Extension */
#define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8
@@ -945,6 +948,7 @@ struct ath11k_base {
struct list_head peers;
wait_queue_head_t peer_mapping_wq;
u8 mac_addr[ETH_ALEN];
+ int userpd_id;
int irq_num[ATH11K_IRQ_NUM_MAX];
struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX];
struct ath11k_targ_cap target_caps;
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -389,6 +389,8 @@ static void ath11k_pci_init_qmi_ce_confi
} else
ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;
+ ab->qmi.service_ins_id += ab->userpd_id;
+
ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,
&cfg->shadow_reg_v2_len);
}

View File

@ -0,0 +1,55 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] wifi: ath11k: add QCN6122 device support
QCN6122 is a 2x2 11AX PCIe based chipset, but it is attached to the WPSS
(Wireless Processor SubSystem) Q6 processor, hence it is enumerated
by the Q6 processor. It is registered to the APSS processor
(Application Processor SubSystem) as a platform device (AHB) and remoteproc
APIs are used to boot up or shutdown the device like other AHB devices.
Also, device information like BAR and its size is not known to the
APSS processor as the chip is enumerated by WPSS Q6. These details
are fetched over QMI.
STA, AP, and MESH modes are supported.
Tested on: Linksys MX2000 and GLiNET B3000 access points for prolonged duration
tests spanning multiple days with multiple clients connected with firmware
WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
An important point to note is that though QCN6122 is a PCIe device,
it is an IPQ5018 SoC specific solution and cannot be attached to any other
platform.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -37,6 +37,9 @@ static const struct of_device_id ath11k_
{ .compatible = "qcom,ipq5018-wifi",
.data = (void *)ATH11K_HW_IPQ5018_HW10,
},
+ { .compatible = "qcom,qcn6122-wifi",
+ .data = (void *)ATH11K_HW_QCN6122_HW10,
+ },
{ }
};
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -126,6 +126,15 @@ static const struct ath11k_msi_config at
},
.hw_rev = ATH11K_HW_QCA2066_HW21,
},
+ {
+ .total_vectors = 13,
+ .total_users = 2,
+ .users = (struct ath11k_msi_user[]) {
+ { .name = "CE", .num_vectors = 5, .base_vector = 0 },
+ { .name = "DP", .num_vectors = 8, .base_vector = 5 },
+ },
+ .hw_rev = ATH11K_HW_QCN6122_HW10,
+ },
};
int ath11k_pcic_init_msi_config(struct ath11k_base *ab)

View File

@ -0,0 +1,31 @@
From 64f6f6cdde0b6b763181145a698207fad4536c06 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Wed, 9 Aug 2023 17:44:49 +0000
Subject: [PATCH] wifi: ath11k: Support to assign m3 dump memory
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/net/wireless/ath/ath11k/qmi.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -2104,6 +2104,18 @@ static int ath11k_qmi_assign_target_mem_
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
break;
+ case M3_DUMP_REGION_TYPE:
+ if (of_property_read_u32(dev->of_node, "qcom,m3-dump-addr", &addr)) {
+ ath11k_warn(ab, "qmi fail to get qcom,m3-dump-addr, ignore m3 dump mem req\n");
+ break;
+ }
+
+ ab->qmi.target_mem[idx].paddr = (phys_addr_t) addr;
+ ab->qmi.target_mem[idx].vaddr = NULL;
+ ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
+ ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
+ idx++;
+ break;
default:
ath11k_warn(ab, "qmi ignore invalid mem req type %d\n",
ab->qmi.target_mem[i].type);

View File

@ -0,0 +1,164 @@
From d890c6d602307c9297df12c7d0287f9ffd26208b Mon Sep 17 00:00:00 2001
From: Sriram R <srirrama@codeaurora.org>
Date: Wed, 12 May 2021 19:21:09 +0530
Subject: [PATCH] ath11k: poll reo status ring for IPQ5018
Currently reo status interrupts are not received
due to wrong mapping of the reo status interrupt
line in IPQ5018.
Hence, until the mapping is resolved in HW, use
polling to reap the reo status ring. Rather than
a period timer to reap the ring, the timer is
triggered only on sending a reo command with
status request.
Without proper reaping of the ring, backpressure
and ring full issues are seen in multi client test
setups which leads to flooding the console with
error messages reporting failure to send reo cmds.
Can be reverted once HW solution is available.
Signed-off-by: Sriram R <srirrama@codeaurora.org>
---
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -719,6 +719,7 @@ static struct ath11k_hw_params ath11k_hw
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
.support_dual_stations = false,
+ .reo_status_poll = true,
},
{
.name = "qca2066 hw2.1",
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -361,12 +361,66 @@ void ath11k_dp_stop_shadow_timers(struct
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
}
+static void ath11k_dp_handle_reo_status_timer(struct timer_list *timer)
+{
+ struct ath11k_dp *dp = from_timer(dp, timer, reo_status_timer);
+ struct ath11k_base *ab = dp->ab;
+
+ spin_lock_bh(&dp->reo_cmd_lock);
+ dp->reo_status_timer_running = false;
+ spin_unlock_bh(&dp->reo_cmd_lock);
+
+ ath11k_dp_process_reo_status(ab);
+}
+
+void ath11k_dp_start_reo_status_timer(struct ath11k_base *ab)
+{
+ struct ath11k_dp *dp = &ab->dp;
+
+ if (!ab->hw_params.reo_status_poll)
+ return;
+
+ spin_lock_bh(&dp->reo_cmd_lock);
+ if (dp->reo_status_timer_running) {
+ spin_unlock_bh(&dp->reo_cmd_lock);
+ return;
+ }
+ dp->reo_status_timer_running = true;
+ spin_unlock_bh(&dp->reo_cmd_lock);
+
+ mod_timer(&dp->reo_status_timer, jiffies +
+ msecs_to_jiffies(ATH11K_REO_STATUS_POLL_TIMEOUT_MS));
+}
+
+static void ath11k_dp_stop_reo_status_timer(struct ath11k_base *ab)
+{
+ struct ath11k_dp *dp = &ab->dp;
+
+ if (!ab->hw_params.reo_status_poll)
+ return;
+
+ del_timer_sync(&dp->reo_status_timer);
+ dp->reo_status_timer_running = false;
+}
+
+static void ath11k_dp_init_reo_status_timer(struct ath11k_base *ab)
+{
+ struct ath11k_dp *dp = &ab->dp;
+
+ if (!ab->hw_params.reo_status_poll)
+ return;
+
+ timer_setup(&dp->reo_status_timer,
+ ath11k_dp_handle_reo_status_timer, 0);
+}
+
static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
{
struct ath11k_dp *dp = &ab->dp;
int i;
ath11k_dp_stop_shadow_timers(ab);
+ ath11k_dp_stop_reo_status_timer(ab);
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
@@ -388,6 +442,8 @@ static int ath11k_dp_srng_common_setup(s
int i, ret;
u8 tcl_num, wbm_num;
+ ath11k_dp_init_reo_status_timer(ab);
+
ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring,
HAL_SW2WBM_RELEASE, 0, 0,
DP_WBM_RELEASE_RING_SIZE);
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -44,6 +44,8 @@ struct dp_rx_tid {
#define DP_MON_PURGE_TIMEOUT_MS 100
#define DP_MON_SERVICE_BUDGET 128
+#define ATH11K_REO_STATUS_POLL_TIMEOUT_MS 10
+
struct dp_reo_cache_flush_elem {
struct list_head list;
struct dp_rx_tid data;
@@ -286,6 +288,10 @@ struct ath11k_dp {
spinlock_t reo_cmd_lock;
struct ath11k_hp_update_timer reo_cmd_timer;
struct ath11k_hp_update_timer tx_ring_timer[DP_TCL_NUM_RING_MAX];
+
+ /* reo status timer and flags */
+ struct timer_list reo_status_timer;
+ bool reo_status_timer_running;
};
/* HTT definitions */
@@ -1712,5 +1718,6 @@ void ath11k_dp_shadow_init_timer(struct
struct ath11k_hp_update_timer *update_timer,
u32 interval, u32 ring_id);
void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab);
+void ath11k_dp_start_reo_status_timer(struct ath11k_base *ab);
#endif
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -787,6 +787,10 @@ int ath11k_dp_tx_send_reo_cmd(struct ath
if (cmd_num == 0)
return -EINVAL;
+ /* Trigger reo status polling if required */
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ ath11k_dp_start_reo_status_timer(ab);
+
if (!cb)
return 0;
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -232,6 +232,7 @@ struct ath11k_hw_params {
bool smp2p_wow_exit;
bool support_fw_mac_sequence;
bool support_dual_stations;
+ bool reo_status_poll;
};
struct ath11k_hw_ops {

View File

@ -0,0 +1,245 @@
From 5ad8cf24897ff903112967a9662cb13ed4cbbf57 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Mon, 22 Apr 2024 21:47:58 +0800
Subject: [PATCH] syn-gmac: use standard DMA api
The SSDK uses several old DMA API calls based on raw assembly which have
been deprecated. So let's convert to and use the standard Linux DMA API
instead.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
hal/dp_ops/syn_gmac_dp/syn_dp_cfg_rx.c | 14 ++++++--
hal/dp_ops/syn_gmac_dp/syn_dp_cfg_tx.c | 2 ++
hal/dp_ops/syn_gmac_dp/syn_dp_rx.c | 47 +++++++++++++-------------
hal/dp_ops/syn_gmac_dp/syn_dp_tx.c | 23 ++++---------
4 files changed, 42 insertions(+), 44 deletions(-)
diff --git a/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_rx.c b/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_rx.c
index 8cbbcaaf..1c9006c7 100644
--- a/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_rx.c
+++ b/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_rx.c
@@ -26,6 +26,7 @@ static int syn_dp_cfg_rx_setup_desc_queue(struct syn_dp_info *dev_info)
{
struct syn_dp_info_rx *rx_info = &dev_info->dp_info_rx;
struct dma_desc_rx *first_desc = NULL;
+ dma_addr_t dma_addr;
struct net_device *netdev = rx_info->netdev;
netdev_dbg(netdev, "Total size of memory required for Rx Descriptors in Ring Mode = %u\n", (uint32_t)((sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE)));
@@ -33,13 +34,15 @@ static int syn_dp_cfg_rx_setup_desc_queue(struct syn_dp_info *dev_info)
/*
* Allocate cacheable descriptors for Rx
*/
- first_desc = kzalloc(sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE, GFP_KERNEL);
+ first_desc = dma_alloc_coherent(rx_info->dev,
+ sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE,
+ &dma_addr, GFP_KERNEL);
if (!first_desc) {
netdev_dbg(netdev, "Error in Rx Descriptor Memory allocation in Ring mode\n");
return -ENOMEM;
}
- dev_info->rx_desc_dma_addr = (dma_addr_t)virt_to_phys(first_desc);
+ dev_info->rx_desc_dma_addr = dma_addr;
rx_info->rx_desc = first_desc;
syn_dp_gmac_rx_desc_init_ring(rx_info->rx_desc, SYN_DP_RX_DESC_SIZE);
@@ -98,6 +101,10 @@ void syn_dp_cfg_rx_cleanup_rings(struct syn_dp_info *dev_info)
for (i = 0; i < rx_info->busy_rx_desc_cnt; i++) {
rx_skb_index = (rx_skb_index + i) & SYN_DP_RX_DESC_MAX_INDEX;
rxdesc = rx_info->rx_desc;
+
+ dma_unmap_single(rx_info->dev, rxdesc->buffer1,
+ rxdesc->length, DMA_FROM_DEVICE);
+
skb = rx_info->rx_buf_pool[rx_skb_index].skb;
if (unlikely(skb != NULL)) {
dev_kfree_skb_any(skb);
@@ -105,7 +112,8 @@ void syn_dp_cfg_rx_cleanup_rings(struct syn_dp_info *dev_info)
}
}
- kfree(rx_info->rx_desc);
+ dma_free_coherent(rx_info->dev, (sizeof(struct dma_desc_rx) * SYN_DP_RX_DESC_SIZE),
+ rx_info->rx_desc, dev_info->rx_desc_dma_addr);
rx_info->rx_desc = NULL;
dev_info->rx_desc_dma_addr = (dma_addr_t)0;
}
diff --git a/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_tx.c b/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_tx.c
index bf5e19a0..284e8880 100644
--- a/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_tx.c
+++ b/hal/dp_ops/syn_gmac_dp/syn_dp_cfg_tx.c
@@ -91,6 +91,8 @@ void syn_dp_cfg_tx_cleanup_rings(struct syn_dp_info *dev_info)
tx_skb_index = syn_dp_tx_inc_index(tx_skb_index, i);
txdesc = tx_info->tx_desc;
+ dma_unmap_single(tx_info->dev, txdesc->buffer1, txdesc->length, DMA_TO_DEVICE);
+
skb = tx_info->tx_buf_pool[tx_skb_index].skb;
if (unlikely(skb != NULL)) {
dev_kfree_skb_any(skb);
diff --git a/hal/dp_ops/syn_gmac_dp/syn_dp_rx.c b/hal/dp_ops/syn_gmac_dp/syn_dp_rx.c
index 1ddeb7d6..1798d4e7 100644
--- a/hal/dp_ops/syn_gmac_dp/syn_dp_rx.c
+++ b/hal/dp_ops/syn_gmac_dp/syn_dp_rx.c
@@ -73,16 +73,6 @@ static inline void syn_dp_rx_refill_one_desc(struct dma_desc_rx *rx_desc,
*/
static inline void syn_dp_rx_inval_and_flush(struct syn_dp_info_rx *rx_info, uint32_t start, uint32_t end)
{
- /*
- * Batched flush and invalidation of the rx descriptors
- */
- if (end > start) {
- dmac_flush_range_no_dsb((void *)&rx_info->rx_desc[start], (void *)&rx_info->rx_desc[end] + sizeof(struct dma_desc_rx));
- } else {
- dmac_flush_range_no_dsb((void *)&rx_info->rx_desc[start], (void *)&rx_info->rx_desc[SYN_DP_RX_DESC_MAX_INDEX] + sizeof(struct dma_desc_rx));
- dmac_flush_range_no_dsb((void *)&rx_info->rx_desc[0], (void *)&rx_info->rx_desc[end] + sizeof(struct dma_desc_rx));
- }
-
dsb(st);
}
@@ -124,15 +114,19 @@ int syn_dp_rx_refill_page_mode(struct syn_dp_info_rx *rx_info)
break;
}
+ skb_fill_page_desc(skb, 0, pg, 0, PAGE_SIZE);
+
/*
* Get virtual address of allocated page.
*/
page_addr = page_address(pg);
- dma_addr = (dma_addr_t)virt_to_phys(page_addr);
-
- skb_fill_page_desc(skb, 0, pg, 0, PAGE_SIZE);
+ dma_addr = dma_map_page(rx_info->dev, pg, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(rx_info->dev, dma_addr))) {
+ dev_kfree_skb(skb);
+ netdev_dbg(netdev, "DMA mapping failed for empty buffer\n");
+ break;
+ }
- dmac_inv_range_no_dsb(page_addr, (page_addr + PAGE_SIZE));
rx_refill_idx = rx_info->rx_refill_idx;
rx_desc = rx_info->rx_desc + rx_refill_idx;
@@ -181,8 +175,15 @@ int syn_dp_rx_refill(struct syn_dp_info_rx *rx_info)
skb_reserve(skb, SYN_DP_SKB_HEADROOM + NET_IP_ALIGN);
- dma_addr = (dma_addr_t)virt_to_phys(skb->data);
- dmac_inv_range_no_dsb((void *)skb->data, (void *)(skb->data + inval_len));
+ dma_addr = dma_map_single(rx_info->dev, skb->data,
+ inval_len,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(rx_info->dev, dma_addr))) {
+ dev_kfree_skb(skb);
+ netdev_dbg(netdev, "DMA mapping failed for empty buffer\n");
+ break;
+ }
+
rx_refill_idx = rx_info->rx_refill_idx;
rx_desc = rx_info->rx_desc + rx_refill_idx;
@@ -407,12 +408,6 @@ int syn_dp_rx(struct syn_dp_info_rx *rx_info, int budget)
* this code is executing.
*/
end = syn_dp_rx_inc_index(rx_info->rx_idx, busy);
- if (end > start) {
- dmac_inv_range_no_dsb((void *)&rx_info->rx_desc[start], (void *)&rx_info->rx_desc[end] + sizeof(struct dma_desc_rx));
- } else {
- dmac_inv_range_no_dsb((void *)&rx_info->rx_desc[start], (void *)&rx_info->rx_desc[SYN_DP_RX_DESC_MAX_INDEX] + sizeof(struct dma_desc_rx));
- dmac_inv_range_no_dsb((void *)&rx_info->rx_desc[0], (void *)&rx_info->rx_desc[end] + sizeof(struct dma_desc_rx));
- }
dsb(st);
@@ -439,8 +434,12 @@ int syn_dp_rx(struct syn_dp_info_rx *rx_info, int budget)
* speculative prefetch by CPU may have occurred.
*/
frame_length = syn_dp_gmac_get_rx_desc_frame_length(status);
- dmac_inv_range((void *)rx_buf->map_addr_virt,
- (void *)(((uint8_t *)rx_buf->map_addr_virt) + frame_length));
+ if (likely(!rx_info->page_mode))
+ dma_unmap_single(rx_info->dev, rx_desc->buffer1,
+ rx_info->alloc_buf_len, DMA_FROM_DEVICE);
+ else
+ dma_unmap_page(rx_info->dev, rx_desc->buffer1,
+ PAGE_SIZE, DMA_FROM_DEVICE);
prefetch((void *)rx_buf->map_addr_virt);
rx_next_idx = syn_dp_rx_inc_index(rx_idx, 1);
diff --git a/hal/dp_ops/syn_gmac_dp/syn_dp_tx.c b/hal/dp_ops/syn_gmac_dp/syn_dp_tx.c
index c97e252b..6d4adb3f 100644
--- a/hal/dp_ops/syn_gmac_dp/syn_dp_tx.c
+++ b/hal/dp_ops/syn_gmac_dp/syn_dp_tx.c
@@ -104,9 +104,7 @@ static inline struct dma_desc_tx *syn_dp_tx_process_nr_frags(struct syn_dp_info_
BUG_ON(!length);
#endif
- dma_addr = (dma_addr_t)virt_to_phys(frag_addr);
-
- dmac_clean_range_no_dsb(frag_addr, frag_addr + length);
+ dma_addr = dma_map_single(tx_info->dev, frag_addr, length, DMA_TO_DEVICE);
*total_length += length;
tx_desc = syn_dp_tx_set_desc_sg(tx_info, dma_addr, length, DESC_OWN_BY_DMA);
@@ -150,8 +148,7 @@ int syn_dp_tx_nr_frags(struct syn_dp_info_tx *tx_info, struct sk_buff *skb)
/*
* Flush the dma for non-paged skb data
*/
- dma_addr = (dma_addr_t)virt_to_phys(skb->data);
- dmac_clean_range_no_dsb((void *)skb->data, (void *)(skb->data + length));
+ dma_addr = dma_map_single(tx_info->dev, skb->data, length, DMA_TO_DEVICE);
total_len = length;
@@ -256,12 +253,7 @@ int syn_dp_tx_frag_list(struct syn_dp_info_tx *tx_info, struct sk_buff *skb)
return NETDEV_TX_BUSY;
}
- dma_addr = (dma_addr_t)virt_to_phys(skb->data);
-
- /*
- * Flush the data area of the head skb
- */
- dmac_clean_range_no_dsb((void *)skb->data, (void *)(skb->data + length));
+ dma_addr = dma_map_single(tx_info->dev, skb->data, length, DMA_TO_DEVICE);
total_len = length;
@@ -290,9 +282,7 @@ int syn_dp_tx_frag_list(struct syn_dp_info_tx *tx_info, struct sk_buff *skb)
BUG_ON(!length);
#endif
- dma_addr = (dma_addr_t)virt_to_phys(iter_skb->data);
-
- dmac_clean_range_no_dsb((void *)iter_skb->data, (void *)(iter_skb->data + length));
+ dma_addr = dma_map_single(tx_info->dev, iter_skb->data, length, DMA_TO_DEVICE);
total_len += length;
@@ -445,6 +435,7 @@ int syn_dp_tx_complete(struct syn_dp_info_tx *tx_info, int budget)
break;
}
+ dma_unmap_single(tx_info->dev, desc->buffer1, desc->length, DMA_TO_DEVICE);
if (likely(status & DESC_TX_LAST)) {
tx_skb_index = syn_dp_tx_comp_index_get(tx_info);
@@ -571,9 +562,7 @@ int syn_dp_tx(struct syn_dp_info_tx *tx_info, struct sk_buff *skb)
return NETDEV_TX_BUSY;
}
- dma_addr = (dma_addr_t)virt_to_phys(skb->data);
-
- dmac_clean_range_no_dsb((void *)skb->data, (void *)(skb->data + skb->len));
+ dma_addr = dma_map_single(tx_info->dev, skb->data, skb->len, DMA_TO_DEVICE);
/*
* Queue packet to the GMAC rings
--
2.40.1

View File

@ -0,0 +1,46 @@
From ba430b1a512dc1972807a1dd5a8d31a78ac572ff Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Mon, 22 Apr 2024 21:49:18 +0800
Subject: [PATCH] ipq50xx: use corrent scm function to write tcsr
QCA leverages its own API function to write to the TCSR register space,
not available upstream. As such, convert to the upstream qcom SCM IO
write function.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
hal/soc_ops/ipq50xx/nss_ipq50xx.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/hal/soc_ops/ipq50xx/nss_ipq50xx.c b/hal/soc_ops/ipq50xx/nss_ipq50xx.c
index 3e4491c0..e56de1cc 100644
--- a/hal/soc_ops/ipq50xx/nss_ipq50xx.c
+++ b/hal/soc_ops/ipq50xx/nss_ipq50xx.c
@@ -18,7 +18,7 @@
#include <linux/of.h>
#include <linux/ioport.h>
-#include <linux/qcom_scm.h>
+#include <linux/firmware/qcom/qcom_scm.h>
#include "nss_dp_hal.h"
/*
@@ -78,13 +78,8 @@ static void nss_dp_hal_tcsr_set(void)
* If TZ is not enabled, we can write to the register directly.
*/
if (qcom_scm_is_available()) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
- err = qcom_scm_tcsr_reg_write((tcsr_base + TCSR_GMAC_AXI_CACHE_OVERRIDE_OFFSET),
+ err = qcom_scm_io_writel((tcsr_base + TCSR_GMAC_AXI_CACHE_OVERRIDE_OFFSET),
TCSR_GMAC_AXI_CACHE_OVERRIDE_VALUE);
-#else
- err = qti_scm_tcsr_reg_write((tcsr_base + TCSR_GMAC_AXI_CACHE_OVERRIDE_OFFSET),
- TCSR_GMAC_AXI_CACHE_OVERRIDE_VALUE);
-#endif
if (err) {
pr_err("%s: SCM TCSR write error: %d\n", __func__, err);
}
--
2.40.1

View File

@ -0,0 +1,49 @@
From 309a1a330ccaa103a7648e944d97a0032116b338 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Mon, 22 Apr 2024 21:50:39 +0800
Subject: [PATCH] nss_dp_main: support fixed-link
Add support for "fixed link" to support ethernet MACs which are not
connected to an MDIO managed PHY. For example, IPQ5018 has two internal
MACs, one connected to a GE PHY and the other connected to a Uniphy to
support connections to an external switch over a fixed link. As such,
check for a fixed link in absence of a phy-handle and return an error
when no phy-handle and fixed link is found.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
nss_dp_main.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/nss_dp_main.c b/nss_dp_main.c
index 9a09edd5..204063bf 100644
--- a/nss_dp_main.c
+++ b/nss_dp_main.c
@@ -619,11 +619,20 @@ static int32_t nss_dp_of_get_pdata(struct device_node *np,
}
dp_priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
- if (!dp_priv->phy_node) {
- pr_err("%s: error parsing phy-handle\n", np->name);
- return -EFAULT;
+ if(!dp_priv->phy_node) {
+ if(of_phy_is_fixed_link(np)) {
+ int ret = of_phy_register_fixed_link(np);
+ if(ret < 0) {
+ pr_err("%s: fail to register fixed-link: %d\n", np->name, ret);
+ return -EFAULT;
+ }
+ }
+ dp_priv->phy_node = of_node_get(np);
}
+ if(!dp_priv->phy_node)
+ pr_err("%s: no phy-handle or fixed-link found\n", np->name);
+
if (of_property_read_u32(np, "qcom,mactype", &hal_pdata->mactype)) {
pr_err("%s: error reading mactype\n", np->name);
return -EFAULT;
--
2.40.1

View File

@ -49,7 +49,7 @@ MAKE_FLAGS+= \
PTP_FEATURE=disable SWCONFIG_FEATURE=disable \
ISISC_ENABLE=disable MHT_ENABLE=disable \
IN_QCA803X_PHY=FALSE IN_QCA808X_PHY=FALSE \
IN_MALIBU_PHY=FALSE \
IN_MALIBU_PHY=FALSE IN_MP_PHY=FALSE \
$(LNX_CONFIG_OPTS)
ifeq ($(CONFIG_TARGET_SUBTARGET), "ipq807x")
@ -60,6 +60,9 @@ ifeq ($(CONFIG_TARGET_SUBTARGET), "ipq60xx")
MAKE_FLAGS+= CHIP_TYPE=CPPE
endif
ifeq ($(CONFIG_TARGET_SUBTARGET), "ipq50xx")
MAKE_FLAGS+= CHIP_TYPE=MP
endif
define Build/Compile
+$(MAKE) $(PKG_JOBS) $(MAKE_FLAGS) -C $(PKG_BUILD_DIR) $(LNX_CONFIG_OPTS)

View File

@ -0,0 +1,127 @@
From 15847e1f56b7f9423095cd96fd9d524a41bee814 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 15:24:07 +0800
Subject: [PATCH] hsl_phy: split MP_PHY config
Compiling the MP_PHY driver for ipq50xx is disabled in the Makefile in
favor of a native driver being upstreamed. As such, conditionally disable
unneeded flags and code associated to initializing the MP GE PHY that
would otherwise conflict with the native driver.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
config | 1 +
make/linux_opt.mk | 5 +++++
src/adpt/mp/adpt_mp_portctrl.c | 4 ++++
src/hsl/phy/Makefile | 8 +-------
src/hsl/phy/hsl_phy.c | 4 ++--
5 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/config b/config
index 99d99dff..1f74e4f8 100644
--- a/config
+++ b/config
@@ -299,6 +299,7 @@ else ifeq (DESS, $(CHIP_TYPE))
else ifeq (MP, $(CHIP_TYPE))
IN_QCA803X_PHY=TRUE
IN_QCA808X_PHY=TRUE
+ IN_MP_PHY=TRUE
IN_SFP_PHY=TRUE
IN_SFP=TRUE
else ifeq (APPE, $(CHIP_TYPE))
diff --git a/make/linux_opt.mk b/make/linux_opt.mk
index 6936b754..66b08ef5 100644
--- a/make/linux_opt.mk
+++ b/make/linux_opt.mk
@@ -183,6 +183,11 @@ endif
ifeq (TRUE, $(IN_QCA808X_PHY))
MODULE_CFLAG += -DIN_QCA808X_PHY
endif
+
+ifeq (TRUE, $(IN_MP_PHY))
+ MODULE_CFLAG += -DIN_MP_PHY
+endif
+
ifeq (TRUE, $(IN_SFP_PHY))
MODULE_CFLAG += -DIN_SFP_PHY
endif
diff --git a/src/adpt/mp/adpt_mp_portctrl.c b/src/adpt/mp/adpt_mp_portctrl.c
index 2c983fff..db60fc72 100644
--- a/src/adpt/mp/adpt_mp_portctrl.c
+++ b/src/adpt/mp/adpt_mp_portctrl.c
@@ -92,12 +92,15 @@ static sw_error_t
adpt_mp_port_reset_set(a_uint32_t dev_id, a_uint32_t port_id)
{
sw_error_t rv = 0;
+#ifdef IN_MP_PHY
a_uint32_t phy_addr;
hsl_phy_ops_t *phy_drv;
+#endif
ADPT_DEV_ID_CHECK(dev_id);
if (port_id == SSDK_PHYSICAL_PORT1) {
+#ifdef IN_MP_PHY
/*internal gephy reset*/
SW_RTN_ON_NULL (phy_drv = hsl_phy_api_ops_get(dev_id,
port_id));
@@ -107,6 +110,7 @@ adpt_mp_port_reset_set(a_uint32_t dev_id, a_uint32_t port_id)
SW_RTN_ON_ERROR (rv);
rv = phy_drv->phy_function_reset(dev_id, phy_addr, PHY_FIFO_RESET);
SW_RTN_ON_ERROR (rv);
+#endif
} else if (port_id == SSDK_PHYSICAL_PORT2) {
rv = adpt_mp_uniphy_adapter_port_reset(dev_id, port_id);
} else {
diff --git a/src/hsl/phy/Makefile b/src/hsl/phy/Makefile
index 68d0679f..0eae9377 100755
--- a/src/hsl/phy/Makefile
+++ b/src/hsl/phy/Makefile
@@ -23,7 +23,7 @@ ifeq (ISIS, $(CHIP_TYPE))
SRC_LIST = f1_phy.c
endif
-ifeq (MP, $(CHIP_TYPE))
+ifeq (TRUE, $(IN_MP_PHY))
SRC_LIST = mpge_phy.c
ifeq (TRUE, $(IN_LED))
SRC_LIST += mpge_led.c
@@ -40,12 +40,6 @@ endif
ifeq (ALL_CHIP, $(CHIP_TYPE))
SRC_LIST = f1_phy.c f2_phy.c malibu_phy.c
-ifneq (,$(filter MP, $(SUPPORT_CHIP)))
- SRC_LIST += mpge_phy.c
-ifeq (TRUE, $(IN_LED))
- SRC_LIST += mpge_led.c
-endif
-endif
endif
ifeq (NONHK_CHIP, $(CHIP_TYPE))
diff --git a/src/hsl/phy/hsl_phy.c b/src/hsl/phy/hsl_phy.c
index f2cf90e2..efab2343 100644
--- a/src/hsl/phy/hsl_phy.c
+++ b/src/hsl/phy/hsl_phy.c
@@ -28,7 +28,7 @@
#if defined(ATHENA) ||defined(SHIVA) ||defined(HORUS)
#include <f2_phy.h>
#endif
-#ifdef MP
+#ifdef IN_MP_PHY
#include "mpge_phy.h"
#endif
#ifdef IN_MALIBU_PHY
@@ -94,7 +94,7 @@ phy_driver_instance_t ssdk_phy_driver[] =
#else
{SFP_PHY_CHIP, {0}, NULL, NULL, NULL},
#endif
- #ifdef MP
+ #ifdef IN_MP_PHY
{MPGE_PHY_CHIP, {0}, NULL, mpge_phy_init, NULL},
#else
{MPGE_PHY_CHIP, {0}, NULL, NULL, NULL},
--
2.40.1

View File

@ -0,0 +1,40 @@
From 01fb404dbda1872ad99cea88bf43313bed30200a Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 15:24:07 +0800
Subject: [PATCH] init: MP: allow to ignore reset controlls
The SSDK is not used anymore to initialize the internal IPQ5018 GE PHY as
there is a separate driver pending upstream review/approval:
https://lore.kernel.org/all/TYZPR01MB5556D5568546D6DA4313209EC9762@ \
TYZPR01MB5556.apcprd01.prod.exchangelabs.com/
As such, change the code to not error out when the reset controls aren't
found in the DTS where the SSDK expects them. These resets are now defined
under the definition based on the new driver mentioned above.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
src/init/ssdk_clk.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/init/ssdk_clk.c b/src/init/ssdk_clk.c
index 71e59452..bc244c6e 100644
--- a/src/init/ssdk_clk.c
+++ b/src/init/ssdk_clk.c
@@ -1282,10 +1282,8 @@ ssdk_mp_reset_init(void)
for (i = 0; i < MP_BCR_RST_MAX; i++) {
rst = of_reset_control_get(rst_node, mp_rst_ids[i]);
- if (IS_ERR(rst)) {
- SSDK_ERROR("%s not exist!\n", mp_rst_ids[i]);
- return;
- }
+ if (IS_ERR(rst))
+ continue;
ssdk_gcc_reset(rst, SSDK_RESET_ASSERT);
msleep(200);
ssdk_gcc_reset(rst, SSDK_RESET_DEASSERT);
--
2.40.1

View File

@ -0,0 +1,82 @@
From a4378eb29c7b9dd95601d20f507a2220457f8ede Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 15:24:07 +0800
Subject: [PATCH] MP: fix build issues
Enable the IN_VSI make flag which enables macro definitions needed to
successfully compile the SSDK for the ipq50xx target. In addition, fix an
incorrect return type by expanding the macro called and return a boolean
instead of an integer.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
config | 30 +-----------------------------
src/adpt/mp/adpt_mp_portctrl.c | 3 ++-
2 files changed, 3 insertions(+), 30 deletions(-)
diff --git a/config b/config
index 1f74e4f8..58d67648 100644
--- a/config
+++ b/config
@@ -374,6 +374,7 @@ ifneq (, $(filter MPPE APPE HPPE CPPE ALL_CHIP, $(CHIP_TYPE)))
endif
ifneq (, $(filter MP, $(CHIP_TYPE)))
+ IN_VSI=TRUE
IN_UNIPHY=TRUE
endif
@@ -436,35 +437,6 @@ endif
# SDK Features According To Specfic Switch #
#############################################
ifeq (MP, $(CHIP_TYPE))
- ifeq (disable, $(ISISC_ENABLE))
- IN_ACL=FALSE
- IN_FDB=FALSE
- IN_IGMP=FALSE
- IN_LEAKY=FALSE
- IN_LED=FALSE
- IN_MIRROR=FALSE
- IN_MISC=FALSE
- IN_PORTVLAN=FALSE
- IN_QOS=FALSE
- IN_RATE=FALSE
- IN_STP=FALSE
- IN_VLAN=FALSE
- IN_REDUCED_ACL=FALSE
- IN_COSMAP=FALSE
- IN_IP=FALSE
- IN_NAT=FALSE
- IN_FLOW=FALSE
- IN_TRUNK=FALSE
- IN_RSS_HASH=FALSE
- IN_SEC=FALSE
- IN_QM=FALSE
- IN_PPPOE=FALSE
- IN_VSI=FALSE
- IN_SERVCODE=FALSE
- IN_BM=FALSE
- IN_SHAPER=FALSE
- IN_POLICER=FALSE
- endif
IN_CTRLPKT=TRUE
endif
diff --git a/src/adpt/mp/adpt_mp_portctrl.c b/src/adpt/mp/adpt_mp_portctrl.c
index db60fc72..c230e214 100644
--- a/src/adpt/mp/adpt_mp_portctrl.c
+++ b/src/adpt/mp/adpt_mp_portctrl.c
@@ -45,7 +45,8 @@ _adpt_mp_gcc_mac_clock_set(a_uint32_t dev_id,
static a_bool_t
_adpt_mp_port_phy_connected (a_uint32_t dev_id, fal_port_t port_id)
{
- ADPT_DEV_ID_CHECK(dev_id);
+ if (dev_id >= SW_MAX_NR_DEV)
+ return A_FALSE;
/* force port which connect s17c or other device chip*/
if (hsl_port_feature_get(dev_id, port_id, PHY_F_FORCE | PHY_F_SFP)) {
--
2.40.1

View File

@ -0,0 +1,57 @@
From a90a9f3e2a21cb87c2cbf2ddb999846aa614e88a Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 15:24:07 +0800
Subject: [PATCH 2/2] init: replace ioremap_nocache() with ioremap()
As per https://lore.kernel.org/linux-mips/20191209194819.GA28157@lst.de/T/,
ioremap_nocache is deprecated so let's replace all calls by ioremap instead.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
src/init/ssdk_clk.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/init/ssdk_clk.c b/src/init/ssdk_clk.c
index bc244c6e..dc45691e 100644
--- a/src/init/ssdk_clk.c
+++ b/src/init/ssdk_clk.c
@@ -1183,7 +1183,7 @@ ssdk_mp_tcsr_get(a_uint32_t tcsr_offset, a_uint32_t *tcsr_val)
{
void __iomem *tcsr_base = NULL;
- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE);
+ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE);
if (!tcsr_base)
{
SSDK_ERROR("Failed to map tcsr eth address!\n");
@@ -1200,7 +1200,7 @@ ssdk_mp_tcsr_set(a_uint32_t tcsr_offset, a_uint32_t tcsr_val)
{
void __iomem *tcsr_base = NULL;
- tcsr_base = ioremap_nocache(TCSR_ETH_ADDR, TCSR_ETH_SIZE);
+ tcsr_base = ioremap(TCSR_ETH_ADDR, TCSR_ETH_SIZE);
if (!tcsr_base)
{
SSDK_ERROR("Failed to map tcsr eth address!\n");
@@ -1248,7 +1248,7 @@ ssdk_mp_cmnblk_stable_check(void)
a_uint32_t reg_val;
int i, loops = 20;
- pll_lock = ioremap_nocache(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE);
+ pll_lock = ioremap(CMN_PLL_LOCKED_ADDR, CMN_PLL_LOCKED_SIZE);
if (!pll_lock) {
SSDK_ERROR("Failed to map CMN PLL LOCK register!\n");
return A_FALSE;
@@ -1303,7 +1303,7 @@ static void ssdk_cmnblk_pll_src_set(enum cmnblk_pll_src_type pll_source)
void __iomem *cmn_pll_src_base = NULL;
a_uint32_t reg_val;
- cmn_pll_src_base = ioremap_nocache(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE);
+ cmn_pll_src_base = ioremap(CMN_BLK_PLL_SRC_ADDR, CMN_BLK_SIZE);
if (!cmn_pll_src_base) {
SSDK_ERROR("Failed to map cmn pll source address!\n");
return;
--
2.40.1

View File

@ -1,12 +1,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=r8168
PKG_VERSION:=8.054.00
PKG_VERSION:=8.055.00
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=https://github.com/openwrt/rtl8168/releases/download/$(PKG_VERSION)
PKG_HASH:=5480120cf823e991e8cbd325118c1ec0c57d8f42760ba1a7334bd07d291d235d
PKG_HASH:=61deb2a9cb7d6b08748ad51734b108da95d629712b64b204e2e6bd3f16d0a48f
PKG_BUILD_PARALLEL:=1
PKG_LICENSE:=GPLv2

View File

@ -13,7 +13,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
--- a/src/r8168_n.c
+++ b/src/r8168_n.c
@@ -1655,9 +1655,9 @@ static int proc_dump_rx_desc_2(struct se
@@ -1668,9 +1668,9 @@ static int proc_dump_rx_desc_2(struct se
j, k);
for (i=0; i<(tp->RxDescLength/4); i++) {
if (!(i % 4))

View File

@ -18,7 +18,7 @@ Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
--- a/src/r8168.h
+++ b/src/r8168.h
@@ -1468,6 +1468,8 @@ enum RTL8168_register_content {
@@ -1480,6 +1480,8 @@ enum RTL8168_register_content {
LinkStatus = 0x02,
FullDup = 0x01,
@ -37,7 +37,7 @@ Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
@@ -5369,6 +5370,36 @@ rtl8168_link_down_patch(struct net_devic
@@ -5396,6 +5397,38 @@ rtl8168_link_down_patch(struct net_devic
#endif
}
@ -66,6 +66,8 @@ Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
+ speed = SPEED_100;
+ else if (status & _10bps)
+ speed = SPEED_10;
+ else if (eee_giga_lite)
+ speed = SPEED_1000;
+ }
+
+ return speed;
@ -74,7 +76,7 @@ Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
static void
rtl8168_check_link_status(struct net_device *dev)
{
@@ -5388,11 +5419,18 @@ rtl8168_check_link_status(struct net_dev
@@ -5415,11 +5448,18 @@ rtl8168_check_link_status(struct net_dev
if (link_status_on) {
rtl8168_link_on_patch(dev);

View File

@ -0,0 +1,66 @@
From d48a5472b8f2b29800bb25913f9403765005f1bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Mon, 18 Sep 2023 21:19:14 +0200
Subject: [PATCH] net: dsa: realtek: Convert to platform remove callback
returning void
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The .remove() callback for a platform driver returns an int which makes
many driver authors wrongly assume it's possible to do error handling by
returning an error code. However the value returned is ignored (apart
from emitting a warning) and this typically results in resource leaks.
To improve here there is a quest to make the remove callback return
void. In the first step of this quest all drivers are converted to
.remove_new() which already returns void. Eventually after all drivers
are converted, .remove_new() is renamed to .remove().
Trivially convert this driver from always returning zero in the remove
callback to the void returning variant.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
drivers/net/dsa/realtek/realtek-smi.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -506,12 +506,12 @@ static int realtek_smi_probe(struct plat
return 0;
}
-static int realtek_smi_remove(struct platform_device *pdev)
+static void realtek_smi_remove(struct platform_device *pdev)
{
struct realtek_priv *priv = platform_get_drvdata(pdev);
if (!priv)
- return 0;
+ return;
dsa_unregister_switch(priv->ds);
if (priv->slave_mii_bus)
@@ -520,8 +520,6 @@ static int realtek_smi_remove(struct pla
/* leave the device reset asserted */
if (priv->reset)
gpiod_set_value(priv->reset, 1);
-
- return 0;
}
static void realtek_smi_shutdown(struct platform_device *pdev)
@@ -559,7 +557,7 @@ static struct platform_driver realtek_sm
.of_match_table = realtek_smi_of_match,
},
.probe = realtek_smi_probe,
- .remove = realtek_smi_remove,
+ .remove_new = realtek_smi_remove,
.shutdown = realtek_smi_shutdown,
};
module_platform_driver(realtek_smi_driver);

View File

@ -0,0 +1,30 @@
From 33f4336cbd32c21717b60d013693a0bd51a27db6 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:37 -0300
Subject: net: dsa: realtek: drop cleanup from realtek_ops
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It was never used and never referenced.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek.h | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -91,7 +91,6 @@ struct realtek_ops {
int (*detect)(struct realtek_priv *priv);
int (*reset_chip)(struct realtek_priv *priv);
int (*setup)(struct realtek_priv *priv);
- void (*cleanup)(struct realtek_priv *priv);
int (*get_mib_counter)(struct realtek_priv *priv,
int port,
struct rtl8366_mib_counter *mib,

View File

@ -0,0 +1,146 @@
From ded3813b44fe11a3bbd2c9d7df8870e8c19a7ccd Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:38 -0300
Subject: net: dsa: realtek: introduce REALTEK_DSA namespace
Create a namespace to group the exported symbols.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-mdio.c | 1 +
drivers/net/dsa/realtek/realtek-smi.c | 1 +
drivers/net/dsa/realtek/rtl8365mb.c | 1 +
drivers/net/dsa/realtek/rtl8366-core.c | 22 +++++++++++-----------
drivers/net/dsa/realtek/rtl8366rb.c | 1 +
5 files changed, 15 insertions(+), 11 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -288,3 +288,4 @@ mdio_module_driver(realtek_mdio_driver);
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(REALTEK_DSA);
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -565,3 +565,4 @@ module_platform_driver(realtek_smi_drive
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(REALTEK_DSA);
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -2178,3 +2178,4 @@ EXPORT_SYMBOL_GPL(rtl8365mb_variant);
MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(REALTEK_DSA);
--- a/drivers/net/dsa/realtek/rtl8366-core.c
+++ b/drivers/net/dsa/realtek/rtl8366-core.c
@@ -34,7 +34,7 @@ int rtl8366_mc_is_used(struct realtek_pr
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
+EXPORT_SYMBOL_NS_GPL(rtl8366_mc_is_used, REALTEK_DSA);
/**
* rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
@@ -187,7 +187,7 @@ int rtl8366_set_vlan(struct realtek_priv
return ret;
}
-EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_vlan, REALTEK_DSA);
int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
unsigned int vid)
@@ -217,7 +217,7 @@ int rtl8366_set_pvid(struct realtek_priv
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_pvid, REALTEK_DSA);
int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable)
{
@@ -243,7 +243,7 @@ int rtl8366_enable_vlan4k(struct realtek
priv->vlan4k_enabled = enable;
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan4k, REALTEK_DSA);
int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable)
{
@@ -265,7 +265,7 @@ int rtl8366_enable_vlan(struct realtek_p
return ret;
}
-EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan, REALTEK_DSA);
int rtl8366_reset_vlan(struct realtek_priv *priv)
{
@@ -290,7 +290,7 @@ int rtl8366_reset_vlan(struct realtek_pr
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_reset_vlan);
+EXPORT_SYMBOL_NS_GPL(rtl8366_reset_vlan, REALTEK_DSA);
int rtl8366_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@@ -345,7 +345,7 @@ int rtl8366_vlan_add(struct dsa_switch *
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_add, REALTEK_DSA);
int rtl8366_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
@@ -389,7 +389,7 @@ int rtl8366_vlan_del(struct dsa_switch *
return 0;
}
-EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_del, REALTEK_DSA);
void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
uint8_t *data)
@@ -407,7 +407,7 @@ void rtl8366_get_strings(struct dsa_swit
mib->name, ETH_GSTRING_LEN);
}
}
-EXPORT_SYMBOL_GPL(rtl8366_get_strings);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_strings, REALTEK_DSA);
int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
{
@@ -421,7 +421,7 @@ int rtl8366_get_sset_count(struct dsa_sw
return priv->num_mib_counters;
}
-EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_sset_count, REALTEK_DSA);
void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
@@ -445,4 +445,4 @@ void rtl8366_get_ethtool_stats(struct ds
data[i] = mibvalue;
}
}
-EXPORT_SYMBOL_GPL(rtl8366_get_ethtool_stats);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_ethtool_stats, REALTEK_DSA);
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1852,3 +1852,4 @@ EXPORT_SYMBOL_GPL(rtl8366rb_variant);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(REALTEK_DSA);

View File

@ -0,0 +1,539 @@
From bce254b839abe67577bebdef0838796af409c229 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:39 -0300
Subject: net: dsa: realtek: convert variants into real drivers
Previously, the interface modules realtek-smi and realtek-mdio served as
a platform and an MDIO driver, respectively. Each interface module
redundantly specified the same compatible strings for both variants and
referenced symbols from the variants.
Now, each variant module has been transformed into a unified driver
serving both as a platform and an MDIO driver. This modification
reverses the relationship between the interface and variant modules,
with the variant module now utilizing symbols from the interface
modules.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/Kconfig | 20 +++----
drivers/net/dsa/realtek/realtek-mdio.c | 68 +++++++++++++++---------
drivers/net/dsa/realtek/realtek-mdio.h | 48 +++++++++++++++++
drivers/net/dsa/realtek/realtek-smi.c | 73 +++++++++++++++-----------
drivers/net/dsa/realtek/realtek-smi.h | 48 +++++++++++++++++
drivers/net/dsa/realtek/rtl8365mb.c | 54 ++++++++++++++++++-
drivers/net/dsa/realtek/rtl8366rb.c | 54 ++++++++++++++++++-
7 files changed, 292 insertions(+), 73 deletions(-)
create mode 100644 drivers/net/dsa/realtek/realtek-mdio.h
create mode 100644 drivers/net/dsa/realtek/realtek-smi.h
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK
if NET_DSA_REALTEK
config NET_DSA_REALTEK_MDIO
- tristate "Realtek MDIO interface driver"
+ tristate "Realtek MDIO interface support"
depends on OF
- depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
- depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
- depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
help
Select to enable support for registering switches configured
through MDIO.
config NET_DSA_REALTEK_SMI
- tristate "Realtek SMI interface driver"
+ tristate "Realtek SMI interface support"
depends on OF
- depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
- depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
- depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
help
Select to enable support for registering switches connected
through SMI.
config NET_DSA_REALTEK_RTL8365MB
- tristate "Realtek RTL8365MB switch subdriver"
- imply NET_DSA_REALTEK_SMI
- imply NET_DSA_REALTEK_MDIO
+ tristate "Realtek RTL8365MB switch driver"
+ depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
select NET_DSA_TAG_RTL8_4
help
Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
config NET_DSA_REALTEK_RTL8366RB
- tristate "Realtek RTL8366RB switch subdriver"
- imply NET_DSA_REALTEK_SMI
- imply NET_DSA_REALTEK_MDIO
+ tristate "Realtek RTL8366RB switch driver"
+ depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
select NET_DSA_TAG_RTL4_A
help
Select to enable support for Realtek RTL8366RB.
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -25,6 +25,7 @@
#include <linux/regmap.h>
#include "realtek.h"
+#include "realtek-mdio.h"
/* Read/write via mdiobus */
#define REALTEK_MDIO_CTRL0_REG 31
@@ -140,7 +141,19 @@ static const struct regmap_config realte
.disable_locking = true,
};
-static int realtek_mdio_probe(struct mdio_device *mdiodev)
+/**
+ * realtek_mdio_probe() - Probe a platform device for an MDIO-connected switch
+ * @mdiodev: mdio_device to probe on.
+ *
+ * This function should be used as the .probe in an mdio_driver. It
+ * initializes realtek_priv and read data from the device-tree node. The switch
+ * is hard reset if a method is provided. It checks the switch chip ID and,
+ * finally, a DSA switch is registered.
+ *
+ * Context: Can sleep. Takes and releases priv->map_lock.
+ * Return: Returns 0 on success, a negative error on failure.
+ */
+int realtek_mdio_probe(struct mdio_device *mdiodev)
{
struct realtek_priv *priv;
struct device *dev = &mdiodev->dev;
@@ -235,8 +248,20 @@ static int realtek_mdio_probe(struct mdi
return 0;
}
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe, REALTEK_DSA);
-static void realtek_mdio_remove(struct mdio_device *mdiodev)
+/**
+ * realtek_mdio_remove() - Remove the driver of an MDIO-connected switch
+ * @mdiodev: mdio_device to be removed.
+ *
+ * This function should be used as the .remove_new in an mdio_driver. First
+ * it unregisters the DSA switch and cleans internal data. If a method is
+ * provided, the hard reset is asserted to avoid traffic leakage.
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void realtek_mdio_remove(struct mdio_device *mdiodev)
{
struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
@@ -249,8 +274,21 @@ static void realtek_mdio_remove(struct m
if (priv->reset)
gpiod_set_value(priv->reset, 1);
}
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, REALTEK_DSA);
-static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
+/**
+ * realtek_mdio_shutdown() - Shutdown the driver of a MDIO-connected switch
+ * @mdiodev: mdio_device shutting down.
+ *
+ * This function should be used as the .shutdown in an mdio_driver. It shuts
+ * down the DSA switch and cleans the platform driver data, to prevent
+ * realtek_mdio_remove() from running afterwards, which is possible if the
+ * parent bus implements its own .shutdown() as .remove().
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void realtek_mdio_shutdown(struct mdio_device *mdiodev)
{
struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
@@ -261,29 +299,7 @@ static void realtek_mdio_shutdown(struct
dev_set_drvdata(&mdiodev->dev, NULL);
}
-
-static const struct of_device_id realtek_mdio_of_match[] = {
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
- { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
- { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
-#endif
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, realtek_mdio_of_match);
-
-static struct mdio_driver realtek_mdio_driver = {
- .mdiodrv.driver = {
- .name = "realtek-mdio",
- .of_match_table = realtek_mdio_of_match,
- },
- .probe = realtek_mdio_probe,
- .remove = realtek_mdio_remove,
- .shutdown = realtek_mdio_shutdown,
-};
-
-mdio_module_driver(realtek_mdio_driver);
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-mdio.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _REALTEK_MDIO_H
+#define _REALTEK_MDIO_H
+
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO)
+
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
+{
+ return mdio_driver_register(drv);
+}
+
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
+{
+ mdio_driver_unregister(drv);
+}
+
+int realtek_mdio_probe(struct mdio_device *mdiodev);
+void realtek_mdio_remove(struct mdio_device *mdiodev);
+void realtek_mdio_shutdown(struct mdio_device *mdiodev);
+
+#else /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO) */
+
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
+{
+ return 0;
+}
+
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
+{
+}
+
+static inline int realtek_mdio_probe(struct mdio_device *mdiodev)
+{
+ return -ENOENT;
+}
+
+static inline void realtek_mdio_remove(struct mdio_device *mdiodev)
+{
+}
+
+static inline void realtek_mdio_shutdown(struct mdio_device *mdiodev)
+{
+}
+
+#endif /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO) */
+
+#endif /* _REALTEK_MDIO_H */
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -40,6 +40,7 @@
#include <linux/if_bridge.h>
#include "realtek.h"
+#include "realtek-smi.h"
#define REALTEK_SMI_ACK_RETRY_COUNT 5
@@ -408,7 +409,19 @@ err_put_node:
return ret;
}
-static int realtek_smi_probe(struct platform_device *pdev)
+/**
+ * realtek_smi_probe() - Probe a platform device for an SMI-connected switch
+ * @pdev: platform_device to probe on.
+ *
+ * This function should be used as the .probe in a platform_driver. It
+ * initializes realtek_priv and read data from the device-tree node. The switch
+ * is hard reset if a method is provided. It checks the switch chip ID and,
+ * finally, a DSA switch is registered.
+ *
+ * Context: Can sleep. Takes and releases priv->map_lock.
+ * Return: Returns 0 on success, a negative error on failure.
+ */
+int realtek_smi_probe(struct platform_device *pdev)
{
const struct realtek_variant *var;
struct device *dev = &pdev->dev;
@@ -505,8 +518,20 @@ static int realtek_smi_probe(struct plat
}
return 0;
}
+EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
-static void realtek_smi_remove(struct platform_device *pdev)
+/**
+ * realtek_smi_remove() - Remove the driver of a SMI-connected switch
+ * @pdev: platform_device to be removed.
+ *
+ * This function should be used as the .remove_new in a platform_driver. First
+ * it unregisters the DSA switch and cleans internal data. If a method is
+ * provided, the hard reset is asserted to avoid traffic leakage.
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void realtek_smi_remove(struct platform_device *pdev)
{
struct realtek_priv *priv = platform_get_drvdata(pdev);
@@ -521,8 +546,21 @@ static void realtek_smi_remove(struct pl
if (priv->reset)
gpiod_set_value(priv->reset, 1);
}
+EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
-static void realtek_smi_shutdown(struct platform_device *pdev)
+/**
+ * realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
+ * @pdev: platform_device shutting down.
+ *
+ * This function should be used as the .shutdown in a platform_driver. It shuts
+ * down the DSA switch and cleans the platform driver data, to prevent
+ * realtek_smi_remove() from running afterwards, which is possible if the
+ * parent bus implements its own .shutdown() as .remove().
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void realtek_smi_shutdown(struct platform_device *pdev)
{
struct realtek_priv *priv = platform_get_drvdata(pdev);
@@ -533,34 +571,7 @@ static void realtek_smi_shutdown(struct
platform_set_drvdata(pdev, NULL);
}
-
-static const struct of_device_id realtek_smi_of_match[] = {
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
- {
- .compatible = "realtek,rtl8366rb",
- .data = &rtl8366rb_variant,
- },
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
- {
- .compatible = "realtek,rtl8365mb",
- .data = &rtl8365mb_variant,
- },
-#endif
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
-
-static struct platform_driver realtek_smi_driver = {
- .driver = {
- .name = "realtek-smi",
- .of_match_table = realtek_smi_of_match,
- },
- .probe = realtek_smi_probe,
- .remove_new = realtek_smi_remove,
- .shutdown = realtek_smi_shutdown,
-};
-module_platform_driver(realtek_smi_driver);
+EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-smi.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _REALTEK_SMI_H
+#define _REALTEK_SMI_H
+
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI)
+
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
+{
+ return platform_driver_register(drv);
+}
+
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
+{
+ platform_driver_unregister(drv);
+}
+
+int realtek_smi_probe(struct platform_device *pdev);
+void realtek_smi_remove(struct platform_device *pdev);
+void realtek_smi_shutdown(struct platform_device *pdev);
+
+#else /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI) */
+
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
+{
+ return 0;
+}
+
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
+{
+}
+
+static inline int realtek_smi_probe(struct platform_device *pdev)
+{
+ return -ENOENT;
+}
+
+static inline void realtek_smi_remove(struct platform_device *pdev)
+{
+}
+
+static inline void realtek_smi_shutdown(struct platform_device *pdev)
+{
+}
+
+#endif /* IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI) */
+
+#endif /* _REALTEK_SMI_H */
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -101,6 +101,8 @@
#include <linux/if_vlan.h>
#include "realtek.h"
+#include "realtek-smi.h"
+#include "realtek-mdio.h"
/* Family-specific data and limits */
#define RTL8365MB_PHYADDRMAX 7
@@ -2173,7 +2175,57 @@ const struct realtek_variant rtl8365mb_v
.cmd_write = 0xb8,
.chip_data_sz = sizeof(struct rtl8365mb),
};
-EXPORT_SYMBOL_GPL(rtl8365mb_variant);
+
+static const struct of_device_id rtl8365mb_of_match[] = {
+ { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rtl8365mb_of_match);
+
+static struct platform_driver rtl8365mb_smi_driver = {
+ .driver = {
+ .name = "rtl8365mb-smi",
+ .of_match_table = rtl8365mb_of_match,
+ },
+ .probe = realtek_smi_probe,
+ .remove_new = realtek_smi_remove,
+ .shutdown = realtek_smi_shutdown,
+};
+
+static struct mdio_driver rtl8365mb_mdio_driver = {
+ .mdiodrv.driver = {
+ .name = "rtl8365mb-mdio",
+ .of_match_table = rtl8365mb_of_match,
+ },
+ .probe = realtek_mdio_probe,
+ .remove = realtek_mdio_remove,
+ .shutdown = realtek_mdio_shutdown,
+};
+
+static int rtl8365mb_init(void)
+{
+ int ret;
+
+ ret = realtek_mdio_driver_register(&rtl8365mb_mdio_driver);
+ if (ret)
+ return ret;
+
+ ret = realtek_smi_driver_register(&rtl8365mb_smi_driver);
+ if (ret) {
+ realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
+ return ret;
+ }
+
+ return 0;
+}
+module_init(rtl8365mb_init);
+
+static void __exit rtl8365mb_exit(void)
+{
+ realtek_smi_driver_unregister(&rtl8365mb_smi_driver);
+ realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
+}
+module_exit(rtl8365mb_exit);
MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -22,6 +22,8 @@
#include <linux/regmap.h>
#include "realtek.h"
+#include "realtek-smi.h"
+#include "realtek-mdio.h"
#define RTL8366RB_PORT_NUM_CPU 5
#define RTL8366RB_NUM_PORTS 6
@@ -1847,7 +1849,57 @@ const struct realtek_variant rtl8366rb_v
.cmd_write = 0xa8,
.chip_data_sz = sizeof(struct rtl8366rb),
};
-EXPORT_SYMBOL_GPL(rtl8366rb_variant);
+
+static const struct of_device_id rtl8366rb_of_match[] = {
+ { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rtl8366rb_of_match);
+
+static struct platform_driver rtl8366rb_smi_driver = {
+ .driver = {
+ .name = "rtl8366rb-smi",
+ .of_match_table = rtl8366rb_of_match,
+ },
+ .probe = realtek_smi_probe,
+ .remove_new = realtek_smi_remove,
+ .shutdown = realtek_smi_shutdown,
+};
+
+static struct mdio_driver rtl8366rb_mdio_driver = {
+ .mdiodrv.driver = {
+ .name = "rtl8366rb-mdio",
+ .of_match_table = rtl8366rb_of_match,
+ },
+ .probe = realtek_mdio_probe,
+ .remove = realtek_mdio_remove,
+ .shutdown = realtek_mdio_shutdown,
+};
+
+static int rtl8366rb_init(void)
+{
+ int ret;
+
+ ret = realtek_mdio_driver_register(&rtl8366rb_mdio_driver);
+ if (ret)
+ return ret;
+
+ ret = realtek_smi_driver_register(&rtl8366rb_smi_driver);
+ if (ret) {
+ realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
+ return ret;
+ }
+
+ return 0;
+}
+module_init(rtl8366rb_init);
+
+static void __exit rtl8366rb_exit(void)
+{
+ realtek_smi_driver_unregister(&rtl8366rb_smi_driver);
+ realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
+}
+module_exit(rtl8366rb_exit);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");

View File

@ -0,0 +1,91 @@
From 4667a1db2f550d23e01ba655fce331196ead6e92 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:40 -0300
Subject: net: dsa: realtek: keep variant reference in
realtek_priv
Instead of copying values from the variant, we can keep a reference in
realtek_priv.
This is a preliminary change for sharing code betwen interfaces. It will
allow to move most of the probe into a common module while still allow
code specific to each interface to read variant fields.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-mdio.c | 4 +---
drivers/net/dsa/realtek/realtek-smi.c | 10 ++++------
drivers/net/dsa/realtek/realtek.h | 5 ++---
3 files changed, 7 insertions(+), 12 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -196,9 +196,7 @@ int realtek_mdio_probe(struct mdio_devic
priv->dev = &mdiodev->dev;
priv->chip_data = (void *)priv + sizeof(*priv);
- priv->clk_delay = var->clk_delay;
- priv->cmd_read = var->cmd_read;
- priv->cmd_write = var->cmd_write;
+ priv->variant = var;
priv->ops = var->ops;
priv->write_reg_noack = realtek_mdio_write;
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -46,7 +46,7 @@
static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
{
- ndelay(priv->clk_delay);
+ ndelay(priv->variant->clk_delay);
}
static void realtek_smi_start(struct realtek_priv *priv)
@@ -209,7 +209,7 @@ static int realtek_smi_read_reg(struct r
realtek_smi_start(priv);
/* Send READ command */
- ret = realtek_smi_write_byte(priv, priv->cmd_read);
+ ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
if (ret)
goto out;
@@ -250,7 +250,7 @@ static int realtek_smi_write_reg(struct
realtek_smi_start(priv);
/* Send WRITE command */
- ret = realtek_smi_write_byte(priv, priv->cmd_write);
+ ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
if (ret)
goto out;
@@ -459,9 +459,7 @@ int realtek_smi_probe(struct platform_de
/* Link forward and backward */
priv->dev = dev;
- priv->clk_delay = var->clk_delay;
- priv->cmd_read = var->cmd_read;
- priv->cmd_write = var->cmd_write;
+ priv->variant = var;
priv->ops = var->ops;
priv->setup_interface = realtek_smi_setup_mdio;
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -58,9 +58,8 @@ struct realtek_priv {
struct mii_bus *bus;
int mdio_addr;
- unsigned int clk_delay;
- u8 cmd_read;
- u8 cmd_write;
+ const struct realtek_variant *variant;
+
spinlock_t lock; /* Locks around command writes */
struct dsa_switch *ds;
struct irq_domain *irqdomain;

View File

@ -0,0 +1,875 @@
From 8be040ecd94c1a9a137927d18534edfae0a9b68a Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:41 -0300
Subject: net: dsa: realtek: common rtl83xx module
Some code can be shared between both interface modules (MDIO and SMI)
and among variants. These interface functions migrated to a common
module:
- rtl83xx_lock
- rtl83xx_unlock
- rtl83xx_probe
- rtl83xx_register_switch
- rtl83xx_unregister_switch
- rtl83xx_shutdown
- rtl83xx_remove
The reset during probe was moved to the end of the common probe. This way,
we avoid a reset if anything else fails.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/Makefile | 2 +
drivers/net/dsa/realtek/realtek-mdio.c | 152 +++-------------
drivers/net/dsa/realtek/realtek-smi.c | 166 ++++-------------
drivers/net/dsa/realtek/realtek.h | 1 +
drivers/net/dsa/realtek/rtl8365mb.c | 9 +-
drivers/net/dsa/realtek/rtl8366rb.c | 9 +-
drivers/net/dsa/realtek/rtl83xx.c | 235 +++++++++++++++++++++++++
drivers/net/dsa/realtek/rtl83xx.h | 21 +++
8 files changed, 322 insertions(+), 273 deletions(-)
create mode 100644 drivers/net/dsa/realtek/rtl83xx.c
create mode 100644 drivers/net/dsa/realtek/rtl83xx.h
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_NET_DSA_REALTEK) += realtek_dsa.o
+realtek_dsa-objs := rtl83xx.o
obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -26,6 +26,7 @@
#include "realtek.h"
#include "realtek-mdio.h"
+#include "rtl83xx.h"
/* Read/write via mdiobus */
#define REALTEK_MDIO_CTRL0_REG 31
@@ -100,147 +101,41 @@ out_unlock:
return ret;
}
-static void realtek_mdio_lock(void *ctx)
-{
- struct realtek_priv *priv = ctx;
-
- mutex_lock(&priv->map_lock);
-}
-
-static void realtek_mdio_unlock(void *ctx)
-{
- struct realtek_priv *priv = ctx;
-
- mutex_unlock(&priv->map_lock);
-}
-
-static const struct regmap_config realtek_mdio_regmap_config = {
- .reg_bits = 10, /* A4..A0 R4..R0 */
- .val_bits = 16,
- .reg_stride = 1,
- /* PHY regs are at 0x8000 */
- .max_register = 0xffff,
- .reg_format_endian = REGMAP_ENDIAN_BIG,
+static const struct realtek_interface_info realtek_mdio_info = {
.reg_read = realtek_mdio_read,
.reg_write = realtek_mdio_write,
- .cache_type = REGCACHE_NONE,
- .lock = realtek_mdio_lock,
- .unlock = realtek_mdio_unlock,
-};
-
-static const struct regmap_config realtek_mdio_nolock_regmap_config = {
- .reg_bits = 10, /* A4..A0 R4..R0 */
- .val_bits = 16,
- .reg_stride = 1,
- /* PHY regs are at 0x8000 */
- .max_register = 0xffff,
- .reg_format_endian = REGMAP_ENDIAN_BIG,
- .reg_read = realtek_mdio_read,
- .reg_write = realtek_mdio_write,
- .cache_type = REGCACHE_NONE,
- .disable_locking = true,
};
/**
* realtek_mdio_probe() - Probe a platform device for an MDIO-connected switch
* @mdiodev: mdio_device to probe on.
*
- * This function should be used as the .probe in an mdio_driver. It
- * initializes realtek_priv and read data from the device-tree node. The switch
- * is hard reset if a method is provided. It checks the switch chip ID and,
- * finally, a DSA switch is registered.
+ * This function should be used as the .probe in an mdio_driver. After
+ * calling the common probe function for both interfaces, it initializes the
+ * values specific for MDIO-connected devices. Finally, it calls a common
+ * function to register the DSA switch.
*
* Context: Can sleep. Takes and releases priv->map_lock.
* Return: Returns 0 on success, a negative error on failure.
*/
int realtek_mdio_probe(struct mdio_device *mdiodev)
{
- struct realtek_priv *priv;
struct device *dev = &mdiodev->dev;
- const struct realtek_variant *var;
- struct regmap_config rc;
- struct device_node *np;
+ struct realtek_priv *priv;
int ret;
- var = of_device_get_match_data(dev);
- if (!var)
- return -EINVAL;
-
- priv = devm_kzalloc(&mdiodev->dev,
- size_add(sizeof(*priv), var->chip_data_sz),
- GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- mutex_init(&priv->map_lock);
-
- rc = realtek_mdio_regmap_config;
- rc.lock_arg = priv;
- priv->map = devm_regmap_init(dev, NULL, priv, &rc);
- if (IS_ERR(priv->map)) {
- ret = PTR_ERR(priv->map);
- dev_err(dev, "regmap init failed: %d\n", ret);
- return ret;
- }
+ priv = rtl83xx_probe(dev, &realtek_mdio_info);
+ if (IS_ERR(priv))
+ return PTR_ERR(priv);
- rc = realtek_mdio_nolock_regmap_config;
- priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
- if (IS_ERR(priv->map_nolock)) {
- ret = PTR_ERR(priv->map_nolock);
- dev_err(dev, "regmap init failed: %d\n", ret);
- return ret;
- }
-
- priv->mdio_addr = mdiodev->addr;
priv->bus = mdiodev->bus;
- priv->dev = &mdiodev->dev;
- priv->chip_data = (void *)priv + sizeof(*priv);
-
- priv->variant = var;
- priv->ops = var->ops;
-
+ priv->mdio_addr = mdiodev->addr;
priv->write_reg_noack = realtek_mdio_write;
+ priv->ds_ops = priv->variant->ds_ops_mdio;
- np = dev->of_node;
-
- dev_set_drvdata(dev, priv);
-
- /* TODO: if power is software controlled, set up any regulators here */
- priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
-
- priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(priv->reset)) {
- dev_err(dev, "failed to get RESET GPIO\n");
- return PTR_ERR(priv->reset);
- }
-
- if (priv->reset) {
- gpiod_set_value(priv->reset, 1);
- dev_dbg(dev, "asserted RESET\n");
- msleep(REALTEK_HW_STOP_DELAY);
- gpiod_set_value(priv->reset, 0);
- msleep(REALTEK_HW_START_DELAY);
- dev_dbg(dev, "deasserted RESET\n");
- }
-
- ret = priv->ops->detect(priv);
- if (ret) {
- dev_err(dev, "unable to detect switch\n");
- return ret;
- }
-
- priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
- if (!priv->ds)
- return -ENOMEM;
-
- priv->ds->dev = dev;
- priv->ds->num_ports = priv->num_ports;
- priv->ds->priv = priv;
- priv->ds->ops = var->ds_ops_mdio;
-
- ret = dsa_register_switch(priv->ds);
+ ret = rtl83xx_register_switch(priv);
if (ret) {
- dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
+ rtl83xx_remove(priv);
return ret;
}
@@ -253,8 +148,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe,
* @mdiodev: mdio_device to be removed.
*
* This function should be used as the .remove_new in an mdio_driver. First
- * it unregisters the DSA switch and cleans internal data. If a method is
- * provided, the hard reset is asserted to avoid traffic leakage.
+ * it unregisters the DSA switch and then it calls the common remove function.
*
* Context: Can sleep.
* Return: Nothing.
@@ -266,11 +160,9 @@ void realtek_mdio_remove(struct mdio_dev
if (!priv)
return;
- dsa_unregister_switch(priv->ds);
+ rtl83xx_unregister_switch(priv);
- /* leave the device reset asserted */
- if (priv->reset)
- gpiod_set_value(priv->reset, 1);
+ rtl83xx_remove(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, REALTEK_DSA);
@@ -278,10 +170,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove
* realtek_mdio_shutdown() - Shutdown the driver of a MDIO-connected switch
* @mdiodev: mdio_device shutting down.
*
- * This function should be used as the .shutdown in an mdio_driver. It shuts
- * down the DSA switch and cleans the platform driver data, to prevent
- * realtek_mdio_remove() from running afterwards, which is possible if the
- * parent bus implements its own .shutdown() as .remove().
+ * This function should be used as the .shutdown in a platform_driver. It calls
+ * the common shutdown function.
*
* Context: Can sleep.
* Return: Nothing.
@@ -293,9 +183,7 @@ void realtek_mdio_shutdown(struct mdio_d
if (!priv)
return;
- dsa_switch_shutdown(priv->ds);
-
- dev_set_drvdata(&mdiodev->dev, NULL);
+ rtl83xx_shutdown(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -41,6 +41,7 @@
#include "realtek.h"
#include "realtek-smi.h"
+#include "rtl83xx.h"
#define REALTEK_SMI_ACK_RETRY_COUNT 5
@@ -311,47 +312,6 @@ static int realtek_smi_read(void *ctx, u
return realtek_smi_read_reg(priv, reg, val);
}
-static void realtek_smi_lock(void *ctx)
-{
- struct realtek_priv *priv = ctx;
-
- mutex_lock(&priv->map_lock);
-}
-
-static void realtek_smi_unlock(void *ctx)
-{
- struct realtek_priv *priv = ctx;
-
- mutex_unlock(&priv->map_lock);
-}
-
-static const struct regmap_config realtek_smi_regmap_config = {
- .reg_bits = 10, /* A4..A0 R4..R0 */
- .val_bits = 16,
- .reg_stride = 1,
- /* PHY regs are at 0x8000 */
- .max_register = 0xffff,
- .reg_format_endian = REGMAP_ENDIAN_BIG,
- .reg_read = realtek_smi_read,
- .reg_write = realtek_smi_write,
- .cache_type = REGCACHE_NONE,
- .lock = realtek_smi_lock,
- .unlock = realtek_smi_unlock,
-};
-
-static const struct regmap_config realtek_smi_nolock_regmap_config = {
- .reg_bits = 10, /* A4..A0 R4..R0 */
- .val_bits = 16,
- .reg_stride = 1,
- /* PHY regs are at 0x8000 */
- .max_register = 0xffff,
- .reg_format_endian = REGMAP_ENDIAN_BIG,
- .reg_read = realtek_smi_read,
- .reg_write = realtek_smi_write,
- .cache_type = REGCACHE_NONE,
- .disable_locking = true,
-};
-
static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
struct realtek_priv *priv = bus->priv;
@@ -409,111 +369,56 @@ err_put_node:
return ret;
}
+static const struct realtek_interface_info realtek_smi_info = {
+ .reg_read = realtek_smi_read,
+ .reg_write = realtek_smi_write,
+};
+
/**
* realtek_smi_probe() - Probe a platform device for an SMI-connected switch
* @pdev: platform_device to probe on.
*
- * This function should be used as the .probe in a platform_driver. It
- * initializes realtek_priv and read data from the device-tree node. The switch
- * is hard reset if a method is provided. It checks the switch chip ID and,
- * finally, a DSA switch is registered.
+ * This function should be used as the .probe in a platform_driver. After
+ * calling the common probe function for both interfaces, it initializes the
+ * values specific for SMI-connected devices. Finally, it calls a common
+ * function to register the DSA switch.
*
* Context: Can sleep. Takes and releases priv->map_lock.
* Return: Returns 0 on success, a negative error on failure.
*/
int realtek_smi_probe(struct platform_device *pdev)
{
- const struct realtek_variant *var;
struct device *dev = &pdev->dev;
struct realtek_priv *priv;
- struct regmap_config rc;
- struct device_node *np;
int ret;
- var = of_device_get_match_data(dev);
- np = dev->of_node;
-
- priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->chip_data = (void *)priv + sizeof(*priv);
-
- mutex_init(&priv->map_lock);
-
- rc = realtek_smi_regmap_config;
- rc.lock_arg = priv;
- priv->map = devm_regmap_init(dev, NULL, priv, &rc);
- if (IS_ERR(priv->map)) {
- ret = PTR_ERR(priv->map);
- dev_err(dev, "regmap init failed: %d\n", ret);
- return ret;
- }
-
- rc = realtek_smi_nolock_regmap_config;
- priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
- if (IS_ERR(priv->map_nolock)) {
- ret = PTR_ERR(priv->map_nolock);
- dev_err(dev, "regmap init failed: %d\n", ret);
- return ret;
- }
-
- /* Link forward and backward */
- priv->dev = dev;
- priv->variant = var;
- priv->ops = var->ops;
-
- priv->setup_interface = realtek_smi_setup_mdio;
- priv->write_reg_noack = realtek_smi_write_reg_noack;
-
- dev_set_drvdata(dev, priv);
- spin_lock_init(&priv->lock);
-
- /* TODO: if power is software controlled, set up any regulators here */
-
- priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(priv->reset)) {
- dev_err(dev, "failed to get RESET GPIO\n");
- return PTR_ERR(priv->reset);
- }
- if (priv->reset) {
- gpiod_set_value(priv->reset, 1);
- dev_dbg(dev, "asserted RESET\n");
- msleep(REALTEK_HW_STOP_DELAY);
- gpiod_set_value(priv->reset, 0);
- msleep(REALTEK_HW_START_DELAY);
- dev_dbg(dev, "deasserted RESET\n");
- }
+ priv = rtl83xx_probe(dev, &realtek_smi_info);
+ if (IS_ERR(priv))
+ return PTR_ERR(priv);
/* Fetch MDIO pins */
priv->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
- if (IS_ERR(priv->mdc))
+ if (IS_ERR(priv->mdc)) {
+ rtl83xx_remove(priv);
return PTR_ERR(priv->mdc);
+ }
+
priv->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
- if (IS_ERR(priv->mdio))
+ if (IS_ERR(priv->mdio)) {
+ rtl83xx_remove(priv);
return PTR_ERR(priv->mdio);
-
- priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
-
- ret = priv->ops->detect(priv);
- if (ret) {
- dev_err(dev, "unable to detect switch\n");
- return ret;
}
- priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
- if (!priv->ds)
- return -ENOMEM;
-
- priv->ds->dev = dev;
- priv->ds->num_ports = priv->num_ports;
- priv->ds->priv = priv;
+ priv->write_reg_noack = realtek_smi_write_reg_noack;
+ priv->setup_interface = realtek_smi_setup_mdio;
+ priv->ds_ops = priv->variant->ds_ops_smi;
- priv->ds->ops = var->ds_ops_smi;
- ret = dsa_register_switch(priv->ds);
+ ret = rtl83xx_register_switch(priv);
if (ret) {
- dev_err_probe(dev, ret, "unable to register switch\n");
+ rtl83xx_remove(priv);
return ret;
}
+
return 0;
}
EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
@@ -523,8 +428,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_probe,
* @pdev: platform_device to be removed.
*
* This function should be used as the .remove_new in a platform_driver. First
- * it unregisters the DSA switch and cleans internal data. If a method is
- * provided, the hard reset is asserted to avoid traffic leakage.
+ * it unregisters the DSA switch and cleans internal data. Finally, it calls
+ * the common remove function.
*
* Context: Can sleep.
* Return: Nothing.
@@ -536,13 +441,12 @@ void realtek_smi_remove(struct platform_
if (!priv)
return;
- dsa_unregister_switch(priv->ds);
+ rtl83xx_unregister_switch(priv);
+
if (priv->slave_mii_bus)
of_node_put(priv->slave_mii_bus->dev.of_node);
- /* leave the device reset asserted */
- if (priv->reset)
- gpiod_set_value(priv->reset, 1);
+ rtl83xx_remove(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
@@ -550,10 +454,8 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_remove,
* realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
* @pdev: platform_device shutting down.
*
- * This function should be used as the .shutdown in a platform_driver. It shuts
- * down the DSA switch and cleans the platform driver data, to prevent
- * realtek_smi_remove() from running afterwards, which is possible if the
- * parent bus implements its own .shutdown() as .remove().
+ * This function should be used as the .shutdown in a platform_driver. It calls
+ * the common shutdown function.
*
* Context: Can sleep.
* Return: Nothing.
@@ -565,9 +467,7 @@ void realtek_smi_shutdown(struct platfor
if (!priv)
return;
- dsa_switch_shutdown(priv->ds);
-
- platform_set_drvdata(pdev, NULL);
+ rtl83xx_shutdown(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -62,6 +62,7 @@ struct realtek_priv {
spinlock_t lock; /* Locks around command writes */
struct dsa_switch *ds;
+ const struct dsa_switch_ops *ds_ops;
struct irq_domain *irqdomain;
bool leds_disabled;
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -103,6 +103,7 @@
#include "realtek.h"
#include "realtek-smi.h"
#include "realtek-mdio.h"
+#include "rtl83xx.h"
/* Family-specific data and limits */
#define RTL8365MB_PHYADDRMAX 7
@@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct
u32 val;
int ret;
- mutex_lock(&priv->map_lock);
+ rtl83xx_lock(priv);
ret = rtl8365mb_phy_poll_busy(priv);
if (ret)
@@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct
*data = val & 0xFFFF;
out:
- mutex_unlock(&priv->map_lock);
+ rtl83xx_unlock(priv);
return ret;
}
@@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struc
u32 val;
int ret;
- mutex_lock(&priv->map_lock);
+ rtl83xx_lock(priv);
ret = rtl8365mb_phy_poll_busy(priv);
if (ret)
@@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struc
goto out;
out:
- mutex_unlock(&priv->map_lock);
+ rtl83xx_unlock(priv);
return 0;
}
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -24,6 +24,7 @@
#include "realtek.h"
#include "realtek-smi.h"
#include "realtek-mdio.h"
+#include "rtl83xx.h"
#define RTL8366RB_PORT_NUM_CPU 5
#define RTL8366RB_NUM_PORTS 6
@@ -1634,7 +1635,7 @@ static int rtl8366rb_phy_read(struct rea
if (phy > RTL8366RB_PHY_NO_MAX)
return -EINVAL;
- mutex_lock(&priv->map_lock);
+ rtl83xx_lock(priv);
ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
RTL8366RB_PHY_CTRL_READ);
@@ -1662,7 +1663,7 @@ static int rtl8366rb_phy_read(struct rea
phy, regnum, reg, val);
out:
- mutex_unlock(&priv->map_lock);
+ rtl83xx_unlock(priv);
return ret;
}
@@ -1676,7 +1677,7 @@ static int rtl8366rb_phy_write(struct re
if (phy > RTL8366RB_PHY_NO_MAX)
return -EINVAL;
- mutex_lock(&priv->map_lock);
+ rtl83xx_lock(priv);
ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
RTL8366RB_PHY_CTRL_WRITE);
@@ -1693,7 +1694,7 @@ static int rtl8366rb_phy_write(struct re
goto out;
out:
- mutex_unlock(&priv->map_lock);
+ rtl83xx_unlock(priv);
return ret;
}
--- /dev/null
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h> /* krnl 6.1 only */
+
+#include "realtek.h"
+#include "rtl83xx.h"
+
+/**
+ * rtl83xx_lock() - Locks the mutex used by regmaps
+ * @ctx: realtek_priv pointer
+ *
+ * This function is passed to regmap to be used as the lock function.
+ * It is also used externally to block regmap before executing multiple
+ * operations that must happen in sequence (which will use
+ * realtek_priv.map_nolock instead).
+ *
+ * Context: Can sleep. Holds priv->map_lock lock.
+ * Return: nothing
+ */
+void rtl83xx_lock(void *ctx)
+{
+ struct realtek_priv *priv = ctx;
+
+ mutex_lock(&priv->map_lock);
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, REALTEK_DSA);
+
+/**
+ * rtl83xx_unlock() - Unlocks the mutex used by regmaps
+ * @ctx: realtek_priv pointer
+ *
+ * This function unlocks the lock acquired by rtl83xx_lock.
+ *
+ * Context: Releases priv->map_lock lock.
+ * Return: nothing
+ */
+void rtl83xx_unlock(void *ctx)
+{
+ struct realtek_priv *priv = ctx;
+
+ mutex_unlock(&priv->map_lock);
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);
+
+/**
+ * rtl83xx_probe() - probe a Realtek switch
+ * @dev: the device being probed
+ * @interface_info: specific management interface info.
+ *
+ * This function initializes realtek_priv and reads data from the device tree
+ * node. The switch is hard resetted if a method is provided.
+ *
+ * Context: Can sleep.
+ * Return: Pointer to the realtek_priv or ERR_PTR() in case of failure.
+ *
+ * The realtek_priv pointer does not need to be freed as it is controlled by
+ * devres.
+ */
+struct realtek_priv *
+rtl83xx_probe(struct device *dev,
+ const struct realtek_interface_info *interface_info)
+{
+ const struct realtek_variant *var;
+ struct realtek_priv *priv;
+ struct regmap_config rc = {
+ .reg_bits = 10, /* A4..A0 R4..R0 */
+ .val_bits = 16,
+ .reg_stride = 1,
+ .max_register = 0xffff,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .reg_read = interface_info->reg_read,
+ .reg_write = interface_info->reg_write,
+ .cache_type = REGCACHE_NONE,
+ .lock = rtl83xx_lock,
+ .unlock = rtl83xx_unlock,
+ };
+ int ret;
+
+ var = of_device_get_match_data(dev);
+ if (!var)
+ return ERR_PTR(-EINVAL);
+
+ priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
+ GFP_KERNEL);
+ if (!priv)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_init(&priv->map_lock);
+
+ rc.lock_arg = priv;
+ priv->map = devm_regmap_init(dev, NULL, priv, &rc);
+ if (IS_ERR(priv->map)) {
+ ret = PTR_ERR(priv->map);
+ dev_err(dev, "regmap init failed: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ rc.disable_locking = true;
+ priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
+ if (IS_ERR(priv->map_nolock)) {
+ ret = PTR_ERR(priv->map_nolock);
+ dev_err(dev, "regmap init failed: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ /* Link forward and backward */
+ priv->dev = dev;
+ priv->variant = var;
+ priv->ops = var->ops;
+ priv->chip_data = (void *)priv + sizeof(*priv);
+
+ spin_lock_init(&priv->lock);
+
+ priv->leds_disabled = of_property_read_bool(dev->of_node,
+ "realtek,disable-leds");
+
+ /* TODO: if power is software controlled, set up any regulators here */
+ priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(priv->reset)) {
+ dev_err(dev, "failed to get RESET GPIO\n");
+ return ERR_CAST(priv->reset);
+ }
+
+ dev_set_drvdata(dev, priv);
+
+ if (priv->reset) {
+ gpiod_set_value(priv->reset, 1);
+ dev_dbg(dev, "asserted RESET\n");
+ msleep(REALTEK_HW_STOP_DELAY);
+ gpiod_set_value(priv->reset, 0);
+ msleep(REALTEK_HW_START_DELAY);
+ dev_dbg(dev, "deasserted RESET\n");
+ }
+
+ return priv;
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REALTEK_DSA);
+
+/**
+ * rtl83xx_register_switch() - detects and register a switch
+ * @priv: realtek_priv pointer
+ *
+ * This function first checks the switch chip ID and register a DSA
+ * switch.
+ *
+ * Context: Can sleep. Takes and releases priv->map_lock.
+ * Return: 0 on success, negative value for failure.
+ */
+int rtl83xx_register_switch(struct realtek_priv *priv)
+{
+ struct dsa_switch *ds;
+ int ret;
+
+ ret = priv->ops->detect(priv);
+ if (ret) {
+ dev_err_probe(priv->dev, ret, "unable to detect switch\n");
+ return ret;
+ }
+
+ ds = devm_kzalloc(priv->dev, sizeof(*ds), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ ds->priv = priv;
+ ds->dev = priv->dev;
+ ds->ops = priv->ds_ops;
+ ds->num_ports = priv->num_ports;
+ priv->ds = ds;
+
+ ret = dsa_register_switch(ds);
+ if (ret) {
+ dev_err_probe(priv->dev, ret, "unable to register switch\n");
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, REALTEK_DSA);
+
+/**
+ * rtl83xx_unregister_switch() - unregister a switch
+ * @priv: realtek_priv pointer
+ *
+ * This function unregister a DSA switch.
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void rtl83xx_unregister_switch(struct realtek_priv *priv)
+{
+ dsa_unregister_switch(priv->ds);
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);
+
+/**
+ * rtl83xx_shutdown() - shutdown a switch
+ * @priv: realtek_priv pointer
+ *
+ * This function shuts down the DSA switch and cleans the platform driver data,
+ * to prevent realtek_{smi,mdio}_remove() from running afterwards, which is
+ * possible if the parent bus implements its own .shutdown() as .remove().
+ *
+ * Context: Can sleep.
+ * Return: Nothing.
+ */
+void rtl83xx_shutdown(struct realtek_priv *priv)
+{
+ dsa_switch_shutdown(priv->ds);
+
+ dev_set_drvdata(priv->dev, NULL);
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA);
+
+/**
+ * rtl83xx_remove() - Cleanup a realtek switch driver
+ * @priv: realtek_priv pointer
+ *
+ * If a method is provided, this function asserts the hard reset of the switch
+ * in order to avoid leaking traffic when the driver is gone.
+ *
+ * Context: Might sleep if priv->gdev->chip->can_sleep.
+ * Return: nothing
+ */
+void rtl83xx_remove(struct realtek_priv *priv)
+{
+ /* leave the device reset asserted */
+ if (priv->reset)
+ gpiod_set_value(priv->reset, 1);
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
+
+MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
+MODULE_DESCRIPTION("Realtek DSA switches common module");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/drivers/net/dsa/realtek/rtl83xx.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _RTL83XX_H
+#define _RTL83XX_H
+
+struct realtek_interface_info {
+ int (*reg_read)(void *ctx, u32 reg, u32 *val);
+ int (*reg_write)(void *ctx, u32 reg, u32 val);
+};
+
+void rtl83xx_lock(void *ctx);
+void rtl83xx_unlock(void *ctx);
+struct realtek_priv *
+rtl83xx_probe(struct device *dev,
+ const struct realtek_interface_info *interface_info);
+int rtl83xx_register_switch(struct realtek_priv *priv);
+void rtl83xx_unregister_switch(struct realtek_priv *priv);
+void rtl83xx_shutdown(struct realtek_priv *priv);
+void rtl83xx_remove(struct realtek_priv *priv);
+
+#endif /* _RTL83XX_H */

View File

@ -0,0 +1,93 @@
From 98b75c1c149c653ad11a440636213eb070325158 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:42 -0300
Subject: net: dsa: realtek: merge rtl83xx and interface
modules into realtek_dsa
Since rtl83xx and realtek-{smi,mdio} are always loaded together,
we can optimize resource usage by consolidating them into a single
module.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/Kconfig | 4 ++--
drivers/net/dsa/realtek/Makefile | 11 +++++++++--
drivers/net/dsa/realtek/realtek-mdio.c | 5 -----
drivers/net/dsa/realtek/realtek-smi.c | 5 -----
drivers/net/dsa/realtek/rtl83xx.c | 1 +
5 files changed, 12 insertions(+), 14 deletions(-)
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
if NET_DSA_REALTEK
config NET_DSA_REALTEK_MDIO
- tristate "Realtek MDIO interface support"
+ bool "Realtek MDIO interface support"
depends on OF
help
Select to enable support for registering switches configured
through MDIO.
config NET_DSA_REALTEK_SMI
- tristate "Realtek SMI interface support"
+ bool "Realtek SMI interface support"
depends on OF
help
Select to enable support for registering switches connected
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -1,8 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_NET_DSA_REALTEK) += realtek_dsa.o
realtek_dsa-objs := rtl83xx.o
-obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
-obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+
+ifdef CONFIG_NET_DSA_REALTEK_MDIO
+realtek_dsa-objs += realtek-mdio.o
+endif
+
+ifdef CONFIG_NET_DSA_REALTEK_SMI
+realtek_dsa-objs += realtek-smi.o
+endif
+
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
rtl8366-objs := rtl8366-core.o rtl8366rb.o
obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -186,8 +186,3 @@ void realtek_mdio_shutdown(struct mdio_d
rtl83xx_shutdown(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
-
-MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
-MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(REALTEK_DSA);
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -470,8 +470,3 @@ void realtek_smi_shutdown(struct platfor
rtl83xx_shutdown(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
-MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(REALTEK_DSA);
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -232,5 +232,6 @@ void rtl83xx_remove(struct realtek_priv
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Realtek DSA switches common module");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,34 @@
From 8685c98d45c54346caf005de69988e13c731c533 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:43 -0300
Subject: net: dsa: realtek: get internal MDIO node by name
The binding docs requires for SMI-connected devices that the switch
must have a child node named "mdio" and with a compatible string of
"realtek,smi-mdio". Meanwile, for MDIO-connected switches, the binding
docs only requires a child node named "mdio".
This patch changes the driver to use the common denominator for both
interfaces, looking for the MDIO node by name, ignoring the compatible
string.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-smi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -333,7 +333,7 @@ static int realtek_smi_setup_mdio(struct
struct device_node *mdio_np;
int ret;
- mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
+ mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
if (!mdio_np) {
dev_err(priv->dev, "no MDIO bus node\n");
return -ENODEV;

View File

@ -0,0 +1,83 @@
From 68c66d8d8a19088967a0ab6bb98cb5ecc80ca0be Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:44 -0300
Subject: net: dsa: realtek: clean slave_mii_bus setup
Remove the line assigning dev.of_node in mdio_bus as subsequent
of_mdiobus_register will always overwrite it.
As discussed in [1], allow the DSA core to be simplified, by not
assigning ds->slave_mii_bus when the MDIO bus is described in OF, as it
is unnecessary.
Since commit 3b73a7b8ec38 ("net: mdio_bus: add refcounting for fwnodes
to mdiobus"), we can put the "mdio" node just after the MDIO bus
registration.
[1] https://lkml.kernel.org/netdev/20231213120656.x46fyad6ls7sqyzv@skbuf/T/#u
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-smi.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -331,7 +331,7 @@ static int realtek_smi_setup_mdio(struct
{
struct realtek_priv *priv = ds->priv;
struct device_node *mdio_np;
- int ret;
+ int ret = 0;
mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
if (!mdio_np) {
@@ -344,15 +344,14 @@ static int realtek_smi_setup_mdio(struct
ret = -ENOMEM;
goto err_put_node;
}
+
priv->slave_mii_bus->priv = priv;
priv->slave_mii_bus->name = "SMI slave MII";
priv->slave_mii_bus->read = realtek_smi_mdio_read;
priv->slave_mii_bus->write = realtek_smi_mdio_write;
snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
ds->index);
- priv->slave_mii_bus->dev.of_node = mdio_np;
priv->slave_mii_bus->parent = priv->dev;
- ds->slave_mii_bus = priv->slave_mii_bus;
ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
if (ret) {
@@ -361,8 +360,6 @@ static int realtek_smi_setup_mdio(struct
goto err_put_node;
}
- return 0;
-
err_put_node:
of_node_put(mdio_np);
@@ -428,8 +425,7 @@ EXPORT_SYMBOL_NS_GPL(realtek_smi_probe,
* @pdev: platform_device to be removed.
*
* This function should be used as the .remove_new in a platform_driver. First
- * it unregisters the DSA switch and cleans internal data. Finally, it calls
- * the common remove function.
+ * it unregisters the DSA switch and then it calls the common remove function.
*
* Context: Can sleep.
* Return: Nothing.
@@ -443,9 +439,6 @@ void realtek_smi_remove(struct platform_
rtl83xx_unregister_switch(priv);
- if (priv->slave_mii_bus)
- of_node_put(priv->slave_mii_bus->dev.of_node);
-
rtl83xx_remove(priv);
}
EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);

View File

@ -0,0 +1,198 @@
From b4bd77971f3c290c4694ed710cc6967593b10bc2 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:45 -0300
Subject: net: dsa: realtek: migrate slave_mii_bus setup to
realtek_dsa
In the user MDIO driver, despite numerous references to SMI, including
its compatible string, there's nothing inherently specific about the SMI
interface in the user MDIO bus. Consequently, the code has been migrated
to the rtl83xx module. All references to SMI have been eliminated.
The MDIO bus id was changed from Realtek-<switch id> to the switch
devname suffixed with :slave_mii, giving more information about the bus
it is referencing.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-smi.c | 57 +---------------------
drivers/net/dsa/realtek/rtl83xx.c | 68 +++++++++++++++++++++++++++
drivers/net/dsa/realtek/rtl83xx.h | 1 +
3 files changed, 70 insertions(+), 56 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -31,7 +31,6 @@
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/of.h>
-#include <linux/of_mdio.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
@@ -312,60 +311,6 @@ static int realtek_smi_read(void *ctx, u
return realtek_smi_read_reg(priv, reg, val);
}
-static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
-{
- struct realtek_priv *priv = bus->priv;
-
- return priv->ops->phy_read(priv, addr, regnum);
-}
-
-static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
- u16 val)
-{
- struct realtek_priv *priv = bus->priv;
-
- return priv->ops->phy_write(priv, addr, regnum, val);
-}
-
-static int realtek_smi_setup_mdio(struct dsa_switch *ds)
-{
- struct realtek_priv *priv = ds->priv;
- struct device_node *mdio_np;
- int ret = 0;
-
- mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
- if (!mdio_np) {
- dev_err(priv->dev, "no MDIO bus node\n");
- return -ENODEV;
- }
-
- priv->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
- if (!priv->slave_mii_bus) {
- ret = -ENOMEM;
- goto err_put_node;
- }
-
- priv->slave_mii_bus->priv = priv;
- priv->slave_mii_bus->name = "SMI slave MII";
- priv->slave_mii_bus->read = realtek_smi_mdio_read;
- priv->slave_mii_bus->write = realtek_smi_mdio_write;
- snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
- ds->index);
- priv->slave_mii_bus->parent = priv->dev;
-
- ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
- if (ret) {
- dev_err(priv->dev, "unable to register MDIO bus %s\n",
- priv->slave_mii_bus->id);
- goto err_put_node;
- }
-
-err_put_node:
- of_node_put(mdio_np);
-
- return ret;
-}
-
static const struct realtek_interface_info realtek_smi_info = {
.reg_read = realtek_smi_read,
.reg_write = realtek_smi_write,
@@ -407,7 +352,7 @@ int realtek_smi_probe(struct platform_de
}
priv->write_reg_noack = realtek_smi_write_reg_noack;
- priv->setup_interface = realtek_smi_setup_mdio;
+ priv->setup_interface = rtl83xx_setup_user_mdio;
priv->ds_ops = priv->variant->ds_ops_smi;
ret = rtl83xx_register_switch(priv);
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/of_device.h> /* krnl 6.1 only */
+#include <linux/of_mdio.h>
#include "realtek.h"
#include "rtl83xx.h"
@@ -44,6 +45,73 @@ void rtl83xx_unlock(void *ctx)
}
EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);
+static int rtl83xx_user_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+ struct realtek_priv *priv = bus->priv;
+
+ return priv->ops->phy_read(priv, addr, regnum);
+}
+
+static int rtl83xx_user_mdio_write(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct realtek_priv *priv = bus->priv;
+
+ return priv->ops->phy_write(priv, addr, regnum, val);
+}
+
+/**
+ * rtl83xx_setup_user_mdio() - register the user mii bus driver
+ * @ds: DSA switch associated with this slave_mii_bus
+ *
+ * Registers the MDIO bus for built-in Ethernet PHYs, and associates it with
+ * the mandatory 'mdio' child OF node of the switch.
+ *
+ * Context: Can sleep.
+ * Return: 0 on success, negative value for failure.
+ */
+int rtl83xx_setup_user_mdio(struct dsa_switch *ds)
+{
+ struct realtek_priv *priv = ds->priv;
+ struct device_node *mdio_np;
+ struct mii_bus *bus;
+ int ret = 0;
+
+ mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
+ if (!mdio_np) {
+ dev_err(priv->dev, "no MDIO bus node\n");
+ return -ENODEV;
+ }
+
+ bus = devm_mdiobus_alloc(priv->dev);
+ if (!bus) {
+ ret = -ENOMEM;
+ goto err_put_node;
+ }
+
+ bus->priv = priv;
+ bus->name = "Realtek user MII";
+ bus->read = rtl83xx_user_mdio_read;
+ bus->write = rtl83xx_user_mdio_write;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s:slave_mii", dev_name(priv->dev));
+ bus->parent = priv->dev;
+
+ ret = devm_of_mdiobus_register(priv->dev, bus, mdio_np);
+ if (ret) {
+ dev_err(priv->dev, "unable to register MDIO bus %s\n",
+ bus->id);
+ goto err_put_node;
+ }
+
+ priv->slave_mii_bus = bus;
+
+err_put_node:
+ of_node_put(mdio_np);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, REALTEK_DSA);
+
/**
* rtl83xx_probe() - probe a Realtek switch
* @dev: the device being probed
--- a/drivers/net/dsa/realtek/rtl83xx.h
+++ b/drivers/net/dsa/realtek/rtl83xx.h
@@ -10,6 +10,7 @@ struct realtek_interface_info {
void rtl83xx_lock(void *ctx);
void rtl83xx_unlock(void *ctx);
+int rtl83xx_setup_user_mdio(struct dsa_switch *ds);
struct realtek_priv *
rtl83xx_probe(struct device *dev,
const struct realtek_interface_info *interface_info);

View File

@ -0,0 +1,261 @@
From bba140a566ed075304c49c52ab32c0016cab624a Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:46 -0300
Subject: net: dsa: realtek: use the same mii bus driver for
both interfaces
The realtek-mdio will now use this driver instead of the generic DSA
driver ("dsa user smi"), which should not be used with OF[1].
With a single ds_ops for both interfaces, the ds_ops in realtek_priv is
no longer necessary. Now, the realtek_variant.ds_ops can be used
directly.
The realtek_priv.setup_interface() has been removed as we can directly
call the new common function.
[1] https://lkml.kernel.org/netdev/20220630200423.tieprdu5fpabflj7@bang-olufsen.dk/T/
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek-mdio.c | 1 -
drivers/net/dsa/realtek/realtek-smi.c | 2 -
drivers/net/dsa/realtek/realtek.h | 5 +--
drivers/net/dsa/realtek/rtl8365mb.c | 49 +++---------------------
drivers/net/dsa/realtek/rtl8366rb.c | 52 +++-----------------------
drivers/net/dsa/realtek/rtl83xx.c | 2 +-
6 files changed, 14 insertions(+), 97 deletions(-)
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -131,7 +131,6 @@ int realtek_mdio_probe(struct mdio_devic
priv->bus = mdiodev->bus;
priv->mdio_addr = mdiodev->addr;
priv->write_reg_noack = realtek_mdio_write;
- priv->ds_ops = priv->variant->ds_ops_mdio;
ret = rtl83xx_register_switch(priv);
if (ret) {
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -352,8 +352,6 @@ int realtek_smi_probe(struct platform_de
}
priv->write_reg_noack = realtek_smi_write_reg_noack;
- priv->setup_interface = rtl83xx_setup_user_mdio;
- priv->ds_ops = priv->variant->ds_ops_smi;
ret = rtl83xx_register_switch(priv);
if (ret) {
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -62,7 +62,6 @@ struct realtek_priv {
spinlock_t lock; /* Locks around command writes */
struct dsa_switch *ds;
- const struct dsa_switch_ops *ds_ops;
struct irq_domain *irqdomain;
bool leds_disabled;
@@ -73,7 +72,6 @@ struct realtek_priv {
struct rtl8366_mib_counter *mib_counters;
const struct realtek_ops *ops;
- int (*setup_interface)(struct dsa_switch *ds);
int (*write_reg_noack)(void *ctx, u32 addr, u32 data);
int vlan_enabled;
@@ -115,8 +113,7 @@ struct realtek_ops {
};
struct realtek_variant {
- const struct dsa_switch_ops *ds_ops_smi;
- const struct dsa_switch_ops *ds_ops_mdio;
+ const struct dsa_switch_ops *ds_ops;
const struct realtek_ops *ops;
unsigned int clk_delay;
u8 cmd_read;
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -828,17 +828,6 @@ static int rtl8365mb_phy_write(struct re
return 0;
}
-static int rtl8365mb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
- return rtl8365mb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8365mb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
- u16 val)
-{
- return rtl8365mb_phy_write(ds->priv, phy, regnum, val);
-}
-
static const struct rtl8365mb_extint *
rtl8365mb_get_port_extint(struct realtek_priv *priv, int port)
{
@@ -2018,12 +2007,10 @@ static int rtl8365mb_setup(struct dsa_sw
if (ret)
goto out_teardown_irq;
- if (priv->setup_interface) {
- ret = priv->setup_interface(ds);
- if (ret) {
- dev_err(priv->dev, "could not set up MDIO bus\n");
- goto out_teardown_irq;
- }
+ ret = rtl83xx_setup_user_mdio(ds);
+ if (ret) {
+ dev_err(priv->dev, "could not set up MDIO bus\n");
+ goto out_teardown_irq;
}
/* Start statistics counter polling */
@@ -2117,28 +2104,7 @@ static int rtl8365mb_detect(struct realt
return 0;
}
-static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
- .get_tag_protocol = rtl8365mb_get_tag_protocol,
- .change_tag_protocol = rtl8365mb_change_tag_protocol,
- .setup = rtl8365mb_setup,
- .teardown = rtl8365mb_teardown,
- .phylink_get_caps = rtl8365mb_phylink_get_caps,
- .phylink_mac_config = rtl8365mb_phylink_mac_config,
- .phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
- .phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
- .port_stp_state_set = rtl8365mb_port_stp_state_set,
- .get_strings = rtl8365mb_get_strings,
- .get_ethtool_stats = rtl8365mb_get_ethtool_stats,
- .get_sset_count = rtl8365mb_get_sset_count,
- .get_eth_phy_stats = rtl8365mb_get_phy_stats,
- .get_eth_mac_stats = rtl8365mb_get_mac_stats,
- .get_eth_ctrl_stats = rtl8365mb_get_ctrl_stats,
- .get_stats64 = rtl8365mb_get_stats64,
- .port_change_mtu = rtl8365mb_port_change_mtu,
- .port_max_mtu = rtl8365mb_port_max_mtu,
-};
-
-static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops = {
.get_tag_protocol = rtl8365mb_get_tag_protocol,
.change_tag_protocol = rtl8365mb_change_tag_protocol,
.setup = rtl8365mb_setup,
@@ -2147,8 +2113,6 @@ static const struct dsa_switch_ops rtl83
.phylink_mac_config = rtl8365mb_phylink_mac_config,
.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
.phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
- .phy_read = rtl8365mb_dsa_phy_read,
- .phy_write = rtl8365mb_dsa_phy_write,
.port_stp_state_set = rtl8365mb_port_stp_state_set,
.get_strings = rtl8365mb_get_strings,
.get_ethtool_stats = rtl8365mb_get_ethtool_stats,
@@ -2168,8 +2132,7 @@ static const struct realtek_ops rtl8365m
};
const struct realtek_variant rtl8365mb_variant = {
- .ds_ops_smi = &rtl8365mb_switch_ops_smi,
- .ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
+ .ds_ops = &rtl8365mb_switch_ops,
.ops = &rtl8365mb_ops,
.clk_delay = 10,
.cmd_read = 0xb9,
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1035,12 +1035,10 @@ static int rtl8366rb_setup(struct dsa_sw
if (ret)
dev_info(priv->dev, "no interrupt support\n");
- if (priv->setup_interface) {
- ret = priv->setup_interface(ds);
- if (ret) {
- dev_err(priv->dev, "could not set up MDIO bus\n");
- return -ENODEV;
- }
+ ret = rtl83xx_setup_user_mdio(ds);
+ if (ret) {
+ dev_err(priv->dev, "could not set up MDIO bus\n");
+ return -ENODEV;
}
return 0;
@@ -1699,17 +1697,6 @@ out:
return ret;
}
-static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
- return rtl8366rb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8366rb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
- u16 val)
-{
- return rtl8366rb_phy_write(ds->priv, phy, regnum, val);
-}
-
static int rtl8366rb_reset_chip(struct realtek_priv *priv)
{
int timeout = 10;
@@ -1775,35 +1762,9 @@ static int rtl8366rb_detect(struct realt
return 0;
}
-static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
- .get_tag_protocol = rtl8366_get_tag_protocol,
- .setup = rtl8366rb_setup,
- .phylink_get_caps = rtl8366rb_phylink_get_caps,
- .phylink_mac_link_up = rtl8366rb_mac_link_up,
- .phylink_mac_link_down = rtl8366rb_mac_link_down,
- .get_strings = rtl8366_get_strings,
- .get_ethtool_stats = rtl8366_get_ethtool_stats,
- .get_sset_count = rtl8366_get_sset_count,
- .port_bridge_join = rtl8366rb_port_bridge_join,
- .port_bridge_leave = rtl8366rb_port_bridge_leave,
- .port_vlan_filtering = rtl8366rb_vlan_filtering,
- .port_vlan_add = rtl8366_vlan_add,
- .port_vlan_del = rtl8366_vlan_del,
- .port_enable = rtl8366rb_port_enable,
- .port_disable = rtl8366rb_port_disable,
- .port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
- .port_bridge_flags = rtl8366rb_port_bridge_flags,
- .port_stp_state_set = rtl8366rb_port_stp_state_set,
- .port_fast_age = rtl8366rb_port_fast_age,
- .port_change_mtu = rtl8366rb_change_mtu,
- .port_max_mtu = rtl8366rb_max_mtu,
-};
-
-static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops = {
.get_tag_protocol = rtl8366_get_tag_protocol,
.setup = rtl8366rb_setup,
- .phy_read = rtl8366rb_dsa_phy_read,
- .phy_write = rtl8366rb_dsa_phy_write,
.phylink_get_caps = rtl8366rb_phylink_get_caps,
.phylink_mac_link_up = rtl8366rb_mac_link_up,
.phylink_mac_link_down = rtl8366rb_mac_link_down,
@@ -1842,8 +1803,7 @@ static const struct realtek_ops rtl8366r
};
const struct realtek_variant rtl8366rb_variant = {
- .ds_ops_smi = &rtl8366rb_switch_ops_smi,
- .ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
+ .ds_ops = &rtl8366rb_switch_ops,
.ops = &rtl8366rb_ops,
.clk_delay = 10,
.cmd_read = 0xa9,
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -233,7 +233,7 @@ int rtl83xx_register_switch(struct realt
ds->priv = priv;
ds->dev = priv->dev;
- ds->ops = priv->ds_ops;
+ ds->ops = priv->variant->ds_ops;
ds->num_ports = priv->num_ports;
priv->ds = ds;

View File

@ -0,0 +1,180 @@
From 9fc469b2943d9b1ff2a7800f823e7cd7a5cac0ca Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Fri, 9 Feb 2024 02:03:47 -0300
Subject: net: dsa: realtek: embed dsa_switch into realtek_priv
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Embed dsa_switch within realtek_priv to eliminate the need for a second
memory allocation.
Suggested-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek.h | 2 +-
drivers/net/dsa/realtek/rtl8365mb.c | 15 +++++++++------
drivers/net/dsa/realtek/rtl8366rb.c | 3 ++-
drivers/net/dsa/realtek/rtl83xx.c | 15 +++++++--------
4 files changed, 19 insertions(+), 16 deletions(-)
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -61,7 +61,7 @@ struct realtek_priv {
const struct realtek_variant *variant;
spinlock_t lock; /* Locks around command writes */
- struct dsa_switch *ds;
+ struct dsa_switch ds;
struct irq_domain *irqdomain;
bool leds_disabled;
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -870,6 +870,7 @@ static int rtl8365mb_ext_config_rgmii(st
{
const struct rtl8365mb_extint *extint =
rtl8365mb_get_port_extint(priv, port);
+ struct dsa_switch *ds = &priv->ds;
struct device_node *dn;
struct dsa_port *dp;
int tx_delay = 0;
@@ -880,7 +881,7 @@ static int rtl8365mb_ext_config_rgmii(st
if (!extint)
return -ENODEV;
- dp = dsa_to_port(priv->ds, port);
+ dp = dsa_to_port(ds, port);
dn = dp->dn;
/* Set the RGMII TX/RX delay
@@ -1534,6 +1535,7 @@ static void rtl8365mb_get_stats64(struct
static void rtl8365mb_stats_setup(struct realtek_priv *priv)
{
struct rtl8365mb *mb = priv->chip_data;
+ struct dsa_switch *ds = &priv->ds;
int i;
/* Per-chip global mutex to protect MIB counter access, since doing
@@ -1544,7 +1546,7 @@ static void rtl8365mb_stats_setup(struct
for (i = 0; i < priv->num_ports; i++) {
struct rtl8365mb_port *p = &mb->ports[i];
- if (dsa_is_unused_port(priv->ds, i))
+ if (dsa_is_unused_port(ds, i))
continue;
/* Per-port spinlock to protect the stats64 data */
@@ -1560,12 +1562,13 @@ static void rtl8365mb_stats_setup(struct
static void rtl8365mb_stats_teardown(struct realtek_priv *priv)
{
struct rtl8365mb *mb = priv->chip_data;
+ struct dsa_switch *ds = &priv->ds;
int i;
for (i = 0; i < priv->num_ports; i++) {
struct rtl8365mb_port *p = &mb->ports[i];
- if (dsa_is_unused_port(priv->ds, i))
+ if (dsa_is_unused_port(ds, i))
continue;
cancel_delayed_work_sync(&p->mib_work);
@@ -1964,7 +1967,7 @@ static int rtl8365mb_setup(struct dsa_sw
dev_info(priv->dev, "no interrupt support\n");
/* Configure CPU tagging */
- dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
+ dsa_switch_for_each_cpu_port(cpu_dp, ds) {
cpu->mask |= BIT(cpu_dp->index);
if (cpu->trap_port == RTL8365MB_MAX_NUM_PORTS)
@@ -1979,7 +1982,7 @@ static int rtl8365mb_setup(struct dsa_sw
for (i = 0; i < priv->num_ports; i++) {
struct rtl8365mb_port *p = &mb->ports[i];
- if (dsa_is_unused_port(priv->ds, i))
+ if (dsa_is_unused_port(ds, i))
continue;
/* Forward only to the CPU */
@@ -1996,7 +1999,7 @@ static int rtl8365mb_setup(struct dsa_sw
* ports will still forward frames to the CPU despite being
* administratively down by default.
*/
- rtl8365mb_port_stp_state_set(priv->ds, i, BR_STATE_DISABLED);
+ rtl8365mb_port_stp_state_set(ds, i, BR_STATE_DISABLED);
/* Set up per-port private data */
p->priv = priv;
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1565,6 +1565,7 @@ static int rtl8366rb_get_mc_index(struct
static int rtl8366rb_set_mc_index(struct realtek_priv *priv, int port, int index)
{
+ struct dsa_switch *ds = &priv->ds;
struct rtl8366rb *rb;
bool pvid_enabled;
int ret;
@@ -1589,7 +1590,7 @@ static int rtl8366rb_set_mc_index(struct
* not drop any untagged or C-tagged frames. Make sure to update the
* filtering setting.
*/
- if (dsa_port_is_vlan_filtering(dsa_to_port(priv->ds, port)))
+ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
ret = rtl8366rb_drop_untagged(priv, port, !pvid_enabled);
return ret;
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -218,7 +218,7 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REAL
*/
int rtl83xx_register_switch(struct realtek_priv *priv)
{
- struct dsa_switch *ds;
+ struct dsa_switch *ds = &priv->ds;
int ret;
ret = priv->ops->detect(priv);
@@ -227,15 +227,10 @@ int rtl83xx_register_switch(struct realt
return ret;
}
- ds = devm_kzalloc(priv->dev, sizeof(*ds), GFP_KERNEL);
- if (!ds)
- return -ENOMEM;
-
ds->priv = priv;
ds->dev = priv->dev;
ds->ops = priv->variant->ds_ops;
ds->num_ports = priv->num_ports;
- priv->ds = ds;
ret = dsa_register_switch(ds);
if (ret) {
@@ -258,7 +253,9 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_register_sw
*/
void rtl83xx_unregister_switch(struct realtek_priv *priv)
{
- dsa_unregister_switch(priv->ds);
+ struct dsa_switch *ds = &priv->ds;
+
+ dsa_unregister_switch(ds);
}
EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);
@@ -275,7 +272,9 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_
*/
void rtl83xx_shutdown(struct realtek_priv *priv)
{
- dsa_switch_shutdown(priv->ds);
+ struct dsa_switch *ds = &priv->ds;
+
+ dsa_switch_shutdown(ds);
dev_set_drvdata(priv->dev, NULL);
}

View File

@ -0,0 +1,38 @@
From 32e4a5447ed9fa904a2dfcf4609c64bce053b4e8 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Mon, 12 Feb 2024 18:34:33 -0300
Subject: [PATCH] net: dsa: realtek: fix digital interface select macro for
EXT0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
While no supported devices currently utilize EXT0, the register reserves
the bits for an EXT0. EXT0 is utilized by devices from the generation
prior to rtl8365mb, such as those supported by the driver library
rtl8367b.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240212-realtek-fix_ext0-v1-1-f3d2536d191a@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/dsa/realtek/rtl8365mb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -209,10 +209,10 @@
#define RTL8365MB_EXT_PORT_MODE_100FX 13
/* External interface mode configuration registers 0~1 */
-#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 0x1305 /* EXT1 */
+#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 0x1305 /* EXT0,EXT1 */
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1 0x13C3 /* EXT2 */
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(_extint) \
- ((_extint) == 1 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 : \
+ ((_extint) <= 1 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 : \
(_extint) == 2 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1 : \
0x0)
#define RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(_extint) \

View File

@ -0,0 +1,34 @@
From 28001bb1955fcfa63e535848c4289fcd7bb88daf Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Sun, 25 Feb 2024 13:29:53 -0300
Subject: [PATCH 1/3] dt-bindings: net: dsa: realtek: reset-gpios is not
required
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The 'reset-gpios' should not be mandatory. although they might be
required for some devices if the switch reset was left asserted by a
previous driver, such as the bootloader.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Cc: devicetree@vger.kernel.org
Acked-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/devicetree/bindings/net/dsa/realtek.yaml | 1 -
1 file changed, 1 deletion(-)
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
@@ -125,7 +125,6 @@ else:
- mdc-gpios
- mdio-gpios
- mdio
- - reset-gpios
required:
- compatible

View File

@ -0,0 +1,33 @@
From 5fc2d68fc81801162188995e4d3dc0b26747dd76 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Sun, 25 Feb 2024 13:29:54 -0300
Subject: [PATCH 2/3] dt-bindings: net: dsa: realtek: add reset controller
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Realtek switches can use a reset controller instead of reset-gpios.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Cc: devicetree@vger.kernel.org
Acked-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/devicetree/bindings/net/dsa/realtek.yaml | 3 +++
1 file changed, 3 insertions(+)
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
@@ -59,6 +59,9 @@ properties:
description: GPIO to be used to reset the whole device
maxItems: 1
+ resets:
+ maxItems: 1
+
realtek,disable-leds:
type: boolean
description: |

View File

@ -0,0 +1,123 @@
From 56998aa6b7f0f31ce8df23c00701af2d8e8a1f1a Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Sun, 25 Feb 2024 13:29:55 -0300
Subject: [PATCH 3/3] net: dsa: realtek: support reset controller
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add support for resetting the device using a reset controller,
complementing the existing GPIO reset functionality (reset-gpios).
Although the reset is optional and the driver performs a soft reset
during setup, if the initial reset pin state was asserted, the driver
will not detect the device until the reset is deasserted.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/realtek.h | 2 ++
drivers/net/dsa/realtek/rtl83xx.c | 42 +++++++++++++++++++++++++++----
drivers/net/dsa/realtek/rtl83xx.h | 2 ++
3 files changed, 41 insertions(+), 5 deletions(-)
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <net/dsa.h>
+#include <linux/reset.h>
#define REALTEK_HW_STOP_DELAY 25 /* msecs */
#define REALTEK_HW_START_DELAY 100 /* msecs */
@@ -48,6 +49,7 @@ struct rtl8366_vlan_4k {
struct realtek_priv {
struct device *dev;
+ struct reset_control *reset_ctl;
struct gpio_desc *reset;
struct gpio_desc *mdc;
struct gpio_desc *mdio;
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -185,6 +185,13 @@ rtl83xx_probe(struct device *dev,
"realtek,disable-leds");
/* TODO: if power is software controlled, set up any regulators here */
+ priv->reset_ctl = devm_reset_control_get_optional(dev, NULL);
+ if (IS_ERR(priv->reset_ctl)) {
+ ret = PTR_ERR(priv->reset_ctl);
+ dev_err_probe(dev, ret, "failed to get reset control\n");
+ return ERR_CAST(priv->reset_ctl);
+ }
+
priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(priv->reset)) {
dev_err(dev, "failed to get RESET GPIO\n");
@@ -193,11 +200,11 @@ rtl83xx_probe(struct device *dev,
dev_set_drvdata(dev, priv);
- if (priv->reset) {
- gpiod_set_value(priv->reset, 1);
+ if (priv->reset_ctl || priv->reset) {
+ rtl83xx_reset_assert(priv);
dev_dbg(dev, "asserted RESET\n");
msleep(REALTEK_HW_STOP_DELAY);
- gpiod_set_value(priv->reset, 0);
+ rtl83xx_reset_deassert(priv);
msleep(REALTEK_HW_START_DELAY);
dev_dbg(dev, "deasserted RESET\n");
}
@@ -293,11 +300,36 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, R
void rtl83xx_remove(struct realtek_priv *priv)
{
/* leave the device reset asserted */
- if (priv->reset)
- gpiod_set_value(priv->reset, 1);
+ rtl83xx_reset_assert(priv);
}
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
+void rtl83xx_reset_assert(struct realtek_priv *priv)
+{
+ int ret;
+
+ ret = reset_control_assert(priv->reset_ctl);
+ if (ret)
+ dev_warn(priv->dev,
+ "Failed to assert the switch reset control: %pe\n",
+ ERR_PTR(ret));
+
+ gpiod_set_value(priv->reset, true);
+}
+
+void rtl83xx_reset_deassert(struct realtek_priv *priv)
+{
+ int ret;
+
+ ret = reset_control_deassert(priv->reset_ctl);
+ if (ret)
+ dev_warn(priv->dev,
+ "Failed to deassert the switch reset control: %pe\n",
+ ERR_PTR(ret));
+
+ gpiod_set_value(priv->reset, false);
+}
+
MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Realtek DSA switches common module");
--- a/drivers/net/dsa/realtek/rtl83xx.h
+++ b/drivers/net/dsa/realtek/rtl83xx.h
@@ -18,5 +18,7 @@ int rtl83xx_register_switch(struct realt
void rtl83xx_unregister_switch(struct realtek_priv *priv);
void rtl83xx_shutdown(struct realtek_priv *priv);
void rtl83xx_remove(struct realtek_priv *priv);
+void rtl83xx_reset_assert(struct realtek_priv *priv);
+void rtl83xx_reset_deassert(struct realtek_priv *priv);
#endif /* _RTL83XX_H */

View File

@ -0,0 +1,45 @@
From 4f580e9aced1816398c1c64f178302a22b8ea6e2 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Sat, 27 Apr 2024 02:11:29 -0300
Subject: [PATCH 2/3] net: dsa: realtek: do not assert reset on remove
The necessity of asserting the reset on removal was previously
questioned, as DSA's own cleanup methods should suffice to prevent
traffic leakage[1].
When a driver has subdrivers controlled by devres, they will be
unregistered after the main driver's .remove is executed. If it asserts
a reset, the subdrivers will be unable to communicate with the hardware
during their cleanup. For LEDs, this means that they will fail to turn
off, resulting in a timeout error.
[1] https://lore.kernel.org/r/20240123215606.26716-9-luizluca@gmail.com/
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/rtl83xx.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -291,16 +291,13 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, R
* rtl83xx_remove() - Cleanup a realtek switch driver
* @priv: realtek_priv pointer
*
- * If a method is provided, this function asserts the hard reset of the switch
- * in order to avoid leaking traffic when the driver is gone.
+ * Placehold for common cleanup procedures.
*
- * Context: Might sleep if priv->gdev->chip->can_sleep.
+ * Context: Any
* Return: nothing
*/
void rtl83xx_remove(struct realtek_priv *priv)
{
- /* leave the device reset asserted */
- rtl83xx_reset_assert(priv);
}
EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);

View File

@ -0,0 +1,396 @@
From 32d617005475a71ebcc4ec8b2791e8d1481e9a10 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Sat, 27 Apr 2024 02:11:30 -0300
Subject: [PATCH 3/3] net: dsa: realtek: add LED drivers for rtl8366rb
This commit introduces LED drivers for rtl8366rb, enabling LEDs to be
described in the device tree using the same format as qca8k. Each port
can configure up to 4 LEDs.
If all LEDs in a group use the default state "keep", they will use the
default behavior after a reset. Changing the brightness of one LED,
either manually or by a trigger, will disable the default hardware
trigger and switch the entire LED group to manually controlled LEDs.
Once in this mode, there is no way to revert to hardware-controlled LEDs
(except by resetting the switch).
Software triggers function as expected with manually controlled LEDs.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/realtek/rtl8366rb.c | 304 ++++++++++++++++++++++++----
1 file changed, 265 insertions(+), 39 deletions(-)
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -180,6 +180,7 @@
#define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f
/* LED control registers */
+/* The LED blink rate is global; it is used by all triggers in all groups. */
#define RTL8366RB_LED_BLINKRATE_REG 0x0430
#define RTL8366RB_LED_BLINKRATE_MASK 0x0007
#define RTL8366RB_LED_BLINKRATE_28MS 0x0000
@@ -195,31 +196,21 @@
(4 * (led_group))
#define RTL8366RB_LED_CTRL_MASK(led_group) \
(0xf << RTL8366RB_LED_CTRL_OFFSET(led_group))
-#define RTL8366RB_LED_OFF 0x0
-#define RTL8366RB_LED_DUP_COL 0x1
-#define RTL8366RB_LED_LINK_ACT 0x2
-#define RTL8366RB_LED_SPD1000 0x3
-#define RTL8366RB_LED_SPD100 0x4
-#define RTL8366RB_LED_SPD10 0x5
-#define RTL8366RB_LED_SPD1000_ACT 0x6
-#define RTL8366RB_LED_SPD100_ACT 0x7
-#define RTL8366RB_LED_SPD10_ACT 0x8
-#define RTL8366RB_LED_SPD100_10_ACT 0x9
-#define RTL8366RB_LED_FIBER 0xa
-#define RTL8366RB_LED_AN_FAULT 0xb
-#define RTL8366RB_LED_LINK_RX 0xc
-#define RTL8366RB_LED_LINK_TX 0xd
-#define RTL8366RB_LED_MASTER 0xe
-#define RTL8366RB_LED_FORCE 0xf
/* The RTL8366RB_LED_X_X registers are used to manually set the LED state only
* when the corresponding LED group in RTL8366RB_LED_CTRL_REG is
- * RTL8366RB_LED_FORCE. Otherwise, it is ignored.
+ * RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored.
*/
#define RTL8366RB_LED_0_1_CTRL_REG 0x0432
-#define RTL8366RB_LED_1_OFFSET 6
#define RTL8366RB_LED_2_3_CTRL_REG 0x0433
-#define RTL8366RB_LED_3_OFFSET 6
+#define RTL8366RB_LED_X_X_CTRL_REG(led_group) \
+ ((led_group) <= 1 ? \
+ RTL8366RB_LED_0_1_CTRL_REG : \
+ RTL8366RB_LED_2_3_CTRL_REG)
+#define RTL8366RB_LED_0_X_CTRL_MASK GENMASK(5, 0)
+#define RTL8366RB_LED_X_1_CTRL_MASK GENMASK(11, 6)
+#define RTL8366RB_LED_2_X_CTRL_MASK GENMASK(5, 0)
+#define RTL8366RB_LED_X_3_CTRL_MASK GENMASK(11, 6)
#define RTL8366RB_MIB_COUNT 33
#define RTL8366RB_GLOBAL_MIB_COUNT 1
@@ -363,14 +354,44 @@
#define RTL8366RB_GREEN_FEATURE_TX BIT(0)
#define RTL8366RB_GREEN_FEATURE_RX BIT(2)
+enum rtl8366_ledgroup_mode {
+ RTL8366RB_LEDGROUP_OFF = 0x0,
+ RTL8366RB_LEDGROUP_DUP_COL = 0x1,
+ RTL8366RB_LEDGROUP_LINK_ACT = 0x2,
+ RTL8366RB_LEDGROUP_SPD1000 = 0x3,
+ RTL8366RB_LEDGROUP_SPD100 = 0x4,
+ RTL8366RB_LEDGROUP_SPD10 = 0x5,
+ RTL8366RB_LEDGROUP_SPD1000_ACT = 0x6,
+ RTL8366RB_LEDGROUP_SPD100_ACT = 0x7,
+ RTL8366RB_LEDGROUP_SPD10_ACT = 0x8,
+ RTL8366RB_LEDGROUP_SPD100_10_ACT = 0x9,
+ RTL8366RB_LEDGROUP_FIBER = 0xa,
+ RTL8366RB_LEDGROUP_AN_FAULT = 0xb,
+ RTL8366RB_LEDGROUP_LINK_RX = 0xc,
+ RTL8366RB_LEDGROUP_LINK_TX = 0xd,
+ RTL8366RB_LEDGROUP_MASTER = 0xe,
+ RTL8366RB_LEDGROUP_FORCE = 0xf,
+
+ __RTL8366RB_LEDGROUP_MODE_MAX
+};
+
+struct rtl8366rb_led {
+ u8 port_num;
+ u8 led_group;
+ struct realtek_priv *priv;
+ struct led_classdev cdev;
+};
+
/**
* struct rtl8366rb - RTL8366RB-specific data
* @max_mtu: per-port max MTU setting
* @pvid_enabled: if PVID is set for respective port
+ * @leds: per-port and per-ledgroup led info
*/
struct rtl8366rb {
unsigned int max_mtu[RTL8366RB_NUM_PORTS];
bool pvid_enabled[RTL8366RB_NUM_PORTS];
+ struct rtl8366rb_led leds[RTL8366RB_NUM_PORTS][RTL8366RB_NUM_LEDGROUPS];
};
static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
@@ -813,6 +834,217 @@ static int rtl8366rb_jam_table(const str
return 0;
}
+static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
+ u8 led_group,
+ enum rtl8366_ledgroup_mode mode)
+{
+ int ret;
+ u32 val;
+
+ val = mode << RTL8366RB_LED_CTRL_OFFSET(led_group);
+
+ ret = regmap_update_bits(priv->map,
+ RTL8366RB_LED_CTRL_REG,
+ RTL8366RB_LED_CTRL_MASK(led_group),
+ val);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
+{
+ switch (led_group) {
+ case 0:
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
+ case 1:
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
+ case 2:
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
+ case 3:
+ return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
+ default:
+ return 0;
+ }
+}
+
+static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
+{
+ struct realtek_priv *priv = led->priv;
+ u8 led_group = led->led_group;
+ u8 port_num = led->port_num;
+ int ret;
+ u32 val;
+
+ ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
+ &val);
+ if (ret) {
+ dev_err(priv->dev, "error reading LED on port %d group %d\n",
+ led_group, port_num);
+ return ret;
+ }
+
+ return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
+}
+
+static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
+{
+ struct realtek_priv *priv = led->priv;
+ u8 led_group = led->led_group;
+ u8 port_num = led->port_num;
+ int ret;
+
+ ret = regmap_update_bits(priv->map,
+ RTL8366RB_LED_X_X_CTRL_REG(led_group),
+ rtl8366rb_led_group_port_mask(led_group,
+ port_num),
+ enable ? 0xffff : 0);
+ if (ret) {
+ dev_err(priv->dev, "error updating LED on port %d group %d\n",
+ led_group, port_num);
+ return ret;
+ }
+
+ /* Change the LED group to manual controlled LEDs if required */
+ ret = rb8366rb_set_ledgroup_mode(priv, led_group,
+ RTL8366RB_LEDGROUP_FORCE);
+
+ if (ret) {
+ dev_err(priv->dev, "error updating LED GROUP group %d\n",
+ led_group);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
+ enum led_brightness brightness)
+{
+ struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
+ cdev);
+
+ return rb8366rb_set_port_led(led, brightness == LED_ON);
+}
+
+static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
+ struct fwnode_handle *led_fwnode)
+{
+ struct rtl8366rb *rb = priv->chip_data;
+ struct led_init_data init_data = { };
+ enum led_default_state state;
+ struct rtl8366rb_led *led;
+ u32 led_group;
+ int ret;
+
+ ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
+ if (ret)
+ return ret;
+
+ if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
+ dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
+ led_group, dp->index);
+ return -EINVAL;
+ }
+
+ led = &rb->leds[dp->index][led_group];
+ led->port_num = dp->index;
+ led->led_group = led_group;
+ led->priv = priv;
+
+ state = led_init_default_state_get(led_fwnode);
+ switch (state) {
+ case LEDS_DEFSTATE_ON:
+ led->cdev.brightness = 1;
+ rb8366rb_set_port_led(led, 1);
+ break;
+ case LEDS_DEFSTATE_KEEP:
+ led->cdev.brightness =
+ rb8366rb_get_port_led(led);
+ break;
+ case LEDS_DEFSTATE_OFF:
+ default:
+ led->cdev.brightness = 0;
+ rb8366rb_set_port_led(led, 0);
+ }
+
+ led->cdev.max_brightness = 1;
+ led->cdev.brightness_set_blocking =
+ rtl8366rb_cled_brightness_set_blocking;
+ init_data.fwnode = led_fwnode;
+ init_data.devname_mandatory = true;
+
+ init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
+ dp->ds->index, dp->index, led_group);
+ if (!init_data.devicename)
+ return -ENOMEM;
+
+ ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
+ if (ret) {
+ dev_warn(priv->dev, "Failed to init LED %d for port %d",
+ led_group, dp->index);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
+{
+ int ret = 0;
+ int i;
+
+ regmap_update_bits(priv->map,
+ RTL8366RB_INTERRUPT_CONTROL_REG,
+ RTL8366RB_P4_RGMII_LED,
+ 0);
+
+ for (i = 0; i < RTL8366RB_NUM_LEDGROUPS; i++) {
+ ret = rb8366rb_set_ledgroup_mode(priv, i,
+ RTL8366RB_LEDGROUP_OFF);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int rtl8366rb_setup_leds(struct realtek_priv *priv)
+{
+ struct device_node *leds_np, *led_np;
+ struct dsa_switch *ds = &priv->ds;
+ struct dsa_port *dp;
+ int ret = 0;
+
+ dsa_switch_for_each_port(dp, ds) {
+ if (!dp->dn)
+ continue;
+
+ leds_np = of_get_child_by_name(dp->dn, "leds");
+ if (!leds_np) {
+ dev_dbg(priv->dev, "No leds defined for port %d",
+ dp->index);
+ continue;
+ }
+
+ for_each_child_of_node(leds_np, led_np) {
+ ret = rtl8366rb_setup_led(priv, dp,
+ of_fwnode_handle(led_np));
+ if (ret) {
+ of_node_put(led_np);
+ break;
+ }
+ }
+
+ of_node_put(leds_np);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
static int rtl8366rb_setup(struct dsa_switch *ds)
{
struct realtek_priv *priv = ds->priv;
@@ -821,7 +1053,6 @@ static int rtl8366rb_setup(struct dsa_sw
u32 chip_ver = 0;
u32 chip_id = 0;
int jam_size;
- u32 val;
int ret;
int i;
@@ -997,7 +1228,9 @@ static int rtl8366rb_setup(struct dsa_sw
if (ret)
return ret;
- /* Set blinking, TODO: make this configurable */
+ /* Set blinking, used by all LED groups using HW triggers.
+ * TODO: make this configurable
+ */
ret = regmap_update_bits(priv->map, RTL8366RB_LED_BLINKRATE_REG,
RTL8366RB_LED_BLINKRATE_MASK,
RTL8366RB_LED_BLINKRATE_56MS);
@@ -1005,26 +1238,19 @@ static int rtl8366rb_setup(struct dsa_sw
return ret;
/* Set up LED activity:
- * Each port has 4 LEDs, we configure all ports to the same
- * behaviour (no individual config) but we can set up each
- * LED separately.
+ * Each port has 4 LEDs on fixed groups. Each group shares the same
+ * hardware trigger across all ports. LEDs can only be indiviually
+ * controlled setting the LED group to fixed mode and using the driver
+ * to toggle them LEDs on/off.
*/
if (priv->leds_disabled) {
- /* Turn everything off */
- regmap_update_bits(priv->map,
- RTL8366RB_INTERRUPT_CONTROL_REG,
- RTL8366RB_P4_RGMII_LED,
- 0);
-
- for (i = 0; i < RTL8366RB_NUM_LEDGROUPS; i++) {
- val = RTL8366RB_LED_OFF << RTL8366RB_LED_CTRL_OFFSET(i);
- ret = regmap_update_bits(priv->map,
- RTL8366RB_LED_CTRL_REG,
- RTL8366RB_LED_CTRL_MASK(i),
- val);
- if (ret)
- return ret;
- }
+ ret = rtl8366rb_setup_all_leds_off(priv);
+ if (ret)
+ return ret;
+ } else {
+ ret = rtl8366rb_setup_leds(priv);
+ if (ret)
+ return ret;
}
ret = rtl8366_reset_vlan(priv);

View File

@ -5,16 +5,38 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
FAT32_BLOCK_SIZE=1024
FAT32_BLOCKS=$(shell echo $$(($(CONFIG_MXS_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
FAT32_BLOCK_SIZE = 1024
FAT32_BLOCKS = $(shell echo $$(($(CONFIG_MXS_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
KERNEL_LOADADDR:=0x40008000
KERNEL_LOADADDR := 0x40008000
define Build/mxs-ext4-rootfs-with-boot
rm -rf $(call mkfs_target_dir,$(1))/boot
mkdir -p $(call mkfs_target_dir,$(1))/boot
$(CP) --no-preserve=mode $(KDIR)/$(KERNEL_NAME) $(call mkfs_target_dir,$(1))/boot/
$(foreach dts,$(DEVICE_DTS), \
$(CP) \
$(DTS_DIR)/$(dts).dtb \
$(call mkfs_target_dir,$(1))/boot/; \
)
rm -rf $@.rootfs
$(STAGING_DIR_HOST)/bin/make_ext4fs -L rootfs \
-l $(ROOTFS_PARTSIZE) -b $(CONFIG_TARGET_EXT4_BLOCKSIZE) \
$(if $(CONFIG_TARGET_EXT4_RESERVED_PCT),-m $(CONFIG_TARGET_EXT4_RESERVED_PCT)) \
$(if $(CONFIG_TARGET_EXT4_JOURNAL),,-J) \
$(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)) \
$@.rootfs $(call mkfs_target_dir,$(1))/
mv $@.rootfs $@
endef
define Build/mxs-sdcard-ext4-ext4
mv $@ $@.rootfs
./gen_sdcard_ext4_ext4.sh \
$@ \
$(STAGING_DIR_IMAGE)/$(DEVICE_NAME)/u-boot.sb \
$(IMAGE_ROOTFS) \
$@.rootfs \
$(CONFIG_TARGET_ROOTFS_PARTSIZE)
endef
@ -46,12 +68,13 @@ endef
define Device/i2se_duckbill
DEVICE_VENDOR := I2SE
DEVICE_MODEL := Duckbill
DEVICE_PACKAGES := -dnsmasq -ppp -ip6tables -iptables -mtd \
uboot-envtools kmod-leds-gpio -kmod-nf-nathelper
SUPPORTED_DEVICES:=i2se,duckbill
SOC:=imx28
DEVICE_DTS:=imx28-duckbill
IMAGE/sdcard.img.gz = mxs-sdcard-ext4-ext4 | append-metadata | gzip
DEVICE_PACKAGES := -dnsmasq -firewall4 -mtd -nftables -odhcpd-ipv6only -ppp -kmod-nft-offload \
uboot-envtools kmod-leds-gpio
SUPPORTED_DEVICES := i2se,duckbill
SOC := imx28
KERNEL := kernel-bin
DEVICE_DTS := imx28-duckbill imx28-duckbill-2 imx28-duckbill-2-485 imx28-duckbill-2-spi
IMAGE/sdcard.img.gz = mxs-ext4-rootfs-with-boot | mxs-sdcard-ext4-ext4 | append-metadata | gzip
endef
TARGET_DEVICES += i2se_duckbill
@ -59,10 +82,10 @@ define Device/olinuxino_maxi
DEVICE_VENDOR := Olimex
DEVICE_MODEL := OLinuXino Maxi
DEVICE_PACKAGES := kmod-usb-net-smsc95xx kmod-pinctrl-mcp23s08-i2c \
kmod-pinctrl-mcp23s08-spi kmod-leds-gpio kmod-sound-core
SUPPORTED_DEVICES:=olimex,imx23-olinuxino
SOC:=imx23
DEVICE_DTS:=imx23-olinuxino
kmod-pinctrl-mcp23s08-spi kmod-leds-gpio kmod-sound-core
SUPPORTED_DEVICES := olimex,imx23-olinuxino
SOC := imx23
DEVICE_DTS := imx23-olinuxino
IMAGE/sdcard.img.gz = mxs-sdcard-vfat-ext4 | append-metadata | gzip
endef
TARGET_DEVICES += olinuxino_maxi
@ -71,10 +94,10 @@ define Device/olinuxino_micro
DEVICE_VENDOR := Olimex
DEVICE_MODEL := OLinuXino Micro
DEVICE_PACKAGES := kmod-pinctrl-mcp23s08-spi kmod-pinctrl-mcp23s08-i2c \
kmod-leds-gpio
SUPPORTED_DEVICES:=olimex,imx23-olinuxino
SOC:=imx23
DEVICE_DTS:=imx23-olinuxino
kmod-leds-gpio
SUPPORTED_DEVICES := olimex,imx23-olinuxino
SOC := imx23
DEVICE_DTS := imx23-olinuxino
IMAGE/sdcard.img.gz = mxs-sdcard-vfat-ext4 | append-metadata | gzip
endef
TARGET_DEVICES += olinuxino_micro

View File

@ -6,7 +6,7 @@ BOARDNAME:=Qualcomm Atheros 802.11ax WiSoC-s
FEATURES:=squashfs ramdisk fpu nand rtc emmc
KERNELNAME:=Image
CPU_TYPE:=cortex-a53
SUBTARGETS:=ipq807x ipq60xx
SUBTARGETS:=ipq807x ipq60xx ipq50xx
KERNEL_PATCHVER:=6.6
@ -14,8 +14,7 @@ include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
kmod-usb3 kmod-usb-dwc3 kmod-usb-dwc3-qcom \
kmod-leds-gpio kmod-gpio-button-hotplug \
kmod-qca-nss-dp \
kmod-ath11k-ahb wpad-openssl \
kmod-qca-nss-dp kmod-ath11k-ahb wpad-openssl \
uboot-envtools losetup \
automount cpufreq

View File

@ -0,0 +1,116 @@
#include <dt-bindings/net/qcom-ipq-ess.h>
&soc {
ess_instance: ess-instance {
#address-cells = <1>;
#size-cells = <1>;
num_devices = <1>;
switch: ess-switch@39c00000 {
compatible = "qcom,ess-switch-ipq50xx";
device_id = <0>;
cmnblk_clk = "internal_96MHz";
reg = <0x39c00000 0x200000>;
switch_access_mode = "local bus";
clocks = <&gcc GCC_CMN_BLK_AHB_CLK>,
<&gcc GCC_CMN_BLK_SYS_CLK>,
<&gcc GCC_UNIPHY_AHB_CLK>,
<&gcc GCC_UNIPHY_SYS_CLK>,
<&gcc GCC_MDIO0_AHB_CLK>,
<&gcc GCC_MDIO1_AHB_CLK>,
<&gcc GCC_GMAC0_CFG_CLK>,
<&gcc GCC_GMAC0_SYS_CLK>,
<&gcc GCC_GMAC1_CFG_CLK>,
<&gcc GCC_GMAC1_SYS_CLK>,
<&gcc GCC_GEPHY_RX_CLK>,
<&gcc GCC_GEPHY_TX_CLK>,
<&gcc GCC_UNIPHY_RX_CLK>,
<&gcc GCC_UNIPHY_TX_CLK>,
<&gcc GCC_GMAC0_RX_CLK>,
<&gcc GCC_GMAC0_TX_CLK>,
<&gcc GCC_GMAC1_RX_CLK>,
<&gcc GCC_GMAC1_TX_CLK>,
<&gcc GCC_SNOC_GMAC0_AHB_CLK>,
<&gcc GCC_SNOC_GMAC1_AHB_CLK>,
<&gcc GCC_GMAC0_PTP_CLK>,
<&gcc GCC_GMAC1_PTP_CLK>;
clock-names = "cmn_ahb_clk",
"cmn_sys_clk",
"uniphy_ahb_clk",
"uniphy_sys_clk",
"gcc_mdio0_ahb_clk",
"gcc_mdio1_ahb_clk",
"gcc_gmac0_cfg_clk",
"gcc_gmac0_sys_clk",
"gcc_gmac1_cfg_clk",
"gcc_gmac1_sys_clk",
"uniphy0_port1_rx_clk",
"uniphy0_port1_tx_clk",
"uniphy1_port5_rx_clk",
"uniphy1_port5_tx_clk",
"nss_port1_rx_clk",
"nss_port1_tx_clk",
"nss_port2_rx_clk",
"nss_port2_tx_clk",
"gcc_snoc_gmac0_ahb_clk",
"gcc_snoc_gmac1_ahb_clk",
"gcc_gmac0_ptp_clk",
"gcc_gmac1_ptp_clk";
resets = <&gcc GCC_GMAC0_BCR>,
<&gcc GCC_GMAC1_BCR>,
<&gcc GCC_UNIPHY_BCR>,
<&gcc GCC_UNIPHY_SOFT_RESET>;
reset-names = "gmac0_bcr_rst",
"gmac1_bcr_rst",
"uniphy_bcr_rst",
"uniphy1_soft_rst";
status = "disabled";
};
};
ess-uniphy@98000 {
compatible = "qcom,ess-uniphy";
reg = <0x98000 0x800>;
uniphy_access_mode = "local bus";
};
nss-dp-common {
compatible = "qcom,nss-dp-common";
qcom,tcsr-base = <0x01937000>;
};
dp1: dp1 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <1>;
reg = <0x39C00000 0x10000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_SNOC_GMAC0_AXI_CLK>;
clock-names = "nss-snoc-gmac-axi-clk";
qcom,mactype = <2>; /* GMAC_HAL_TYPE_SYN_GMAC */
local-mac-address = [000000000000];
phy-mode = "internal";
phy-handle = <&ge_phy>;
status = "disabled";
};
dp2: dp2 {
device_type = "network";
compatible = "qcom,nss-dp";
qcom,id = <2>;
reg = <0x39D00000 0x10000>;
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_SNOC_GMAC1_AXI_CLK>;
clock-names = "nss-snoc-gmac-axi-clk";
qcom,mactype = <2>; /* GMAC_HAL_TYPE_SYN_GMAC */
local-mac-address = [000000000000];
phy-mode = "sgmii";
status = "disabled";
};
};

View File

@ -0,0 +1,325 @@
#include "ipq5018.dtsi"
#include "ipq5018-ess.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
/ {
aliases {
ethernet0 = &dp1;
ethernet1 = &dp2;
led-boot = &led_system_blue;
led-failsafe = &led_system_red;
led-running = &led_system_blue;
led-upgrade = &led_system_red;
serial0 = &blsp1_uart1;
};
chosen {
bootargs-append = " root=/dev/ubiblock0_0 coherent_pool=2M";
stdout-path = "serial0:115200n8";
};
keys {
compatible = "gpio-keys";
pinctrl-0 = <&button_pins>;
pinctrl-names = "default";
wps-button {
label = "wps";
gpios = <&tlmm 27 GPIO_ACTIVE_LOW>;
linux,code = <KEY_WPS_BUTTON>;
};
reset-button {
label = "reset";
gpios = <&tlmm 28 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
leds {
compatible = "pwm-leds";
led_system_red: red {
color = <LED_COLOR_ID_RED>;
function = LED_FUNCTION_POWER;
pwms = <&pwm 3 1250000>;
max-brightness = <255>;
};
green {
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_POWER;
pwms = <&pwm 0 1250000>;
max-brightness = <255>;
};
led_system_blue: blue {
color = <LED_COLOR_ID_BLUE>;
function = LED_FUNCTION_POWER;
pwms = <&pwm 1 1250000>;
max-brightness = <255>;
};
};
reserved-memory {
q6_mem_regions: q6_mem_regions@4b000000 {
no-map;
reg = <0x0 0x4b000000 0x0 0x3000000>;
};
};
};
&sleep_clk {
clock-frequency = <32000>;
};
&xo_board_clk {
clock-frequency = <24000000>;
};
&blsp1_uart1 {
status = "okay";
pinctrl-0 = <&serial_0_pins>;
pinctrl-names = "default";
};
&crypto {
status = "okay";
};
&cryptobam {
status = "okay";
};
&prng {
status = "okay";
};
&pwm {
status = "okay";
#pwm-cells = <2>;
pinctrl-0 = <&pwm_pins>;
pinctrl-names = "default";
};
&qfprom {
status = "okay";
};
&qpic_bam {
status = "okay";
};
&qpic_nand {
pinctrl-0 = <&qpic_pins>;
pinctrl-names = "default";
status = "okay";
partitions {
status = "disabled";
};
nand@0 {
compatible = "spi-nand";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-ecc-engine = <&qpic_nand>;
nand-ecc-strength = <8>;
nand-ecc-step-size = <512>;
nand-bus-width = <8>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "0:SBL1";
reg = <0x00000000 0x80000>;
read-only;
};
partition@80000 {
label = "0:MIBIB";
reg = <0x00080000 0x80000>;
read-only;
};
partition@100000 {
label = "0:QSEE";
reg = <0x00100000 0x100000>;
read-only;
};
partition@200000 {
label = "0:DEVCFG";
reg = <0x00200000 0x40000>;
read-only;
};
partition@240000 {
label = "0:CDT";
reg = <0x00240000 0x40000>;
read-only;
};
partition@280000 {
label = "0:APPSBLENV";
reg = <0x00280000 0x80000>;
};
partition@300000 {
label = "0:APPSBL";
reg = <0x00300000 0x140000>;
read-only;
};
partition@440000 {
label = "0:ART";
reg = <0x00440000 0x100000>;
read-only;
};
partition@540000 {
label = "0:TRAINING";
reg = <0x00540000 0x80000>;
read-only;
};
partition@5c0000 {
label = "u_env";
reg = <0x005c0000 0x80000>;
};
partition@640000 {
label = "s_env";
reg = <0x00640000 0x40000>;
};
partition@680000 {
label = "devinfo";
reg = <0x00680000 0x40000>;
read-only;
};
partition@6c0000 {
label = "kernel";
reg = <0x006c0000 0x5200000>;
};
partition@ec0000 {
label = "rootfs";
reg = <0x0ec0000 0x4a00000>;
};
partition@58c0000 {
label = "alt_kernel";
reg = <0x058c0000 0x5200000>;
};
partition@60c0000 {
label = "alt_rootfs";
reg = <0x060c0000 0x4a00000>;
};
partition@aac0000 {
label = "sysdiag";
reg = <0x0aac0000 0x200000>;
read-only;
};
partition@acc0000 {
label = "syscfg";
reg = <0x0acc0000 0x4400000>;
read-only;
};
};
};
};
&tlmm {
button_pins: button-state {
pins = "gpio27", "gpio28";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
mdio1_pins: mdio-state {
mdc-pins {
pins = "gpio36";
function = "mdc";
drive-strength = <8>;
bias-pull-up;
};
mdio-pins {
pins = "gpio37";
function = "mdio";
drive-strength = <8>;
bias-pull-up;
};
};
pwm_pins: pwm-state {
mux_1 {
pins = "gpio1";
function = "pwm1";
drive-strength = <8>;
};
mux_2 {
pins = "gpio30";
function = "pwm3";
drive-strength = <8>;
};
mux_3 {
pins = "gpio46";
function = "pwm0";
drive-strength = <8>;
};
};
qpic_pins: qpic-state {
clock-pins {
pins = "gpio9";
function = "qspi_clk";
drive-strength = <8>;
bias-disable;
};
cs-pins {
pins = "gpio8";
function = "qspi_cs";
drive-strength = <8>;
bias-disable;
};
data-pins {
pins = "gpio4", "gpio5", "gpio6", "gpio7";
function = "qspi_data";
drive-strength = <8>;
bias-disable;
};
};
serial_0_pins: uart0-state {
pins = "gpio20", "gpio21";
function = "blsp0_uart0";
bias-disable;
};
};
&tsens {
status = "okay";
};

View File

@ -0,0 +1,262 @@
/dts-v1/;
#include "ipq5018.dtsi"
#include "ipq5018-mx-base.dtsi"
/ {
model = "Linksys MX2000";
compatible = "linksys,mx2000", "qcom,ipq5018";
};
/*
* ===============================================================
* _______________________ _______________________
* | IPQ5018 | | QCA8337 |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC0 |---| GE Phy | | | | Phy0 |---| MAC1 | |
* | +------+ +--------+ | | +--------+ +------+ |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC1 |---| Uniphy |-+-SGMII-+-| SerDes |---| MAC6 | |
* | +------+ +--------+ | | +--------+ +------+ |
* |_______________________| |_______________________|
*
* ===============================================================
*/
&switch {
status = "okay";
switch_mac_mode = <MAC_MODE_SGMII_CHANNEL0>;
qcom,port_phyinfo {
// MAC0 -> GE Phy -> QCA8337 Phy4
port@0 {
port_id = <1>;
mdiobus = <&mdio0>;
phy_address = <7>;
};
// MAC1 ---SGMII---> QCA8337 SerDes
port@1 {
port_id = <2>;
forced-speed = <1000>;
forced-duplex = <1>;
};
};
};
// MAC1 ---SGMII---> QCA8337 SerDes
&dp2 {
status = "okay";
phy-mode = "sgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
&mdio0 {
status = "okay";
};
/* IPQ5018 GE Phy -> Not connected
* needs to be enabled for QSDK to identify the IPQ5018 dummy switch
*/
&ge_phy {
status = "okay";
};
&mdio1 {
status = "okay";
pinctrl-0 = <&mdio1_pins>;
pinctrl-names = "default";
reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
// QCA8337 Phy0 not connected
qca8337_0: ethernet-phy@0 {
reg = <0>;
};
// QCA8337 Phy1 -> WAN
qca8337_1: ethernet-phy@1 {
reg = <1>;
};
// QCA8337 Phy2 -> LAN1
qca8337_2: ethernet-phy@2 {
reg = <2>;
};
// QCA8337 Phy3 -> LAN2
qca8337_3: ethernet-phy@3 {
reg = <3>;
};
// QCA8337 Phy4 -> LAN3
qca8337_4: ethernet-phy@4 {
reg = <4>;
};
// QCA8337 switch
switch1: ethernet-switch@17 {
compatible = "qca,qca8337";
reg = <17>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@2 {
reg = <2>;
label = "wan";
phy-handle = <&qca8337_1>;
};
port@3 {
reg = <3>;
label = "lan3";
phy-handle = <&qca8337_2>;
};
port@4 {
reg = <4>;
label = "lan2";
phy-handle = <&qca8337_3>;
};
port@5 {
reg = <5>;
label = "lan1";
phy-handle = <&qca8337_4>;
};
port@6 {
reg = <6>;
label = "cpu";
phy-mode = "sgmii";
ethernet = <&dp2>;
qca,sgmii-enable-pll;
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};
&q6v5_wcss {
status = "okay";
memory-region = <&q6_mem_regions>;
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt",
"ath11k/IPQ5018/hw1.0/m3_fw.mdt",
"ath11k/QCN6122/hw1.0/m3_fw.mdt";
/* The QCN6102 radio should map to UPD ID 2. Without */
/* bootargs, the firmware will expect it to be on UPD ID 3 */
boot-args = <
/* type: */ 0x1 /* PCIE0 */
/* length: */ 4
/* UPD ID: */ 2
/* reset GPIO: */ 15
/* reserved: */ 0 0>;
// IPQ5018
q6_wcss_pd1: pd-1 {
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt";
resets =
<&gcc GCC_WCSSAON_RESET>,
<&gcc GCC_WCSS_BCR>,
<&gcc GCC_CE_BCR>;
reset-names =
"wcss_aon_reset",
"wcss_reset",
"ce_reset";
clocks =
<&gcc GCC_WCSS_AHB_S_CLK>,
<&gcc GCC_WCSS_ACMT_CLK>,
<&gcc GCC_WCSS_AXI_M_CLK>;
clock-names =
"gcc_wcss_ahb_s_clk",
"gcc_wcss_acmt_clk",
"gcc_wcss_axi_m_clk";
// qcom,halt-regs = <&tcsr_q6_block 0xa000 0xd000 0x0>;
interrupts-extended =
<&wcss_smp2p_in 8 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 9 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 12 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 11 IRQ_TYPE_NONE>;
interrupt-names =
"fatal",
"ready",
"spawn-ack",
"stop-ack";
qcom,smem-states =
<&wcss_smp2p_out 8>,
<&wcss_smp2p_out 9>,
<&wcss_smp2p_out 10>;
qcom,smem-state-names =
"shutdown",
"stop",
"spawn";
status = "okay";
};
// QCN6102 5G
q6_wcss_pd2: pd-2 {
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt";
interrupts-extended =
<&wcss_smp2p_in 16 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 17 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 20 IRQ_TYPE_NONE>,
<&wcss_smp2p_in 19 IRQ_TYPE_NONE>;
interrupt-names =
"fatal",
"ready",
"spawn-ack",
"stop-ack";
qcom,smem-states =
<&wcss_smp2p_out 16>,
<&wcss_smp2p_out 17>,
<&wcss_smp2p_out 18>;
qcom,smem-state-names =
"shutdown",
"stop",
"spawn";
status = "okay";
};
};
&wifi0 {
// IPQ5018
qcom,rproc = <&q6_wcss_pd1>;
qcom,ath11k-calibration-variant = "Linksys-MX2000";
qcom,ath11k-fw-memory-mode = <2>;
qcom,bdf-addr = <0x4c400000>;
status = "okay";
};
&wifi1 {
// QCN6102 5G
qcom,rproc = <&q6_wcss_pd2>;
qcom,userpd-subsys-name = "q6v5_wcss_userpd2";
qcom,ath11k-calibration-variant = "Linksys-MX2000";
qcom,ath11k-fw-memory-mode = <2>;
qcom,bdf-addr = <0x4d100000>;
qcom,m3-dump-addr = <0x4df00000>;
status = "okay";
};

View File

@ -0,0 +1,240 @@
/dts-v1/;
#include "ipq5018.dtsi"
#include "ipq5018-mx-base.dtsi"
/ {
model = "Linksys MX5500";
compatible = "linksys,mx5500", "qcom,ipq5018";
};
/*
* ===============================================================
* _______________________ _______________________
* | IPQ5018 | | QCA8337 |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC0 |---| GE Phy | | | | Phy0 |---| MAC1 | |
* | +------+ +--------+ | | +--------+ +------+ |
* | +------+ +--------+ | | +--------+ +------+ |
* | | MAC1 |---| Uniphy |-+-SGMII-+-| SerDes |---| MAC6 | |
* | +------+ +--------+ | | +--------+ +------+ |
* |_______________________| |_______________________|
*
* ===============================================================
*/
&switch {
status = "okay";
switch_mac_mode = <MAC_MODE_SGMII_CHANNEL0>;
qcom,port_phyinfo {
// MAC0 -> GE Phy -> QCA8337 Phy4
port@0 {
port_id = <1>;
mdiobus = <&mdio0>;
phy_address = <7>;
};
// MAC1 ---SGMII---> QCA8337 SerDes
port@1 {
port_id = <2>;
forced-speed = <1000>;
forced-duplex = <1>;
};
};
};
// MAC1 ---SGMII---> QCA8337 SerDes
&dp2 {
status = "okay";
phy-mode = "sgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
&mdio0 {
status = "okay";
};
/* IPQ5018 GE Phy -> Not connected
* needs to be enabled for QSDK to identify the IPQ5018 dummy switch
*/
&ge_phy {
status = "okay";
};
&mdio1 {
status = "okay";
pinctrl-0 = <&mdio1_pins>;
pinctrl-names = "default";
reset-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
// QCA8337 Phy0 not connected
qca8337_0: ethernet-phy@0 {
reg = <0>;
};
// QCA8337 Phy1 -> WAN
qca8337_1: ethernet-phy@1 {
reg = <1>;
};
// QCA8337 Phy2 -> LAN1
qca8337_2: ethernet-phy@2 {
reg = <2>;
};
// QCA8337 Phy3 -> LAN2
qca8337_3: ethernet-phy@3 {
reg = <3>;
};
// QCA8337 Phy4 -> LAN3
qca8337_4: ethernet-phy@4 {
reg = <4>;
};
// QCA8337 switch
switch1: ethernet-switch@17 {
compatible = "qca,qca8337";
reg = <17>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@2 {
reg = <2>;
label = "wan";
phy-handle = <&qca8337_1>;
};
port@3 {
reg = <3>;
label = "lan3";
phy-handle = <&qca8337_2>;
};
port@4 {
reg = <4>;
label = "lan2";
phy-handle = <&qca8337_3>;
};
port@5 {
reg = <5>;
label = "lan1";
phy-handle = <&qca8337_4>;
};
port@6 {
reg = <6>;
label = "cpu";
phy-mode = "sgmii";
ethernet = <&dp2>;
qca,sgmii-enable-pll;
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};
&pcie0_phy {
status = "okay";
};
&pcie0 {
status = "okay";
perst-gpios = <&tlmm 15 GPIO_ACTIVE_LOW>;
bridge@0,0 {
reg = <0x00000000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
ranges;
wifi@1,0 {
status = "okay";
/* QCN9074: ath11k lacks DT compatible for PCI cards */
compatible = "pci17cb,1104";
reg = <0x00010000 0 0 0 0>;
qcom,ath11k-calibration-variant = "Linksys-MX5500";
};
};
};
&q6v5_wcss {
status = "okay";
memory-region = <&q6_mem_regions>;
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt",
"ath11k/IPQ5018/hw1.0/m3_fw.mdt";
// IPQ5018
q6_wcss_pd1: pd-1 {
firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mdt";
resets =
<&gcc GCC_WCSSAON_RESET>,
<&gcc GCC_WCSS_BCR>,
<&gcc GCC_CE_BCR>;
reset-names =
"wcss_aon_reset",
"wcss_reset",
"ce_reset";
clocks =
<&gcc GCC_WCSS_AHB_S_CLK>,
<&gcc GCC_WCSS_ACMT_CLK>,
<&gcc GCC_WCSS_AXI_M_CLK>;
clock-names =
"gcc_wcss_ahb_s_clk",
"gcc_wcss_acmt_clk",
"gcc_wcss_axi_m_clk";
interrupts-extended =
<&wcss_smp2p_in 8 0>,
<&wcss_smp2p_in 9 0>,
<&wcss_smp2p_in 12 0>,
<&wcss_smp2p_in 11 0>;
interrupt-names =
"fatal",
"ready",
"spawn-ack",
"stop-ack";
qcom,smem-states =
<&wcss_smp2p_out 8>,
<&wcss_smp2p_out 9>,
<&wcss_smp2p_out 10>;
qcom,smem-state-names =
"shutdown",
"stop",
"spawn";
status = "okay";
};
};
&wifi0 {
// IPQ5018
qcom,rproc = <&q6_wcss_pd1>;
qcom,ath11k-calibration-variant = "Linksys-MX5500";
qcom,ath11k-fw-memory-mode = <2>;
qcom,bdf-addr = <0x4c400000>;
status = "okay";
};

View File

@ -0,0 +1,31 @@
define Device/linksys_ipq50xx_mx_base
$(call Device/FitImageLzma)
DEVICE_VENDOR := Linksys
BLOCKSIZE := 128k
PAGESIZE := 2048
KERNEL_SIZE := 8192k
IMAGE_SIZE := 83968k
NAND_SIZE := 256m
SOC := ipq5018
IMAGES += factory.bin
IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=$$$$(DEVICE_MODEL)
endef
define Device/linksys_mx2000
$(call Device/linksys_ipq50xx_mx_base)
DEVICE_MODEL := MX2000
DEVICE_DTS_CONFIG := config@mp03.5-c1
DEVICE_PACKAGES := ath11k-firmware-qcn6122 \
ipq-wifi-linksys_mx2000
endef
TARGET_DEVICES += linksys_mx2000
define Device/linksys_mx5500
$(call Device/linksys_ipq50xx_mx_base)
DEVICE_MODEL := MX5500
DEVICE_DTS_CONFIG := config@mp03.1
DEVICE_PACKAGES := kmod-ath11k-pci \
ath11k-firmware-qcn9074 \
ipq-wifi-linksys_mx5500
endef
TARGET_DEVICES += linksys_mx5500

View File

@ -0,0 +1,45 @@
#!/bin/sh
. /lib/functions/uci-defaults.sh
. /lib/functions/system.sh
ipq50xx_setup_interfaces()
{
local board="$1"
case $board in
linksys,mx2000|\
linksys,mx5500)
ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan"
;;
esac
}
ipq50xx_setup_macs()
{
local board="$1"
local lan_mac=""
local wan_mac=""
local label_mac=""
case "$board" in
linksys,mx2000|\
linksys,mx5500)
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
lan_mac=$label_mac
wan_mac=$label_mac
ucidef_set_network_device_mac eth0 $label_mac
;;
esac
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
[ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac
}
board_config_update
board=$(board_name)
ipq50xx_setup_interfaces $board
ipq50xx_setup_macs $board
board_config_flush
exit 0

View File

@ -0,0 +1,47 @@
#!/bin/sh
[ -e /lib/firmware/$FIRMWARE ] && exit 0
. /lib/functions/caldata.sh
board=$(board_name)
case "$FIRMWARE" in
"ath11k/IPQ5018/hw1.0/cal-ahb-c000000.wifi.bin")
case "$board" in
linksys,mx2000|\
linksys,mx5500)
caldata_extract "0:ART" 0x1000 0x20000
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ath11k_patch_mac $(macaddr_add $label_mac 1) 0
ath11k_remove_regdomain
ath11k_set_macflag
;;
esac
;;
"ath11k/QCN6122/hw1.0/cal-ahb-b00a040.wifi1.bin")
case "$board" in
linksys,mx2000)
caldata_extract "0:ART" 0x26800 0x20000
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ath11k_patch_mac $(macaddr_add $label_mac 2) 0
ath11k_remove_regdomain
ath11k_set_macflag
;;
esac
;;
"ath11k/QCN9074/hw1.0/cal-pci-0001:01:00.0.bin")
case "$board" in
linksys,mx5500)
caldata_extract "0:ART" 0x26800 0x20000
label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
ath11k_patch_mac $(macaddr_add $label_mac 2) 0
ath11k_remove_regdomain
ath11k_set_macflag
;;
esac
;;
*)
exit 1
;;
esac

View File

@ -0,0 +1,12 @@
#!/bin/sh /etc/rc.common
START=99
boot() {
case $(board_name) in
linksys,mx2000|\
linksys,mx5500)
mtd resetbc s_env || true
;;
esac
}

View File

@ -0,0 +1,84 @@
PART_NAME=firmware
REQUIRE_IMAGE_METADATA=1
RAMFS_COPY_BIN='fw_printenv fw_setenv head'
RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
remove_oem_ubi_volume() {
local oem_volume_name="$1"
local oem_ubivol
local mtdnum
local ubidev
mtdnum=$(find_mtd_index "$CI_UBIPART")
if [ ! "$mtdnum" ]; then
return
fi
ubidev=$(nand_find_ubi "$CI_UBIPART")
if [ ! "$ubidev" ]; then
ubiattach --mtdn="$mtdnum"
ubidev=$(nand_find_ubi "$CI_UBIPART")
fi
if [ "$ubidev" ]; then
oem_ubivol=$(nand_find_volume "$ubidev" "$oem_volume_name")
[ "$oem_ubivol" ] && ubirmvol "/dev/$ubidev" --name="$oem_volume_name"
fi
}
linksys_mx_do_upgrade() {
local setenv_script="/tmp/fw_env_upgrade"
CI_UBIPART="rootfs"
boot_part="$(fw_printenv -n boot_part)"
if [ -n "$UPGRADE_OPT_USE_CURR_PART" ]; then
if [ "$boot_part" -eq "2" ]; then
CI_KERNPART="alt_kernel"
CI_UBIPART="alt_rootfs"
fi
else
if [ "$boot_part" -eq "1" ]; then
echo "boot_part 2" >> $setenv_script
CI_KERNPART="alt_kernel"
CI_UBIPART="alt_rootfs"
else
echo "boot_part 1" >> $setenv_script
fi
fi
boot_part_ready="$(fw_printenv -n boot_part_ready)"
if [ "$boot_part_ready" -ne "3" ]; then
echo "boot_part_ready 3" >> $setenv_script
fi
auto_recovery="$(fw_printenv -n auto_recovery)"
if [ "$auto_recovery" != "yes" ]; then
echo "auto_recovery yes" >> $setenv_script
fi
if [ -f "$setenv_script" ]; then
fw_setenv -s $setenv_script || {
echo "failed to update U-Boot environment"
return 1
}
fi
nand_do_upgrade "$1"
}
platform_check_image() {
return 0;
}
platform_do_upgrade() {
case "$(board_name)" in
linksys,mx2000|\
linksys,mx5500)
remove_oem_ubi_volume rootfs
linksys_mx_do_upgrade "$1"
;;
*)
default_do_upgrade "$1"
;;
esac
}

View File

@ -0,0 +1,26 @@
CONFIG_QCOM_APM=y
CONFIG_IPQ_GCC_5018=y
CONFIG_PINCTRL_IPQ5018=y
CONFIG_MTD_SPI_NAND=y
CONFIG_SPI_QPIC_SNAND=y
CONFIG_IPQ_CMN_PLL=y
CONFIG_IPQ5018_PHY=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_QCA8K=y
CONFIG_NET_DSA_TAG_QCA=y
CONFIG_QCA83XX_PHY=y
CONFIG_QCOM_Q6V5_MPD=y
CONFIG_QCOM_QMI_HELPERS=y
CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP=y
CONFIG_PCIE_QCOM=y
CONFIG_PWM=y
CONFIG_PWM_IPQ=y
CONFIG_LEDS_PWM=y
CONFIG_PHY_QCOM_M31_USB=y
CONFIG_USB_DWC3_QCOM=y

View File

@ -0,0 +1,7 @@
SUBTARGET:=ipq50xx
BOARDNAME:=Qualcomm Atheros IPQ50xx
DEFAULT_PACKAGES += ath11k-firmware-ipq5018
define Target/Description
Build firmware images for Qualcomm Atheros IPQ50xx based boards.
endef

View File

@ -0,0 +1,31 @@
From 9cbaee8379e620f82112002f973adde19679df31 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Aug 2023 18:14:00 +0200
Subject: [PATCH] arm64: dts: qcom: ipq5018: add watchdog
Add the required DT node for watchdog operation.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20230816161455.3310629-2-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -181,6 +181,13 @@
};
};
+ watchdog: watchdog@b017000 {
+ compatible = "qcom,apss-wdt-ipq5018", "qcom,kpss-wdt";
+ reg = <0x0b017000 0x40>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&sleep_clk>;
+ };
+
timer@b120000 {
compatible = "arm,armv7-timer-mem";
reg = <0x0b120000 0x1000>;

View File

@ -0,0 +1,41 @@
From 92dab9ea5f389c12828283146c60054642453a91 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Aug 2023 18:45:38 +0200
Subject: [PATCH] dt-bindings: firmware: qcom,scm: support indicating SDI
default state
IPQ5018 has SDI (Secure Debug Image) enabled by TZ by default, and that
means that WDT being asserted or just trying to reboot will hang the board
in the debug mode and only pulling the power and repowering will help.
Some IPQ4019 boards like Google WiFI have it enabled as well.
So, lets add a boolean property to indicate that SDI is enabled by default
and thus needs to be disabled by the kernel.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Acked-by: Mukesh Ojha <quic_mojha@quicinc.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Brian Norris <computersforpeace@gmail.com>
Link: https://lore.kernel.org/r/20230816164641.3371878-1-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -89,6 +89,14 @@ properties:
protocol to handle sleeping SCM calls.
maxItems: 1
+ qcom,sdi-enabled:
+ description:
+ Indicates that the SDI (Secure Debug Image) has been enabled by TZ
+ by default and it needs to be disabled.
+ If not disabled WDT assertion or reboot will cause the board to hang
+ in the debug mode.
+ type: boolean
+
qcom,dload-mode:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:

View File

@ -0,0 +1,83 @@
From ff4aa3bc98258a240b9bbab53fd8d2fb8184c485 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Aug 2023 18:45:39 +0200
Subject: [PATCH] firmware: qcom_scm: disable SDI if required
IPQ5018 has SDI (Secure Debug Image) enabled by TZ by default, and that
means that WDT being asserted or just trying to reboot will hang the board
in the debug mode and only pulling the power and repowering will help.
Some IPQ4019 boards like Google WiFI have it enabled as well.
Luckily, SDI can be disabled via an SCM call.
So, lets use the boolean DT property to identify boards that have SDI
enabled by default and use the SCM call to disable SDI during SCM probe.
It is important to disable it as soon as possible as we might have a WDT
assertion at any time which would then leave the board in debug mode,
thus disabling it during SCM removal is not enough.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Guru Das Srinagesh <quic_gurus@quicinc.com>
Link: https://lore.kernel.org/r/20230816164641.3371878-2-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/firmware/qcom_scm.c | 30 ++++++++++++++++++++++++++++++
drivers/firmware/qcom_scm.h | 1 +
2 files changed, 31 insertions(+)
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -410,6 +410,29 @@ int qcom_scm_set_remote_state(u32 state,
}
EXPORT_SYMBOL_GPL(qcom_scm_set_remote_state);
+static int qcom_scm_disable_sdi(void)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_BOOT,
+ .cmd = QCOM_SCM_BOOT_SDI_CONFIG,
+ .args[0] = 1, /* Disable watchdog debug */
+ .args[1] = 0, /* Disable SDI */
+ .arginfo = QCOM_SCM_ARGS(2),
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ qcom_scm_clk_disable();
+
+ return ret ? : res.result[0];
+}
+
static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
{
struct qcom_scm_desc desc = {
@@ -1473,6 +1496,13 @@ static int qcom_scm_probe(struct platfor
__get_convention();
+
+ /*
+ * Disable SDI if indicated by DT that it is enabled by default.
+ */
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled"))
+ qcom_scm_disable_sdi();
+
/*
* If requested enable "download mode", from this point on warmboot
* will cause the boot stages to enter download mode, unless
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -80,6 +80,7 @@ extern int scm_legacy_call(struct device
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
+#define QCOM_SCM_BOOT_SDI_CONFIG 0x09
#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a

View File

@ -0,0 +1,25 @@
From f6aa7386bc40b552eea8ec1b1d2168afe3b31110 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Aug 2023 18:45:40 +0200
Subject: [PATCH] dt-bindings: firmware: qcom,scm: document IPQ5018 compatible
It seems that IPQ5018 compatible was never documented in the bindings.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20230816164641.3371878-3-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
Documentation/devicetree/bindings/firmware/qcom,scm.yaml | 1 +
1 file changed, 1 insertion(+)
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -24,6 +24,7 @@ properties:
- qcom,scm-apq8064
- qcom,scm-apq8084
- qcom,scm-ipq4019
+ - qcom,scm-ipq5018
- qcom,scm-ipq5332
- qcom,scm-ipq6018
- qcom,scm-ipq806x

View File

@ -0,0 +1,26 @@
From 79796e87215db9587d6c66ec6f6781e091bc6464 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Aug 2023 18:45:41 +0200
Subject: [PATCH] arm64: dts: qcom: ipq5018: indicate that SDI should be
disabled
Now that SCM has support for indicating that SDI has been enabled by
default, lets set the property so SCM disables it during probing.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Link: https://lore.kernel.org/r/20230816164641.3371878-4-robimarko@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 1 +
1 file changed, 1 insertion(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -57,6 +57,7 @@
firmware {
scm {
compatible = "qcom,scm-ipq5018", "qcom,scm";
+ qcom,sdi-enabled;
};
};

View File

@ -0,0 +1,28 @@
From 1852dfaacd3f4358bbfca134b63a02bbb30c1136 Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Mon, 4 Sep 2023 12:06:32 +0530
Subject: [PATCH] dt-bindings: phy: qcom,m31: Add IPQ5018 compatible
IPQ5332 qcom,m31 phy driver can support IPQ5018.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Link: https://lore.kernel.org/r/20230904063635.24975-2-quic_nsekar@quicinc.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-usb-hsphy.yaml
@@ -17,7 +17,9 @@ description:
properties:
compatible:
items:
- - const: qcom,ipq5332-usb-hsphy
+ - enum:
+ - qcom,ipq5018-usb-hsphy
+ - qcom,ipq5332-usb-hsphy
"#phy-cells":
const: 0

View File

@ -0,0 +1,89 @@
From 68320e35f8cb1987b4ad34347fc7033832da99e3 Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Mon, 4 Sep 2023 12:06:33 +0530
Subject: [PATCH] phy: qcom-m31: Add compatible, phy init sequence for IPQ5018
Add phy init sequence and compatible string for IPQ5018
chipset.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Link: https://lore.kernel.org/r/20230904063635.24975-3-quic_nsekar@quicinc.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/qualcomm/phy-qcom-m31.c | 51 +++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
--- a/drivers/phy/qualcomm/phy-qcom-m31.c
+++ b/drivers/phy/qualcomm/phy-qcom-m31.c
@@ -82,6 +82,50 @@ struct m31_priv_data {
unsigned int nregs;
};
+static const struct m31_phy_regs m31_ipq5018_regs[] = {
+ {
+ .off = USB_PHY_CFG0,
+ .val = UTMI_PHY_OVERRIDE_EN
+ },
+ {
+ .off = USB_PHY_UTMI_CTRL5,
+ .val = POR_EN,
+ .delay = 15
+ },
+ {
+ .off = USB_PHY_FSEL_SEL,
+ .val = FREQ_SEL
+ },
+ {
+ .off = USB_PHY_HS_PHY_CTRL_COMMON0,
+ .val = COMMONONN | FSEL | RETENABLEN
+ },
+ {
+ .off = USB_PHY_REFCLK_CTRL,
+ .val = CLKCORE
+ },
+ {
+ .off = USB_PHY_UTMI_CTRL5,
+ .val = POR_EN
+ },
+ {
+ .off = USB_PHY_HS_PHY_CTRL2,
+ .val = USB2_SUSPEND_N_SEL | USB2_SUSPEND_N | USB2_UTMI_CLK_EN
+ },
+ {
+ .off = USB_PHY_UTMI_CTRL5,
+ .val = 0x0
+ },
+ {
+ .off = USB_PHY_HS_PHY_CTRL2,
+ .val = USB2_SUSPEND_N | USB2_UTMI_CLK_EN
+ },
+ {
+ .off = USB_PHY_CFG0,
+ .val = 0x0
+ },
+};
+
static struct m31_phy_regs m31_ipq5332_regs[] = {
{
USB_PHY_CFG0,
@@ -267,6 +311,12 @@ static int m31usb_phy_probe(struct platf
return PTR_ERR_OR_ZERO(phy_provider);
}
+static const struct m31_priv_data m31_ipq5018_data = {
+ .ulpi_mode = false,
+ .regs = m31_ipq5018_regs,
+ .nregs = ARRAY_SIZE(m31_ipq5018_regs),
+};
+
static const struct m31_priv_data m31_ipq5332_data = {
.ulpi_mode = false,
.regs = m31_ipq5332_regs,
@@ -274,6 +324,7 @@ static const struct m31_priv_data m31_ip
};
static const struct of_device_id m31usb_phy_id_table[] = {
+ { .compatible = "qcom,ipq5018-usb-hsphy", .data = &m31_ipq5018_data },
{ .compatible = "qcom,ipq5332-usb-hsphy", .data = &m31_ipq5332_data },
{ },
};

View File

@ -0,0 +1,41 @@
From 3865a64284cc4845c61cf3dc6c7246349d80cc49 Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Thu, 31 Aug 2023 08:35:03 +0530
Subject: [PATCH] dt-bindings: usb: dwc3: Add IPQ5018 compatible
Document the IPQ5018 dwc3 compatible.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Link: https://lore.kernel.org/r/20230831030503.17100-1-quic_nsekar@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 3 +++
1 file changed, 3 insertions(+)
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -14,6 +14,7 @@ properties:
items:
- enum:
- qcom,ipq4019-dwc3
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,ipq6018-dwc3
- qcom,ipq8064-dwc3
@@ -238,6 +239,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,msm8994-dwc3
- qcom,qcs404-dwc3
@@ -411,6 +413,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq5018-dwc3
- qcom,ipq5332-dwc3
- qcom,sdm660-dwc3
then:

View File

@ -0,0 +1,86 @@
From e7166f2774aafefd29ff26ffbbb7f6d40ac8ea1c Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Mon, 4 Sep 2023 12:06:34 +0530
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add USB related nodes
Add USB phy and controller nodes.
Co-developed-by: Amandeep Singh <quic_amansing@quicinc.com>
Signed-off-by: Amandeep Singh <quic_amansing@quicinc.com>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Link: https://lore.kernel.org/r/20230904063635.24975-4-quic_nsekar@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 54 +++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -94,6 +94,19 @@
#size-cells = <1>;
ranges = <0 0 0 0xffffffff>;
+ usbphy0: phy@5b000 {
+ compatible = "qcom,ipq5018-usb-hsphy";
+ reg = <0x0005b000 0x120>;
+
+ clocks = <&gcc GCC_USB0_PHY_CFG_AHB_CLK>;
+
+ resets = <&gcc GCC_QUSB2_0_PHY_BCR>;
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;
@@ -156,6 +169,47 @@
status = "disabled";
};
+ usb: usb@8af8800 {
+ compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
+ reg = <0x08af8800 0x400>;
+
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq";
+
+ clocks = <&gcc GCC_USB0_MASTER_CLK>,
+ <&gcc GCC_SYS_NOC_USB0_AXI_CLK>,
+ <&gcc GCC_USB0_SLEEP_CLK>,
+ <&gcc GCC_USB0_MOCK_UTMI_CLK>;
+ clock-names = "core",
+ "iface",
+ "sleep",
+ "mock_utmi";
+
+ resets = <&gcc GCC_USB0_BCR>;
+
+ qcom,select-utmi-as-pipe-clk;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ usb_dwc: usb@8a00000 {
+ compatible = "snps,dwc3";
+ reg = <0x08a00000 0xe000>;
+ clocks = <&gcc GCC_USB0_MOCK_UTMI_CLK>;
+ clock-names = "ref";
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+ phy-names = "usb2-phy";
+ phys = <&usbphy0>;
+ tx-fifo-resize;
+ snps,is-utmi-l1-suspend;
+ snps,hird-threshold = /bits/ 8 <0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_u3_susphy_quirk;
+ };
+ };
+
intc: interrupt-controller@b000000 {
compatible = "qcom,msm-qgic2";
reg = <0x0b000000 0x1000>, /* GICD */

View File

@ -0,0 +1,56 @@
From a1f42e08f0f04b72a6597f080db4bfbb3737910c Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 4 Oct 2023 21:12:30 +0200
Subject: [PATCH] arm64: dts: qcom: ipq5018: add QUP1 SPI controller
Add the required BAM and QUP nodes for the QUP1 SPI controller on IPQ5018.
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reviewed-by: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
Link: https://lore.kernel.org/r/20231004191303.331055-1-robimarko@gmail.com
[bjorn: Padded address to 8 digits, fixed node sort order]
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -159,6 +159,16 @@
status = "disabled";
};
+ blsp_dma: dma-controller@7884000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x07884000 0x1d000>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ };
+
blsp1_uart1: serial@78af000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x078af000 0x200>;
@@ -169,6 +179,20 @@
status = "disabled";
};
+ blsp1_spi1: spi@78b5000 {
+ compatible = "qcom,spi-qup-v2.2.1";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x078b5000 0x600>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp_dma 4>, <&blsp_dma 5>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
usb: usb@8af8800 {
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
reg = <0x08af8800 0x400>;

View File

@ -0,0 +1,25 @@
From 4d45d56e17348c6b6bb2bce126a4a5ea97b19900 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Date: Mon, 25 Sep 2023 15:58:24 +0530
Subject: [PATCH] dt-bindings: clock: qcom,a53pll: add IPQ5018 compatible
Add IPQ5018 compatible to A53 PLL bindings.
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20230925102826.405446-2-quic_gokulsri@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
Documentation/devicetree/bindings/clock/qcom,a53pll.yaml | 1 +
1 file changed, 1 insertion(+)
--- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
@@ -16,6 +16,7 @@ description:
properties:
compatible:
enum:
+ - qcom,ipq5018-a53pll
- qcom,ipq5332-a53pll
- qcom,ipq6018-a53pll
- qcom,ipq8074-a53pll

View File

@ -0,0 +1,62 @@
From 50492f929486c044b43cb3e2c0e040aa9b61ea2b Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Date: Mon, 25 Sep 2023 15:58:25 +0530
Subject: [PATCH] clk: qcom: apss-ipq-pll: add support for IPQ5018
IPQ5018 APSS PLL is of type Stromer. Reuse Stromer Plus PLL offsets,
add configuration values and the compatible.
Co-developed-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20230925102826.405446-3-quic_gokulsri@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/apss-ipq-pll.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -73,6 +73,20 @@ static struct clk_alpha_pll ipq_pll_stro
},
};
+static const struct alpha_pll_config ipq5018_pll_config = {
+ .l = 0x32,
+ .config_ctl_val = 0x4001075b,
+ .config_ctl_hi_val = 0x304,
+ .main_output_mask = BIT(0),
+ .aux_output_mask = BIT(1),
+ .early_output_mask = BIT(3),
+ .alpha_en_mask = BIT(24),
+ .status_val = 0x3,
+ .status_mask = GENMASK(10, 8),
+ .lock_det = BIT(2),
+ .test_ctl_hi_val = 0x00400003,
+};
+
static const struct alpha_pll_config ipq5332_pll_config = {
.l = 0x2d,
.config_ctl_val = 0x4001075b,
@@ -129,6 +143,12 @@ struct apss_pll_data {
const struct alpha_pll_config *pll_config;
};
+static const struct apss_pll_data ipq5018_pll_data = {
+ .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
+ .pll = &ipq_pll_stromer_plus,
+ .pll_config = &ipq5018_pll_config,
+};
+
static struct apss_pll_data ipq5332_pll_data = {
.pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
.pll = &ipq_pll_stromer_plus,
@@ -195,6 +215,7 @@ static int apss_ipq_pll_probe(struct pla
}
static const struct of_device_id apss_ipq_pll_match_table[] = {
+ { .compatible = "qcom,ipq5018-a53pll", .data = &ipq5018_pll_data },
{ .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data },
{ .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
{ .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data },

View File

@ -0,0 +1,98 @@
From 3e4b53e04281ed3d9c7a4329c027097265c04d54 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Date: Mon, 25 Sep 2023 15:58:26 +0530
Subject: [PATCH] arm64: dts: qcom: ipq5018: enable the CPUFreq support
Add the APCS, A53 PLL, cpu-opp-table nodes to set
the CPU frequency at 800MHz (idle) or 1.008GHz.
Co-developed-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20230925102826.405446-4-quic_gokulsri@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 40 +++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -5,6 +5,7 @@
* Copyright (c) 2023 The Linux Foundation. All rights reserved.
*/
+#include <dt-bindings/clock/qcom,apss-ipq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
@@ -36,6 +37,8 @@
reg = <0x0>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ operating-points-v2 = <&cpu_opp_table>;
};
CPU1: cpu@1 {
@@ -44,6 +47,8 @@
reg = <0x1>;
enable-method = "psci";
next-level-cache = <&L2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ operating-points-v2 = <&cpu_opp_table>;
};
L2_0: l2-cache {
@@ -54,6 +59,25 @@
};
};
+ cpu_opp_table: opp-table-cpu {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ /*
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <200000>;
+ };
+ */
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <200000>;
+ };
+ };
+
firmware {
scm {
compatible = "qcom,scm-ipq5018", "qcom,scm";
@@ -267,6 +291,24 @@
clocks = <&sleep_clk>;
};
+ apcs_glb: mailbox@b111000 {
+ compatible = "qcom,ipq5018-apcs-apps-global",
+ "qcom,ipq6018-apcs-apps-global";
+ reg = <0x0b111000 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&a53pll>, <&xo_board_clk>, <&gcc GPLL0>;
+ clock-names = "pll", "xo", "gpll0";
+ #mbox-cells = <1>;
+ };
+
+ a53pll: clock@b116000 {
+ compatible = "qcom,ipq5018-a53pll";
+ reg = <0x0b116000 0x40>;
+ #clock-cells = <0>;
+ clocks = <&xo_board_clk>;
+ clock-names = "xo";
+ };
+
timer@b120000 {
compatible = "arm,armv7-timer-mem";
reg = <0x0b120000 0x1000>;

View File

@ -0,0 +1,66 @@
From a427dd16e61f3d145bc24f0ed09692fc25931250 Mon Sep 17 00:00:00 2001
From: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
Date: Wed, 25 Oct 2023 22:12:12 +0530
Subject: [PATCH] arm64: dts: qcom: ipq5018: add few more reserved memory
regions
Like all other IPQ SoCs, bootloader will collect the system RAM contents
upon crash for the post morterm analysis. If we don't reserve the memory
region used by bootloader, obviously linux will consume it and upon next
boot on crash, bootloader will be loaded in the same region, which will
lead to loose some of the data, sometimes we may miss out critical
information. So lets reserve the region used by the bootloader.
Similarly SBL copies some data into the reserved region and it will be
used in the crash scenario. So reserve 1MB for SBL as well.
While at it, enable the SMEM support along with TCSR mutex.
Signed-off-by: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20231025-ipq5018-misc-v1-1-7d14fde97fe7@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -106,6 +106,24 @@
#size-cells = <2>;
ranges;
+ bootloader@4a800000 {
+ reg = <0x0 0x4a800000 0x0 0x200000>;
+ no-map;
+ };
+
+ sbl@4aa00000 {
+ reg = <0x0 0x4aa00000 0x0 0x100000>;
+ no-map;
+ };
+
+ smem@4ab00000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x4ab00000 0x0 0x100000>;
+ no-map;
+
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
tz_region: tz@4ac00000 {
reg = <0x0 0x4ac00000 0x0 0x200000>;
no-map;
@@ -166,6 +184,12 @@
#power-domain-cells = <1>;
};
+ tcsr_mutex: hwlock@1905000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x01905000 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
sdhc_1: mmc@7804000 {
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
reg = <0x7804000 0x1000>;

View File

@ -0,0 +1,83 @@
From: Gabor Juhos <j4g8y7@gmail.com>
Subject: [PATCH] clk: qcom: apss-ipq-pll: use stromer ops for IPQ5018 to fix boot failure
Date: Fri, 15 Mar 2024 17:16:41 +0100
Booting v6.8 results in a hang on various IPQ5018 based boards.
Investigating the problem showed that the hang happens when the
clk_alpha_pll_stromer_plus_set_rate() function tries to write
into the PLL_MODE register of the APSS PLL.
Checking the downstream code revealed that it uses [1] stromer
specific operations for IPQ5018, whereas in the current code
the stromer plus specific operations are used.
The ops in the 'ipq_pll_stromer_plus' clock definition can't be
changed since that is needed for IPQ5332, so add a new alpha pll
clock declaration which uses the correct stromer ops and use this
new clock for IPQ5018 to avoid the boot failure.
Also, change pll_type in 'ipq5018_pll_data' to
CLK_ALPHA_PLL_TYPE_STROMER to better reflect that it is a Stromer
PLL and change the apss_ipq_pll_probe() function accordingly.
1. https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c#L67
Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018")
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
---
drivers/clk/qcom/apss-ipq-pll.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -55,6 +55,29 @@ static struct clk_alpha_pll ipq_pll_huay
},
};
+static struct clk_alpha_pll ipq_pll_stromer = {
+ .offset = 0x0,
+ /*
+ * Reuse CLK_ALPHA_PLL_TYPE_STROMER_PLUS register offsets.
+ * Although this is a bit confusing, but the offset values
+ * are correct nevertheless.
+ */
+ .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS],
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .clkr = {
+ .enable_reg = 0x0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "a53pll",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_stromer_ops,
+ },
+ },
+};
+
static struct clk_alpha_pll ipq_pll_stromer_plus = {
.offset = 0x0,
.regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS],
@@ -144,8 +167,8 @@ struct apss_pll_data {
};
static const struct apss_pll_data ipq5018_pll_data = {
- .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
- .pll = &ipq_pll_stromer_plus,
+ .pll_type = CLK_ALPHA_PLL_TYPE_STROMER,
+ .pll = &ipq_pll_stromer,
.pll_config = &ipq5018_pll_config,
};
@@ -203,7 +226,8 @@ static int apss_ipq_pll_probe(struct pla
if (data->pll_type == CLK_ALPHA_PLL_TYPE_HUAYRA)
clk_alpha_pll_configure(data->pll, regmap, data->pll_config);
- else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS)
+ else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER ||
+ data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS)
clk_stromer_pll_configure(data->pll, regmap, data->pll_config);
ret = devm_clk_register_regmap(dev, &data->pll->clkr);

View File

@ -0,0 +1,32 @@
From: Gabor Juhos <j4g8y7@gmail.com>
Subject: [PATCH] clk: qcom: apss-ipq-pll: fix PLL rate for IPQ5018
Date: Tue, 26 Mar 2024 14:34:11 +0100
According to ipq5018.dtsi, the maximum supported rate by the
CPU is 1.008 GHz on the IPQ5018 platform, however the current
configuration of the PLL results in 1.2 GHz rate.
Change the 'L' value in the PLL configuration to limit the
rate to 1.008 GHz. The downstream kernel also uses the same
value [1]. Also add a comment to indicate the desired
frequency.
[1] https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c?ref_type=heads#L151
Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018")
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
---
drivers/clk/qcom/apss-ipq-pll.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/clk/qcom/apss-ipq-pll.c
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -97,7 +97,7 @@ static struct clk_alpha_pll ipq_pll_stro
};
static const struct alpha_pll_config ipq5018_pll_config = {
- .l = 0x32,
+ .l = 0x2a,
.config_ctl_val = 0x4001075b,
.config_ctl_hi_val = 0x304,
.main_output_mask = BIT(0),

View File

@ -0,0 +1,60 @@
From: Devi Priya <quic_devipriy@quicinc.com>
Date: Thu, 5 Oct 2023 21:35:48 +0530
Subject: [PATCH] dt-bindings: pwm: add IPQ6018 binding
DT binding for the PWM block in Qualcomm IPQ6018 SoC.
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
---
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/qcom,ipq6018-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm IPQ6018 PWM controller
+
+maintainers:
+ - Baruch Siach <baruch@tkos.co.il>
+
+properties:
+ compatible:
+ const: qcom,ipq6018-pwm
+
+ reg:
+ description: Offset of PWM register in the TCSR block.
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - "#pwm-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-ipq6018.h>
+
+ pwm: pwm@a010 {
+ compatible = "qcom,ipq6018-pwm";
+ reg = <0xa010 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <2>;
+ };

View File

@ -0,0 +1,330 @@
From: Devi Priya <quic_devipriy@quicinc.com>
Date: Thu, 5 Oct 2023 21:35:47 +0530
Subject: [PATCH] pwm: driver for qualcomm ipq6018 pwm block
Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on
driver from downstream Codeaurora kernel tree. Removed support for older
(V1) variants because I have no access to that hardware.
Tested on IPQ6010 based hardware.
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
---
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -282,6 +282,18 @@ config PWM_INTEL_LGM
To compile this driver as a module, choose M here: the module
will be called pwm-intel-lgm.
+config PWM_IPQ
+ tristate "IPQ PWM support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on HAVE_CLK && HAS_IOMEM
+ help
+ Generic PWM framework driver for IPQ PWM block which supports
+ 4 pwm channels. Each of the these channels can be configured
+ independent of each other.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-ipq.
+
config PWM_IQS620A
tristate "Azoteq IQS620A PWM support"
depends on MFD_IQS62X || COMPILE_TEST
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o
obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o
obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o
obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o
+obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o
obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o
--- /dev/null
+++ b/drivers/pwm/pwm-ipq.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/math64.h>
+#include <linux/of_device.h>
+#include <linux/bitfield.h>
+#include <linux/units.h>
+
+/* The frequency range supported is 1 Hz to clock rate */
+#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC)
+
+/*
+ * The max value specified for each field is based on the number of bits
+ * in the pwm control register for that field
+ */
+#define IPQ_PWM_MAX_DIV 0xFFFF
+
+/*
+ * Two 32-bit registers for each PWM: REG0, and REG1.
+ * Base offset for PWM #i is at 8 * #i.
+ */
+#define IPQ_PWM_REG0 0
+#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0)
+#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16)
+
+#define IPQ_PWM_REG1 4
+#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0)
+/*
+ * Enable bit is set to enable output toggling in pwm device.
+ * Update bit is set to reflect the changed divider and high duration
+ * values in register.
+ */
+#define IPQ_PWM_REG1_UPDATE BIT(30)
+#define IPQ_PWM_REG1_ENABLE BIT(31)
+
+struct ipq_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ void __iomem *mem;
+};
+
+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct ipq_pwm_chip, chip);
+}
+
+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
+ unsigned int off = 8 * pwm->hwpwm + reg;
+
+ return readl(ipq_chip->mem + off);
+}
+
+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg,
+ unsigned int val)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
+ unsigned int off = 8 * pwm->hwpwm + reg;
+
+ writel(val, ipq_chip->mem + off);
+}
+
+static void config_div_and_duty(struct pwm_device *pwm, unsigned int pre_div,
+ unsigned int pwm_div, unsigned long rate, u64 duty_ns,
+ bool enable)
+{
+ unsigned long hi_dur;
+ unsigned long val = 0;
+
+ /*
+ * high duration = pwm duty * (pwm div + 1)
+ * pwm duty = duty_ns / period_ns
+ */
+ hi_dur = div64_u64(duty_ns * rate, (pre_div + 1) * NSEC_PER_SEC);
+
+ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) |
+ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div);
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val);
+
+ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div);
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
+
+ /* PWM enable toggle needs a separate write to REG1 */
+ val |= IPQ_PWM_REG1_UPDATE;
+ if (enable)
+ val |= IPQ_PWM_REG1_ENABLE;
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
+}
+
+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
+ unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div;
+ unsigned long rate = clk_get_rate(ipq_chip->clk);
+ u64 period_ns, duty_ns, period_rate;
+ u64 min_diff;
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC, rate))
+ return -ERANGE;
+
+ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);
+ duty_ns = min(state->duty_cycle, period_ns);
+
+ /*
+ * period_ns is 1G or less. As long as rate is less than 16 GHz,
+ * period_rate does not overflow. Make that explicit.
+ */
+ if ((unsigned long long)rate > 16ULL * GIGA)
+ return -EINVAL;
+ period_rate = period_ns * rate;
+ best_pre_div = IPQ_PWM_MAX_DIV;
+ best_pwm_div = IPQ_PWM_MAX_DIV;
+ /*
+ * We don't need to consider pre_div values smaller than
+ *
+ * period_rate
+ * pre_div_min := ------------------------------------
+ * NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1)
+ *
+ * because pre_div = pre_div_min results in a better
+ * approximation.
+ */
+ pre_div = div64_u64(period_rate,
+ (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1));
+ min_diff = period_rate;
+
+ for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) {
+ u64 remainder;
+
+ pwm_div = div64_u64_rem(period_rate,
+ (u64)NSEC_PER_SEC * (pre_div + 1), &remainder);
+ /* pwm_div is unsigned; the check below catches underflow */
+ pwm_div--;
+
+ /*
+ * Swapping values for pre_div and pwm_div produces the same
+ * period length. So we can skip all settings with pre_div >
+ * pwm_div which results in bigger constraints for selecting
+ * the duty_cycle than with the two values swapped.
+ */
+ if (pre_div > pwm_div)
+ break;
+
+ /*
+ * Make sure we can do 100% duty cycle where
+ * hi_dur == pwm_div + 1
+ */
+ if (pwm_div > IPQ_PWM_MAX_DIV - 1)
+ continue;
+
+ if (remainder < min_diff) {
+ best_pre_div = pre_div;
+ best_pwm_div = pwm_div;
+ min_diff = remainder;
+
+ if (min_diff == 0) /* bingo */
+ break;
+ }
+ }
+
+ /* config divider values for the closest possible frequency */
+ config_div_and_duty(pwm, best_pre_div, best_pwm_div,
+ rate, duty_ns, state->enabled);
+
+ return 0;
+}
+
+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
+ unsigned long rate = clk_get_rate(ipq_chip->clk);
+ unsigned int pre_div, pwm_div, hi_dur;
+ u64 effective_div, hi_div;
+ u32 reg0, reg1;
+
+ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0);
+ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1);
+
+ state->polarity = PWM_POLARITY_NORMAL;
+ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE;
+
+ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0);
+ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0);
+ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1);
+
+ /* No overflow here, both pre_div and pwm_div <= 0xffff */
+ effective_div = (u64)(pre_div + 1) * (pwm_div + 1);
+ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, rate);
+
+ hi_div = hi_dur * (pre_div + 1);
+ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, rate);
+
+ return 0;
+}
+
+static const struct pwm_ops ipq_pwm_ops = {
+ .apply = ipq_pwm_apply,
+ .get_state = ipq_pwm_get_state,
+ .owner = THIS_MODULE,
+};
+
+static int ipq_pwm_probe(struct platform_device *pdev)
+{
+ struct ipq_pwm_chip *pwm;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
+ if (!pwm)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pwm);
+
+ pwm->mem = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pwm->mem))
+ return dev_err_probe(dev, PTR_ERR(pwm->mem),
+ "regs map failed");
+
+ pwm->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(pwm->clk))
+ return dev_err_probe(dev, PTR_ERR(pwm->clk),
+ "failed to get clock");
+
+ ret = clk_prepare_enable(pwm->clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "clock enable failed");
+
+ pwm->chip.dev = dev;
+ pwm->chip.ops = &ipq_pwm_ops;
+ pwm->chip.npwm = 4;
+
+ ret = pwmchip_add(&pwm->chip);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "pwmchip_add() failed\n");
+ clk_disable_unprepare(pwm->clk);
+ }
+
+ return ret;
+}
+
+static int ipq_pwm_remove(struct platform_device *pdev)
+{
+ struct ipq_pwm_chip *pwm = platform_get_drvdata(pdev);
+
+ pwmchip_remove(&pwm->chip);
+ clk_disable_unprepare(pwm->clk);
+
+ return 0;
+}
+
+static const struct of_device_id pwm_ipq_dt_match[] = {
+ { .compatible = "qcom,ipq6018-pwm", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match);
+
+static struct platform_driver ipq_pwm_driver = {
+ .driver = {
+ .name = "ipq-pwm",
+ .of_match_table = pwm_ipq_dt_match,
+ },
+ .probe = ipq_pwm_probe,
+ .remove = ipq_pwm_remove,
+};
+
+module_platform_driver(ipq_pwm_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,148 @@
From: Devi Priya <quic_devipriy@quicinc.com>
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add simple-mfd support for IPQ6018
Date: Thu, 5 Oct 2023 21:35:49 +0530
Update the binding to include pwm as the child node to TCSR block and
add simple-mfd support for IPQ6018.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
---
.../devicetree/bindings/mfd/qcom,tcsr.yaml | 112 +++++++++++++-----
1 file changed, 81 insertions(+), 31 deletions(-)
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -15,49 +15,101 @@ description:
properties:
compatible:
- items:
- - enum:
- - qcom,msm8976-tcsr
- - qcom,msm8998-tcsr
- - qcom,qcs404-tcsr
- - qcom,sc7180-tcsr
- - qcom,sc7280-tcsr
- - qcom,sc8280xp-tcsr
- - qcom,sdm630-tcsr
- - qcom,sdm845-tcsr
- - qcom,sdx55-tcsr
- - qcom,sdx65-tcsr
- - qcom,sm8150-tcsr
- - qcom,sm8450-tcsr
- - qcom,tcsr-apq8064
- - qcom,tcsr-apq8084
- - qcom,tcsr-ipq5332
- - qcom,tcsr-ipq6018
- - qcom,tcsr-ipq8064
- - qcom,tcsr-ipq8074
- - qcom,tcsr-ipq9574
- - qcom,tcsr-mdm9615
- - qcom,tcsr-msm8226
- - qcom,tcsr-msm8660
- - qcom,tcsr-msm8916
- - qcom,tcsr-msm8953
- - qcom,tcsr-msm8960
- - qcom,tcsr-msm8974
- - qcom,tcsr-msm8996
- - const: syscon
+ oneOf:
+ - items:
+ - enum:
+ - qcom,msm8976-tcsr
+ - qcom,msm8998-tcsr
+ - qcom,qcs404-tcsr
+ - qcom,sc7180-tcsr
+ - qcom,sc7280-tcsr
+ - qcom,sc8280xp-tcsr
+ - qcom,sdm630-tcsr
+ - qcom,sdm845-tcsr
+ - qcom,sdx55-tcsr
+ - qcom,sdx65-tcsr
+ - qcom,sm4450-tcsr
+ - qcom,sm8150-tcsr
+ - qcom,sm8450-tcsr
+ - qcom,tcsr-apq8064
+ - qcom,tcsr-apq8084
+ - qcom,tcsr-ipq5332
+ - qcom,tcsr-ipq8064
+ - qcom,tcsr-ipq8074
+ - qcom,tcsr-ipq9574
+ - qcom,tcsr-mdm9615
+ - qcom,tcsr-msm8226
+ - qcom,tcsr-msm8660
+ - qcom,tcsr-msm8916
+ - qcom,tcsr-msm8953
+ - qcom,tcsr-msm8960
+ - qcom,tcsr-msm8974
+ - qcom,tcsr-msm8996
+ - const: syscon
+ - items:
+ - const: qcom,tcsr-ipq6018
+ - const: syscon
+ - const: simple-mfd
reg:
maxItems: 1
+ ranges: true
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+patternProperties:
+ "pwm@[a-f0-9]+$":
+ type: object
+ $ref: /schemas/pwm/qcom,ipq6018-pwm.yaml
+
+
required:
- compatible
- reg
+allOf:
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,tcsr-ipq6018
+ then:
+ patternProperties:
+ "pwm@[a-f0-9]+$": false
+
additionalProperties: false
examples:
+ # Example 1 - Syscon node found on MSM8960
- |
syscon@1a400000 {
compatible = "qcom,tcsr-msm8960", "syscon";
reg = <0x1a400000 0x100>;
};
+ # Example 2 - Syscon node found on IPQ6018
+ - |
+ #include <dt-bindings/clock/qcom,gcc-ipq6018.h>
+
+ syscon@1937000 {
+ compatible = "qcom,tcsr-ipq6018", "syscon", "simple-mfd";
+ reg = <0x01937000 0x21000>;
+ ranges = <0 0x1937000 0x21000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pwm: pwm@a010 {
+ compatible = "qcom,ipq6018-pwm";
+ reg = <0xa010 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <2>;
+ };
+ };
\ No newline at end of file

View File

@ -0,0 +1,22 @@
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Subject: [PATCH V2 1/1] dt-bindings: nvmem: Add compatible for IPQ5018
Date: Fri, 15 Sep 2023 17:31:20 +0530
Document the QFPROM on IPQ5018.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 1 +
1 file changed, 1 insertion(+)
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -18,6 +18,7 @@ properties:
- enum:
- qcom,apq8064-qfprom
- qcom,apq8084-qfprom
+ - qcom,ipq5018-qfprom
- qcom,ipq5332-qfprom
- qcom,ipq6018-qfprom
- qcom,ipq8064-qfprom

View File

@ -0,0 +1,26 @@
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Date: Fri, 22 Sep 2023 17:21:13 +0530
Subject: [PATCH] dt-bindings: thermal: qcom-tsens: Add ipq5018 compatible
IPQ5018 has tsens v1.0 block with 4 sensors and 1 interrupt.
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
@@ -39,6 +39,7 @@ properties:
- description: v1 of TSENS
items:
- enum:
+ - qcom,ipq5018-tsens
- qcom,msm8956-tsens
- qcom,msm8976-tsens
- qcom,qcs404-tsens
@@ -232,6 +233,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,ipq5018-tsens
- qcom,ipq8064-tsens
- qcom,msm8960-tsens
- qcom,tsens-v0_1

View File

@ -0,0 +1,45 @@
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Subject: [PATCH] thermal/drivers/qcom: Add new feat for soc without rpm
Date: Fri, 22 Sep 2023 17:21:14 +0530
In IPQ5018, Tsens IP doesn't have RPM. Hence the early init to
enable tsens would not be done. So add a flag for that in feat
and skip enable checks. Without this, tsens probe fails.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
drivers/thermal/qcom/tsens.c | 2 +-
drivers/thermal/qcom/tsens.h | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -974,7 +974,7 @@ int __init init_common(struct tsens_priv
ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
if (ret)
goto err_put_device;
- if (!enabled) {
+ if (!enabled && !(priv->feat->ignore_enable)) {
dev_err(dev, "%s: device not enabled\n", __func__);
ret = -ENODEV;
goto err_put_device;
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -505,6 +505,8 @@ enum regfield_ids {
* @srot_split: does the IP neatly splits the register space into SROT and TM,
* with SROT only being available to secure boot firmware?
* @has_watchdog: does this IP support watchdog functionality?
+ * @ignore_enable: does this IP reside in a soc that does not have rpm to
+ * do pre-init.
* @max_sensors: maximum sensors supported by this version of the IP
* @trip_min_temp: minimum trip temperature supported by this version of the IP
* @trip_max_temp: maximum trip temperature supported by this version of the IP
@@ -516,6 +518,7 @@ struct tsens_features {
unsigned int adc:1;
unsigned int srot_split:1;
unsigned int has_watchdog:1;
+ unsigned int ignore_enable:1;
unsigned int max_sensors;
int trip_min_temp;
int trip_max_temp;

View File

@ -0,0 +1,118 @@
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Subject: [PATCH] thermal/drivers/tsens: Add support for IPQ5018 tsens
Date: Fri, 22 Sep 2023 17:21:15 +0530
IPQ5018 has tsens IP V1.0, 4 sensors and 1 interrupt.
The soc does not have a RPM, hence tsens has to be reset and
enabled in the driver init. Adding the driver support for same.
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
drivers/thermal/qcom/tsens-v1.c | 60 +++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 3 ++
drivers/thermal/qcom/tsens.h | 2 +-
3 files changed, 64 insertions(+), 1 deletion(-)
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -79,6 +79,18 @@ static struct tsens_features tsens_v1_fe
.trip_max_temp = 120000,
};
+static struct tsens_features tsens_v1_ipq5018_feat = {
+ .ver_major = VER_1_X,
+ .crit_int = 0,
+ .combo_int = 0,
+ .adc = 1,
+ .srot_split = 1,
+ .max_sensors = 11,
+ .trip_min_temp = -40000,
+ .trip_max_temp = 120000,
+ .ignore_enable = 1,
+};
+
static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
/* ----- SROT ------ */
/* VERSION */
@@ -150,6 +162,41 @@ static int __init init_8956(struct tsens
return init_common(priv);
}
+static int __init init_ipq5018(struct tsens_priv *priv)
+{
+ int ret;
+ u32 mask;
+
+ ret = init_common(priv);
+ if (ret < 0) {
+ dev_err(priv->dev, "Init common failed %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 1);
+ if (ret) {
+ dev_err(priv->dev, "Reset failed\n");
+ return ret;
+ }
+
+ mask = GENMASK(priv->num_sensors, 0);
+ ret = regmap_field_update_bits(priv->rf[SENSOR_EN], mask, mask);
+ if (ret) {
+ dev_err(priv->dev, "Sensor Enable failed\n");
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_EN], 1);
+ if (ret) {
+ dev_err(priv->dev, "Enable failed\n");
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 0);
+
+ return ret;
+}
+
static const struct tsens_ops ops_generic_v1 = {
.init = init_common,
.calibrate = calibrate_v1,
@@ -194,3 +241,16 @@ struct tsens_plat_data data_8976 = {
.feat = &tsens_v1_feat,
.fields = tsens_v1_regfields,
};
+
+const struct tsens_ops ops_ipq5018 = {
+ .init = init_ipq5018,
+ .calibrate = tsens_calibrate_common,
+ .get_temp = get_temp_tsens_valid,
+};
+
+struct tsens_plat_data data_ipq5018 = {
+ .num_sensors = 5,
+ .ops = &ops_ipq5018,
+ .feat = &tsens_v1_ipq5018_feat,
+ .fields = tsens_v1_regfields,
+};
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -1101,6 +1101,9 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, t
static const struct of_device_id tsens_table[] = {
{
+ .compatible = "qcom,ipq5018-tsens",
+ .data = &data_ipq5018,
+ }, {
.compatible = "qcom,ipq8064-tsens",
.data = &data_8960,
}, {
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -645,7 +645,7 @@ extern struct tsens_plat_data data_8960;
extern struct tsens_plat_data data_8226, data_8909, data_8916, data_8939, data_8974, data_9607;
/* TSENS v1 targets */
-extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956;
+extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956, data_ipq5018;
/* TSENS v2 targets */
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;

View File

@ -0,0 +1,200 @@
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add tsens node
Date: Fri, 22 Sep 2023 17:21:16 +0530
IPQ5018 has tsens V1.0 IP with 4 sensors.
There is no RPM, so tsens has to be manually enabled. Adding the tsens
and nvmem node and IPQ5018 has 4 thermal sensors (zones). With the
critical temperature being 120'C and action is to reboot. Adding all
the 4 zones here.
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 169 ++++++++++++++++++++++++++
1 file changed, 169 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -149,6 +149,117 @@
status = "disabled";
};
+ qfprom: qfprom@a0000 {
+ compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
+ reg = <0xa0000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ tsens_mode: mode@249 {
+ reg = <0x249 1>;
+ bits = <0 3>;
+ };
+
+ tsens_base1: base1@249 {
+ reg = <0x249 2>;
+ bits = <3 8>;
+ };
+
+ tsens_base2: base2@24a {
+ reg = <0x24a 2>;
+ bits = <3 8>;
+ };
+
+ tsens_s0_p1: s0-p1@24b {
+ reg = <0x24b 0x2>;
+ bits = <2 6>;
+ };
+
+ tsens_s0_p2: s0-p2@24c {
+ reg = <0x24c 0x1>;
+ bits = <1 6>;
+ };
+
+ tsens_s1_p1: s1-p1@24c {
+ reg = <0x24c 0x2>;
+ bits = <7 6>;
+ };
+
+ tsens_s1_p2: s1-p2@24d {
+ reg = <0x24d 0x2>;
+ bits = <5 6>;
+ };
+
+ tsens_s2_p1: s2-p1@24e {
+ reg = <0x24e 0x2>;
+ bits = <3 6>;
+ };
+
+ tsens_s2_p2: s2-p2@24f {
+ reg = <0x24f 0x1>;
+ bits = <1 6>;
+ };
+
+ tsens_s3_p1: s3-p1@24f {
+ reg = <0x24f 0x2>;
+ bits = <7 6>;
+ };
+
+ tsens_s3_p2: s3-p2@250 {
+ reg = <0x250 0x2>;
+ bits = <5 6>;
+ };
+
+ tsens_s4_p1: s4-p1@251 {
+ reg = <0x251 0x2>;
+ bits = <3 6>;
+ };
+
+ tsens_s4_p2: s4-p2@254 {
+ reg = <0x254 0x1>;
+ bits = <0 6>;
+ };
+ };
+
+ tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,ipq5018-tsens";
+ reg = <0x4a9000 0x1000>, /* TM */
+ <0x4a8000 0x1000>; /* SROT */
+
+ nvmem-cells = <&tsens_mode>,
+ <&tsens_base1>,
+ <&tsens_base2>,
+ <&tsens_s0_p1>,
+ <&tsens_s0_p2>,
+ <&tsens_s1_p1>,
+ <&tsens_s1_p2>,
+ <&tsens_s2_p1>,
+ <&tsens_s2_p2>,
+ <&tsens_s3_p1>,
+ <&tsens_s3_p2>,
+ <&tsens_s4_p1>,
+ <&tsens_s4_p2>;
+
+ nvmem-cell-names = "mode",
+ "base1",
+ "base2",
+ "s0_p1",
+ "s0_p2",
+ "s1_p1",
+ "s1_p2",
+ "s2_p1",
+ "s2_p2",
+ "s3_p1",
+ "s3_p2",
+ "s4_p1",
+ "s4_p2";
+
+ interrupts = <GIC_SPI 184 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "uplow";
+ #qcom,sensors = <5>;
+ #thermal-sensor-cells = <1>;
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;
@@ -391,6 +502,64 @@
};
};
};
+
+ thermal-zones {
+ cpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens 2>;
+
+ trips {
+ cpu-critical {
+ temperature = <120000>;
+ hysteresis = <2>;
+ type = "critical";
+ };
+ };
+ };
+
+ gephy-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ gephy-critical {
+ temperature = <120000>;
+ hysteresis = <2>;
+ type = "critical";
+ };
+ };
+ };
+
+ top-glue-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens 3>;
+
+ trips {
+ top_glue-critical {
+ temperature = <120000>;
+ hysteresis = <2>;
+ type = "critical";
+ };
+ };
+ };
+
+ ubi32-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens 1>;
+
+ trips {
+ ubi32-critical {
+ temperature = <120000>;
+ hysteresis = <2>;
+ type = "critical";
+ };
+ };
+ };
+ };
timer {
compatible = "arm,armv8-timer";

View File

@ -0,0 +1,85 @@
From: Varadarajan Narayanan <quic_varada@quicinc.com>
Date: Thu, 2 Jan 2025 17:00:15 +0530
Subject: [PATCH] dt-bindings: phy: qcom,uniphy-pcie: Document PCIe uniphy
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Document the Qualcomm UNIPHY PCIe 28LP present in IPQ5332.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
---
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/qcom,ipq5332-uniphy-pcie-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm UNIPHY PCIe 28LP PHY
+
+maintainers:
+ - Nitheesh Sekar <quic_nsekar@quicinc.com>
+ - Varadarajan Narayanan <quic_varada@quicinc.com>
+
+description:
+ PCIe and USB combo PHY found in Qualcomm IPQ5332 SoC
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq5332-uniphy-pcie-phy
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: pcie pipe clock
+ - description: pcie ahb clock
+
+ resets:
+ items:
+ - description: phy reset
+ - description: ahb reset
+ - description: cfg reset
+
+ "#phy-cells":
+ const: 0
+
+ "#clock-cells":
+ const: 0
+
+ num-lanes: true
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - "#phy-cells"
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,ipq5332-gcc.h>
+
+ pcie0_phy: phy@4b0000 {
+ compatible = "qcom,ipq5332-uniphy-pcie-phy";
+ reg = <0x004b0000 0x800>;
+
+ clocks = <&gcc GCC_PCIE3X1_0_PIPE_CLK>,
+ <&gcc GCC_PCIE3X1_PHY_AHB_CLK>;
+
+ resets = <&gcc GCC_PCIE3X1_0_PHY_BCR>,
+ <&gcc GCC_PCIE3X1_PHY_AHB_CLK_ARES>,
+ <&gcc GCC_PCIE3X1_0_PHY_PHY_BCR>;
+
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
+ };

View File

@ -0,0 +1,332 @@
From: Varadarajan Narayanan <quic_varada@quicinc.com>
Date: Thu, 2 Jan 2025 17:00:16 +0530
Subject: [PATCH] phy: qcom: Introduce PCIe UNIPHY 28LP driver
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Add Qualcomm PCIe UNIPHY 28LP driver support present
in Qualcomm IPQ5332 SoC and the phy init sequence.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
---
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -154,6 +154,18 @@ config PHY_QCOM_M31_USB
management. This driver is required even for peripheral only or
host only mode configurations.
+config PHY_QCOM_UNIPHY_PCIE_28LP
+ bool "PCIE UNIPHY 28LP PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support the PCIe UNIPHY 28LP phy transceiver that
+ is used with PCIe controllers on Qualcomm IPQ5332 chips. It
+ handles PHY initialization, clock management required after
+ resetting the hardware and power management.
+
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY) +=
obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o
obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) += phy-qcom-eusb2-repeater.o
+obj-$(CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP) += phy-qcom-uniphy-pcie-28lp.o
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define RST_ASSERT_DELAY_MIN_US 100
+#define RST_ASSERT_DELAY_MAX_US 150
+#define PIPE_CLK_DELAY_MIN_US 5000
+#define PIPE_CLK_DELAY_MAX_US 5100
+#define CLK_EN_DELAY_MIN_US 30
+#define CLK_EN_DELAY_MAX_US 50
+#define CDR_CTRL_REG_1 0x80
+#define CDR_CTRL_REG_2 0x84
+#define CDR_CTRL_REG_3 0x88
+#define CDR_CTRL_REG_4 0x8c
+#define CDR_CTRL_REG_5 0x90
+#define CDR_CTRL_REG_6 0x94
+#define CDR_CTRL_REG_7 0x98
+#define SSCG_CTRL_REG_1 0x9c
+#define SSCG_CTRL_REG_2 0xa0
+#define SSCG_CTRL_REG_3 0xa4
+#define SSCG_CTRL_REG_4 0xa8
+#define SSCG_CTRL_REG_5 0xac
+#define SSCG_CTRL_REG_6 0xb0
+#define PCS_INTERNAL_CONTROL_2 0x2d8
+
+#define PHY_CFG_PLLCFG 0x220
+#define PHY_CFG_EIOS_DTCT_REG 0x3e4
+#define PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME 0x3e8
+
+#define PHY_MODE_FIXED 0x1
+
+enum qcom_uniphy_pcie_type {
+ PHY_TYPE_PCIE = 1,
+ PHY_TYPE_PCIE_GEN2,
+ PHY_TYPE_PCIE_GEN3,
+};
+
+struct qcom_uniphy_pcie_regs {
+ u32 offset;
+ u32 val;
+};
+
+struct qcom_uniphy_pcie_data {
+ int lane_offset; /* offset between the lane register bases */
+ u32 phy_type;
+ const struct qcom_uniphy_pcie_regs *init_seq;
+ u32 init_seq_num;
+ u32 pipe_clk_rate;
+};
+
+struct qcom_uniphy_pcie {
+ struct phy phy;
+ struct device *dev;
+ const struct qcom_uniphy_pcie_data *data;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct reset_control *resets;
+ void __iomem *base;
+ int lanes;
+};
+
+#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
+
+static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
+ {
+ .offset = PHY_CFG_PLLCFG,
+ .val = 0x30,
+ }, {
+ .offset = PHY_CFG_EIOS_DTCT_REG,
+ .val = 0x53ef,
+ }, {
+ .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME,
+ .val = 0xcf,
+ },
+};
+
+static const struct qcom_uniphy_pcie_data ipq5332_data = {
+ .lane_offset = 0x800,
+ .phy_type = PHY_TYPE_PCIE_GEN3,
+ .init_seq = ipq5332_regs,
+ .init_seq_num = ARRAY_SIZE(ipq5332_regs),
+ .pipe_clk_rate = 250000000,
+};
+
+static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy)
+{
+ const struct qcom_uniphy_pcie_data *data = phy->data;
+ const struct qcom_uniphy_pcie_regs *init_seq;
+ void __iomem *base = phy->base;
+ int lane, i;
+
+ for (lane = 0; lane < phy->lanes; lane++) {
+ init_seq = data->init_seq;
+
+ for (i = 0; i < data->init_seq_num; i++)
+ writel(init_seq[i].val, base + init_seq[i].offset);
+
+ base += data->lane_offset;
+ }
+}
+
+static int qcom_uniphy_pcie_power_off(struct phy *x)
+{
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
+
+ clk_bulk_disable_unprepare(phy->num_clks, phy->clks);
+
+ return reset_control_assert(phy->resets);
+}
+
+static int qcom_uniphy_pcie_power_on(struct phy *x)
+{
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
+ int ret;
+
+ ret = reset_control_assert(phy->resets);
+ if (ret) {
+ dev_err(phy->dev, "reset assert failed (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US);
+
+ ret = reset_control_deassert(phy->resets);
+ if (ret) {
+ dev_err(phy->dev, "reset deassert failed (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US);
+
+ ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks);
+ if (ret) {
+ dev_err(phy->dev, "clk prepare and enable failed %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US);
+
+ qcom_uniphy_pcie_init(phy);
+ return 0;
+}
+
+static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev,
+ struct qcom_uniphy_pcie *phy)
+{
+ struct resource *res;
+
+ phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(phy->base))
+ return PTR_ERR(phy->base);
+
+ phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks);
+ if (phy->num_clks < 0)
+ return phy->num_clks;
+
+ phy->resets = devm_reset_control_array_get_exclusive(phy->dev);
+ if (IS_ERR(phy->resets))
+ return PTR_ERR(phy->resets);
+
+ return 0;
+}
+
+/*
+ * Register a fixed rate pipe clock.
+ *
+ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
+ * controls it. The <s>_pipe_clk coming out of the GCC is requested
+ * by the PHY driver for its operations.
+ * We register the <s>_pipe_clksrc here. The gcc driver takes care
+ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
+ * Below picture shows this relationship.
+ *
+ * +---------------+
+ * | PHY block |<<---------------------------------------+
+ * | | |
+ * | +-------+ | +-----+ |
+ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
+ * clk | +-------+ | +-----+
+ * +---------------+
+ */
+static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id)
+{
+ const struct qcom_uniphy_pcie_data *data = phy->data;
+ struct clk_hw *hw;
+ char name[64];
+
+ snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id);
+ hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0,
+ data->pipe_clk_rate);
+ if (IS_ERR(hw))
+ return dev_err_probe(phy->dev, PTR_ERR(hw),
+ "Unable to register %s\n", name);
+
+ return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw);
+}
+
+static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
+ {
+ .compatible = "qcom,ipq5332-uniphy-pcie-phy",
+ .data = &ipq5332_data,
+ }, {
+ /* Sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table);
+
+static const struct phy_ops pcie_ops = {
+ .power_on = qcom_uniphy_pcie_power_on,
+ .power_off = qcom_uniphy_pcie_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_uniphy_pcie_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct qcom_uniphy_pcie *phy;
+ struct phy *generic_phy;
+ int ret;
+
+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, phy);
+ phy->dev = &pdev->dev;
+
+ phy->data = of_device_get_match_data(dev);
+ if (!phy->data)
+ return -EINVAL;
+
+ phy->lanes = 1;
+ ret = of_property_read_u32(dev->of_node, "num-lanes", &phy->lanes);
+
+ ret = qcom_uniphy_pcie_get_resources(pdev, phy);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to get resources: %d\n", ret);
+
+ generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops);
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, phy);
+
+ ret = phy_pipe_clk_register(phy, generic_phy->id);
+ if (ret)
+ dev_err(&pdev->dev, "failed to register phy pipe clk\n");
+
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static struct platform_driver qcom_uniphy_pcie_driver = {
+ .probe = qcom_uniphy_pcie_probe,
+ .driver = {
+ .name = "qcom-uniphy-pcie",
+ .of_match_table = qcom_uniphy_pcie_id_table,
+ },
+};
+
+module_platform_driver(qcom_uniphy_pcie_driver);
+
+MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,25 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Tue, 07 Jan 2025 17:34:13 +0400
Subject: [PATCH] phy: qualcomm: qcom-uniphy-pcie add IPQ5018 compatible
The Qualcomm UNIPHY PCIe PHY 28lp part of the IPQ5332 SoC is also present on
the IPQ5018 SoC, so adding the compatible for IPQ5018.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,ipq5332-uniphy-pcie-phy.yaml
@@ -11,11 +11,12 @@ maintainers:
- Varadarajan Narayanan <quic_varada@quicinc.com>
description:
- PCIe and USB combo PHY found in Qualcomm IPQ5332 SoC
+ PCIe and USB combo PHY found in Qualcomm IPQ5018 and IPQ5332 SoCs
properties:
compatible:
enum:
+ - qcom,ipq5018-uniphy-pcie-phy
- qcom,ipq5332-uniphy-pcie-phy
reg:

View File

@ -0,0 +1,77 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Tue, 07 Jan 2025 17:34:13 +0400
Subject: [PATCH] phy: qualcomm: qcom-uniphy-pcie 28lp add support for IPQ5018
The Qualcomm UNIPHY PCIe PHY 28lp is found on both IPQ5332 and IPQ5018.
Adding the PHY init sequence, pipe clock rate, and compatible for IPQ5018.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
@@ -76,6 +76,40 @@ struct qcom_uniphy_pcie {
#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
+static const struct qcom_uniphy_pcie_regs ipq5018_regs[] = {
+ {
+ .offset = SSCG_CTRL_REG_4,
+ .val = 0x1cb9,
+ }, {
+ .offset = SSCG_CTRL_REG_5,
+ .val = 0x023a,
+ }, {
+ .offset = SSCG_CTRL_REG_3,
+ .val = 0xd360,
+ }, {
+ .offset = SSCG_CTRL_REG_1,
+ .val = 0x1,
+ }, {
+ .offset = SSCG_CTRL_REG_2,
+ .val = 0xeb,
+ }, {
+ .offset = CDR_CTRL_REG_4,
+ .val = 0x3f9,
+ }, {
+ .offset = CDR_CTRL_REG_5,
+ .val = 0x1c9,
+ }, {
+ .offset = CDR_CTRL_REG_2,
+ .val = 0x419,
+ }, {
+ .offset = CDR_CTRL_REG_1,
+ .val = 0x200,
+ }, {
+ .offset = PCS_INTERNAL_CONTROL_2,
+ .val = 0xf101,
+ },
+};
+
static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
{
.offset = PHY_CFG_PLLCFG,
@@ -89,6 +123,14 @@ static const struct qcom_uniphy_pcie_reg
},
};
+static const struct qcom_uniphy_pcie_data ipq5018_data = {
+ .lane_offset = 0x800,
+ .phy_type = PHY_TYPE_PCIE_GEN2,
+ .init_seq = ipq5018_regs,
+ .init_seq_num = ARRAY_SIZE(ipq5018_regs),
+ .pipe_clk_rate = 125000000,
+};
+
static const struct qcom_uniphy_pcie_data ipq5332_data = {
.lane_offset = 0x800,
.phy_type = PHY_TYPE_PCIE_GEN3,
@@ -212,6 +254,9 @@ static inline int phy_pipe_clk_register(
static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
{
+ .compatible = "qcom,ipq5018-uniphy-pcie-phy",
+ .data = &ipq5018_data,
+ }, {
.compatible = "qcom,ipq5332-uniphy-pcie-phy",
.data = &ipq5332_data,
}, {

View File

@ -0,0 +1,78 @@
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Tue, 3 Oct 2023 17:38:42 +0530
Subject: [PATCH] dt-bindings: PCI: qcom: Add IPQ5108 SoC
Add support for the PCIe controller on the Qualcomm
IPQ5108 SoC to the bindings.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
---
.../devicetree/bindings/pci/qcom,pcie.yaml | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
@@ -21,6 +21,7 @@ properties:
- qcom,pcie-apq8064
- qcom,pcie-apq8084
- qcom,pcie-ipq4019
+ - qcom,pcie-ipq5018
- qcom,pcie-ipq6018
- qcom,pcie-ipq8064
- qcom,pcie-ipq8064-v2
@@ -170,6 +171,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pcie-ipq5018
- qcom,pcie-ipq6018
- qcom,pcie-ipq8074-gen3
then:
@@ -337,6 +339,39 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pcie-ipq5018
+ then:
+ properties:
+ clocks:
+ minItems: 6
+ maxItems: 6
+ clock-names:
+ items:
+ - const: iface # PCIe to SysNOC BIU clock
+ - const: axi_m # AXI Master clock
+ - const: axi_s # AXI Slave clock
+ - const: ahb # AHB clock
+ - const: aux # Auxiliary clock
+ - const: axi_bridge # AXI bridge clock
+ resets:
+ minItems: 8
+ maxItems: 8
+ reset-names:
+ items:
+ - const: pipe # PIPE reset
+ - const: sleep # Sleep reset
+ - const: sticky # Core sticky reset
+ - const: axi_m # AXI master reset
+ - const: axi_s # AXI slave reset
+ - const: ahb # AHB reset
+ - const: axi_m_sticky # AXI master sticky reset
+ - const: axi_s_sticky # AXI slave sticky reset
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pcie-msm8996
then:
properties:
@@ -875,6 +910,7 @@ allOf:
- qcom,pcie-apq8064
- qcom,pcie-apq8084
- qcom,pcie-ipq4019
+ - qcom,pcie-ipq5018
- qcom,pcie-ipq6018
- qcom,pcie-ipq8064
- qcom,pcie-ipq8064-v2

View File

@ -0,0 +1,77 @@
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Subject: [PATCH] PCI: qcom: Add support for IPQ5018
Date: Tue, 3 Oct 2023 17:38:44 +0530
Added a new compatible 'qcom,pcie-ipq5018' and modified
get_resources of 'ops 2_9_0' to get the clocks from the
device-tree.
Co-developed-by: Anusha Rao <quic_anusha@quicinc.com>
Signed-off-by: Anusha Rao <quic_anusha@quicinc.com>
Co-developed-by: Devi Priya <quic_devipriy@quicinc.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
---
drivers/pci/controller/dwc/pcie-qcom.c | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -202,8 +202,9 @@ struct qcom_pcie_resources_2_7_0 {
#define QCOM_PCIE_2_9_0_MAX_CLOCKS 5
struct qcom_pcie_resources_2_9_0 {
- struct clk_bulk_data clks[QCOM_PCIE_2_9_0_MAX_CLOCKS];
+ struct clk_bulk_data *clks;
struct reset_control *rst;
+ int num_clks;
};
union qcom_pcie_resources {
@@ -1073,17 +1074,10 @@ static int qcom_pcie_get_resources_2_9_0
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
- int ret;
-
- res->clks[0].id = "iface";
- res->clks[1].id = "axi_m";
- res->clks[2].id = "axi_s";
- res->clks[3].id = "axi_bridge";
- res->clks[4].id = "rchng";
- ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks);
- if (ret < 0)
- return ret;
+ res->num_clks = devm_clk_bulk_get_all(dev, &res->clks);
+ if (res->num_clks < 0)
+ return res->num_clks;
res->rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(res->rst))
@@ -1096,7 +1090,7 @@ static void qcom_pcie_deinit_2_9_0(struc
{
struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0;
- clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
+ clk_bulk_disable_unprepare(res->num_clks, res->clks);
}
static int qcom_pcie_init_2_9_0(struct qcom_pcie *pcie)
@@ -1125,7 +1119,7 @@ static int qcom_pcie_init_2_9_0(struct q
usleep_range(2000, 2500);
- return clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
+ return clk_bulk_prepare_enable(res->num_clks, res->clks);
}
static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)
@@ -1641,6 +1635,7 @@ static const struct of_device_id qcom_pc
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
+ { .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },

View File

@ -0,0 +1,216 @@
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PCIe related nodes
Date: Tue, 3 Oct 2023 17:38:45 +0530
Add phy and controller nodes for PCIe0 and PCIe1.
PCIe0 is 2-lane Gen2 and PCIe1 is 1-lane Gen2.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 186 +++++++++++++++++++++++++-
1 file changed, 184 insertions(+), 2 deletions(-)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -149,6 +149,42 @@
status = "disabled";
};
+ pcie1_phy: phy@7e000{
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
+ reg = <0x0007e000 0x800>;
+
+ clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
+
+ resets = <&gcc GCC_PCIE1_PHY_BCR>,
+ <&gcc GCC_PCIE1PHY_PHY_BCR>;
+
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
+
+ num-lanes = <1>;
+
+ status = "disabled";
+ };
+
+ pcie0_phy: phy@86000{
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
+ reg = <0x00086000 0x800>;
+
+ clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
+
+ resets = <&gcc GCC_PCIE0_PHY_BCR>,
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
+
+ #clock-cells = <0>;
+
+ #phy-cells = <0>;
+
+ num-lanes = <2>;
+
+ status = "disabled";
+ };
+
qfprom: qfprom@a0000 {
compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
reg = <0xa0000 0x1000>;
@@ -283,8 +319,8 @@
reg = <0x01800000 0x80000>;
clocks = <&xo_board_clk>,
<&sleep_clk>,
- <0>,
- <0>,
+ <&pcie0_phy>,
+ <&pcie1_phy>,
<0>,
<0>,
<0>,
@@ -501,6 +537,146 @@
status = "disabled";
};
};
+
+ pcie1: pcie@80000000 {
+ compatible = "qcom,pcie-ipq5018";
+ reg = <0x80000000 0xf1d>,
+ <0x80000f20 0xa8>,
+ <0x80001000 0x1000>,
+ <0x00078000 0x3000>,
+ <0x80100000 0x1000>;
+ reg-names = "dbi",
+ "elbi",
+ "atu",
+ "parf",
+ "config";
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ max-link-speed = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ phys = <&pcie1_phy>;
+ phy-names ="pciephy";
+
+ ranges = <0x81000000 0 0x80200000 0x80200000 0 0x00100000>, /* I/O */
+ <0x82000000 0 0x80300000 0x80300000 0 0x10000000>; /* MEM */
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 142 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 143 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 144 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 145 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global_irq";
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE1_AXI_CLK>,
+ <&gcc GCC_PCIE1_AXI_M_CLK>,
+ <&gcc GCC_PCIE1_AXI_S_CLK>,
+ <&gcc GCC_PCIE1_AHB_CLK>,
+ <&gcc GCC_PCIE1_AUX_CLK>,
+ <&gcc GCC_PCIE1_AXI_S_BRIDGE_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux",
+ "axi_bridge";
+
+ resets = <&gcc GCC_PCIE1_PIPE_ARES>,
+ <&gcc GCC_PCIE1_SLEEP_ARES>,
+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE1_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE1_AHB_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_STICKY_ARES>,
+ <&gcc GCC_PCIE1_AXI_SLAVE_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky",
+ "axi_s_sticky";
+
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
+ status = "disabled";
+ };
+
+ pcie0: pcie@a0000000 {
+ compatible = "qcom,pcie-ipq5018";
+ reg = <0xa0000000 0xf1d>,
+ <0xa0000f20 0xa8>,
+ <0xa0001000 0x1000>,
+ <0x00080000 0x3000>,
+ <0xa0100000 0x1000>;
+ reg-names = "dbi",
+ "elbi",
+ "atu",
+ "parf",
+ "config";
+ device_type = "pci";
+ linux,pci-domain = <1>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <2>;
+ max-link-speed = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ phys = <&pcie0_phy>;
+ phy-names ="pciephy";
+
+ ranges = <0x81000000 0 0xa0200000 0xa0200000 0 0x00100000>, /* I/O */
+ <0x82000000 0 0xa0300000 0xa0300000 0 0x10000000>; /* MEM */
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 78 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 79 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 83 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global_irq";
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>,
+ <&gcc GCC_PCIE0_AXI_M_CLK>,
+ <&gcc GCC_PCIE0_AXI_S_CLK>,
+ <&gcc GCC_PCIE0_AHB_CLK>,
+ <&gcc GCC_PCIE0_AUX_CLK>,
+ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux",
+ "axi_bridge";
+
+ resets = <&gcc GCC_PCIE0_PIPE_ARES>,
+ <&gcc GCC_PCIE0_SLEEP_ARES>,
+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE0_AHB_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky",
+ "axi_s_sticky";
+
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
+ status = "disabled";
+ };
};
thermal-zones {

View File

@ -0,0 +1,18 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add IPQ5018 compatible
Date: Sun, 06 Oct 2024 16:34:11 +0400
Document the qcom,tcsr-ipq5018 compatible.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,tcsr.yaml
@@ -33,6 +33,7 @@ properties:
- qcom,sm8450-tcsr
- qcom,tcsr-apq8064
- qcom,tcsr-apq8084
+ - qcom,tcsr-ipq5018
- qcom,tcsr-ipq5332
- qcom,tcsr-ipq8064
- qcom,tcsr-ipq8074

View File

@ -0,0 +1,22 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add TCSR node
Date: Sun, 06 Oct 2024 16:34:11 +0400
Add TCSR node.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -337,6 +337,11 @@
#hwlock-cells = <1>;
};
+ tcsr: syscon@1937000 {
+ compatible = "qcom,tcsr-ipq5018", "syscon", "simple-mfd";
+ reg = <0x01937000 0x21000>;
+ };
+
sdhc_1: mmc@7804000 {
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
reg = <0x7804000 0x1000>;

View File

@ -0,0 +1,19 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: enable the download mode support
Date: Sun, 06 Oct 2024 16:34:11 +0400
IPQ5018 also supports the download mode to collect the RAM dumps if system crashes, to perform
the post mortem analysis. Add support for the same.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -82,6 +82,7 @@
scm {
compatible = "qcom,scm-ipq5018", "qcom,scm";
qcom,sdi-enabled;
+ qcom,dload-mode = <&tcsr 0x6100>;
};
};

View File

@ -0,0 +1,22 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] dt-bindings: mfd: qcom,tcsr: Add IPQ5018 compatible
Date: Sun, 06 Oct 2024 16:34:11 +0400
Add compatible for IPQ5018.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
@@ -11,7 +11,10 @@ maintainers:
properties:
compatible:
- const: qcom,ipq6018-pwm
+ items:
+ - enum:
+ - qcom,ipq5018-pwm
+ - const: qcom,ipq6018-pwm
reg:
description: Offset of PWM register in the TCSR block.

View File

@ -0,0 +1,65 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] pinctrl: qcom: IPQ5018: update pwm groups
Date: Wed, 27 Nov 2024 09:14:11 +0400
GPIO 1, 30, and 46 are used to control PWM1, PWM3, and PWM0 respectively which
in turn drive the PWM led, so let's update the pwm# and pingroups accordingly.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -541,7 +541,7 @@ static const char * const qdss_tracectl_
};
static const char * const pwm0_groups[] = {
- "gpio42",
+ "gpio42", "gpio46",
};
static const char * const qdss_cti_trig_out_b0_groups[] = {
@@ -549,7 +549,7 @@ static const char * const qdss_cti_trig_
};
static const char * const pwm1_groups[] = {
- "gpio43",
+ "gpio43", "gpio1",
};
static const char * const qdss_cti_trig_in_b0_groups[] = {
@@ -565,7 +565,7 @@ static const char * const qdss_cti_trig_
};
static const char * const pwm3_groups[] = {
- "gpio45",
+ "gpio45", "gpio30",
};
static const char * const qdss_cti_trig_in_b1_groups[] = {
@@ -679,7 +679,7 @@ static const struct pinfunction ipq5018_
static const struct msm_pingroup ipq5018_groups[] = {
PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _),
- PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(1, atest_char, pwm1, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _),
@@ -708,7 +708,7 @@ static const struct msm_pingroup ipq5018
PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _),
PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _),
PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _),
- PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _),
+ PINGROUP(30, audio_txd, led2, led0, pwm3, _, _, _, _, _),
PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _),
@@ -724,7 +724,7 @@ static const struct msm_pingroup ipq5018
PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _),
PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
- PINGROUP(46, led0, _, _, _, _, _, _, _, _),
+ PINGROUP(46, led0, pwm0, _, _, _, _, _, _, _),
};
static const struct msm_pinctrl_soc_data ipq5018_pinctrl = {

View File

@ -0,0 +1,27 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PWM node
Date: Sun, 06 Oct 2024 16:34:11 +0400
Add PWM node.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -343,6 +343,16 @@
reg = <0x01937000 0x21000>;
};
+ pwm: pwm@1941010 {
+ compatible = "qcom,ipq5018-pwm", "qcom,ipq6018-pwm";
+ reg = <0x01941010 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <2>;
+ status = "disabled";
+ };
+
sdhc_1: mmc@7804000 {
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
reg = <0x7804000 0x1000>;

View File

@ -0,0 +1,41 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add crypto nodes
Date: Sun, 06 Oct 2024 16:34:11 +0400
Add dma controller and crypto nodes.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -297,6 +297,30 @@
#thermal-sensor-cells = <1>;
};
+ cryptobam: dma-controller@704000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x00704000 0x20000>;
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <1>;
+ qcom,controlled-remotely;
+ status = "disabled";
+ };
+
+ crypto: crypto@73a000 {
+ compatible = "qcom,crypto-v5.1";
+ reg = <0x0073a000 0x6000>;
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
+ <&gcc GCC_CRYPTO_AXI_CLK>,
+ <&gcc GCC_CRYPTO_CLK>;
+ clock-names = "iface", "bus", "core";
+ dmas = <&cryptobam 2>, <&cryptobam 3>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;

View File

@ -0,0 +1,25 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PRNG node
Date: Sun, 06 Oct 2024 16:34:11 +0400
Add PRNG node.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -258,6 +258,14 @@
};
};
+ prng: rng@e3000 {
+ compatible = "qcom,prng-ee";
+ reg = <0x000e3000 0x1000>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ status = "disabled";
+ };
+
tsens: thermal-sensor@4a9000 {
compatible = "qcom,ipq5018-tsens";
reg = <0x4a9000 0x1000>, /* TM */

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