mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-18 02:22:10 -05:00
airoha: an7581: add support for kernel 6.12
Enable kernel 6.12 as the testing kernel for airoha. This first commit will largely maintain feature-parity with kernel 6.6. DTS changes are backwards-compatible with kernel 6.6. Tested to flash and boot on Gemtek W1700K (#17869). Signed-off-by: Kenneth Kasilag <kenneth@kasilag.me> Link: https://github.com/openwrt/openwrt/pull/19038 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
87f3bf704c
commit
122135b964
@ -7,6 +7,7 @@ SUBTARGETS:=en7523 an7581
|
||||
FEATURES:=dt squashfs nand ramdisk gpio
|
||||
|
||||
KERNEL_PATCHVER:=6.6
|
||||
KERNEL_TESTING_PATCHVER:=6.12
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_AIROHA_CPU_PM_DOMAIN=y
|
||||
CONFIG_AIROHA_SCU_SSR=y
|
||||
CONFIG_AIROHA_THERMAL=y
|
||||
CONFIG_AIROHA_WATCHDOG=y
|
||||
CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y
|
||||
@ -25,21 +26,23 @@ CONFIG_ARM64=y
|
||||
CONFIG_ARM64_4K_PAGES=y
|
||||
CONFIG_ARM64_ERRATUM_843419=y
|
||||
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
|
||||
CONFIG_ARM64_PAGE_SHIFT=12
|
||||
CONFIG_ARM64_PA_BITS=48
|
||||
CONFIG_ARM64_PA_BITS_48=y
|
||||
CONFIG_ARM64_PLATFORM_DEVICES=y
|
||||
CONFIG_ARM64_TAGGED_ADDR_ABI=y
|
||||
CONFIG_ARM64_VA_BITS=39
|
||||
CONFIG_ARM64_VA_BITS_39=y
|
||||
# CONFIG_ARM64_VA_BITS_48 is not set
|
||||
# CONFIG_ARM64_VA_BITS_52 is not set
|
||||
CONFIG_ARM_AIROHA_SOC_CPUFREQ=y
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ARM_ARCH_TIMER=y
|
||||
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
|
||||
# CONFIG_ARM_DEBUG_WX is not set
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_GIC_V2M=y
|
||||
CONFIG_ARM_GIC_V3=y
|
||||
CONFIG_ARM_GIC_V3_ITS=y
|
||||
CONFIG_ARM_GIC_V3_ITS_PCI=y
|
||||
CONFIG_ARM_PMU=y
|
||||
CONFIG_ARM_PMUV3=y
|
||||
CONFIG_ARM_PSCI_FW=y
|
||||
@ -58,6 +61,7 @@ CONFIG_COMMON_CLK=y
|
||||
CONFIG_COMMON_CLK_EN7523=y
|
||||
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
|
||||
# CONFIG_COMPAT_32BIT_TIME is not set
|
||||
# CONFIG_COMPRESSED_INSTALL is not set
|
||||
CONFIG_CONTEXT_TRACKING=y
|
||||
CONFIG_CONTEXT_TRACKING_IDLE=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
@ -85,6 +89,9 @@ CONFIG_CRYPTO_ECB=y
|
||||
CONFIG_CRYPTO_HASH_INFO=y
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_JITTERENTROPY=y
|
||||
CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64
|
||||
CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32
|
||||
CONFIG_CRYPTO_JITTERENTROPY_OSR=1
|
||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||
CONFIG_CRYPTO_LIB_SHA1=y
|
||||
@ -104,7 +111,9 @@ CONFIG_DMADEVICES=y
|
||||
CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y
|
||||
CONFIG_DMA_DIRECT_REMAP=y
|
||||
CONFIG_DMA_ENGINE=y
|
||||
CONFIG_DMA_NEED_SYNC=y
|
||||
CONFIG_DMA_OF=y
|
||||
CONFIG_DMA_OPS_HELPERS=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_EDAC_SUPPORT=y
|
||||
CONFIG_EXT4_FS=y
|
||||
@ -126,6 +135,7 @@ CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
|
||||
CONFIG_GENERIC_CPU_AUTOPROBE=y
|
||||
CONFIG_GENERIC_CPU_DEVICES=y
|
||||
CONFIG_GENERIC_CPU_VULNERABILITIES=y
|
||||
CONFIG_GENERIC_CSUM=y
|
||||
CONFIG_GENERIC_EARLY_IOREMAP=y
|
||||
@ -160,6 +170,8 @@ CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_IOPORT_MAP=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_AIROHA=y
|
||||
# CONFIG_HISILICON_ERRATUM_162100801 is not set
|
||||
# CONFIG_IDPF is not set
|
||||
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
||||
CONFIG_INET_AH=y
|
||||
CONFIG_INET_ESP=y
|
||||
@ -185,11 +197,13 @@ CONFIG_IRQCHIP=y
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_IRQ_MSI_LIB=y
|
||||
CONFIG_IRQ_WORK=y
|
||||
CONFIG_JBD2=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
CONFIG_LOCK_SPIN_ON_OWNER=y
|
||||
CONFIG_LRU_GEN_WALKS_MMU=y
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_MDIO_BUS=y
|
||||
@ -221,6 +235,7 @@ CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_AIROHA=y
|
||||
CONFIG_NET_AIROHA_FLOW_STATS=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
@ -237,6 +252,11 @@ CONFIG_NLS=y
|
||||
CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_BLOCK=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_NVMEM_LAYOUT_ASCII_ENV=y
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
@ -272,6 +292,7 @@ CONFIG_PHYLIB_LEDS=y
|
||||
CONFIG_PHYLINK=y
|
||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_PHY_AIROHA_PCIE=y
|
||||
CONFIG_PHY_AIROHA_USB=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_AIROHA=y
|
||||
# CONFIG_PINCTRL_MT2712 is not set
|
||||
@ -293,7 +314,6 @@ CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_SYSCON=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_PREEMPT_NONE_BUILD=y
|
||||
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
||||
CONFIG_QUEUED_RWLOCKS=y
|
||||
CONFIG_QUEUED_SPINLOCKS=y
|
||||
@ -309,6 +329,7 @@ CONFIG_RESET_CONTROLLER=y
|
||||
CONFIG_RFS_ACCEL=y
|
||||
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
|
||||
CONFIG_RPS=y
|
||||
CONFIG_RTL8261N_PHY=y
|
||||
CONFIG_RWSEM_SPIN_ON_OWNER=y
|
||||
CONFIG_SERIAL_8250_EXTENDED=y
|
||||
CONFIG_SERIAL_8250_FSL=y
|
||||
@ -337,6 +358,7 @@ CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
|
||||
CONFIG_SWIOTLB=y
|
||||
CONFIG_SWPHY=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
# CONFIG_TEST_FPU is not set
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
|
||||
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
|
||||
@ -351,6 +373,8 @@ CONFIG_TREE_RCU=y
|
||||
CONFIG_TREE_SRCU=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
|
||||
CONFIG_USER_STACKTRACE_SUPPORT=y
|
||||
CONFIG_VDSO_GETRANDOM=y
|
||||
CONFIG_VMAP_STACK=y
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
# CONFIG_WLAN is not set
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From 428ae88ef519f2009fac37563de76ffa6f93046f Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Danzberger <dd@embedd.com>
|
||||
Date: Sat, 9 Mar 2024 10:32:16 +0100
|
||||
Subject: [PATCH] arm64: add Airoha EN7581 platform
|
||||
|
||||
Introduce the Kconfig entry for the Airoha EN7581 multicore architecture
|
||||
available in the Airoha EN7581 evaluation board.
|
||||
|
||||
Signed-off-by: Daniel Danzberger <dd@embedd.com>
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/d52d95db313e6a58ba997ba2181faf78a1014bcc.1709975956.git.lorenzo@kernel.org
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
---
|
||||
arch/arm64/Kconfig.platforms | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/arm64/Kconfig.platforms
|
||||
+++ b/arch/arm64/Kconfig.platforms
|
||||
@@ -8,6 +8,13 @@ config ARCH_ACTIONS
|
||||
help
|
||||
This enables support for the Actions Semiconductor S900 SoC family.
|
||||
|
||||
+config ARCH_AIROHA
|
||||
+ bool "Airoha SoC Support"
|
||||
+ select ARM_PSCI
|
||||
+ select HAVE_ARM_ARCH_TIMER
|
||||
+ help
|
||||
+ This enables support for the ARM64 based Airoha SoCs.
|
||||
+
|
||||
config ARCH_SUNXI
|
||||
bool "Allwinner sunxi 64-bit SoC Family"
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
@ -1,27 +0,0 @@
|
||||
From fd6acb0d21b8683fd8804129beeb4fe629488aff Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 9 Jul 2024 00:42:38 +0200
|
||||
Subject: [PATCH] i2c: mt7621: Add Airoha EN7581 i2c support
|
||||
|
||||
Introduce i2c support to Airoha EN7581 SoC through the i2c-mt7621
|
||||
driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Ray Liu <ray.liu@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
|
||||
---
|
||||
drivers/i2c/busses/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -841,7 +841,7 @@ config I2C_MT65XX
|
||||
|
||||
config I2C_MT7621
|
||||
tristate "MT7621/MT7628 I2C Controller"
|
||||
- depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST
|
||||
+ depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || ARCH_AIROHA || COMPILE_TEST
|
||||
help
|
||||
Say Y here to include support for I2C controller in the
|
||||
MediaTek MT7621/MT7628 SoCs.
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
From 1f038d5897fe6b439039fc28420842abcc0d126b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:15:46 +0200
|
||||
Subject: [PATCH] net: airoha: fix error branch in airoha_dev_xmit and
|
||||
airoha_set_gdm_ports
|
||||
|
||||
Fix error case management in airoha_dev_xmit routine since we need to
|
||||
DMA unmap pending buffers starting from q->head.
|
||||
Moreover fix a typo in error case branch in airoha_set_gdm_ports
|
||||
routine.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/b628871bc8ae4861b5e2ab4db90aaf373cbb7cee.1721203880.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct a
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- for (i--; i >= 0; i++)
|
||||
+ for (i--; i >= 0; i--)
|
||||
airoha_set_gdm_port(eth, port_list[i], false);
|
||||
|
||||
return err;
|
||||
@@ -2432,9 +2432,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
error_unmap:
|
||||
- for (i--; i >= 0; i++)
|
||||
- dma_unmap_single(dev->dev.parent, q->entry[i].dma_addr,
|
||||
- q->entry[i].dma_len, DMA_TO_DEVICE);
|
||||
+ for (i--; i >= 0; i--) {
|
||||
+ index = (q->head + i) % q->ndesc;
|
||||
+ dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr,
|
||||
+ q->entry[index].dma_len, DMA_TO_DEVICE);
|
||||
+ }
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
error:
|
||||
@ -1,39 +0,0 @@
|
||||
From 4e076ff6ad5302c015617da30d877b4cdcbdf613 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:47:19 +0200
|
||||
Subject: [PATCH] net: airoha: Fix NULL pointer dereference in
|
||||
airoha_qdma_cleanup_rx_queue()
|
||||
|
||||
Move page_pool_get_dma_dir() inside the while loop of
|
||||
airoha_qdma_cleanup_rx_queue routine in order to avoid possible NULL
|
||||
pointer dereference if airoha_qdma_init_rx_queue() fails before
|
||||
properly allocating the page_pool pointer.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/7330a41bba720c33abc039955f6172457a3a34f0.1721205981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1586,7 +1586,6 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_eth *eth = q->eth;
|
||||
|
||||
while (q->queued) {
|
||||
@@ -1594,7 +1593,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
struct page *page = virt_to_head_page(e->buf);
|
||||
|
||||
dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
|
||||
- dir);
|
||||
+ page_pool_get_dma_dir(q->page_pool));
|
||||
page_pool_put_full_page(q->page_pool, page, false);
|
||||
q->tail = (q->tail + 1) % q->ndesc;
|
||||
q->queued--;
|
||||
@ -1,27 +0,0 @@
|
||||
From 39a9c25bcdfb5e88995841c47439b74cac74a527 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 19 Jul 2024 22:38:31 +0200
|
||||
Subject: [PATCH] net: airoha: Fix MBI_RX_AGE_SEL_MASK definition
|
||||
|
||||
Fix copy-paste error in MBI_RX_AGE_SEL_MASK macro definition
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/d27d0465be1bff3369e886e5f10c4d37fefc4934.1721419930.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -249,7 +249,7 @@
|
||||
#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc)
|
||||
|
||||
#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20)
|
||||
-#define MBI_RX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
+#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25)
|
||||
#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
|
||||
#define REG_GDM3_FWD_CFG GDM3_BASE
|
||||
@ -1,553 +0,0 @@
|
||||
From 16874d1cf3818a5804cded8eaff634122b1d6c7c Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:03 +0200
|
||||
Subject: [PATCH 1/8] net: airoha: Introduce airoha_qdma struct
|
||||
|
||||
Introduce airoha_qdma struct and move qdma IO register mapping in
|
||||
airoha_qdma. This is a preliminary patch to enable both QDMA controllers
|
||||
available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/7df163bdc72ee29c3d27a0cbf54522ffeeafe53c.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 197 ++++++++++++---------
|
||||
1 file changed, 112 insertions(+), 85 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 1
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -782,6 +783,10 @@ struct airoha_hw_stats {
|
||||
u64 rx_len[7];
|
||||
};
|
||||
|
||||
+struct airoha_qdma {
|
||||
+ void __iomem *regs;
|
||||
+};
|
||||
+
|
||||
struct airoha_gdm_port {
|
||||
struct net_device *dev;
|
||||
struct airoha_eth *eth;
|
||||
@@ -794,8 +799,6 @@ struct airoha_eth {
|
||||
struct device *dev;
|
||||
|
||||
unsigned long state;
|
||||
-
|
||||
- void __iomem *qdma_regs;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -806,6 +809,7 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
|
||||
struct net_device *napi_dev;
|
||||
@@ -850,16 +854,16 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_fe_clear(eth, offset, val) \
|
||||
airoha_rmw((eth)->fe_regs, (offset), (val), 0)
|
||||
|
||||
-#define airoha_qdma_rr(eth, offset) \
|
||||
- airoha_rr((eth)->qdma_regs, (offset))
|
||||
-#define airoha_qdma_wr(eth, offset, val) \
|
||||
- airoha_wr((eth)->qdma_regs, (offset), (val))
|
||||
-#define airoha_qdma_rmw(eth, offset, mask, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (mask), (val))
|
||||
-#define airoha_qdma_set(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), 0, (val))
|
||||
-#define airoha_qdma_clear(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (val), 0)
|
||||
+#define airoha_qdma_rr(qdma, offset) \
|
||||
+ airoha_rr((qdma)->regs, (offset))
|
||||
+#define airoha_qdma_wr(qdma, offset, val) \
|
||||
+ airoha_wr((qdma)->regs, (offset), (val))
|
||||
+#define airoha_qdma_rmw(qdma, offset, mask, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (mask), (val))
|
||||
+#define airoha_qdma_set(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), 0, (val))
|
||||
+#define airoha_qdma_clear(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
u32 clear, u32 set)
|
||||
@@ -873,11 +877,12 @@ static void airoha_qdma_set_irqmask(stru
|
||||
|
||||
eth->irqmask[index] &= ~clear;
|
||||
eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(eth, REG_INT_ENABLE(index), eth->irqmask[index]);
|
||||
+ airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
+ eth->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(eth, REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
|
||||
spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
}
|
||||
@@ -1383,6 +1388,7 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
int qid = q - ð->q_rx[0];
|
||||
int nframes = 0;
|
||||
@@ -1420,7 +1426,8 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
WRITE_ONCE(desc->msg2, 0);
|
||||
WRITE_ONCE(desc->msg3, 0);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid),
|
||||
+ RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head));
|
||||
}
|
||||
|
||||
@@ -1529,7 +1536,8 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int ndesc)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
.order = 0,
|
||||
@@ -1569,14 +1577,15 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
|
||||
|
||||
- airoha_qdma_wr(eth, REG_RX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_SIZE_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid),
|
||||
+ RX_RING_SIZE_MASK,
|
||||
FIELD_PREP(RX_RING_SIZE_MASK, ndesc));
|
||||
|
||||
thr = clamp(ndesc >> 3, 1, 32);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
FIELD_PREP(RX_RING_THR_MASK, thr));
|
||||
- airoha_qdma_rmw(eth, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
airoha_qdma_fill_rx_queue(q);
|
||||
@@ -1600,7 +1609,8 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1613,7 +1623,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
}
|
||||
|
||||
err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
- RX_DSCP_NUM(i));
|
||||
+ qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1624,11 +1634,13 @@ static int airoha_qdma_init_rx(struct ai
|
||||
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_tx_irq_queue *irq_q;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_eth *eth;
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
+ qdma = ð->qdma[0];
|
||||
id = irq_q - ð->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
@@ -1698,9 +1710,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int i, len = done >> 7;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, 0x80);
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, (done & 0x7f));
|
||||
}
|
||||
|
||||
@@ -1712,7 +1724,8 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int size)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int i, qid = q - ð->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1739,10 +1752,10 @@ static int airoha_qdma_init_tx_queue(str
|
||||
WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val));
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
- airoha_qdma_rmw(eth, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
return 0;
|
||||
@@ -1750,7 +1763,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
|
||||
static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
- int size)
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - ð->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1766,29 +1779,30 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
irq_q->size = size;
|
||||
irq_q->eth = eth;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
FIELD_PREP(TX_IRQ_DEPTH_MASK, size));
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
FIELD_PREP(TX_IRQ_THR_MASK, 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
- IRQ_QUEUE_LEN(i));
|
||||
+ qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
- TX_DSCP_NUM);
|
||||
+ qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1815,7 +1829,8 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
@@ -1827,7 +1842,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_DSCP_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
@@ -1835,14 +1850,14 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_BUF_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_HW_FWD_DSCP_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG,
|
||||
HW_FWD_DSCP_PAYLOAD_SIZE_MASK,
|
||||
FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0));
|
||||
- airoha_qdma_rmw(eth, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128));
|
||||
- airoha_qdma_rmw(eth, REG_LMGR_INIT_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG,
|
||||
LMGR_INIT_START | LMGR_SRAM_MODE_MASK |
|
||||
HW_FWD_DESC_NUM_MASK,
|
||||
FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) |
|
||||
@@ -1850,67 +1865,69 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
|
||||
return read_poll_timeout(airoha_qdma_rr, status,
|
||||
!(status & LMGR_INIT_START), USEC_PER_MSEC,
|
||||
- 30 * USEC_PER_MSEC, true, eth,
|
||||
+ 30 * USEC_PER_MSEC, true, qdma,
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- airoha_qdma_clear(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
- airoha_qdma_set(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
|
||||
- airoha_qdma_clear(eth, REG_PSE_BUF_USAGE_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_PSE_BUF_USAGE_CFG,
|
||||
PSE_BUF_ESTIMATE_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_EN_MASK |
|
||||
EGRESS_RATE_METER_EQ_RATE_EN_MASK);
|
||||
/* 2047us x 31 = 63.457ms */
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_WINDOW_SZ_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_WINDOW_SZ_MASK, 0x1f));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_TIMESLICE_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_TIMESLICE_MASK, 0x7ff));
|
||||
|
||||
/* ratelimit init */
|
||||
- airoha_qdma_set(eth, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
/* fast-tick 25us */
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
FIELD_PREP(GLB_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(GLB_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(EGRESS_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG,
|
||||
EGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(EGRESS_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_TRTCM_MODE_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(INGRESS_FAST_TICK_MASK, 125));
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(INGRESS_SLOW_TICK_RATIO_MASK, 8));
|
||||
|
||||
- airoha_qdma_set(eth, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
FIELD_PREP(SLA_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), 0xffffffff);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
@@ -1923,14 +1940,14 @@ static int airoha_qdma_hw_init(struct ai
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
- airoha_qdma_set(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
else
|
||||
- airoha_qdma_clear(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_clear(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_RX_2B_OFFSET_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) |
|
||||
GLOBAL_CFG_CPU_TXR_RR_MASK |
|
||||
@@ -1941,18 +1958,18 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth);
|
||||
+ airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
if (!eth->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_RX_DELAY_INT_IDX(i),
|
||||
+ airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
RX_DELAY_INT_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_set(eth, REG_TXQ_CNGST_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG,
|
||||
TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN);
|
||||
|
||||
return 0;
|
||||
@@ -1962,12 +1979,14 @@ static irqreturn_t airoha_irq_handler(in
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
+ struct airoha_qdma *qdma;
|
||||
int i;
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
- intr[i] = airoha_qdma_rr(eth, REG_INT_STATUS(i));
|
||||
+ intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
intr[i] &= eth->irqmask[i];
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), intr[i]);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
@@ -1997,7 +2016,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
- status = airoha_qdma_rr(eth, REG_IRQ_STATUS(i));
|
||||
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
@@ -2011,6 +2030,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
|
||||
static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
@@ -2018,19 +2038,19 @@ static int airoha_qdma_init(struct airoh
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth);
|
||||
+ err = airoha_qdma_init_rx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth);
|
||||
+ err = airoha_qdma_init_tx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth);
|
||||
+ err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth);
|
||||
+ err = airoha_qdma_hw_init(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -2263,8 +2283,9 @@ static int airoha_dev_open(struct net_de
|
||||
airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2280,8 +2301,9 @@ static int airoha_dev_stop(struct net_de
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2341,6 +2363,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_eth *eth = port->eth;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2368,6 +2391,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
q = ð->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2412,7 +2436,8 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
|
||||
data = skb_frag_address(frag);
|
||||
@@ -2614,9 +2639,11 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma_regs = devm_platform_ioremap_resource_byname(pdev, "qdma0");
|
||||
- if (IS_ERR(eth->qdma_regs))
|
||||
- return dev_err_probe(eth->dev, PTR_ERR(eth->qdma_regs),
|
||||
+ eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
+ "qdma0");
|
||||
+ if (IS_ERR(eth->qdma[0].regs))
|
||||
+ return dev_err_probe(eth->dev,
|
||||
+ PTR_ERR(eth->qdma[0].regs),
|
||||
"failed to iomap qdma regs\n");
|
||||
|
||||
eth->rsts[0].id = "fe";
|
||||
@ -1,318 +0,0 @@
|
||||
From 245c7bc86b198e5ec227eba6b582da73cb0721c8 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:04 +0200
|
||||
Subject: [PATCH 2/8] net: airoha: Move airoha_queues in airoha_qdma
|
||||
|
||||
QDMA controllers available in EN7581 SoC have independent tx/rx hw queues
|
||||
so move them in airoha_queues structure.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/795fc4797bffbf7f0a1351308aa9bf0e65b5126e.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 126 +++++++++++----------
|
||||
1 file changed, 65 insertions(+), 61 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -785,6 +785,17 @@ struct airoha_hw_stats {
|
||||
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
+
|
||||
+ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
+
|
||||
+ struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
+ struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
+
|
||||
+ /* descriptor and packet buffers for qdma hw forward */
|
||||
+ struct {
|
||||
+ void *desc;
|
||||
+ void *q;
|
||||
+ } hfwd;
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
@@ -809,20 +820,10 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
-
|
||||
struct net_device *napi_dev;
|
||||
- struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
- struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
-
|
||||
- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
- /* descriptor and packet buffers for qdma hw forward */
|
||||
- struct {
|
||||
- void *desc;
|
||||
- void *q;
|
||||
- } hfwd;
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
+ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
};
|
||||
|
||||
static u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
@@ -1390,7 +1391,7 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
while (q->queued < q->ndesc - 1) {
|
||||
@@ -1457,8 +1458,9 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
while (done < budget) {
|
||||
@@ -1550,7 +1552,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dev = eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
- int qid = q - ð->q_rx[0], thr;
|
||||
+ int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
@@ -1614,7 +1616,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
{
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
int err;
|
||||
|
||||
if (!(RX_DONE_INT_MASK & BIT(i))) {
|
||||
@@ -1622,7 +1624,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
+ err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1641,7 +1643,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
qdma = ð->qdma[0];
|
||||
- id = irq_q - ð->q_tx_irq[0];
|
||||
+ id = irq_q - &qdma->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1658,10 +1660,10 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
qid = FIELD_GET(IRQ_RING_IDX_MASK, val);
|
||||
|
||||
- if (qid >= ARRAY_SIZE(eth->q_tx))
|
||||
+ if (qid >= ARRAY_SIZE(qdma->q_tx))
|
||||
continue;
|
||||
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (!q->ndesc)
|
||||
continue;
|
||||
|
||||
@@ -1727,7 +1729,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int i, qid = q - ð->q_tx[0];
|
||||
+ int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
@@ -1765,7 +1767,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int id = irq_q - ð->q_tx_irq[0];
|
||||
+ int id = irq_q - &qdma->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1793,15 +1795,15 @@ static int airoha_qdma_init_tx(struct ai
|
||||
{
|
||||
int i, err;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1837,17 +1839,17 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
int size;
|
||||
|
||||
size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc);
|
||||
- eth->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.desc)
|
||||
+ qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
- eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.q)
|
||||
+ qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
@@ -1935,8 +1937,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
@@ -1961,8 +1963,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
@@ -1996,18 +1998,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (intr[1] & BIT(i))
|
||||
- napi_schedule(ð->q_rx[i].napi);
|
||||
+ napi_schedule(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
if (intr[0] & INT_TX_MASK) {
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- struct airoha_tx_irq_queue *irq_q = ð->q_tx_irq[i];
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
|
||||
u32 status, head;
|
||||
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
@@ -2021,7 +2023,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
|
||||
- napi_schedule(ð->q_tx_irq[i].napi);
|
||||
+ napi_schedule(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2080,44 +2082,46 @@ static int airoha_hw_init(struct airoha_
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_disable(ð->q_rx[i].napi);
|
||||
- netif_napi_del(ð->q_rx[i].napi);
|
||||
- airoha_qdma_cleanup_rx_queue(ð->q_rx[i]);
|
||||
- if (eth->q_rx[i].page_pool)
|
||||
- page_pool_destroy(eth->q_rx[i].page_pool);
|
||||
+ napi_disable(&qdma->q_rx[i].napi);
|
||||
+ netif_napi_del(&qdma->q_rx[i].napi);
|
||||
+ airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
|
||||
+ if (qdma->q_rx[i].page_pool)
|
||||
+ page_pool_destroy(qdma->q_rx[i].page_pool);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- napi_disable(ð->q_tx_irq[i].napi);
|
||||
- netif_napi_del(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+ netif_napi_del(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_cleanup_tx_queue(ð->q_tx[i]);
|
||||
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++)
|
||||
- napi_enable(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
+ napi_enable(&qdma->q_tx_irq[i].napi);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_enable(ð->q_rx[i].napi);
|
||||
+ napi_enable(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2392,7 +2396,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
qdma = ð->qdma[0];
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
|
||||
@ -1,236 +0,0 @@
|
||||
From 19e47fc2aeda3a657c4f64144ffd6e65f7a66601 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:05 +0200
|
||||
Subject: [PATCH 3/8] net: airoha: Move irq_mask in airoha_qdma structure
|
||||
|
||||
QDMA controllers have independent irq lines, so move irqmask in
|
||||
airoha_qdma structure. This is a preliminary patch to support multiple
|
||||
QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1c8a06e8be605278a7b2f3cd8ac06e74bf5ebf2b.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 42 insertions(+), 42 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -786,6 +786,11 @@ struct airoha_hw_stats {
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
|
||||
+ /* protect concurrent irqmask accesses */
|
||||
+ spinlock_t irq_lock;
|
||||
+ u32 irqmask[QDMA_INT_REG_MAX];
|
||||
+ int irq;
|
||||
+
|
||||
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
@@ -812,11 +817,6 @@ struct airoha_eth {
|
||||
unsigned long state;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
- /* protect concurrent irqmask accesses */
|
||||
- spinlock_t irq_lock;
|
||||
- u32 irqmask[QDMA_INT_REG_MAX];
|
||||
- int irq;
|
||||
-
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
@@ -866,38 +866,37 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_qdma_clear(qdma, offset, val) \
|
||||
airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
-static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index,
|
||||
u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
- if (WARN_ON_ONCE(index >= ARRAY_SIZE(eth->irqmask)))
|
||||
+ if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask)))
|
||||
return;
|
||||
|
||||
- spin_lock_irqsave(ð->irq_lock, flags);
|
||||
+ spin_lock_irqsave(&qdma->irq_lock, flags);
|
||||
|
||||
- eth->irqmask[index] &= ~clear;
|
||||
- eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
- eth->irqmask[index]);
|
||||
+ qdma->irqmask[index] &= ~clear;
|
||||
+ qdma->irqmask[index] |= set;
|
||||
+ airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(qdma, REG_INT_ENABLE(index));
|
||||
|
||||
- spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
+ spin_unlock_irqrestore(&qdma->irq_lock, flags);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_enable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, 0, mask);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, 0, mask);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_disable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, mask, 0);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
@@ -1522,7 +1521,7 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1531,7 +1530,7 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
@@ -1719,7 +1718,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(id));
|
||||
|
||||
return done;
|
||||
@@ -1928,13 +1927,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++)
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
@@ -1980,14 +1979,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
- u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
- struct airoha_qdma *qdma;
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) {
|
||||
intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
- intr[i] &= eth->irqmask[i];
|
||||
+ intr[i] &= qdma->irqmask[i];
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
@@ -1995,7 +1993,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2015,7 +2013,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
continue;
|
||||
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
@@ -2030,12 +2028,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
- err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
+ spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ if (qdma->irq < 0)
|
||||
+ return qdma->irq;
|
||||
+
|
||||
+ err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -2061,7 +2065,8 @@ static int airoha_qdma_init(struct airoh
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_hw_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -2077,7 +2082,7 @@ static int airoha_hw_init(struct airoha_
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(eth);
|
||||
+ return airoha_qdma_init(pdev, eth);
|
||||
}
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
@@ -2674,11 +2679,6 @@ static int airoha_probe(struct platform_
|
||||
return err;
|
||||
}
|
||||
|
||||
- spin_lock_init(ð->irq_lock);
|
||||
- eth->irq = platform_get_irq(pdev, 0);
|
||||
- if (eth->irq < 0)
|
||||
- return eth->irq;
|
||||
-
|
||||
eth->napi_dev = alloc_netdev_dummy(0);
|
||||
if (!eth->napi_dev)
|
||||
return -ENOMEM;
|
||||
@@ -2688,7 +2688,7 @@ static int airoha_probe(struct platform_
|
||||
strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name));
|
||||
platform_set_drvdata(pdev, eth);
|
||||
|
||||
- err = airoha_hw_init(eth);
|
||||
+ err = airoha_hw_init(pdev, eth);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
@ -1,306 +0,0 @@
|
||||
From 9a2500ab22f059e596942172a8e4a60ae8243ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:06 +0200
|
||||
Subject: [PATCH 4/8] net: airoha: Add airoha_qdma pointer in
|
||||
airoha_tx_irq_queue/airoha_queue structures
|
||||
|
||||
Move airoha_eth pointer in airoha_qdma structure from
|
||||
airoha_tx_irq_queue/airoha_queue ones. This is a preliminary patch to
|
||||
introduce support for multi-QDMA controllers available on EN7581.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/074565b82fd0ceefe66e186f21133d825dbd48eb.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 41 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -728,7 +728,7 @@ struct airoha_queue_entry {
|
||||
};
|
||||
|
||||
struct airoha_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
/* protect concurrent queue accesses */
|
||||
spinlock_t lock;
|
||||
@@ -747,7 +747,7 @@ struct airoha_queue {
|
||||
};
|
||||
|
||||
struct airoha_tx_irq_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
struct napi_struct napi;
|
||||
u32 *q;
|
||||
@@ -784,6 +784,7 @@ struct airoha_hw_stats {
|
||||
};
|
||||
|
||||
struct airoha_qdma {
|
||||
+ struct airoha_eth *eth;
|
||||
void __iomem *regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -1388,8 +1389,8 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
@@ -1457,8 +1458,8 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
@@ -1521,7 +1522,6 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1530,14 +1530,13 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
@@ -1548,15 +1547,16 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dma_dir = DMA_FROM_DEVICE,
|
||||
.max_len = PAGE_SIZE,
|
||||
.nid = NUMA_NO_NODE,
|
||||
- .dev = eth->dev,
|
||||
+ .dev = qdma->eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
q->ndesc = ndesc;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
GFP_KERNEL);
|
||||
@@ -1596,7 +1596,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
while (q->queued) {
|
||||
struct airoha_queue_entry *e = &q->entry[q->tail];
|
||||
@@ -1610,8 +1610,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_rx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1623,8 +1622,8 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
- qdma, RX_DSCP_NUM(i));
|
||||
+ err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma,
|
||||
+ RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1640,9 +1639,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
- eth = irq_q->eth;
|
||||
- qdma = ð->qdma[0];
|
||||
+ qdma = irq_q->qdma;
|
||||
id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ eth = qdma->eth;
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1724,16 +1723,16 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_tx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
q->ndesc = size;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
q->free_thr = 1 + MAX_SKB_FRAGS;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
@@ -1762,11 +1761,11 @@ static int airoha_qdma_init_tx_queue(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
- struct airoha_tx_irq_queue *irq_q,
|
||||
+static int airoha_qdma_tx_irq_init(struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1778,7 +1777,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
|
||||
memset(irq_q->q, 0xff, size * sizeof(u32));
|
||||
irq_q->size = size;
|
||||
- irq_q->eth = eth;
|
||||
+ irq_q->qdma = qdma;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
@@ -1789,21 +1788,20 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
- qdma, IRQ_QUEUE_LEN(i));
|
||||
+ err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma,
|
||||
+ IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
- qdma, TX_DSCP_NUM);
|
||||
+ err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma,
|
||||
+ TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1813,7 +1811,7 @@ static int airoha_qdma_init_tx(struct ai
|
||||
|
||||
static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
while (q->queued) {
|
||||
@@ -1830,9 +1828,9 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
int size;
|
||||
@@ -1870,8 +1868,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static void airoha_qdma_init_qos(struct airoha_qdma *qdma)
|
||||
{
|
||||
airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
@@ -1921,8 +1918,7 @@ static void airoha_qdma_init_qos(struct
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1959,7 +1955,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth, qdma);
|
||||
+ airoha_qdma_init_qos(qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2035,6 +2031,8 @@ static int airoha_qdma_init(struct platf
|
||||
int err;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->eth = eth;
|
||||
+
|
||||
qdma->irq = platform_get_irq(pdev, 0);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
@@ -2044,19 +2042,19 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth, qdma);
|
||||
+ err = airoha_qdma_init_rx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth, qdma);
|
||||
+ err = airoha_qdma_init_tx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
+ err = airoha_qdma_init_hfwd_queues(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth, qdma);
|
||||
+ err = airoha_qdma_hw_init(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
From e3d6bfdfc0aeb8c1d7965413b1050ec07f9761e5 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:07 +0200
|
||||
Subject: [PATCH 5/8] net: airoha: Use qdma pointer as private structure in
|
||||
airoha_irq_handler routine
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1e40c3cb973881c0eb3c3c247c78550da62054ab.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1974,8 +1974,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
- struct airoha_eth *eth = dev_instance;
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ struct airoha_qdma *qdma = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
@@ -1985,7 +1984,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
- if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
+ if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
@@ -2038,7 +2037,7 @@ static int airoha_qdma_init(struct platf
|
||||
return qdma->irq;
|
||||
|
||||
err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
- IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
+ IRQF_SHARED, KBUILD_MODNAME, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
From e618447cf492d04415007336eec025fae6e9a2ea Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:08 +0200
|
||||
Subject: [PATCH 6/8] net: airoha: Allow mapping IO region for multiple qdma
|
||||
controllers
|
||||
|
||||
Map MMIO regions of both qdma controllers available on EN7581 SoC.
|
||||
Run airoha_hw_cleanup routine for both QDMA controllers available on
|
||||
EN7581 SoC removing airoha_eth module or in airoha_probe error path.
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/a734ae608da14b67ae749b375d880dbbc70868ea.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 56 ++++++++++++----------
|
||||
1 file changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2024,15 +2024,25 @@ static irqreturn_t airoha_irq_handler(in
|
||||
}
|
||||
|
||||
static int airoha_qdma_init(struct platform_device *pdev,
|
||||
- struct airoha_eth *eth)
|
||||
+ struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
- int err;
|
||||
+ int err, id = qdma - ð->qdma[0];
|
||||
+ const char *res;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
qdma->eth = eth;
|
||||
|
||||
- qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id);
|
||||
+ if (!res)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ qdma->regs = devm_platform_ioremap_resource_byname(pdev, res);
|
||||
+ if (IS_ERR(qdma->regs))
|
||||
+ return dev_err_probe(eth->dev, PTR_ERR(qdma->regs),
|
||||
+ "failed to iomap qdma%d regs\n", id);
|
||||
+
|
||||
+ qdma->irq = platform_get_irq(pdev, 4 * id);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
|
||||
@@ -2053,19 +2063,13 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(qdma);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
-
|
||||
- return 0;
|
||||
+ return airoha_qdma_hw_init(qdma);
|
||||
}
|
||||
|
||||
static int airoha_hw_init(struct platform_device *pdev,
|
||||
struct airoha_eth *eth)
|
||||
{
|
||||
- int err;
|
||||
+ int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
@@ -2079,12 +2083,19 @@ static int airoha_hw_init(struct platfor
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(pdev, eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
|
||||
+ err = airoha_qdma_init(pdev, eth, ð->qdma[i]);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
+static void airoha_hw_cleanup(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2645,13 +2656,6 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
- "qdma0");
|
||||
- if (IS_ERR(eth->qdma[0].regs))
|
||||
- return dev_err_probe(eth->dev,
|
||||
- PTR_ERR(eth->qdma[0].regs),
|
||||
- "failed to iomap qdma regs\n");
|
||||
-
|
||||
eth->rsts[0].id = "fe";
|
||||
eth->rsts[1].id = "pdma";
|
||||
eth->rsts[2].id = "qdma";
|
||||
@@ -2707,7 +2711,9 @@ static int airoha_probe(struct platform_
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
||||
@@ -2725,7 +2731,9 @@ static void airoha_remove(struct platfor
|
||||
struct airoha_eth *eth = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
From 160231e34b8e9512ba20530f3e68fb0ac499af87 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:09 +0200
|
||||
Subject: [PATCH 7/8] net: airoha: Start all qdma NAPIs in airoha_probe()
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/b51cf69c94d8cbc81e0a0b35587f024d01e6d9c0.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2122,9 +2122,8 @@ static void airoha_hw_cleanup(struct air
|
||||
}
|
||||
}
|
||||
|
||||
-static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_start_napi(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
@@ -2693,7 +2692,9 @@ static int airoha_probe(struct platform_
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
- airoha_qdma_start_napi(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_qdma_start_napi(ð->qdma[i]);
|
||||
+
|
||||
for_each_child_of_node(pdev->dev.of_node, np) {
|
||||
if (!of_device_is_compatible(np, "airoha,eth-mac"))
|
||||
continue;
|
||||
@ -1,174 +0,0 @@
|
||||
From 9304640f2f78147dddf97a5ea01502ae175e41d9 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:10 +0200
|
||||
Subject: [PATCH 8/8] net: airoha: Link the gdm port to the selected qdma
|
||||
controller
|
||||
|
||||
Link the running gdm port to the qdma controller used to connect with
|
||||
the CPU. Moreover, load all QDMA controllers available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/95b515df34ba4727f7ae5b14a1d0462cceec84ff.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 37 +++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
-#define AIROHA_MAX_NUM_QDMA 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 2
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -805,8 +805,8 @@ struct airoha_qdma {
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
- struct airoha_eth *eth;
|
||||
int id;
|
||||
|
||||
struct airoha_hw_stats stats;
|
||||
@@ -2139,7 +2139,7 @@ static void airoha_qdma_start_napi(struc
|
||||
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
|
||||
{
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 val, i = 0;
|
||||
|
||||
spin_lock(&port->stats.lock);
|
||||
@@ -2284,22 +2284,22 @@ static void airoha_update_hw_stats(struc
|
||||
static int airoha_dev_open(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
- err = airoha_set_gdm_ports(eth, true);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (netdev_uses_dsa(dev))
|
||||
- airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
else
|
||||
- airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2309,15 +2309,15 @@ static int airoha_dev_open(struct net_de
|
||||
static int airoha_dev_stop(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_disable(dev);
|
||||
- err = airoha_set_gdm_ports(eth, false);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2333,7 +2333,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2342,7 +2342,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2376,10 +2376,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
u32 msg0 = 0, msg1, len = skb_headlen(skb);
|
||||
int i, qid = skb_get_queue_mapping(skb);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
- struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2407,7 +2406,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2490,7 +2488,7 @@ static void airoha_ethtool_get_drvinfo(s
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
|
||||
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
|
||||
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
|
||||
@@ -2571,6 +2569,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
{
|
||||
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
|
||||
struct airoha_gdm_port *port;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
int err, index;
|
||||
u32 id;
|
||||
@@ -2600,6 +2599,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+ qdma = ð->qdma[index % AIROHA_MAX_NUM_QDMA];
|
||||
dev->netdev_ops = &airoha_netdev_ops;
|
||||
dev->ethtool_ops = &airoha_ethtool_ops;
|
||||
dev->max_mtu = AIROHA_MAX_MTU;
|
||||
@@ -2609,6 +2609,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
NETIF_F_SG | NETIF_F_TSO;
|
||||
dev->features |= dev->hw_features;
|
||||
dev->dev.of_node = np;
|
||||
+ dev->irq = qdma->irq;
|
||||
SET_NETDEV_DEV(dev, eth->dev);
|
||||
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
@@ -2624,8 +2625,8 @@ static int airoha_alloc_gdm_port(struct
|
||||
port = netdev_priv(dev);
|
||||
u64_stats_init(&port->stats.syncp);
|
||||
spin_lock_init(&port->stats.lock);
|
||||
+ port->qdma = qdma;
|
||||
port->dev = dev;
|
||||
- port->eth = eth;
|
||||
port->id = id;
|
||||
eth->ports[index] = port;
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
From 63a796b4988c3dca83176a534890b510d44f105a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 3 Aug 2024 17:50:50 +0200
|
||||
Subject: [PATCH] net: airoha: honor reset return value in airoha_hw_init()
|
||||
|
||||
Take into account return value from reset_control_bulk_assert and
|
||||
reset_control_bulk_deassert routines in airoha_hw_init().
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/f49dc04a87653e0155f4fab3e3eb584785c8ad6a.1722699555.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2072,13 +2072,21 @@ static int airoha_hw_init(struct platfor
|
||||
int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts),
|
||||
+ eth->xsi_rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
- msleep(20);
|
||||
- reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
msleep(20);
|
||||
+ err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
+ msleep(20);
|
||||
err = airoha_fe_init(eth);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1,85 +0,0 @@
|
||||
From 812a2751e827fa1eb01f3bd268b4d74c23f4226a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 21 Aug 2024 09:30:14 +0200
|
||||
Subject: [PATCH] net: airoha: configure hw mac address according to the port
|
||||
id
|
||||
|
||||
GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
GDM{2,3,4} can be used as wan port connected to an external
|
||||
phy module. Configure hw mac address registers according to the port id.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240821-airoha-eth-wan-mac-addr-v2-1-8706d0cd6cd5@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 32 ++++++++++++++++------
|
||||
1 file changed, 23 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -67,9 +67,11 @@
|
||||
#define FE_RST_GDM3_MBI_ARB_MASK BIT(2)
|
||||
#define FE_RST_CORE_MASK BIT(0)
|
||||
|
||||
+#define REG_FE_WAN_MAC_H 0x0030
|
||||
#define REG_FE_LAN_MAC_H 0x0040
|
||||
-#define REG_FE_LAN_MAC_LMIN 0x0044
|
||||
-#define REG_FE_LAN_MAC_LMAX 0x0048
|
||||
+
|
||||
+#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04)
|
||||
+#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08)
|
||||
|
||||
#define REG_FE_CDM1_OQ_MAP0 0x0050
|
||||
#define REG_FE_CDM1_OQ_MAP1 0x0054
|
||||
@@ -900,16 +902,28 @@ static void airoha_qdma_irq_disable(stru
|
||||
airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
-static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
+static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)
|
||||
{
|
||||
- u32 val;
|
||||
+ /* GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
+ * GDM{2,3,4} can be used as wan port connected to an external
|
||||
+ * phy module.
|
||||
+ */
|
||||
+ return port->id == 1;
|
||||
+}
|
||||
+
|
||||
+static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
|
||||
+{
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
+ u32 val, reg;
|
||||
|
||||
+ reg = airhoa_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
|
||||
+ : REG_FE_WAN_MAC_H;
|
||||
val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_H, val);
|
||||
+ airoha_fe_wr(eth, reg, val);
|
||||
|
||||
val = (addr[3] << 16) | (addr[4] << 8) | addr[5];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMIN, val);
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMAX, val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
|
||||
}
|
||||
|
||||
static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
|
||||
@@ -2341,7 +2355,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2350,7 +2364,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
From 7d2bd8ac9d2494cf9b16c4b00df9424ad24ed18c Mon Sep 17 00:00:00 2001
|
||||
From: Liao Chen <liaochen4@huawei.com>
|
||||
Date: Mon, 26 Aug 2024 09:18:58 +0000
|
||||
Subject: [PATCH] net: airoha: fix module autoloading
|
||||
|
||||
Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded
|
||||
based on the alias from of_device_id table.
|
||||
|
||||
Signed-off-by: Liao Chen <liaochen4@huawei.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240826091858.369910-4-liaochen4@huawei.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2776,6 +2776,7 @@ static const struct of_device_id of_airo
|
||||
{ .compatible = "airoha,en7581-eth" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
+MODULE_DEVICE_TABLE(of, of_airoha_match);
|
||||
|
||||
static struct platform_driver airoha_driver = {
|
||||
.probe = airoha_probe,
|
||||
@ -1,45 +0,0 @@
|
||||
From 3dc6e998d18bfba6e0dc979d3cc68eba98dfeef7 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 4 Oct 2024 15:51:26 +0200
|
||||
Subject: [PATCH] net: airoha: Update tx cpu dma ring idx at the end of xmit
|
||||
loop
|
||||
|
||||
Move the tx cpu dma ring index update out of transmit loop of
|
||||
airoha_dev_xmit routine in order to not start transmitting the packet
|
||||
before it is fully DMA mapped (e.g. fragmented skbs).
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Reported-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241004-airoha-eth-7581-mapping-fix-v1-1-8e4279ab1812@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2480,10 +2480,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
- TX_RING_CPU_IDX_MASK,
|
||||
- FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
-
|
||||
data = skb_frag_address(frag);
|
||||
len = skb_frag_size(frag);
|
||||
}
|
||||
@@ -2492,6 +2488,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
q->queued += i;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
+ if (!netdev_xmit_more())
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
+ FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
+
|
||||
if (q->ndesc - q->queued < q->free_thr)
|
||||
netif_tx_stop_queue(txq);
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
From 457e74667f452d7f071ad2b2d9313ec62ebc4b02 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:43 +0200
|
||||
Subject: [PATCH 1/2] clk: en7523: Add en_clk_soc_data data structure
|
||||
|
||||
Introduce en_clk_soc_data data structure in order to define multiple
|
||||
clk_ops for each supported SoC. This is a preliminary patch to
|
||||
introduce EN7581 clock support.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/562a0da8d7874a02a324687c152c87a1549924bd.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 34 +++++++++++++++++++++-------------
|
||||
1 file changed, 21 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
-#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
@@ -48,6 +48,10 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_clk_soc_data {
|
||||
+ const struct clk_ops pcie_ops;
|
||||
+};
|
||||
+
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
static const u32 emi_base[] = { 333000000, 400000000 };
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
@@ -150,11 +154,6 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
-static const struct of_device_id of_match_clk_en7523[] = {
|
||||
- { .compatible = "airoha,en7523-scu", },
|
||||
- { /* sentinel */ }
|
||||
-};
|
||||
-
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -252,14 +251,10 @@ static void en7523_pci_unprepare(struct
|
||||
static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- static const struct clk_ops pcie_gate_ops = {
|
||||
- .is_enabled = en7523_pci_is_enabled,
|
||||
- .prepare = en7523_pci_prepare,
|
||||
- .unprepare = en7523_pci_unprepare,
|
||||
- };
|
||||
+ const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
|
||||
struct clk_init_data init = {
|
||||
.name = "pcie",
|
||||
- .ops = &pcie_gate_ops,
|
||||
+ .ops = &soc_data->pcie_ops,
|
||||
};
|
||||
struct en_clk_gate *cg;
|
||||
|
||||
@@ -269,7 +264,7 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
- en7523_pci_unprepare(&cg->hw);
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -338,6 +333,19 @@ static int en7523_clk_probe(struct platf
|
||||
return r;
|
||||
}
|
||||
|
||||
+static const struct en_clk_soc_data en7523_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7523_pci_is_enabled,
|
||||
+ .prepare = en7523_pci_prepare,
|
||||
+ .unprepare = en7523_pci_unprepare,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id of_match_clk_en7523[] = {
|
||||
+ { .compatible = "airoha,en7523-scu", .data = &en7523_data },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
static struct platform_driver clk_en7523_drv = {
|
||||
.probe = en7523_clk_probe,
|
||||
.driver = {
|
||||
@ -1,248 +0,0 @@
|
||||
From 66bc47326ce2a319add7e933d9340215711236ac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:44 +0200
|
||||
Subject: [PATCH 2/2] clk: en7523: Add EN7581 support
|
||||
|
||||
Introduce EN7581 clock support to clk-en7523 driver.
|
||||
Add hw_init callback to en_clk_soc_data data structure.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/57b6e53ed4d2b2e38abff6a3ea56841bad6be8a9.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 157 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 152 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -10,7 +10,9 @@
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
#define REG_PCI_CONTROL_PERSTOUT1 BIT(26)
|
||||
+#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23)
|
||||
#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22)
|
||||
+#define REG_PCI_CONTROL_PERSTOUT2 BIT(16)
|
||||
#define REG_GSW_CLK_DIV_SEL 0x1b4
|
||||
#define REG_EMI_CLK_DIV_SEL 0x1b8
|
||||
#define REG_BUS_CLK_DIV_SEL 0x1bc
|
||||
@@ -18,10 +20,25 @@
|
||||
#define REG_SPI_CLK_FREQ_SEL 0x1c8
|
||||
#define REG_NPU_CLK_DIV_SEL 0x1fc
|
||||
#define REG_CRYPTO_CLKSRC 0x200
|
||||
-#define REG_RESET_CONTROL 0x834
|
||||
+#define REG_RESET_CONTROL2 0x830
|
||||
+#define REG_RESET2_CONTROL_PCIE2 BIT(27)
|
||||
+#define REG_RESET_CONTROL1 0x834
|
||||
#define REG_RESET_CONTROL_PCIEHB BIT(29)
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
+/* EN7581 */
|
||||
+#define REG_PCIE0_MEM 0x00
|
||||
+#define REG_PCIE0_MEM_MASK 0x04
|
||||
+#define REG_PCIE1_MEM 0x08
|
||||
+#define REG_PCIE1_MEM_MASK 0x0c
|
||||
+#define REG_PCIE2_MEM 0x10
|
||||
+#define REG_PCIE2_MEM_MASK 0x14
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
+#define REG_NP_SCU_PCIC 0x88
|
||||
+#define REG_NP_SCU_SSTR 0x9c
|
||||
+#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
+#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
@@ -50,6 +67,8 @@ struct en_clk_gate {
|
||||
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
+ void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -216,14 +235,14 @@ static int en7523_pci_prepare(struct clk
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/* Reset to default */
|
||||
- val = readl(np_base + REG_RESET_CONTROL);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
REG_RESET_CONTROL_PCIEHB;
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(1000, 2000);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
msleep(100);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
/* Release device */
|
||||
@@ -264,6 +283,9 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
+
|
||||
+ if (init.ops->disable)
|
||||
+ init.ops->disable(&cg->hw);
|
||||
init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
@@ -272,6 +294,111 @@ static struct clk_hw *en7523_register_pc
|
||||
return &cg->hw;
|
||||
}
|
||||
|
||||
+static int en7581_pci_is_enabled(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
|
||||
+ val = readl(cg->base + REG_PCI_CONTROL);
|
||||
+ return (val & mask) == mask;
|
||||
+}
|
||||
+
|
||||
+static int en7581_pci_prepare(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ usleep_range(5000, 10000);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7581_pci_enable(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT;
|
||||
+ val = readl(np_base + REG_PCI_CONTROL);
|
||||
+ writel(val | mask, np_base + REG_PCI_CONTROL);
|
||||
+ msleep(250);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void en7581_pci_unprepare(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static void en7581_pci_disable(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT;
|
||||
+ val = readl(np_base + REG_PCI_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_PCI_CONTROL);
|
||||
+ usleep_range(1000, 2000);
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ void __iomem *base,
|
||||
+ void __iomem *np_base)
|
||||
+{
|
||||
+ void __iomem *pb_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(pb_base))
|
||||
+ return PTR_ERR(pb_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
+ writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
+ writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
+
|
||||
+ val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+ writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
+ base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -304,6 +431,7 @@ static void en7523_register_clocks(struc
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
+ const struct en_clk_soc_data *soc_data;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
void __iomem *base, *np_base;
|
||||
int r;
|
||||
@@ -316,6 +444,13 @@ static int en7523_clk_probe(struct platf
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ if (soc_data->hw_init) {
|
||||
+ r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
@@ -341,8 +476,20 @@ static const struct en_clk_soc_data en75
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct en_clk_soc_data en7581_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7581_pci_is_enabled,
|
||||
+ .prepare = en7581_pci_prepare,
|
||||
+ .enable = en7581_pci_enable,
|
||||
+ .unprepare = en7581_pci_unprepare,
|
||||
+ .disable = en7581_pci_disable,
|
||||
+ },
|
||||
+ .hw_init = en7581_clk_hw_init,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id of_match_clk_en7523[] = {
|
||||
{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
|
||||
+ { .compatible = "airoha,en7581-scu", .data = &en7581_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@ -1,270 +0,0 @@
|
||||
From e0d8ea4ed5fa70fd085a54d0b574a044b9407c39 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:23 +0200
|
||||
Subject: [PATCH 1/4] clk: en7523: Add reset-controller support for EN7581 SoC
|
||||
|
||||
Introduce reset API support to EN7581 clock driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/4f735d17e549ea53769bf5a3f50406debb879a44.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 192 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 187 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
+#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
+
|
||||
+#define RST_NR_PER_BANK 32
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
@@ -40,6 +44,9 @@
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
+#define REG_RST_CTRL2 0x00
|
||||
+#define REG_RST_CTRL1 0x04
|
||||
+
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
const char *name;
|
||||
@@ -65,8 +72,20 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_rst_data {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ void __iomem *base;
|
||||
+ struct reset_controller_dev rcdev;
|
||||
+};
|
||||
+
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ struct {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ u16 idx_map_nr;
|
||||
+ } reset;
|
||||
int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
void __iomem *np_base);
|
||||
};
|
||||
@@ -173,6 +192,69 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const u16 en7581_rst_ofs[] = {
|
||||
+ REG_RST_CTRL2,
|
||||
+ REG_RST_CTRL1,
|
||||
+};
|
||||
+
|
||||
+static const u16 en7581_rst_map[] = {
|
||||
+ /* RST_CTRL2 */
|
||||
+ [EN7581_XPON_PHY_RST] = 0,
|
||||
+ [EN7581_CPU_TIMER2_RST] = 2,
|
||||
+ [EN7581_HSUART_RST] = 3,
|
||||
+ [EN7581_UART4_RST] = 4,
|
||||
+ [EN7581_UART5_RST] = 5,
|
||||
+ [EN7581_I2C2_RST] = 6,
|
||||
+ [EN7581_XSI_MAC_RST] = 7,
|
||||
+ [EN7581_XSI_PHY_RST] = 8,
|
||||
+ [EN7581_NPU_RST] = 9,
|
||||
+ [EN7581_I2S_RST] = 10,
|
||||
+ [EN7581_TRNG_RST] = 11,
|
||||
+ [EN7581_TRNG_MSTART_RST] = 12,
|
||||
+ [EN7581_DUAL_HSI0_RST] = 13,
|
||||
+ [EN7581_DUAL_HSI1_RST] = 14,
|
||||
+ [EN7581_HSI_RST] = 15,
|
||||
+ [EN7581_DUAL_HSI0_MAC_RST] = 16,
|
||||
+ [EN7581_DUAL_HSI1_MAC_RST] = 17,
|
||||
+ [EN7581_HSI_MAC_RST] = 18,
|
||||
+ [EN7581_WDMA_RST] = 19,
|
||||
+ [EN7581_WOE0_RST] = 20,
|
||||
+ [EN7581_WOE1_RST] = 21,
|
||||
+ [EN7581_HSDMA_RST] = 22,
|
||||
+ [EN7581_TDMA_RST] = 24,
|
||||
+ [EN7581_EMMC_RST] = 25,
|
||||
+ [EN7581_SOE_RST] = 26,
|
||||
+ [EN7581_PCIE2_RST] = 27,
|
||||
+ [EN7581_XFP_MAC_RST] = 28,
|
||||
+ [EN7581_USB_HOST_P1_RST] = 29,
|
||||
+ [EN7581_USB_HOST_P1_U3_PHY_RST] = 30,
|
||||
+ /* RST_CTRL1 */
|
||||
+ [EN7581_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
|
||||
+ [EN7581_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
|
||||
+ [EN7581_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
|
||||
+ [EN7581_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
|
||||
+ [EN7581_CRYPTO_RST] = RST_NR_PER_BANK + 6,
|
||||
+ [EN7581_TIMER_RST] = RST_NR_PER_BANK + 8,
|
||||
+ [EN7581_PCM1_RST] = RST_NR_PER_BANK + 11,
|
||||
+ [EN7581_UART_RST] = RST_NR_PER_BANK + 12,
|
||||
+ [EN7581_GPIO_RST] = RST_NR_PER_BANK + 13,
|
||||
+ [EN7581_GDMA_RST] = RST_NR_PER_BANK + 14,
|
||||
+ [EN7581_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
|
||||
+ [EN7581_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
|
||||
+ [EN7581_SFC_RST] = RST_NR_PER_BANK + 18,
|
||||
+ [EN7581_UART2_RST] = RST_NR_PER_BANK + 19,
|
||||
+ [EN7581_GDMP_RST] = RST_NR_PER_BANK + 20,
|
||||
+ [EN7581_FE_RST] = RST_NR_PER_BANK + 21,
|
||||
+ [EN7581_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
|
||||
+ [EN7581_GSW_RST] = RST_NR_PER_BANK + 23,
|
||||
+ [EN7581_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
|
||||
+ [EN7581_PCIE0_RST] = RST_NR_PER_BANK + 26,
|
||||
+ [EN7581_PCIE1_RST] = RST_NR_PER_BANK + 27,
|
||||
+ [EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
|
||||
+ [EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
|
||||
+ [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
+};
|
||||
+
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -375,7 +457,7 @@ static int en7581_clk_hw_init(struct pla
|
||||
void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
if (IS_ERR(pb_base))
|
||||
return PTR_ERR(pb_base);
|
||||
|
||||
@@ -428,6 +510,95 @@ static void en7523_register_clocks(struc
|
||||
clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
}
|
||||
|
||||
+static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id, bool assert)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+ void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(addr);
|
||||
+ if (assert)
|
||||
+ val |= BIT(id % RST_NR_PER_BANK);
|
||||
+ else
|
||||
+ val &= ~BIT(id % RST_NR_PER_BANK);
|
||||
+ writel(val, addr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_assert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, true);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, false);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_status(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+ void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
+
|
||||
+ return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
|
||||
+ const struct of_phandle_args *reset_spec)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+
|
||||
+ if (reset_spec->args[0] >= rcdev->nr_resets)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return rst_data->idx_map[reset_spec->args[0]];
|
||||
+}
|
||||
+
|
||||
+static const struct reset_control_ops en7523_reset_ops = {
|
||||
+ .assert = en7523_reset_assert,
|
||||
+ .deassert = en7523_reset_deassert,
|
||||
+ .status = en7523_reset_status,
|
||||
+};
|
||||
+
|
||||
+static int en7523_reset_register(struct platform_device *pdev,
|
||||
+ const struct en_clk_soc_data *soc_data)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct en_rst_data *rst_data;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ /* no reset lines available */
|
||||
+ if (!soc_data->reset.idx_map_nr)
|
||||
+ return 0;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
|
||||
+ if (!rst_data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rst_data->bank_ofs = soc_data->reset.bank_ofs;
|
||||
+ rst_data->idx_map = soc_data->reset.idx_map;
|
||||
+ rst_data->base = base;
|
||||
+
|
||||
+ rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
|
||||
+ rst_data->rcdev.of_xlate = en7523_reset_xlate;
|
||||
+ rst_data->rcdev.ops = &en7523_reset_ops;
|
||||
+ rst_data->rcdev.of_node = dev->of_node;
|
||||
+ rst_data->rcdev.of_reset_n_cells = 1;
|
||||
+ rst_data->rcdev.owner = THIS_MODULE;
|
||||
+ rst_data->rcdev.dev = dev;
|
||||
+
|
||||
+ return devm_reset_controller_register(dev, &rst_data->rcdev);
|
||||
+}
|
||||
+
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -461,11 +632,17 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
- dev_err(&pdev->dev,
|
||||
- "could not register clock provider: %s: %d\n",
|
||||
- pdev->name, r);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
|
||||
+ pdev->name);
|
||||
+
|
||||
+ r = en7523_reset_register(pdev, soc_data);
|
||||
+ if (r) {
|
||||
+ of_clk_del_provider(node);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
|
||||
+ pdev->name);
|
||||
+ }
|
||||
|
||||
- return r;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
@@ -484,6 +661,11 @@ static const struct en_clk_soc_data en75
|
||||
.unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
+ .reset = {
|
||||
+ .bank_ofs = en7581_rst_ofs,
|
||||
+ .idx_map = en7581_rst_map,
|
||||
+ .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
|
||||
+ },
|
||||
.hw_init = en7581_clk_hw_init,
|
||||
};
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
From db7a4a11e8be375b0a9c159f688e0cea49eacc5d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:24 +0200
|
||||
Subject: [PATCH 2/4] clk: en7523: Remove pcie prepare/unpreare callbacks for
|
||||
EN7581 SoC
|
||||
|
||||
Get rid of prepare and unpreare callbacks for PCIe clock since they can
|
||||
be modeled as a reset line cosumed by the PCIe driver
|
||||
(pcie-mediatek-gen3)
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/16df149975514d3030499c48fc1c64f090093595.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 41 ++--------------------------------------
|
||||
1 file changed, 2 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -366,9 +366,8 @@ static struct clk_hw *en7523_register_pc
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
|
||||
- if (init.ops->disable)
|
||||
- init.ops->disable(&cg->hw);
|
||||
- init.ops->unprepare(&cg->hw);
|
||||
+ if (init.ops->unprepare)
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -386,23 +385,6 @@ static int en7581_pci_is_enabled(struct
|
||||
return (val & mask) == mask;
|
||||
}
|
||||
|
||||
-static int en7581_pci_prepare(struct clk_hw *hw)
|
||||
-{
|
||||
- struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
- void __iomem *np_base = cg->base;
|
||||
- u32 val, mask;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- usleep_range(5000, 10000);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int en7581_pci_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -419,23 +401,6 @@ static int en7581_pci_enable(struct clk_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void en7581_pci_unprepare(struct clk_hw *hw)
|
||||
-{
|
||||
- struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
- void __iomem *np_base = cg->base;
|
||||
- u32 val, mask;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- msleep(100);
|
||||
-}
|
||||
-
|
||||
static void en7581_pci_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -656,9 +621,7 @@ static const struct en_clk_soc_data en75
|
||||
static const struct en_clk_soc_data en7581_data = {
|
||||
.pcie_ops = {
|
||||
.is_enabled = en7581_pci_is_enabled,
|
||||
- .prepare = en7581_pci_prepare,
|
||||
.enable = en7581_pci_enable,
|
||||
- .unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
.reset = {
|
||||
@ -1,65 +0,0 @@
|
||||
From bf288bd25d6232310abb81db417376ce460eb032 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:25 +0200
|
||||
Subject: [PATCH 3/4] clk: en7523: Remove PCIe reset open drain configuration
|
||||
for EN7581
|
||||
|
||||
PCIe reset open drain configuration will be managed by pinctrl driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/43276af5f08a554b4ab2e52e8d437fff5c06a732.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,8 +37,6 @@
|
||||
#define REG_PCIE1_MEM_MASK 0x0c
|
||||
#define REG_PCIE2_MEM 0x10
|
||||
#define REG_PCIE2_MEM_MASK 0x14
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -86,8 +84,7 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
- void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -416,7 +413,6 @@ static void en7581_pci_disable(struct cl
|
||||
}
|
||||
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *base,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
void __iomem *pb_base;
|
||||
@@ -439,10 +435,6 @@ static int en7581_clk_hw_init(struct pla
|
||||
writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
|
||||
- val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
- writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
- base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -582,7 +574,7 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
soc_data = device_get_match_data(&pdev->dev);
|
||||
if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ r = soc_data->hw_init(pdev, np_base);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
From 7aa291962f4c3b7afb9a12fa60b406b95e5eacb4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:22 +0200
|
||||
Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7581 clock
|
||||
binding
|
||||
|
||||
Introduce reset capability to EN7581 device-tree clock binding
|
||||
documentation. Add reset register mapping between misc scu and pb scu
|
||||
ones in order to follow the memory order. This change is not
|
||||
introducing any backward compatibility issue since the EN7581 dts is not
|
||||
upstream yet.
|
||||
|
||||
Fixes: 0a382be005cf ("dt-bindings: clock: airoha: add EN7581 binding")
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/28fef3e83062d5d71e7b4be4b47583f851a15bf8.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
.../bindings/clock/airoha,en7523-scu.yaml | 25 ++++++-
|
||||
.../dt-bindings/reset/airoha,en7581-reset.h | 66 +++++++++++++++++++
|
||||
2 files changed, 90 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
@@ -0,0 +1,66 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2024 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+
|
||||
+/* RST_CTRL2 */
|
||||
+#define EN7581_XPON_PHY_RST 0
|
||||
+#define EN7581_CPU_TIMER2_RST 1
|
||||
+#define EN7581_HSUART_RST 2
|
||||
+#define EN7581_UART4_RST 3
|
||||
+#define EN7581_UART5_RST 4
|
||||
+#define EN7581_I2C2_RST 5
|
||||
+#define EN7581_XSI_MAC_RST 6
|
||||
+#define EN7581_XSI_PHY_RST 7
|
||||
+#define EN7581_NPU_RST 8
|
||||
+#define EN7581_I2S_RST 9
|
||||
+#define EN7581_TRNG_RST 10
|
||||
+#define EN7581_TRNG_MSTART_RST 11
|
||||
+#define EN7581_DUAL_HSI0_RST 12
|
||||
+#define EN7581_DUAL_HSI1_RST 13
|
||||
+#define EN7581_HSI_RST 14
|
||||
+#define EN7581_DUAL_HSI0_MAC_RST 15
|
||||
+#define EN7581_DUAL_HSI1_MAC_RST 16
|
||||
+#define EN7581_HSI_MAC_RST 17
|
||||
+#define EN7581_WDMA_RST 18
|
||||
+#define EN7581_WOE0_RST 19
|
||||
+#define EN7581_WOE1_RST 20
|
||||
+#define EN7581_HSDMA_RST 21
|
||||
+#define EN7581_TDMA_RST 22
|
||||
+#define EN7581_EMMC_RST 23
|
||||
+#define EN7581_SOE_RST 24
|
||||
+#define EN7581_PCIE2_RST 25
|
||||
+#define EN7581_XFP_MAC_RST 26
|
||||
+#define EN7581_USB_HOST_P1_RST 27
|
||||
+#define EN7581_USB_HOST_P1_U3_PHY_RST 28
|
||||
+/* RST_CTRL1 */
|
||||
+#define EN7581_PCM1_ZSI_ISI_RST 29
|
||||
+#define EN7581_FE_PDMA_RST 30
|
||||
+#define EN7581_FE_QDMA_RST 31
|
||||
+#define EN7581_PCM_SPIWP_RST 32
|
||||
+#define EN7581_CRYPTO_RST 33
|
||||
+#define EN7581_TIMER_RST 34
|
||||
+#define EN7581_PCM1_RST 35
|
||||
+#define EN7581_UART_RST 36
|
||||
+#define EN7581_GPIO_RST 37
|
||||
+#define EN7581_GDMA_RST 38
|
||||
+#define EN7581_I2C_MASTER_RST 39
|
||||
+#define EN7581_PCM2_ZSI_ISI_RST 40
|
||||
+#define EN7581_SFC_RST 41
|
||||
+#define EN7581_UART2_RST 42
|
||||
+#define EN7581_GDMP_RST 43
|
||||
+#define EN7581_FE_RST 44
|
||||
+#define EN7581_USB_HOST_P0_RST 45
|
||||
+#define EN7581_GSW_RST 46
|
||||
+#define EN7581_SFC2_PCM_RST 47
|
||||
+#define EN7581_PCIE0_RST 48
|
||||
+#define EN7581_PCIE1_RST 49
|
||||
+#define EN7581_CPU_TIMER_RST 50
|
||||
+#define EN7581_PCIE_HB_RST 51
|
||||
+#define EN7581_XPON_MAC_RST 52
|
||||
+
|
||||
+#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_ */
|
||||
@ -1,100 +0,0 @@
|
||||
From dc869a40d73ee6e9f47d683690ae507e30e56044 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:42 +0200
|
||||
Subject: [PATCH 1/3] PCI: mediatek-gen3: Add mtk_gen3_pcie_pdata data
|
||||
structure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce mtk_gen3_pcie_pdata data structure in order to define
|
||||
multiple callbacks for each supported SoC.
|
||||
|
||||
This is a preliminary patch to introduce EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/c193d1a87505d045e2e0ef33317bce17012ee095.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 24 ++++++++++++++++++---
|
||||
1 file changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,6 +100,16 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+struct mtk_gen3_pcie;
|
||||
+
|
||||
+/**
|
||||
+ * struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
+ * @power_up: pcie power_up callback
|
||||
+ */
|
||||
+struct mtk_gen3_pcie_pdata {
|
||||
+ int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct mtk_msi_set - MSI information for each set
|
||||
* @base: IO mapped register base
|
||||
@@ -131,6 +141,7 @@ struct mtk_msi_set {
|
||||
* @msi_sets: MSI sets information
|
||||
* @lock: lock protecting IRQ bit map
|
||||
* @msi_irq_in_use: bit map for assigned MSI IRQ
|
||||
+ * @soc: pointer to SoC-dependent operations
|
||||
*/
|
||||
struct mtk_gen3_pcie {
|
||||
struct device *dev;
|
||||
@@ -151,6 +162,8 @@ struct mtk_gen3_pcie {
|
||||
struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM];
|
||||
struct mutex lock;
|
||||
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
|
||||
+
|
||||
+ const struct mtk_gen3_pcie_pdata *soc;
|
||||
};
|
||||
|
||||
/* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
|
||||
@@ -904,7 +917,7 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
usleep_range(10, 20);
|
||||
|
||||
/* Don't touch the hardware registers before power up */
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -939,6 +952,7 @@ static int mtk_pcie_probe(struct platfor
|
||||
pcie = pci_host_bridge_priv(host);
|
||||
|
||||
pcie->dev = dev;
|
||||
+ pcie->soc = device_get_match_data(dev);
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
err = mtk_pcie_setup(pcie);
|
||||
@@ -1054,7 +1068,7 @@ static int mtk_pcie_resume_noirq(struct
|
||||
struct mtk_gen3_pcie *pcie = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1074,8 +1088,12 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
mtk_pcie_resume_noirq)
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
+ .power_up = mtk_pcie_power_up,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
- { .compatible = "mediatek,mt8192-pcie" },
|
||||
+ { .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_pcie_of_match);
|
||||
@ -1,155 +0,0 @@
|
||||
From ee9eabbe3f0f0c7458d89840add97e54d4e0bccf Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:43 +0200
|
||||
Subject: [PATCH 2/3] PCI: mediatek-gen3: Rely on reset_bulk APIs for PHY reset
|
||||
lines
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Use reset_bulk APIs to manage PHY reset lines.
|
||||
|
||||
This is a preliminary patch in order to add Airoha EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/3ceb83bc0defbcf868521f8df4b9100e55ec2614.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 45 +++++++++++++++------
|
||||
1 file changed, 33 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,14 +100,21 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+#define MAX_NUM_PHY_RESETS 1
|
||||
+
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
/**
|
||||
* struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
* @power_up: pcie power_up callback
|
||||
+ * @phy_resets: phy reset lines SoC data.
|
||||
*/
|
||||
struct mtk_gen3_pcie_pdata {
|
||||
int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+ struct {
|
||||
+ const char *id[MAX_NUM_PHY_RESETS];
|
||||
+ int num_resets;
|
||||
+ } phy_resets;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -128,7 +135,7 @@ struct mtk_msi_set {
|
||||
* @base: IO mapped register base
|
||||
* @reg_base: physical register base
|
||||
* @mac_reset: MAC reset control
|
||||
- * @phy_reset: PHY reset control
|
||||
+ * @phy_resets: PHY reset controllers
|
||||
* @phy: PHY controller block
|
||||
* @clks: PCIe clocks
|
||||
* @num_clks: PCIe clocks count for this port
|
||||
@@ -148,7 +155,7 @@ struct mtk_gen3_pcie {
|
||||
void __iomem *base;
|
||||
phys_addr_t reg_base;
|
||||
struct reset_control *mac_reset;
|
||||
- struct reset_control *phy_reset;
|
||||
+ struct reset_control_bulk_data phy_resets[MAX_NUM_PHY_RESETS];
|
||||
struct phy *phy;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
@@ -788,10 +795,10 @@ static int mtk_pcie_setup_irq(struct mtk
|
||||
|
||||
static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
+ int i, ret, num_resets = pcie->soc->phy_resets.num_resets;
|
||||
struct device *dev = pcie->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *regs;
|
||||
- int ret;
|
||||
|
||||
regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-mac");
|
||||
if (!regs)
|
||||
@@ -804,12 +811,12 @@ static int mtk_pcie_parse_port(struct mt
|
||||
|
||||
pcie->reg_base = regs->start;
|
||||
|
||||
- pcie->phy_reset = devm_reset_control_get_optional_exclusive(dev, "phy");
|
||||
- if (IS_ERR(pcie->phy_reset)) {
|
||||
- ret = PTR_ERR(pcie->phy_reset);
|
||||
- if (ret != -EPROBE_DEFER)
|
||||
- dev_err(dev, "failed to get PHY reset\n");
|
||||
+ for (i = 0; i < num_resets; i++)
|
||||
+ pcie->phy_resets[i].id = pcie->soc->phy_resets.id[i];
|
||||
|
||||
+ ret = devm_reset_control_bulk_get_optional_shared(dev, num_resets, pcie->phy_resets);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to get PHY bulk reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -846,7 +853,11 @@ static int mtk_pcie_power_up(struct mtk_
|
||||
int err;
|
||||
|
||||
/* PHY power on and enable pipe clock */
|
||||
- reset_control_deassert(pcie->phy_reset);
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
if (err) {
|
||||
@@ -882,7 +893,7 @@ err_clk_init:
|
||||
err_phy_on:
|
||||
phy_exit(pcie->phy);
|
||||
err_phy_init:
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -897,7 +908,7 @@ static void mtk_pcie_power_down(struct m
|
||||
|
||||
phy_power_off(pcie->phy);
|
||||
phy_exit(pcie->phy);
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
}
|
||||
|
||||
static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
|
||||
@@ -909,10 +920,16 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
return err;
|
||||
|
||||
/*
|
||||
+ * Deassert the line in order to avoid unbalance in deassert_count
|
||||
+ * counter since the bulk is shared.
|
||||
+ */
|
||||
+ reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ /*
|
||||
* The controller may have been left out of reset by the bootloader
|
||||
* so make sure that we get a clean start by asserting resets here.
|
||||
*/
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+
|
||||
reset_control_assert(pcie->mac_reset);
|
||||
usleep_range(10, 20);
|
||||
|
||||
@@ -1090,6 +1107,10 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
|
||||
static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
.power_up = mtk_pcie_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy",
|
||||
+ .num_resets = 1,
|
||||
+ },
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
@ -1,199 +0,0 @@
|
||||
From f6ab898356dd70f267c49045a79d28ea5cf5e43e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:44 +0200
|
||||
Subject: [PATCH 3/3] PCI: mediatek-gen3: Add Airoha EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for Airoha EN7581 PCIe controller to mediatek-gen3
|
||||
PCIe controller driver.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/aca00bd672ee576ad96d279414fc0835ff31f637.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/Kconfig | 2 +-
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 113 +++++++++++++++++++-
|
||||
2 files changed, 113 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/Kconfig
|
||||
+++ b/drivers/pci/controller/Kconfig
|
||||
@@ -196,7 +196,7 @@ config PCIE_MEDIATEK
|
||||
|
||||
config PCIE_MEDIATEK_GEN3
|
||||
tristate "MediaTek Gen3 PCIe controller"
|
||||
- depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
+ depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on PCI_MSI
|
||||
help
|
||||
Adds support for PCIe Gen3 MAC controller for MediaTek SoCs.
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -6,7 +6,9 @@
|
||||
* Author: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
*/
|
||||
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -15,6 +17,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -29,6 +33,12 @@
|
||||
#define PCI_CLASS(class) (class << 8)
|
||||
#define PCIE_RC_MODE BIT(0)
|
||||
|
||||
+#define PCIE_EQ_PRESET_01_REG 0x100
|
||||
+#define PCIE_VAL_LN0_DOWNSTREAM GENMASK(6, 0)
|
||||
+#define PCIE_VAL_LN0_UPSTREAM GENMASK(14, 8)
|
||||
+#define PCIE_VAL_LN1_DOWNSTREAM GENMASK(22, 16)
|
||||
+#define PCIE_VAL_LN1_UPSTREAM GENMASK(30, 24)
|
||||
+
|
||||
#define PCIE_CFGNUM_REG 0x140
|
||||
#define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0))
|
||||
#define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8))
|
||||
@@ -68,6 +78,14 @@
|
||||
#define PCIE_MSI_SET_ENABLE_REG 0x190
|
||||
#define PCIE_MSI_SET_ENABLE GENMASK(PCIE_MSI_SET_NUM - 1, 0)
|
||||
|
||||
+#define PCIE_PIPE4_PIE8_REG 0x338
|
||||
+#define PCIE_K_FINETUNE_MAX GENMASK(5, 0)
|
||||
+#define PCIE_K_FINETUNE_ERR GENMASK(7, 6)
|
||||
+#define PCIE_K_PRESET_TO_USE GENMASK(18, 8)
|
||||
+#define PCIE_K_PHYPARAM_QUERY BIT(19)
|
||||
+#define PCIE_K_QUERY_TIMEOUT BIT(20)
|
||||
+#define PCIE_K_PRESET_TO_USE_16G GENMASK(31, 21)
|
||||
+
|
||||
#define PCIE_MSI_SET_BASE_REG 0xc00
|
||||
#define PCIE_MSI_SET_OFFSET 0x10
|
||||
#define PCIE_MSI_SET_STATUS_OFFSET 0x04
|
||||
@@ -100,7 +118,10 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
-#define MAX_NUM_PHY_RESETS 1
|
||||
+#define MAX_NUM_PHY_RESETS 3
|
||||
+
|
||||
+/* Time in ms needed to complete PCIe reset on EN7581 SoC */
|
||||
+#define PCIE_EN7581_RESET_TIME_MS 100
|
||||
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
@@ -847,6 +868,85 @@ static int mtk_pcie_parse_port(struct mt
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
|
||||
+{
|
||||
+ struct device *dev = pcie->dev;
|
||||
+ int err;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk assert in
|
||||
+ * mtk_pcie_setup for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ err = phy_init(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to initialize PHY\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = phy_power_on(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to power on PHY\n");
|
||||
+ goto err_phy_on;
|
||||
+ }
|
||||
+
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ goto err_phy_deassert;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk de-assert above.
|
||||
+ * This time is specific for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ pm_runtime_enable(dev);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
+
|
||||
+ err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_prepare;
|
||||
+ }
|
||||
+
|
||||
+ val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG);
|
||||
+
|
||||
+ val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
|
||||
+ FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
|
||||
+
|
||||
+ err = clk_bulk_enable(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_enable;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_clk_enable:
|
||||
+ clk_bulk_unprepare(pcie->num_clks, pcie->clks);
|
||||
+err_clk_prepare:
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ pm_runtime_disable(dev);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+err_phy_deassert:
|
||||
+ phy_power_off(pcie->phy);
|
||||
+err_phy_on:
|
||||
+ phy_exit(pcie->phy);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
struct device *dev = pcie->dev;
|
||||
@@ -1113,7 +1213,18 @@ static const struct mtk_gen3_pcie_pdata
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
|
||||
+ .power_up = mtk_pcie_en7581_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy-lane0",
|
||||
+ .id[1] = "phy-lane1",
|
||||
+ .id[2] = "phy-lane2",
|
||||
+ .num_resets = 3,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-pcie", .data = &mtk_pcie_soc_en7581 },
|
||||
{ .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,112 +0,0 @@
|
||||
From 2a011c3c12e8de461fb1fdce85fa38d308c4eb8b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 29 Jun 2024 19:51:49 +0200
|
||||
Subject: [PATCH] phy: airoha: Add dtime and Rx AEQ IO registers
|
||||
|
||||
Introduce Tx-Rx detection Time and Rx AEQ training mappings to
|
||||
phy-airoha-pcie driver. This is a preliminary patch to introduce PCIe
|
||||
support to En7581 SoC through the mediatek-gen3 PCIe driver.
|
||||
This change is not introducing any backward compatibility issue since
|
||||
the EN7581 dts is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://lore.kernel.org/r/edf3b28926177166c65256604d69f2f576cb6fb3.1719682943.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 17 +++++++++++++
|
||||
drivers/phy/phy-airoha-pcie.c | 38 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 55 insertions(+)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -474,4 +474,21 @@
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914
|
||||
|
||||
+/* DTIME */
|
||||
+#define REG_PCIE_PEXTP_DIG_GLB44 0x00
|
||||
+#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0)
|
||||
+#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8)
|
||||
+#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16)
|
||||
+#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24)
|
||||
+#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28)
|
||||
+#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29)
|
||||
+
|
||||
+/* RX AEQ */
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16)
|
||||
+
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100
|
||||
+
|
||||
#endif /* _PHY_AIROHA_PCIE_H */
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -31,6 +31,9 @@ enum airoha_pcie_port_gen {
|
||||
* @csr_2l: Analogic lane IO mapped register base address
|
||||
* @pma0: IO mapped register base address of PMA0-PCIe
|
||||
* @pma1: IO mapped register base address of PMA1-PCIe
|
||||
+ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
|
||||
+ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
|
||||
+ * @rx_aeq: IO mapped register base address of Rx AEQ training
|
||||
*/
|
||||
struct airoha_pcie_phy {
|
||||
struct device *dev;
|
||||
@@ -38,6 +41,9 @@ struct airoha_pcie_phy {
|
||||
void __iomem *csr_2l;
|
||||
void __iomem *pma0;
|
||||
void __iomem *pma1;
|
||||
+ void __iomem *p0_xr_dtime;
|
||||
+ void __iomem *p1_xr_dtime;
|
||||
+ void __iomem *rx_aeq;
|
||||
};
|
||||
|
||||
static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
|
||||
@@ -1101,6 +1107,21 @@ static void airoha_pcie_phy_load_kflow(s
|
||||
static int airoha_pcie_phy_init(struct phy *phy)
|
||||
{
|
||||
struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* Setup Tx-Rx detection time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
|
||||
+ FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
|
||||
+ writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ /* Setup Rx AEQ training time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
|
||||
+ FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
|
||||
|
||||
/* enable load FLL-K flow */
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
|
||||
@@ -1217,6 +1238,23 @@ static int airoha_pcie_phy_probe(struct
|
||||
return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
|
||||
"Failed to create PCIe phy\n");
|
||||
|
||||
+ pcie_phy->p0_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p0_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
|
||||
+ "Failed to map P0 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->p1_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p1_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
|
||||
+ "Failed to map P1 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
|
||||
+ if (IS_ERR(pcie_phy->rx_aeq))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
|
||||
+ "Failed to map Rx AEQ base\n");
|
||||
+
|
||||
pcie_phy->dev = dev;
|
||||
phy_set_drvdata(pcie_phy->phy, pcie_phy);
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
From 7f7315db3d262298ab33d198d3f0b09cabfa7b6b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 6 Aug 2024 17:55:48 +0200
|
||||
Subject: [PATCH] phy: airoha: adjust initialization delay in
|
||||
airoha_pcie_phy_init()
|
||||
|
||||
Align phy-pcie initialization delay to the vendor sdk in
|
||||
airoha_pcie_phy_init routine and allow the hw to complete required
|
||||
configuration before proceeding
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/8af6f27857619f1e0dd227f08b8584ae8fb22fb2.1722959625.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -18,6 +18,9 @@
|
||||
#define LEQ_LEN_CTRL_MAX_VAL 7
|
||||
#define FREQ_LOCK_MAX_ATTEMPT 10
|
||||
|
||||
+/* PCIe-PHY initialization time in ms needed by the hw to complete */
|
||||
+#define PHY_HW_INIT_TIME_MS 30
|
||||
+
|
||||
enum airoha_pcie_port_gen {
|
||||
PCIE_PORT_GEN1 = 1,
|
||||
PCIE_PORT_GEN2,
|
||||
@@ -1181,7 +1184,8 @@ static int airoha_pcie_phy_init(struct p
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
|
||||
PCIE_DA_XPON_CDR_PR_PWDB);
|
||||
|
||||
- usleep_range(100, 200);
|
||||
+ /* Wait for the PCIe PHY to complete initialization before returning */
|
||||
+ msleep(PHY_HW_INIT_TIME_MS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
From ca9afde0563a80200eab856a53d7eab28c8fdd90 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:52 +0200
|
||||
Subject: [PATCH 1/4] phy: airoha: Fix REG_CSR_2L_PLL_CMN_RESERVE0 config in
|
||||
airoha_pcie_phy_init_clk_out()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_PLL_CMN_RESERVE0 register in
|
||||
airoha_pcie_phy_init_clk_out routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
|
||||
CSR_2L_PXP_CLKTX1_SR);
|
||||
airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
|
||||
- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd);
|
||||
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
|
||||
@ -1,29 +0,0 @@
|
||||
From 2c2313c84ad7c0e5e39fbd98559d40f6b9ec1f83 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:53 +0200
|
||||
Subject: [PATCH 2/4] phy: airoha: Fix REG_PCIE_PMA_TX_RESET config in
|
||||
airoha_pcie_phy_init_csr_2l()
|
||||
|
||||
Fix typos configuring REG_PCIE_PMA_TX_RESET register in
|
||||
airoha_pcie_phy_init_csr_2l routine for lane0 and lane1
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(
|
||||
PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
|
||||
PCIE_SW_RX_RST);
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
|
||||
@ -1,26 +0,0 @@
|
||||
From 6e0c349a8a59959c3d3571b5f6776bc2d2ca62bc Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:54 +0200
|
||||
Subject: [PATCH 3/4] phy: airoha: Fix REG_CSR_2L_JCPLL_SDM_HREN config in
|
||||
airoha_pcie_phy_init_ssc_jcpll()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_JCPLL_SDM_HREN register in
|
||||
airoha_pcie_phy_init_ssc_jcpll routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcp
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
|
||||
CSR_2L_PXP_JCPLL_SDM_IFM);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
|
||||
- REG_CSR_2L_JCPLL_SDM_HREN);
|
||||
+ CSR_2L_PXP_JCPLL_SDM_HREN);
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
|
||||
CSR_2L_PXP_JCPLL_SDM_DI_EN);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
|
||||
@ -1,32 +0,0 @@
|
||||
From bc1bb265f504ea19ce611a1aec1a40dec409cd15 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:55 +0200
|
||||
Subject: [PATCH 4/4] phy: airoha: Fix REG_CSR_2L_RX{0,1}_REV0 definitions
|
||||
|
||||
Fix the following register definitions for REG_CSR_2L_RX{0,1}_REV0
|
||||
registers:
|
||||
- CSR_2L_PXP_VOS_PNINV
|
||||
- CSR_2L_PXP_FE_GAIN_NORMAL_MODE
|
||||
- CSR_2L_PXP_FE_GAIN_TRAIN_MODE
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -197,9 +197,9 @@
|
||||
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
|
||||
|
||||
#define REG_CSR_2L_RX0_REV0 0x00fc
|
||||
-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
|
||||
-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
|
||||
-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
|
||||
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
|
||||
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
|
||||
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
|
||||
|
||||
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
|
||||
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,55 +0,0 @@
|
||||
From 2e6bbfe7b0c0607001b784082c2685b134174fac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:13 +0200
|
||||
Subject: [PATCH 1/2] spi: airoha: fix dirmap_{read,write} operations
|
||||
|
||||
SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end of
|
||||
dirmap_read operation even if it is already set.
|
||||
In the same way, SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the
|
||||
end of dirmap_write operation even if it is already set.
|
||||
For this reason use regmap_write_bits() instead of regmap_set_bits().
|
||||
This patch fixes mtd_pagetest kernel module test.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-1-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -739,8 +739,13 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_read operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -870,8 +875,13 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_write operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From 0e58637eb968c636725dcd6c7055249b4e5326fb Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:14 +0200
|
||||
Subject: [PATCH 2/2] spi: airoha: fix airoha_snand_{write,read}_data data_len
|
||||
estimation
|
||||
|
||||
Fix data length written and read in airoha_snand_write_data and
|
||||
airoha_snand_read_data routines respectively if it is bigger than
|
||||
SPI_MAX_TRANSFER_SIZE.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-2-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -405,7 +405,7 @@ static int airoha_snand_write_data(struc
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -427,7 +427,7 @@ static int airoha_snand_read_data(struct
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1,116 +0,0 @@
|
||||
From fffca269e4f31c3633c6d810833ba1b184407915 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 19 Sep 2024 18:57:16 +0200
|
||||
Subject: [PATCH] spi: airoha: remove read cache in airoha_snand_dirmap_read()
|
||||
|
||||
Current upstream driver reports errors running mtd_oobtest kernel module
|
||||
test:
|
||||
|
||||
root@OpenWrt:/# insmod mtd_test.ko
|
||||
root@OpenWrt:/# insmod mtd_oobtest.ko dev=5
|
||||
[ 7023.730584] =================================================
|
||||
[ 7023.736399] mtd_oobtest: MTD device: 5
|
||||
[ 7023.740160] mtd_oobtest: MTD device size 3670016, eraseblock size 131072, page size 2048, count of eraseblocks 28, pages per eraseblock 64, OOB size 128
|
||||
[ 7023.753837] mtd_test: scanning for bad eraseblocks
|
||||
[ 7023.758636] mtd_test: scanned 28 eraseblocks, 0 are bad
|
||||
[ 7023.763861] mtd_oobtest: test 1 of 5
|
||||
[ 7024.042076] mtd_oobtest: writing OOBs of whole device
|
||||
[ 7024.682069] mtd_oobtest: written up to eraseblock 0
|
||||
[ 7041.962077] mtd_oobtest: written 28 eraseblocks
|
||||
[ 7041.966626] mtd_oobtest: verifying all eraseblocks
|
||||
[ 7041.972276] mtd_oobtest: error @addr[0x0:0x0] 0xff -> 0xe diff 0xf1
|
||||
[ 7041.978550] mtd_oobtest: error @addr[0x0:0x1] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.984932] mtd_oobtest: error @addr[0x0:0x2] 0xff -> 0x82 diff 0x7d
|
||||
[ 7041.991293] mtd_oobtest: error @addr[0x0:0x3] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.997659] mtd_oobtest: error @addr[0x0:0x4] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.003942] mtd_oobtest: error @addr[0x0:0x5] 0xff -> 0x8a diff 0x75
|
||||
[ 7042.010294] mtd_oobtest: error @addr[0x0:0x6] 0xff -> 0x20 diff 0xdf
|
||||
[ 7042.016659] mtd_oobtest: error @addr[0x0:0x7] 0xff -> 0x1 diff 0xfe
|
||||
[ 7042.022935] mtd_oobtest: error @addr[0x0:0x8] 0xff -> 0x2e diff 0xd1
|
||||
[ 7042.029295] mtd_oobtest: error @addr[0x0:0x9] 0xff -> 0x40 diff 0xbf
|
||||
[ 7042.035661] mtd_oobtest: error @addr[0x0:0xa] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.041935] mtd_oobtest: error @addr[0x0:0xb] 0xff -> 0x89 diff 0x76
|
||||
[ 7042.048300] mtd_oobtest: error @addr[0x0:0xc] 0xff -> 0x82 diff 0x7d
|
||||
[ 7042.054662] mtd_oobtest: error @addr[0x0:0xd] 0xff -> 0x15 diff 0xea
|
||||
[ 7042.061014] mtd_oobtest: error @addr[0x0:0xe] 0xff -> 0x90 diff 0x6f
|
||||
[ 7042.067380] mtd_oobtest: error @addr[0x0:0xf] 0xff -> 0x0 diff 0xff
|
||||
....
|
||||
[ 7432.421369] mtd_oobtest: error @addr[0x237800:0x36] 0xff -> 0x5f diff 0xa0
|
||||
[ 7432.428242] mtd_oobtest: error @addr[0x237800:0x37] 0xff -> 0x21 diff 0xde
|
||||
[ 7432.435118] mtd_oobtest: error: verify failed at 0x237800
|
||||
[ 7432.440510] mtd_oobtest: error: too many errors
|
||||
[ 7432.445053] mtd_oobtest: error -1 occurred
|
||||
|
||||
The above errors are due to the buggy logic in the 'read cache' available
|
||||
in airoha_snand_dirmap_read() routine since there are some corner cases
|
||||
where we are missing data updates. Since we do not get any read/write speed
|
||||
improvement using the cache (according to the mtd_speedtest kernel
|
||||
module test), in order to fix the mtd_oobtest test, remove the 'read cache'
|
||||
in airoha_snand_dirmap_read routine. Now the driver is passing all the
|
||||
tests available in mtd_test suite.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240919-airoha-spi-fixes-v2-1-cb0f0ed9920a@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 21 ---------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -211,9 +211,6 @@ struct airoha_snand_dev {
|
||||
|
||||
u8 *txrx_buf;
|
||||
dma_addr_t dma_addr;
|
||||
-
|
||||
- u64 cur_page_num;
|
||||
- bool data_need_update;
|
||||
};
|
||||
|
||||
struct airoha_snand_ctrl {
|
||||
@@ -644,11 +641,6 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
- if (!as_dev->data_need_update)
|
||||
- return len;
|
||||
-
|
||||
- as_dev->data_need_update = false;
|
||||
-
|
||||
switch (op->cmd.opcode) {
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
|
||||
rd_mode = 1;
|
||||
@@ -895,23 +887,11 @@ static ssize_t airoha_snand_dirmap_write
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(mem->spi);
|
||||
u8 data[8], cmd, opcode = op->cmd.opcode;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
int i, err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
|
||||
- if (opcode == SPI_NAND_OP_PROGRAM_EXECUTE &&
|
||||
- op->addr.val == as_dev->cur_page_num) {
|
||||
- as_dev->data_need_update = true;
|
||||
- } else if (opcode == SPI_NAND_OP_PAGE_READ) {
|
||||
- if (!as_dev->data_need_update &&
|
||||
- op->addr.val == as_dev->cur_page_num)
|
||||
- return 0;
|
||||
-
|
||||
- as_dev->data_need_update = true;
|
||||
- as_dev->cur_page_num = op->addr.val;
|
||||
- }
|
||||
|
||||
/* switch to manual mode */
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
@@ -996,7 +976,6 @@ static int airoha_snand_setup(struct spi
|
||||
if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
return -ENOMEM;
|
||||
|
||||
- as_dev->data_need_update = true;
|
||||
spi_set_ctldata(spi, as_dev);
|
||||
|
||||
return 0;
|
||||
@ -1,184 +0,0 @@
|
||||
From 2b0229f67932e4b9e2f458bf286903582bd30740 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 09:35:12 +0200
|
||||
Subject: [PATCH] net: dsa: mt7530: Add EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for the DSA built-in switch available on the EN7581
|
||||
development board. EN7581 support is similar to MT7988 one except
|
||||
it requires to set MT7530_FORCE_MODE bit in MT753X_PMCR_P register
|
||||
for on cpu port.
|
||||
|
||||
Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mt7530-mmio.c | 1 +
|
||||
drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++-----
|
||||
drivers/net/dsa/mt7530.h | 20 ++++++++++----
|
||||
3 files changed, 59 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/mt7530-mmio.c
|
||||
+++ b/drivers/net/dsa/mt7530-mmio.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mt7530.h"
|
||||
|
||||
static const struct of_device_id mt7988_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], },
|
||||
{ .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
--- a/drivers/net/dsa/mt7530.c
|
||||
+++ b/drivers/net/dsa/mt7530.c
|
||||
@@ -1152,7 +1152,8 @@ mt753x_cpu_port_enable(struct dsa_switch
|
||||
* the MT7988 SoC. Trapped frames will be forwarded to the CPU port that
|
||||
* is affine to the inbound user port.
|
||||
*/
|
||||
- if (priv->id == ID_MT7531 || priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7531 || priv->id == ID_MT7988 ||
|
||||
+ priv->id == ID_EN7581)
|
||||
mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
|
||||
|
||||
/* CPU port gets connected to all user ports of
|
||||
@@ -2207,7 +2208,7 @@ mt7530_setup_irq(struct mt7530_priv *pri
|
||||
return priv->irq ? : -EINVAL;
|
||||
}
|
||||
|
||||
- if (priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7988 || priv->id == ID_EN7581)
|
||||
priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
|
||||
&mt7988_irq_domain_ops,
|
||||
priv);
|
||||
@@ -2438,8 +2439,10 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7530_FORCE_MODE, MT7530_FORCE_MODE);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2553,8 +2556,10 @@ mt7531_setup_common(struct dsa_switch *d
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7531_FORCE_MODE_MASK, MT7531_FORCE_MODE_MASK);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2779,6 +2784,28 @@ static void mt7988_mac_port_get_caps(str
|
||||
}
|
||||
}
|
||||
|
||||
+static void en7581_mac_port_get_caps(struct dsa_switch *ds, int port,
|
||||
+ struct phylink_config *config)
|
||||
+{
|
||||
+ switch (port) {
|
||||
+ /* Ports which are connected to switch PHYs. There is no MII pinout. */
|
||||
+ case 0 ... 4:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
|
||||
+ break;
|
||||
+
|
||||
+ /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */
|
||||
+ case 6:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10000FD;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
@@ -3216,6 +3243,16 @@ const struct mt753x_info mt753x_table[]
|
||||
.phy_write_c45 = mt7531_ind_c45_phy_write,
|
||||
.mac_port_get_caps = mt7988_mac_port_get_caps,
|
||||
},
|
||||
+ [ID_EN7581] = {
|
||||
+ .id = ID_EN7581,
|
||||
+ .pcs_ops = &mt7530_pcs_ops,
|
||||
+ .sw_setup = mt7988_setup,
|
||||
+ .phy_read_c22 = mt7531_ind_c22_phy_read,
|
||||
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
|
||||
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
|
||||
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
|
||||
+ .mac_port_get_caps = en7581_mac_port_get_caps,
|
||||
+ },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt753x_table);
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.h
|
||||
+++ b/drivers/net/dsa/mt7530.h
|
||||
@@ -19,6 +19,7 @@ enum mt753x_id {
|
||||
ID_MT7621 = 1,
|
||||
ID_MT7531 = 2,
|
||||
ID_MT7988 = 3,
|
||||
+ ID_EN7581 = 4,
|
||||
};
|
||||
|
||||
#define NUM_TRGMII_CTRL 5
|
||||
@@ -64,25 +65,30 @@ enum mt753x_id {
|
||||
#define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x)
|
||||
|
||||
#define MT753X_MIRROR_REG(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_CFC : MT753X_MFC)
|
||||
|
||||
#define MT753X_MIRROR_EN(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_EN : MT7530_MIRROR_EN)
|
||||
|
||||
#define MT753X_MIRROR_PORT_MASK(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_MASK : \
|
||||
MT7530_MIRROR_PORT_MASK)
|
||||
|
||||
#define MT753X_MIRROR_PORT_GET(id, val) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_GET(val) : \
|
||||
MT7530_MIRROR_PORT_GET(val))
|
||||
|
||||
#define MT753X_MIRROR_PORT_SET(id, val) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_SET(val) : \
|
||||
MT7530_MIRROR_PORT_SET(val))
|
||||
|
||||
@@ -355,6 +361,10 @@ enum mt7530_vlan_port_acc_frm {
|
||||
MT7531_FORCE_MODE_TX_FC | \
|
||||
MT7531_FORCE_MODE_EEE100 | \
|
||||
MT7531_FORCE_MODE_EEE1G)
|
||||
+#define MT753X_FORCE_MODE(id) ((id == ID_MT7531 || \
|
||||
+ id == ID_MT7988) ? \
|
||||
+ MT7531_FORCE_MODE_MASK : \
|
||||
+ MT7530_FORCE_MODE)
|
||||
#define PMCR_LINK_SETTINGS_MASK (PMCR_MAC_TX_EN | PMCR_MAC_RX_EN | \
|
||||
PMCR_FORCE_EEE1G | \
|
||||
PMCR_FORCE_EEE100 | \
|
||||
@ -1,62 +0,0 @@
|
||||
From c31d1cdd7bff1d2c13d435bb9d0c76bfaa332097 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:49 +0100
|
||||
Subject: [PATCH 1/6] clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK}
|
||||
configuration
|
||||
|
||||
REG_PCIE*_MEM and REG_PCIE*_MEM_MASK regs (PBUS_CSR memory region) are not
|
||||
part of the scu block on the EN7581 SoC and they are used to select the
|
||||
PCIE ports on the PBUS, so remove this configuration from the clock driver
|
||||
and set these registers in the PCIE host driver instead.
|
||||
This patch does not introduce any backward incompatibility since the dts
|
||||
for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-2-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 18 ------------------
|
||||
1 file changed, 18 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -31,12 +31,6 @@
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
/* EN7581 */
|
||||
-#define REG_PCIE0_MEM 0x00
|
||||
-#define REG_PCIE0_MEM_MASK 0x04
|
||||
-#define REG_PCIE1_MEM 0x08
|
||||
-#define REG_PCIE1_MEM_MASK 0x0c
|
||||
-#define REG_PCIE2_MEM 0x10
|
||||
-#define REG_PCIE2_MEM_MASK 0x14
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -415,26 +409,14 @@ static void en7581_pci_disable(struct cl
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
- if (IS_ERR(pb_base))
|
||||
- return PTR_ERR(pb_base);
|
||||
-
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
|
||||
- writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
- writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
- writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,146 +0,0 @@
|
||||
From b8bdfc666bc5f58caf46e67b615132fccbaca3d4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:50 +0100
|
||||
Subject: [PATCH 2/6] clk: en7523: move clock_register in hw_init callback
|
||||
|
||||
Move en7523_register_clocks routine in hw_init callback.
|
||||
Introduce en7523_clk_hw_init callback for EN7523 SoC.
|
||||
This is a preliminary patch to differentiate IO mapped region between
|
||||
EN7523 and EN7581 SoCs in order to access chip-scu IO region
|
||||
<0x1fa20000 0x384> on EN7581 SoC as syscon device since it contains
|
||||
miscellaneous registers needed by multiple devices (clock, pinctrl ..).
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-3-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 82 ++++++++++++++++++++++++----------------
|
||||
1 file changed, 50 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -78,7 +78,8 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -406,20 +407,6 @@ static void en7581_pci_disable(struct cl
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
-static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *np_base)
|
||||
-{
|
||||
- u32 val;
|
||||
-
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -449,6 +436,49 @@ static void en7523_register_clocks(struc
|
||||
clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
}
|
||||
|
||||
+static int en7523_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
@@ -543,31 +573,18 @@ static int en7523_clk_probe(struct platf
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct en_clk_soc_data *soc_data;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
- void __iomem *base, *np_base;
|
||||
int r;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
-
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
-
|
||||
- soc_data = device_get_match_data(&pdev->dev);
|
||||
- if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, np_base);
|
||||
- if (r)
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ r = soc_data->hw_init(pdev, clk_data);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
@@ -590,6 +607,7 @@ static const struct en_clk_soc_data en75
|
||||
.prepare = en7523_pci_prepare,
|
||||
.unprepare = en7523_pci_unprepare,
|
||||
},
|
||||
+ .hw_init = en7523_clk_hw_init,
|
||||
};
|
||||
|
||||
static const struct en_clk_soc_data en7581_data = {
|
||||
@ -1,162 +0,0 @@
|
||||
From f72fc22038dd544fa4d39c06e8c81c09c0041ed4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:51 +0100
|
||||
Subject: [PATCH 3/6] clk: en7523: introduce chip_scu regmap
|
||||
|
||||
Introduce chip_scu regmap pointer since EN7581 SoC will access chip-scu
|
||||
memory area via a syscon node. Remove first memory region mapping
|
||||
for EN7581 SoC. This patch does not introduce any backward incompatibility
|
||||
since the dts for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-4-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 81 ++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 61 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
@@ -247,15 +249,11 @@ static const u16 en7581_rst_map[] = {
|
||||
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
};
|
||||
|
||||
-static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
+static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 val;
|
||||
-
|
||||
if (!desc->base_bits)
|
||||
return desc->base_value;
|
||||
|
||||
- val = readl(base + desc->base_reg);
|
||||
val >>= desc->base_shift;
|
||||
val &= (1 << desc->base_bits) - 1;
|
||||
|
||||
@@ -265,16 +263,11 @@ static unsigned int en7523_get_base_rate
|
||||
return desc->base_values[val];
|
||||
}
|
||||
|
||||
-static u32 en7523_get_div(void __iomem *base, int i)
|
||||
+static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 reg, val;
|
||||
-
|
||||
if (!desc->div_bits)
|
||||
return 1;
|
||||
|
||||
- reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
- val = readl(base + reg);
|
||||
val >>= desc->div_shift;
|
||||
val &= (1 << desc->div_bits) - 1;
|
||||
|
||||
@@ -418,9 +411,12 @@ static void en7523_register_clocks(struc
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
+ u32 val = readl(base + desc->base_reg);
|
||||
|
||||
- rate = en7523_get_base_rate(base, i);
|
||||
- rate /= en7523_get_div(base, i);
|
||||
+ rate = en7523_get_base_rate(desc, val);
|
||||
+ val = readl(base + reg);
|
||||
+ rate /= en7523_get_div(desc, val);
|
||||
|
||||
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
|
||||
if (IS_ERR(hw)) {
|
||||
@@ -454,21 +450,66 @@ static int en7523_clk_hw_init(struct pla
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
+ struct regmap *map, void __iomem *base)
|
||||
+{
|
||||
+ struct clk_hw *hw;
|
||||
+ u32 rate;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
+ const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
+ int err;
|
||||
+
|
||||
+ err = regmap_read(map, desc->base_reg, &val);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed reading fixed clk rate %s: %d\n",
|
||||
+ desc->name, err);
|
||||
+ continue;
|
||||
+ }
|
||||
+ rate = en7523_get_base_rate(desc, val);
|
||||
+
|
||||
+ err = regmap_read(map, reg, &val);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed reading fixed clk div %s: %d\n",
|
||||
+ desc->name, err);
|
||||
+ continue;
|
||||
+ }
|
||||
+ rate /= en7523_get_div(desc, val);
|
||||
+
|
||||
+ hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
|
||||
+ if (IS_ERR(hw)) {
|
||||
+ pr_err("Failed to register clk %s: %ld\n",
|
||||
+ desc->name, PTR_ERR(hw));
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ clk_data->hws[desc->id] = hw;
|
||||
+ }
|
||||
+
|
||||
+ hw = en7523_register_pcie_clk(dev, base);
|
||||
+ clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
+
|
||||
+ clk_data->num = EN7523_NUM_CLOCKS;
|
||||
+}
|
||||
+
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
- void __iomem *base, *np_base;
|
||||
+ void __iomem *np_base;
|
||||
+ struct regmap *map;
|
||||
u32 val;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
+ if (IS_ERR(map))
|
||||
+ return PTR_ERR(map);
|
||||
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
@@ -545,7 +586,7 @@ static int en7523_reset_register(struct
|
||||
if (!soc_data->reset.idx_map_nr)
|
||||
return 0;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
@ -1,152 +0,0 @@
|
||||
From f98eded9e9ab048c88ff59c5523e703a6ced5523 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:52 +0100
|
||||
Subject: [PATCH 4/6] clk: en7523: fix estimation of fixed rate for EN7581
|
||||
|
||||
Introduce en7581_base_clks array in order to define per-SoC fixed-rate
|
||||
clock parameters and fix wrong parameters for emi, npu and crypto EN7581
|
||||
clocks
|
||||
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-5-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 105 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 103 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
+#define REG_CRYPTO_CLKSRC2 0x20c
|
||||
|
||||
#define REG_RST_CTRL2 0x00
|
||||
#define REG_RST_CTRL1 0x04
|
||||
@@ -89,6 +90,10 @@ static const u32 emi_base[] = { 33300000
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
static const u32 slic_base[] = { 100000000, 3125000 };
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
+/* EN7581 */
|
||||
+static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
+static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
static const struct en_clk_desc en7523_base_clks[] = {
|
||||
{
|
||||
@@ -186,6 +191,102 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const struct en_clk_desc en7581_base_clks[] = {
|
||||
+ {
|
||||
+ .id = EN7523_CLK_GSW,
|
||||
+ .name = "gsw",
|
||||
+
|
||||
+ .base_reg = REG_GSW_CLK_DIV_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = gsw_base,
|
||||
+ .n_base_values = ARRAY_SIZE(gsw_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_EMI,
|
||||
+ .name = "emi",
|
||||
+
|
||||
+ .base_reg = REG_EMI_CLK_DIV_SEL,
|
||||
+ .base_bits = 2,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = emi7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(emi7581_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_BUS,
|
||||
+ .name = "bus",
|
||||
+
|
||||
+ .base_reg = REG_BUS_CLK_DIV_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = bus_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_SLIC,
|
||||
+ .name = "slic",
|
||||
+
|
||||
+ .base_reg = REG_SPI_CLK_FREQ_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 0,
|
||||
+ .base_values = slic_base,
|
||||
+ .n_base_values = ARRAY_SIZE(slic_base),
|
||||
+
|
||||
+ .div_reg = REG_SPI_CLK_DIV_SEL,
|
||||
+ .div_bits = 5,
|
||||
+ .div_shift = 24,
|
||||
+ .div_val0 = 20,
|
||||
+ .div_step = 2,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_SPI,
|
||||
+ .name = "spi",
|
||||
+
|
||||
+ .base_reg = REG_SPI_CLK_DIV_SEL,
|
||||
+
|
||||
+ .base_value = 400000000,
|
||||
+
|
||||
+ .div_bits = 5,
|
||||
+ .div_shift = 8,
|
||||
+ .div_val0 = 40,
|
||||
+ .div_step = 2,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_NPU,
|
||||
+ .name = "npu",
|
||||
+
|
||||
+ .base_reg = REG_NPU_CLK_DIV_SEL,
|
||||
+ .base_bits = 2,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = npu7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(npu7581_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_CRYPTO,
|
||||
+ .name = "crypto",
|
||||
+
|
||||
+ .base_reg = REG_CRYPTO_CLKSRC2,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 0,
|
||||
+ .base_values = crypto_base,
|
||||
+ .n_base_values = ARRAY_SIZE(crypto_base),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
static const u16 en7581_rst_ofs[] = {
|
||||
REG_RST_CTRL2,
|
||||
REG_RST_CTRL1,
|
||||
@@ -457,8 +558,8 @@ static void en7581_register_clocks(struc
|
||||
u32 rate;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
|
||||
+ const struct en_clk_desc *desc = &en7581_base_clks[i];
|
||||
u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
int err;
|
||||
|
||||
@ -27,9 +27,11 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
4 files changed, 2994 insertions(+), 1 deletion(-)
|
||||
create mode 100644 drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
|
||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index 67634f0ea30e13..38ccb620cc2497 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -16872,6 +16872,13 @@ F: drivers/pinctrl/
|
||||
@@ -18232,6 +18232,13 @@ F: drivers/pinctrl/
|
||||
F: include/dt-bindings/pinctrl/
|
||||
F: include/linux/pinctrl/
|
||||
|
||||
@ -43,6 +45,8 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
PIN CONTROLLER - AMD
|
||||
M: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
|
||||
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
|
||||
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
|
||||
index 7af287252834a4..a417a031659c65 100644
|
||||
--- a/drivers/pinctrl/mediatek/Kconfig
|
||||
+++ b/drivers/pinctrl/mediatek/Kconfig
|
||||
@@ -1,6 +1,6 @@
|
||||
@ -75,9 +79,11 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
config PINCTRL_MT2712
|
||||
bool "MediaTek MT2712 pin control"
|
||||
depends on OF
|
||||
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
|
||||
index 680f7e8526e00a..1405d434218ea1 100644
|
||||
--- a/drivers/pinctrl/mediatek/Makefile
|
||||
+++ b/drivers/pinctrl/mediatek/Makefile
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinc
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o
|
||||
obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o
|
||||
|
||||
# SoC Drivers
|
||||
@ -85,6 +91,9 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o
|
||||
obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o
|
||||
obj-$(CONFIG_PINCTRL_MT76X8) += pinctrl-mt76x8.o
|
||||
diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
new file mode 100644
|
||||
index 00000000000000..7692e6d9b87105
|
||||
--- /dev/null
|
||||
+++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
@@ -0,0 +1,2970 @@
|
||||
@ -124,7 +133,13 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+
|
||||
+#define PINCTRL_FUNC_DESC(id) \
|
||||
+ { \
|
||||
+ .desc = { #id, id##_groups, ARRAY_SIZE(id##_groups) }, \
|
||||
+ .desc = { \
|
||||
+ .func = { \
|
||||
+ .name = #id, \
|
||||
+ .groups = id##_groups, \
|
||||
+ .ngroups = ARRAY_SIZE(id##_groups), \
|
||||
+ } \
|
||||
+ }, \
|
||||
+ .groups = id##_func_group, \
|
||||
+ .group_size = ARRAY_SIZE(id##_func_group), \
|
||||
+ }
|
||||
@ -2379,7 +2394,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = pinctrl_gpio_direction_output(chip->base + gpio);
|
||||
+ err = pinctrl_gpio_direction_output(chip, gpio);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
@ -2499,12 +2514,6 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE,
|
||||
+};
|
||||
+
|
||||
+static int airoha_pinctrl_gpio_direction_input(struct gpio_chip *chip,
|
||||
+ unsigned int gpio)
|
||||
+{
|
||||
+ return pinctrl_gpio_direction_input(chip->base + gpio);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl,
|
||||
+ struct platform_device *pdev)
|
||||
+{
|
||||
@ -2525,7 +2534,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+ gc->label = dev_name(dev);
|
||||
+ gc->request = gpiochip_generic_request;
|
||||
+ gc->free = gpiochip_generic_free;
|
||||
+ gc->direction_input = airoha_pinctrl_gpio_direction_input;
|
||||
+ gc->direction_input = pinctrl_gpio_direction_input;
|
||||
+ gc->direction_output = airoha_gpio_direction_output;
|
||||
+ gc->set = airoha_gpio_set;
|
||||
+ gc->get = airoha_gpio_get;
|
||||
@ -2570,7 +2579,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dev_dbg(pctrl_dev->dev, "enable function %s group %s\n",
|
||||
+ desc->name, grp->name);
|
||||
+ desc->func.name, grp->grp.name);
|
||||
+
|
||||
+ func = desc->data;
|
||||
+ for (i = 0; i < func->group_size; i++) {
|
||||
@ -2578,7 +2587,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+ int j;
|
||||
+
|
||||
+ group = &func->groups[i];
|
||||
+ if (strcmp(group->name, grp->name))
|
||||
+ if (strcmp(group->name, grp->grp.name))
|
||||
+ continue;
|
||||
+
|
||||
+ for (j = 0; j < group->regmap_size; j++) {
|
||||
@ -3004,7 +3013,7 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+ const struct pingroup *grp = &airoha_pinctrl_groups[i];
|
||||
+
|
||||
+ err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name,
|
||||
+ (int *)grp->pins, grp->npins,
|
||||
+ grp->pins, grp->npins,
|
||||
+ (void *)grp);
|
||||
+ if (err < 0) {
|
||||
+ dev_err(&pdev->dev, "Failed to register group %s\n",
|
||||
@ -3019,13 +3028,13 @@ Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
+
|
||||
+ func = &airoha_pinctrl_funcs[i];
|
||||
+ err = pinmux_generic_add_function(pinctrl->ctrl,
|
||||
+ func->desc.name,
|
||||
+ func->desc.group_names,
|
||||
+ func->desc.num_group_names,
|
||||
+ func->desc.func.name,
|
||||
+ func->desc.func.groups,
|
||||
+ func->desc.func.ngroups,
|
||||
+ (void *)func);
|
||||
+ if (err < 0) {
|
||||
+ dev_err(dev, "Failed to register function %s\n",
|
||||
+ func->desc.name);
|
||||
+ func->desc.func.name);
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
@ -0,0 +1,63 @@
|
||||
From ac6f0825e582f2216a582c9edf0cee7bfe347ba6 Mon Sep 17 00:00:00 2001
|
||||
From: Kees Cook <kees@kernel.org>
|
||||
Date: Sun, 17 Nov 2024 03:45:38 -0800
|
||||
Subject: [PATCH] pinctrl: airoha: Use unsigned long for bit search
|
||||
|
||||
Instead of risking alignment problems and causing (false positive) array
|
||||
bound warnings when casting a u32 to (64-bit) unsigned long, just use a
|
||||
native unsigned long for doing bit searches. Avoids warning with GCC 15's
|
||||
-Warray-bounds -fdiagnostics-details:
|
||||
|
||||
In file included from ../include/linux/bitmap.h:11,
|
||||
from ../include/linux/cpumask.h:12,
|
||||
from ../arch/x86/include/asm/paravirt.h:21,
|
||||
from ../arch/x86/include/asm/irqflags.h:80,
|
||||
from ../include/linux/irqflags.h:18,
|
||||
from ../include/linux/spinlock.h:59,
|
||||
from ../include/linux/irq.h:14,
|
||||
from ../include/linux/irqchip/chained_irq.h:10,
|
||||
from ../include/linux/gpio/driver.h:8,
|
||||
from ../drivers/pinctrl/mediatek/pinctrl-airoha.c:11:
|
||||
In function 'find_next_bit',
|
||||
inlined from 'airoha_irq_handler' at ../drivers/pinctrl/mediatek/pinctrl-airoha.c:2394:3:
|
||||
../include/linux/find.h:65:23: error: array subscript 'long unsigned int[0]' is partly outside array bounds of 'u32[1]' {aka 'unsigned int[1]'} [-Werror=array-bounds=]
|
||||
65 | val = *addr & GENMASK(size - 1, offset);
|
||||
| ^~~~~
|
||||
../drivers/pinctrl/mediatek/pinctrl-airoha.c: In function 'airoha_irq_handler':
|
||||
../drivers/pinctrl/mediatek/pinctrl-airoha.c:2387:21: note: object 'status' of size 4
|
||||
2387 | u32 status;
|
||||
| ^~~~~~
|
||||
|
||||
Signed-off-by: Kees Cook <kees@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://lore.kernel.org/20241117114534.work.292-kees@kernel.org
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
drivers/pinctrl/mediatek/pinctrl-airoha.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
index 7692e6d9b87105..547a798b71c8ae 100644
|
||||
--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
+++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
@@ -2384,15 +2384,16 @@ static irqreturn_t airoha_irq_handler(int irq, void *data)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) {
|
||||
struct gpio_irq_chip *girq = &pinctrl->gpiochip.chip.irq;
|
||||
- u32 status;
|
||||
+ u32 regmap;
|
||||
+ unsigned long status;
|
||||
int irq;
|
||||
|
||||
if (regmap_read(pinctrl->regmap, pinctrl->gpiochip.status[i],
|
||||
- &status))
|
||||
+ ®map))
|
||||
continue;
|
||||
|
||||
- for_each_set_bit(irq, (unsigned long *)&status,
|
||||
- AIROHA_PIN_BANK_SIZE) {
|
||||
+ status = regmap;
|
||||
+ for_each_set_bit(irq, &status, AIROHA_PIN_BANK_SIZE) {
|
||||
u32 offset = irq + i * AIROHA_PIN_BANK_SIZE;
|
||||
|
||||
generic_handle_irq(irq_find_mapping(girq->domain,
|
||||
@ -1,48 +0,0 @@
|
||||
From 2eb75f86d52565367211c51334d15fe672633085 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sat, 16 Nov 2024 11:56:53 +0100
|
||||
Subject: [PATCH] clk: en7523: Fix wrong BUS clock for EN7581
|
||||
|
||||
The Documentation for EN7581 had a typo and still referenced the EN7523
|
||||
BUS base source frequency. This was in conflict with a different page in
|
||||
the Documentration that state that the BUS runs at 300MHz (600MHz source
|
||||
with divisor set to 2) and the actual watchdog that tick at half the BUS
|
||||
clock (150MHz). This was verified with the watchdog by timing the
|
||||
seconds that the system takes to reboot (due too watchdog) and by
|
||||
operating on different values of the BUS divisor.
|
||||
|
||||
The correct values for source of BUS clock are 600MHz and 540MHz.
|
||||
|
||||
This was also confirmed by Airoha.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20241116105710.19748-1-ansuelsmth@gmail.com
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -87,6 +87,7 @@ static const u32 slic_base[] = { 1000000
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
/* EN7581 */
|
||||
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 bus7581_base[] = { 600000000, 540000000 };
|
||||
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
@@ -222,8 +223,8 @@ static const struct en_clk_desc en7581_b
|
||||
.base_reg = REG_BUS_CLK_DIV_SEL,
|
||||
.base_bits = 1,
|
||||
.base_shift = 8,
|
||||
- .base_values = bus_base,
|
||||
- .n_base_values = ARRAY_SIZE(bus_base),
|
||||
+ .base_values = bus7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus7581_base),
|
||||
|
||||
.div_bits = 3,
|
||||
.div_shift = 0,
|
||||
@ -1,102 +0,0 @@
|
||||
From 0c7469ee718e1dd929f52bfb142a7f6fb68f0765 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 16 Dec 2024 18:47:33 +0100
|
||||
Subject: [PATCH] net: airoha: Fix error path in airoha_probe()
|
||||
|
||||
Do not run napi_disable() if airoha_hw_init() fails since Tx/Rx napi
|
||||
has not been started yet. In order to fix the issue, introduce
|
||||
airoha_qdma_stop_napi routine and remove napi_disable in
|
||||
airoha_hw_cleanup().
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241216-airoha_probe-error-path-fix-v2-1-6b10e04e9a5c@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 33 ++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2139,17 +2139,14 @@ static void airoha_hw_cleanup(struct air
|
||||
if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_disable(&qdma->q_rx[i].napi);
|
||||
netif_napi_del(&qdma->q_rx[i].napi);
|
||||
airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
|
||||
if (qdma->q_rx[i].page_pool)
|
||||
page_pool_destroy(qdma->q_rx[i].page_pool);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
netif_napi_del(&qdma->q_tx_irq[i].napi);
|
||||
- }
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
if (!qdma->q_tx[i].ndesc)
|
||||
@@ -2174,6 +2171,21 @@ static void airoha_qdma_start_napi(struc
|
||||
}
|
||||
}
|
||||
|
||||
+static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
+ napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
+ continue;
|
||||
+
|
||||
+ napi_disable(&qdma->q_rx[i].napi);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
|
||||
{
|
||||
struct airoha_eth *eth = port->qdma->eth;
|
||||
@@ -2731,7 +2743,7 @@ static int airoha_probe(struct platform_
|
||||
|
||||
err = airoha_hw_init(pdev, eth);
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto error_hw_cleanup;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
airoha_qdma_start_napi(ð->qdma[i]);
|
||||
@@ -2746,13 +2758,16 @@ static int airoha_probe(struct platform_
|
||||
err = airoha_alloc_gdm_port(eth, np);
|
||||
if (err) {
|
||||
of_node_put(np);
|
||||
- goto error;
|
||||
+ goto error_napi_stop;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
-error:
|
||||
+error_napi_stop:
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_qdma_stop_napi(ð->qdma[i]);
|
||||
+error_hw_cleanup:
|
||||
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
airoha_hw_cleanup(ð->qdma[i]);
|
||||
|
||||
@@ -2773,8 +2788,10 @@ static void airoha_remove(struct platfor
|
||||
struct airoha_eth *eth = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
|
||||
+ airoha_qdma_stop_napi(ð->qdma[i]);
|
||||
airoha_hw_cleanup(ð->qdma[i]);
|
||||
+ }
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
@ -1,41 +0,0 @@
|
||||
From d31a49d37cb132b31cc6683eef2122f8609d6229 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Mon, 20 Jan 2025 16:41:40 +0100
|
||||
Subject: [PATCH] net: airoha: Fix wrong GDM4 register definition
|
||||
|
||||
Fix wrong GDM4 register definition, in Airoha SDK GDM4 is defined at
|
||||
offset 0x2400 but this doesn't make sense as it does conflict with the
|
||||
CDM4 that is in the same location.
|
||||
|
||||
Following the pattern where each GDM base is at the FWD_CFG, currently
|
||||
GDM4 base offset is set to 0x2500. This is correct but REG_GDM4_FWD_CFG
|
||||
and REG_GDM4_SRC_PORT_SET are still using the SDK reference with the
|
||||
0x2400 offset. Fix these 2 define by subtracting 0x100 to each register
|
||||
to reflect the real address location.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
Link: https://patch.msgid.link/20250120154148.13424-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -266,11 +266,11 @@
|
||||
#define REG_GDM3_FWD_CFG GDM3_BASE
|
||||
#define GDM3_PAD_EN_MASK BIT(28)
|
||||
|
||||
-#define REG_GDM4_FWD_CFG (GDM4_BASE + 0x100)
|
||||
+#define REG_GDM4_FWD_CFG GDM4_BASE
|
||||
#define GDM4_PAD_EN_MASK BIT(28)
|
||||
#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8)
|
||||
|
||||
-#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x33c)
|
||||
+#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c)
|
||||
#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16)
|
||||
#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12)
|
||||
#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8)
|
||||
@ -101,7 +101,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
-obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -0,0 +1,3359 @@
|
||||
@@ -0,0 +1,3358 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2024 AIROHA Inc
|
||||
@ -1751,8 +1751,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
+ const struct page_pool_params pp_params = {
|
||||
+ .order = 0,
|
||||
+ .pool_size = 256,
|
||||
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV |
|
||||
+ PP_FLAG_PAGE_FRAG,
|
||||
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
|
||||
+ .dma_dir = DMA_FROM_DEVICE,
|
||||
+ .max_len = PAGE_SIZE,
|
||||
+ .nid = NUMA_NO_NODE,
|
||||
@ -3463,7 +3462,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
+MODULE_DESCRIPTION("Ethernet driver for Airoha SoC");
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ /dev/null
|
||||
@@ -1,3359 +0,0 @@
|
||||
@@ -1,3358 +0,0 @@
|
||||
-// SPDX-License-Identifier: GPL-2.0-only
|
||||
-/*
|
||||
- * Copyright (c) 2024 AIROHA Inc
|
||||
@ -5113,8 +5112,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
- const struct page_pool_params pp_params = {
|
||||
- .order = 0,
|
||||
- .pool_size = 256,
|
||||
- .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV |
|
||||
- PP_FLAG_PAGE_FRAG,
|
||||
- .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
|
||||
- .dma_dir = DMA_FROM_DEVICE,
|
||||
- .max_len = PAGE_SIZE,
|
||||
- .nid = NUMA_NO_NODE,
|
||||
|
||||
@ -640,7 +640,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
+ if (IS_ERR(dp))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ *dev = dsa_port_to_master(dp);
|
||||
+ *dev = dsa_port_to_conduit(dp);
|
||||
+ return dp->index;
|
||||
+#else
|
||||
+ return -ENODEV;
|
||||
|
||||
@ -16,37 +16,11 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://patch.msgid.link/20250410100410.348-2-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/mediatek/Kconfig | 4 +-
|
||||
drivers/net/phy/mediatek/mtk-ge-soc.c | 62 +++++++++++++++++++++++++++
|
||||
2 files changed, 65 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/mediatek/Kconfig
|
||||
+++ b/drivers/net/phy/mediatek/Kconfig
|
||||
@@ -15,7 +15,9 @@ config MEDIATEK_GE_PHY
|
||||
|
||||
config MEDIATEK_GE_SOC_PHY
|
||||
tristate "MediaTek SoC Ethernet PHYs"
|
||||
- depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST
|
||||
+ depends on ARM64 || COMPILE_TEST
|
||||
+ depends on ARCH_AIROHA || (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || \
|
||||
+ COMPILE_TEST
|
||||
select MTK_NET_PHYLIB
|
||||
help
|
||||
Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
|
||||
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||
@@ -10,8 +10,11 @@
|
||||
|
||||
#include "mtk.h"
|
||||
|
||||
+#define MTK_PHY_MAX_LEDS 2
|
||||
+
|
||||
#define MTK_GPHY_ID_MT7981 0x03a29461
|
||||
#define MTK_GPHY_ID_MT7988 0x03a29481
|
||||
+#define MTK_GPHY_ID_AN7581 0x03a294c1
|
||||
|
||||
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||
@@ -1405,6 +1408,53 @@ static int mt7981_phy_probe(struct phy_d
|
||||
return mt798x_phy_calibration(phydev);
|
||||
}
|
||||
@ -118,12 +92,4 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
+ },
|
||||
};
|
||||
|
||||
module_phy_driver(mtk_socphy_driver);
|
||||
@@ -1447,6 +1508,7 @@ module_phy_driver(mtk_socphy_driver);
|
||||
static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
|
||||
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
|
||||
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
|
||||
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581) },
|
||||
{ }
|
||||
};
|
||||
|
||||
module_phy_driver(mtk_socphy_driver);
|
||||
|
||||
@ -26,9 +26,9 @@ Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
+#include <linux/ioport.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
@@ -514,3 +515,82 @@ struct reserved_mem *of_reserved_mem_loo
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -137,14 +137,14 @@
|
||||
* is written without DLAB set, this mode will be disabled.
|
||||
--- a/drivers/tty/serial/8250/Makefile
|
||||
+++ b/drivers/tty/serial/8250/Makefile
|
||||
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_8250_PERICOM) += 825
|
||||
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
|
||||
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
|
||||
obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
|
||||
+obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o
|
||||
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
|
||||
obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
|
||||
obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
|
||||
+obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o
|
||||
obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o
|
||||
obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o
|
||||
obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
|
||||
--- a/include/uapi/linux/serial_reg.h
|
||||
+++ b/include/uapi/linux/serial_reg.h
|
||||
@@ -382,5 +382,17 @@
|
||||
|
||||
@ -1,7 +1,22 @@
|
||||
From 97e4e7b106b08373f90ff1b8c4daf6c2254386a8 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= <ukleinek@kernel.org>,
|
||||
linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org
|
||||
Cc: Benjamin Larsson <benjamin.larsson@genexis.eu>,
|
||||
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>,
|
||||
Lorenzo Bianconi <lorenzo@kernel.org>,
|
||||
Christian Marangi <ansuelsmth@gmail.com>
|
||||
Subject: [PATCH v13] pwm: airoha: Add support for EN7581 SoC
|
||||
Date: Sat, 10 May 2025 00:36:52 +0200
|
||||
Message-ID: <20250509223653.8800-1-ansuelsmth@gmail.com>
|
||||
X-Mailer: git-send-email 2.48.1
|
||||
Precedence: bulk
|
||||
X-Mailing-List: linux-pwm@vger.kernel.org
|
||||
List-Id: <linux-pwm.vger.kernel.org>
|
||||
List-Subscribe: <mailto:linux-pwm+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:linux-pwm+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
|
||||
From: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Date: Wed, 23 Oct 2024 01:20:06 +0200
|
||||
Subject: [PATCH] pwm: airoha: Add support for EN7581 SoC
|
||||
|
||||
Introduce driver for PWM module available on EN7581 SoC.
|
||||
|
||||
@ -9,18 +24,129 @@ Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/pwm/Kconfig | 11 ++
|
||||
Changes v13:
|
||||
- Reorder include
|
||||
- Split ticks_from_ns function
|
||||
- Add additional comments for shift register chip clock
|
||||
- Address suggested minor optimization (Uwe)
|
||||
|
||||
Changes v12:
|
||||
- Make shift function more readable
|
||||
- Use unsigned int where possible
|
||||
- Better comment some SIPO strangeness
|
||||
- Move SIPO init after flash map config
|
||||
- Retrun real values in get_state instead of the
|
||||
one saved in bucket
|
||||
- Improve period_ns parsing so we can better share generators
|
||||
|
||||
Changes v11:
|
||||
- Fix wrong calculation of period and duty
|
||||
- Use AIROHA_PWM prefix for each define
|
||||
- Drop set/get special define in favour of BITS and GENMASK
|
||||
- Correctly use dev_err_probe
|
||||
- Init bucket with initial values
|
||||
- Rework define to make use of FIELD_PREP and FIELD_GET
|
||||
|
||||
Changes in v10:
|
||||
- repost just patch 6/6 (pwm driver) since patches {1/6-5/6} have been
|
||||
already applied in linux-pinctrl tree
|
||||
- pwm: introduce AIROHA_PWM_FIELD_GET and AIROHA_PWM_FIELD_SET macros to
|
||||
get/set field with non-const mask
|
||||
- pwm: simplify airoha_pwm_get_generator() to report unused generator
|
||||
and remove double lookup
|
||||
- pwm: remove device_node pointer in airoha_pwm struct since this is
|
||||
write-only field
|
||||
- pwm: cosmetics
|
||||
- Link to v9: https://lore.kernel.org/r/20241023-en7581-pinctrl-v9-0-afb0cbcab0ec@kernel.org
|
||||
|
||||
Changes in v9:
|
||||
- pwm: remove unused properties
|
||||
- Link to v8: https://lore.kernel.org/r/20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org
|
||||
|
||||
Changes in v8:
|
||||
- pwm: add missing properties documentation
|
||||
- Link to v7: https://lore.kernel.org/r/20241016-en7581-pinctrl-v7-0-4ff611f263a7@kernel.org
|
||||
|
||||
Changes in v7:
|
||||
- pinctrl: cosmetics
|
||||
- pinctrl: fix compilation warning
|
||||
- Link to v6: https://lore.kernel.org/r/20241013-en7581-pinctrl-v6-0-2048e2d099c2@kernel.org
|
||||
|
||||
Changes in v6:
|
||||
- pwm: rely on regmap APIs
|
||||
- pwm: introduce compatible string
|
||||
- pinctrl: introduce compatible string
|
||||
- remove airoha-mfd driver
|
||||
- add airoha,en7581-pinctrl binding
|
||||
- add airoha,en7581-pwm binding
|
||||
- update airoha,en7581-gpio-sysctl binding
|
||||
- Link to v5: https://lore.kernel.org/r/20241001-en7581-pinctrl-v5-0-dc1ce542b6c6@kernel.org
|
||||
|
||||
Changes in v5:
|
||||
- use spin_lock in airoha_pinctrl_rmw instead of a mutex since it can run
|
||||
in interrupt context
|
||||
- remove unused includes in pinctrl driver
|
||||
- since the irq_chip is immutable, allocate the gpio_irq_chip struct
|
||||
statically in pinctrl driver
|
||||
- rely on regmap APIs in pinctrl driver but keep the spin_lock local to the
|
||||
driver
|
||||
- rely on guard/guard_scope APIs in pinctrl driver
|
||||
- improve naming convention pinctrl driver
|
||||
- introduce airoha_pinconf_set_pin_value utility routine
|
||||
- Link to v4: https://lore.kernel.org/r/20240911-en7581-pinctrl-v4-0-60ac93d760bb@kernel.org
|
||||
|
||||
Changes in v4:
|
||||
- add 'Limitation' description in pwm driver
|
||||
- fix comments in pwm driver
|
||||
- rely on mfd->base __iomem pointer in pwm driver, modify register
|
||||
offsets according to it and get rid of sgpio_cfg, flash_cfg and
|
||||
cycle_cfg pointers
|
||||
- simplify register utility routines in pwm driver
|
||||
- use 'generator' instead of 'waveform' suffix for pwm routines
|
||||
- fix possible overflow calculating duty cycle in pwm driver
|
||||
- do not modify pwm state in free callback in pwm driver
|
||||
- cap the maximum period in pwm driver
|
||||
- do not allow inverse polarity in pwm driver
|
||||
- do not set of_xlate callback in the pwm driver and allow the stack to
|
||||
do it
|
||||
- fix MAINTAINERS file for airoha pinctrl driver
|
||||
- fix undefined reference to __ffsdi2 in pinctrl driver
|
||||
- simplify airoha,en7581-gpio-sysctl.yam binding
|
||||
- Link to v3: https://lore.kernel.org/r/20240831-en7581-pinctrl-v3-0-98eebfb4da66@kernel.org
|
||||
|
||||
Changes in v3:
|
||||
- introduce airoha-mfd driver
|
||||
- add pwm driver to the same series
|
||||
- model pinctrl and pwm drivers as childs of a parent mfd driver.
|
||||
- access chip-scu memory region in pinctrl driver via syscon
|
||||
- introduce a single airoha,en7581-gpio-sysctl.yaml binding and get rid
|
||||
of dedicated bindings for pinctrl and pwm
|
||||
- add airoha,en7581-chip-scu.yaml binding do the series
|
||||
- Link to v2: https://lore.kernel.org/r/20240822-en7581-pinctrl-v2-0-ba1559173a7f@kernel.org
|
||||
|
||||
Changes in v2:
|
||||
- Fix compilation errors
|
||||
- Collapse some register mappings for gpio and irq controllers
|
||||
- update dt-bindings according to new register mapping
|
||||
- fix some dt-bindings errors
|
||||
- Link to v1: https://lore.kernel.org/all/cover.1723392444.git.lorenzo@kernel.org/
|
||||
|
||||
drivers/pwm/Kconfig | 11 +
|
||||
drivers/pwm/Makefile | 1 +
|
||||
drivers/pwm/pwm-airoha.c | 386 +++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 398 insertions(+)
|
||||
drivers/pwm/pwm-airoha.c | 536 +++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 548 insertions(+)
|
||||
create mode 100644 drivers/pwm/pwm-airoha.c
|
||||
|
||||
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
|
||||
index c866ed388da9..113ca01f319f 100644
|
||||
--- a/drivers/pwm/Kconfig
|
||||
+++ b/drivers/pwm/Kconfig
|
||||
@@ -51,6 +51,17 @@ config PWM_AB8500
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-ab8500.
|
||||
@@ -54,6 +54,17 @@ config PWM_ADP5585
|
||||
This option enables support for the PWM function found in the Analog
|
||||
Devices ADP5585.
|
||||
|
||||
+config PWM_AIROHA
|
||||
+ tristate "Airoha PWM support"
|
||||
@ -36,71 +162,103 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
config PWM_APPLE
|
||||
tristate "Apple SoC PWM support"
|
||||
depends on ARCH_APPLE || COMPILE_TEST
|
||||
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
|
||||
index 5c782af8f49b..cd3e6de2e44a 100644
|
||||
--- a/drivers/pwm/Makefile
|
||||
+++ b/drivers/pwm/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
obj-$(CONFIG_PWM) += core.o
|
||||
obj-$(CONFIG_PWM_SYSFS) += sysfs.o
|
||||
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
|
||||
obj-$(CONFIG_PWM_ADP5585) += pwm-adp5585.o
|
||||
+obj-$(CONFIG_PWM_AIROHA) += pwm-airoha.o
|
||||
obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
|
||||
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
|
||||
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
|
||||
diff --git a/drivers/pwm/pwm-airoha.c b/drivers/pwm/pwm-airoha.c
|
||||
new file mode 100644
|
||||
index 000000000000..eaf946a53c81
|
||||
--- /dev/null
|
||||
+++ b/drivers/pwm/pwm-airoha.c
|
||||
@@ -0,0 +1,388 @@
|
||||
@@ -0,0 +1,536 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright 2022 Markus Gothe <markus.gothe@genexis.eu>
|
||||
+ *
|
||||
+ * Limitations:
|
||||
+ * - No disable bit, so a disabled PWM is simulated by setting duty_cycle to 0
|
||||
+ * - Only 8 concurrent waveform generators are available for 8 combinations of
|
||||
+ * duty_cycle and period. Waveform generators are shared between 16 GPIO
|
||||
+ * pins and 17 SIPO GPIO pins.
|
||||
+ * - Supports only normal polarity.
|
||||
+ * - On configuration the currently running period is completed.
|
||||
+ * - Minimum supported period is 4ms
|
||||
+ * - Maximum supported period is 1s
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/math64.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pwm.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <asm/div64.h>
|
||||
+
|
||||
+#define REG_SGPIO_LED_DATA 0x0024
|
||||
+#define SGPIO_LED_DATA_SHIFT_FLAG BIT(31)
|
||||
+#define SGPIO_LED_DATA_DATA GENMASK(16, 0)
|
||||
+#define AIROHA_PWM_REG_SGPIO_LED_DATA 0x0024
|
||||
+#define AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG BIT(31)
|
||||
+#define AIROHA_PWM_SGPIO_LED_DATA_DATA GENMASK(16, 0)
|
||||
+
|
||||
+#define REG_SGPIO_CLK_DIVR 0x0028
|
||||
+#define REG_SGPIO_CLK_DIVR_MASK GENMASK(1, 0)
|
||||
+#define REG_SGPIO_CLK_DLY 0x002c
|
||||
+#define AIROHA_PWM_REG_SGPIO_CLK_DIVR 0x0028
|
||||
+#define AIROHA_PWM_SGPIO_CLK_DIVR GENMASK(1, 0)
|
||||
+#define AIROHA_PWM_SGPIO_CLK_DIVR_32 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0x3)
|
||||
+#define AIROHA_PWM_SGPIO_CLK_DIVR_16 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0x2)
|
||||
+#define AIROHA_PWM_SGPIO_CLK_DIVR_8 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0x1)
|
||||
+#define AIROHA_PWM_SGPIO_CLK_DIVR_4 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0x0)
|
||||
+
|
||||
+#define REG_SIPO_FLASH_MODE_CFG 0x0030
|
||||
+#define SERIAL_GPIO_FLASH_MODE BIT(1)
|
||||
+#define SERIAL_GPIO_MODE_74HC164 BIT(0)
|
||||
+#define AIROHA_PWM_REG_SGPIO_CLK_DLY 0x002c
|
||||
+
|
||||
+#define REG_GPIO_FLASH_PRD_SET(_n) (0x003c + ((_n) << 2))
|
||||
+#define GPIO_FLASH_PRD_MASK(_n) GENMASK(15 + ((_n) << 4), ((_n) << 4))
|
||||
+#define AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG 0x0030
|
||||
+#define AIROHA_PWM_SERIAL_GPIO_FLASH_MODE BIT(1)
|
||||
+#define AIROHA_PWM_SERIAL_GPIO_MODE_74HC164 BIT(0)
|
||||
+
|
||||
+#define REG_GPIO_FLASH_MAP(_n) (0x004c + ((_n) << 2))
|
||||
+#define GPIO_FLASH_SETID_MASK(_n) GENMASK(2 + ((_n) << 2), ((_n) << 2))
|
||||
+#define GPIO_FLASH_EN(_n) BIT(3 + ((_n) << 2))
|
||||
+#define AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(_n) (0x003c + (4 * (_n)))
|
||||
+#define AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(_n) (16 * (_n))
|
||||
+#define AIROHA_PWM_GPIO_FLASH_PRD_LOW GENMASK(15, 8)
|
||||
+#define AIROHA_PWM_GPIO_FLASH_PRD_HIGH GENMASK(7, 0)
|
||||
+
|
||||
+#define REG_SIPO_FLASH_MAP(_n) (0x0054 + ((_n) << 2))
|
||||
+#define AIROHA_PWM_REG_GPIO_FLASH_MAP(_n) (0x004c + (4 * (_n)))
|
||||
+#define AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(_n) (4 * (_n))
|
||||
+#define AIROHA_PWM_GPIO_FLASH_EN BIT(3)
|
||||
+#define AIROHA_PWM_GPIO_FLASH_SET_ID GENMASK(2, 0)
|
||||
+
|
||||
+#define REG_CYCLE_CFG_VALUE(_n) (0x0098 + ((_n) << 2))
|
||||
+#define WAVE_GEN_CYCLE_MASK(_n) GENMASK(7 + ((_n) << 3), ((_n) << 3))
|
||||
+/* Register map is equal to GPIO flash map */
|
||||
+#define AIROHA_PWM_REG_SIPO_FLASH_MAP(_n) (0x0054 + (4 * (_n)))
|
||||
+
|
||||
+#define PWM_NUM_BUCKETS 8
|
||||
+#define AIROHA_PWM_REG_CYCLE_CFG_VALUE(_n) (0x0098 + (4 * (_n)))
|
||||
+#define AIROHA_PWM_REG_CYCLE_CFG_SHIFT(_n) (8 * (_n))
|
||||
+#define AIROHA_PWM_WAVE_GEN_CYCLE GENMASK(7, 0)
|
||||
+
|
||||
+/* GPIO/SIPO flash map handles 8 pins in one register */
|
||||
+#define AIROHA_PWM_PINS_PER_FLASH_MAP 8
|
||||
+/* Cycle cfg handles 4 generators in one register */
|
||||
+#define AIROHA_PWM_BUCKET_PER_CYCLE_CFG 4
|
||||
+/* Flash producer handles 2 generators in one register */
|
||||
+#define AIROHA_PWM_BUCKET_PER_FLASH_PROD 2
|
||||
+
|
||||
+#define AIROHA_PWM_NUM_BUCKETS 8
|
||||
+/*
|
||||
+ * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15.
|
||||
+ * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32.
|
||||
+ * However, we've only got 8 concurrent waveform generators and can therefore
|
||||
+ * only use up to 8 different combinations of duty cycle and period at a time.
|
||||
+ */
|
||||
+#define AIROHA_PWM_NUM_GPIO 16
|
||||
+#define AIROHA_PWM_NUM_SIPO 17
|
||||
+#define AIROHA_PWM_MAX_CHANNELS (AIROHA_PWM_NUM_GPIO + AIROHA_PWM_NUM_SIPO)
|
||||
+
|
||||
+struct airoha_pwm_bucket {
|
||||
+ /* Bitmask of PWM channels using this bucket */
|
||||
@ -110,311 +268,432 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+};
|
||||
+
|
||||
+struct airoha_pwm {
|
||||
+ struct pwm_chip chip;
|
||||
+
|
||||
+ struct regmap *regmap;
|
||||
+
|
||||
+ struct device_node *np;
|
||||
+ u64 initialized;
|
||||
+
|
||||
+ struct airoha_pwm_bucket bucket[PWM_NUM_BUCKETS];
|
||||
+ struct airoha_pwm_bucket buckets[AIROHA_PWM_NUM_BUCKETS];
|
||||
+
|
||||
+ /* Cache bucket used by each pwm channel */
|
||||
+ u8 channel_bucket[AIROHA_PWM_MAX_CHANNELS];
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15.
|
||||
+ * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32.
|
||||
+ * However, we've only got 8 concurrent waveform generators and can therefore
|
||||
+ * only use up to 8 different combinations of duty cycle and period at a time.
|
||||
+ */
|
||||
+#define PWM_NUM_GPIO 16
|
||||
+#define PWM_NUM_SIPO 17
|
||||
+
|
||||
+/* The PWM hardware supports periods between 4 ms and 1 s */
|
||||
+#define PERIOD_MIN_NS (4 * NSEC_PER_MSEC)
|
||||
+#define PERIOD_MAX_NS (1 * NSEC_PER_SEC)
|
||||
+/* It is represented internally as 1/250 s between 1 and 250 */
|
||||
+#define PERIOD_MIN 1
|
||||
+#define PERIOD_MAX 250
|
||||
+#define AIROHA_PWM_PERIOD_TICK_NS (4 * NSEC_PER_MSEC)
|
||||
+#define AIROHA_PWM_PERIOD_MAX_NS (1 * NSEC_PER_SEC)
|
||||
+/* It is represented internally as 1/250 s between 1 and 250. Unit is ticks. */
|
||||
+#define AIROHA_PWM_PERIOD_MIN 1
|
||||
+#define AIROHA_PWM_PERIOD_MAX 250
|
||||
+/* Duty cycle is relative with 255 corresponding to 100% */
|
||||
+#define DUTY_FULL 255
|
||||
+#define AIROHA_PWM_DUTY_FULL 255
|
||||
+
|
||||
+static void airoha_pwm_get_flash_map_addr_and_shift(unsigned int hwpwm,
|
||||
+ u32 *addr, u32 *shift)
|
||||
+{
|
||||
+ unsigned int offset, hwpwm_bit;
|
||||
+
|
||||
+ if (hwpwm >= AIROHA_PWM_NUM_GPIO) {
|
||||
+ unsigned int sipohwpwm = hwpwm - AIROHA_PWM_NUM_GPIO;
|
||||
+
|
||||
+ offset = sipohwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP;
|
||||
+ hwpwm_bit = sipohwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP;
|
||||
+
|
||||
+ /* One FLASH_MAP register handles 8 pins */
|
||||
+ *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit);
|
||||
+ *addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(offset);
|
||||
+ } else {
|
||||
+ offset = hwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP;
|
||||
+ hwpwm_bit = hwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP;
|
||||
+
|
||||
+ /* One FLASH_MAP register handles 8 pins */
|
||||
+ *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit);
|
||||
+ *addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(offset);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static u32 airoha_pwm_get_period_ticks_from_ns(u64 period_ns)
|
||||
+{
|
||||
+ return div_u64(period_ns, AIROHA_PWM_PERIOD_TICK_NS);
|
||||
+}
|
||||
+
|
||||
+static u32 airoha_pwm_get_duty_ticks_from_ns(u64 period_ns, u64 duty_ns)
|
||||
+{
|
||||
+ return mul_u64_u64_div_u64(duty_ns, AIROHA_PWM_DUTY_FULL,
|
||||
+ period_ns);
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_get_bucket(struct airoha_pwm *pc, int bucket,
|
||||
+ u64 *period_ns, u64 *duty_ns)
|
||||
+{
|
||||
+ u32 period_tick, duty_tick;
|
||||
+ unsigned int offset;
|
||||
+ u32 shift, val;
|
||||
+
|
||||
+ offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
|
||||
+ shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
|
||||
+ shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift);
|
||||
+
|
||||
+ regmap_read(pc->regmap, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), &val);
|
||||
+
|
||||
+ period_tick = FIELD_GET(AIROHA_PWM_WAVE_GEN_CYCLE, val >> shift);
|
||||
+ *period_ns = period_tick * AIROHA_PWM_PERIOD_TICK_NS;
|
||||
+
|
||||
+ offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD;
|
||||
+ shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD;
|
||||
+ shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift);
|
||||
+
|
||||
+ regmap_read(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
|
||||
+ &val);
|
||||
+
|
||||
+ duty_tick = FIELD_GET(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, val >> shift);
|
||||
+ /*
|
||||
+ * Overflow can't occur in multiplication as duty_tick is just 8 bit
|
||||
+ * and period_ns is clamped to AIROHA_PWM_PERIOD_MAX_NS and fit in a
|
||||
+ * u64.
|
||||
+ */
|
||||
+ *duty_ns = DIV_U64_ROUND_UP(duty_tick * *period_ns, AIROHA_PWM_DUTY_FULL);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_get_generator(struct airoha_pwm *pc, u64 duty_ns,
|
||||
+ u64 period_ns)
|
||||
+{
|
||||
+ int i;
|
||||
+ int i, best = -ENOENT, unused = -ENOENT;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (!pc->bucket[i].used)
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->buckets); i++) {
|
||||
+ struct airoha_pwm_bucket *bucket = &pc->buckets[i];
|
||||
+ u32 duty_ticks, duty_ticks_bucket;
|
||||
+
|
||||
+ /* If found, save an unused bucket to return it later */
|
||||
+ if (!bucket->used && unused == -ENOENT) {
|
||||
+ unused = i;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (duty_ns == pc->bucket[i].duty_ns &&
|
||||
+ period_ns == pc->bucket[i].period_ns)
|
||||
+ return i;
|
||||
+ if (duty_ns == bucket->duty_ns) {
|
||||
+ /* We found a matching bucket */
|
||||
+ if (period_ns == bucket->period_ns)
|
||||
+ return i;
|
||||
+
|
||||
+ /*
|
||||
+ * Save a bucket for later that is not bigger than the
|
||||
+ * requested period_ns (to be used if we don't have
|
||||
+ * any unused bucket)
|
||||
+ */
|
||||
+ if (bucket->period_ns <= period_ns)
|
||||
+ best = i;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Unlike duty cycle zero, which can be handled by
|
||||
+ * disabling PWM, a generator is needed for full duty
|
||||
+ * cycle but it can be reused regardless of period
|
||||
+ */
|
||||
+ if (duty_ns == DUTY_FULL && pc->bucket[i].duty_ns == DUTY_FULL)
|
||||
+ duty_ticks = airoha_pwm_get_duty_ticks_from_ns(period_ns, duty_ns);
|
||||
+ duty_ticks_bucket = airoha_pwm_get_duty_ticks_from_ns(bucket->period_ns,
|
||||
+ bucket->duty_ns);
|
||||
+ if (duty_ticks == AIROHA_PWM_DUTY_FULL &&
|
||||
+ duty_ticks_bucket == AIROHA_PWM_DUTY_FULL)
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+ /* With no unused bucket, return the best one found (if ever) */
|
||||
+ return unused == -ENOENT ? best : unused;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc,
|
||||
+ unsigned int hwpwm)
|
||||
+{
|
||||
+ int i;
|
||||
+ int bucket;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++)
|
||||
+ pc->bucket[i].used &= ~BIT_ULL(hwpwm);
|
||||
+ /* Nothing to clear, PWM channel never used */
|
||||
+ if (!(pc->initialized & BIT_ULL(hwpwm)))
|
||||
+ return;
|
||||
+
|
||||
+ bucket = pc->channel_bucket[hwpwm];
|
||||
+ pc->buckets[bucket].used &= ~BIT_ULL(hwpwm);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_consume_generator(struct airoha_pwm *pc,
|
||||
+ u64 duty_ns, u64 period_ns,
|
||||
+ unsigned int hwpwm)
|
||||
+{
|
||||
+ int id = airoha_pwm_get_generator(pc, duty_ns, period_ns);
|
||||
+ int bucket;
|
||||
+
|
||||
+ if (id < 0) {
|
||||
+ int i;
|
||||
+ /*
|
||||
+ * Search for a bucket that already satisfy duty and period
|
||||
+ * or an unused one.
|
||||
+ * If not found, -ENOENT is returned.
|
||||
+ */
|
||||
+ bucket = airoha_pwm_get_generator(pc, duty_ns, period_ns);
|
||||
+ if (bucket < 0)
|
||||
+ return bucket;
|
||||
+
|
||||
+ /* find an unused waveform generator */
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (!(pc->bucket[i].used & ~BIT_ULL(hwpwm))) {
|
||||
+ id = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ airoha_pwm_release_bucket_config(pc, hwpwm);
|
||||
+ pc->buckets[bucket].used |= BIT_ULL(hwpwm);
|
||||
+ pc->buckets[bucket].period_ns = period_ns;
|
||||
+ pc->buckets[bucket].duty_ns = duty_ns;
|
||||
+
|
||||
+ if (id >= 0) {
|
||||
+ airoha_pwm_release_bucket_config(pc, hwpwm);
|
||||
+ pc->bucket[id].used |= BIT_ULL(hwpwm);
|
||||
+ pc->bucket[id].period_ns = period_ns;
|
||||
+ pc->bucket[id].duty_ns = duty_ns;
|
||||
+ }
|
||||
+
|
||||
+ return id;
|
||||
+ return bucket;
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_sipo_init(struct airoha_pwm *pc)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ if (!(pc->initialized >> PWM_NUM_GPIO))
|
||||
+ if (!(pc->initialized >> AIROHA_PWM_NUM_GPIO))
|
||||
+ return 0;
|
||||
+
|
||||
+ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_MODE_74HC164);
|
||||
+ regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
|
||||
+ AIROHA_PWM_SERIAL_GPIO_MODE_74HC164);
|
||||
+
|
||||
+ /* Configure shift register timings, use 32x divisor */
|
||||
+ regmap_write(pc->regmap, REG_SGPIO_CLK_DIVR,
|
||||
+ FIELD_PREP(REG_SGPIO_CLK_DIVR_MASK, 0x3));
|
||||
+ /* Configure shift register chip clock timings, use 32x divisor */
|
||||
+ regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DIVR,
|
||||
+ AIROHA_PWM_SGPIO_CLK_DIVR_32);
|
||||
+
|
||||
+ /*
|
||||
+ * The actual delay is clock + 1.
|
||||
+ * Notice that clock delay should not be greater
|
||||
+ * than (divisor / 2) - 1.
|
||||
+ * Set to 0 by default. (aka 1)
|
||||
+ * Configure the shift register chip clock delay. This needs
|
||||
+ * to be configured based on the chip characteristics when the SoC
|
||||
+ * apply the shift register configuration.
|
||||
+ * This doesn't affect actual PWM operation and is only specific to
|
||||
+ * the shift register chip.
|
||||
+ *
|
||||
+ * For 74HC164 we set it to 0.
|
||||
+ *
|
||||
+ * For reference, the actual delay applied is the internal clock
|
||||
+ * feed to the SGPIO chip + 1.
|
||||
+ *
|
||||
+ * From documentation is specified that clock delay should not be
|
||||
+ * greater than (AIROHA_PWM_REG_SGPIO_CLK_DIVR / 2) - 1.
|
||||
+ */
|
||||
+ regmap_write(pc->regmap, REG_SGPIO_CLK_DLY, 0x0);
|
||||
+ regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DLY, 0x0);
|
||||
+
|
||||
+ /*
|
||||
+ * It it necessary to after muxing explicitly shift out all
|
||||
+ * zeroes to initialize the shift register before enabling PWM
|
||||
+ * It is necessary to explicitly shift out all zeros after muxing
|
||||
+ * to initialize the shift register before enabling PWM
|
||||
+ * mode because in PWM mode SIPO will not start shifting until
|
||||
+ * it needs to output a non-zero value (bit 31 of led_data
|
||||
+ * indicates shifting in progress and it must return to zero
|
||||
+ * before led_data can be written or PWM mode can be set)
|
||||
+ */
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10,
|
||||
+ 200 * USEC_PER_MSEC))
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG),
|
||||
+ 10, 200 * USEC_PER_MSEC))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ regmap_clear_bits(pc->regmap, REG_SGPIO_LED_DATA, SGPIO_LED_DATA_DATA);
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10,
|
||||
+ 200 * USEC_PER_MSEC))
|
||||
+ regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA,
|
||||
+ AIROHA_PWM_SGPIO_LED_DATA_DATA);
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG),
|
||||
+ 10, 200 * USEC_PER_MSEC))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* Set SIPO in PWM mode */
|
||||
+ regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_FLASH_MODE);
|
||||
+ regmap_set_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
|
||||
+ AIROHA_PWM_SERIAL_GPIO_FLASH_MODE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_calc_bucket_config(struct airoha_pwm *pc, int index,
|
||||
+static void airoha_pwm_calc_bucket_config(struct airoha_pwm *pc, int bucket,
|
||||
+ u64 duty_ns, u64 period_ns)
|
||||
+{
|
||||
+ u32 period, duty, mask, val;
|
||||
+ u64 tmp;
|
||||
+ u32 period_ticks, duty_ticks;
|
||||
+ u32 mask, shift, val;
|
||||
+ u64 offset;
|
||||
+
|
||||
+ tmp = duty_ns * DUTY_FULL;
|
||||
+ duty = clamp_val(div64_u64(tmp, period_ns), 0, DUTY_FULL);
|
||||
+ tmp = period_ns * 25;
|
||||
+ period = clamp_val(div64_u64(tmp, 100000000), PERIOD_MIN, PERIOD_MAX);
|
||||
+ period_ticks = airoha_pwm_get_period_ticks_from_ns(period_ns);
|
||||
+ duty_ticks = airoha_pwm_get_duty_ticks_from_ns(period_ns, duty_ns);
|
||||
+
|
||||
+ offset = bucket;
|
||||
+ shift = do_div(offset, AIROHA_PWM_BUCKET_PER_CYCLE_CFG);
|
||||
+ shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift);
|
||||
+
|
||||
+ /* Configure frequency divisor */
|
||||
+ mask = WAVE_GEN_CYCLE_MASK(index % 4);
|
||||
+ val = (period << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, REG_CYCLE_CFG_VALUE(index / 4),
|
||||
+ mask, val);
|
||||
+ mask = AIROHA_PWM_WAVE_GEN_CYCLE << shift;
|
||||
+ val = FIELD_PREP(AIROHA_PWM_WAVE_GEN_CYCLE, period_ticks) << shift;
|
||||
+ regmap_update_bits(pc->regmap, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), mask, val);
|
||||
+
|
||||
+ offset = bucket;
|
||||
+ shift = do_div(offset, AIROHA_PWM_BUCKET_PER_FLASH_PROD);
|
||||
+ shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift);
|
||||
+
|
||||
+ /* Configure duty cycle */
|
||||
+ duty = ((DUTY_FULL - duty) << 8) | duty;
|
||||
+ mask = GPIO_FLASH_PRD_MASK(index % 2);
|
||||
+ val = (duty << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, REG_GPIO_FLASH_PRD_SET(index / 2),
|
||||
+ mask = AIROHA_PWM_GPIO_FLASH_PRD_HIGH << shift;
|
||||
+ val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, duty_ticks) << shift;
|
||||
+ regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
|
||||
+ mask, val);
|
||||
+
|
||||
+ mask = AIROHA_PWM_GPIO_FLASH_PRD_LOW << shift;
|
||||
+ val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_LOW,
|
||||
+ AIROHA_PWM_DUTY_FULL - duty_ticks) << shift;
|
||||
+ regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
|
||||
+ mask, val);
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_config_flash_map(struct airoha_pwm *pc,
|
||||
+ unsigned int hwpwm, int index)
|
||||
+{
|
||||
+ u32 addr, mask, val;
|
||||
+ unsigned int addr;
|
||||
+ u32 shift;
|
||||
+
|
||||
+ if (hwpwm < PWM_NUM_GPIO) {
|
||||
+ addr = REG_GPIO_FLASH_MAP(hwpwm / 8);
|
||||
+ } else {
|
||||
+ addr = REG_SIPO_FLASH_MAP(hwpwm / 8);
|
||||
+ hwpwm -= PWM_NUM_GPIO;
|
||||
+ }
|
||||
+ airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift);
|
||||
+
|
||||
+ /* index -1 means disable PWM channel */
|
||||
+ if (index < 0) {
|
||||
+ /*
|
||||
+ * Change of waveform takes effect immediately but
|
||||
+ * disabling has some delay so to prevent glitching
|
||||
+ * only the enable bit is touched when disabling
|
||||
+ * If we need to disable the PWM, we just put low the
|
||||
+ * GPIO. No need to setup buckets.
|
||||
+ */
|
||||
+ regmap_clear_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8));
|
||||
+ regmap_clear_bits(pc->regmap, addr,
|
||||
+ AIROHA_PWM_GPIO_FLASH_EN << shift);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ mask = GPIO_FLASH_SETID_MASK(hwpwm % 8);
|
||||
+ val = ((index & 7) << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, addr, mask, val);
|
||||
+ regmap_set_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8));
|
||||
+ regmap_update_bits(pc->regmap, addr,
|
||||
+ AIROHA_PWM_GPIO_FLASH_SET_ID << shift,
|
||||
+ FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID, index) << shift);
|
||||
+ regmap_set_bits(pc->regmap, addr, AIROHA_PWM_GPIO_FLASH_EN << shift);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm,
|
||||
+ u64 duty_ns, u64 period_ns)
|
||||
+{
|
||||
+ int index = -1;
|
||||
+ unsigned int hwpwm = pwm->hwpwm;
|
||||
+ int bucket;
|
||||
+
|
||||
+ index = airoha_pwm_consume_generator(pc, duty_ns, period_ns,
|
||||
+ pwm->hwpwm);
|
||||
+ if (index < 0)
|
||||
+ bucket = airoha_pwm_consume_generator(pc, duty_ns, period_ns,
|
||||
+ hwpwm);
|
||||
+ if (bucket < 0)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ if (!(pc->initialized & BIT_ULL(pwm->hwpwm)) &&
|
||||
+ pwm->hwpwm >= PWM_NUM_GPIO)
|
||||
+ airoha_pwm_calc_bucket_config(pc, bucket, duty_ns, period_ns);
|
||||
+ airoha_pwm_config_flash_map(pc, hwpwm, bucket);
|
||||
+
|
||||
+ pc->initialized |= BIT_ULL(hwpwm);
|
||||
+ pc->channel_bucket[hwpwm] = bucket;
|
||||
+
|
||||
+ /*
|
||||
+ * SIPO are special GPIO attached to a shift register chip. The handling
|
||||
+ * of this chip is internal to the SoC that takes care of applying the
|
||||
+ * values based on the flash map. To apply a new flash map, it's needed
|
||||
+ * to trigger a refresh on the shift register chip.
|
||||
+ * If we are configuring a SIPO, always reinit the shift register chip
|
||||
+ * to make sure the correct flash map is applied.
|
||||
+ * We skip reconfiguring the shift register if we related hwpwm
|
||||
+ * is disabled (as it doesn't need to be mapped).
|
||||
+ */
|
||||
+ if (!(pc->initialized & BIT_ULL(hwpwm)) && hwpwm >= AIROHA_PWM_NUM_GPIO)
|
||||
+ airoha_pwm_sipo_init(pc);
|
||||
+
|
||||
+ if (index >= 0) {
|
||||
+ airoha_pwm_calc_bucket_config(pc, index, duty_ns, period_ns);
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, index);
|
||||
+ } else {
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, index);
|
||||
+ airoha_pwm_release_bucket_config(pc, pwm->hwpwm);
|
||||
+ }
|
||||
+
|
||||
+ pc->initialized |= BIT_ULL(pwm->hwpwm);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+static void airoha_pwm_disable(struct airoha_pwm *pc, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
|
||||
+
|
||||
+ /* Disable PWM and release the waveform */
|
||||
+ /* Disable PWM and release the bucket */
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1);
|
||||
+ airoha_pwm_release_bucket_config(pc, pwm->hwpwm);
|
||||
+
|
||||
+ pc->initialized &= ~BIT_ULL(pwm->hwpwm);
|
||||
+ if (!(pc->initialized >> PWM_NUM_GPIO))
|
||||
+ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_FLASH_MODE);
|
||||
+
|
||||
+ /* If no SIPO is used, disable the shift register chip */
|
||||
+ if (!(pc->initialized >> AIROHA_PWM_NUM_GPIO))
|
||||
+ regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
|
||||
+ AIROHA_PWM_SERIAL_GPIO_FLASH_MODE);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ const struct pwm_state *state)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
|
||||
+ u64 duty = state->enabled ? state->duty_cycle : 0;
|
||||
+ u64 period = state->period;
|
||||
+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
|
||||
+ u64 duty_ns = state->duty_cycle;
|
||||
+ u64 period_ns = state->period;
|
||||
+
|
||||
+ /* Only normal polarity is supported */
|
||||
+ if (state->polarity == PWM_POLARITY_INVERSED)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!state->enabled) {
|
||||
+ airoha_pwm_disable(chip, pwm);
|
||||
+ airoha_pwm_disable(pc, pwm);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (period < PERIOD_MIN_NS)
|
||||
+ /* Exit early if period is less than minimum supported */
|
||||
+ if (period_ns < AIROHA_PWM_PERIOD_TICK_NS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (period > PERIOD_MAX_NS)
|
||||
+ period = PERIOD_MAX_NS;
|
||||
+ /*
|
||||
+ * Period goes at 4ns step, normalize it to check if we can
|
||||
+ * share a generator.
|
||||
+ */
|
||||
+ period_ns = rounddown(period_ns, AIROHA_PWM_PERIOD_TICK_NS);
|
||||
+
|
||||
+ return airoha_pwm_config(pc, pwm, duty, period);
|
||||
+ /* Clamp period to MAX supported value */
|
||||
+ if (period_ns > AIROHA_PWM_PERIOD_MAX_NS) {
|
||||
+ period_ns = AIROHA_PWM_PERIOD_MAX_NS;
|
||||
+
|
||||
+ if (duty_ns > period_ns)
|
||||
+ duty_ns = period_ns;
|
||||
+ }
|
||||
+
|
||||
+ return airoha_pwm_config(pc, pwm, duty_ns, period_ns);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ struct pwm_state *state)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
|
||||
+ int i;
|
||||
+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
|
||||
+ int ret, hwpwm = pwm->hwpwm;
|
||||
+ u32 addr, shift, val;
|
||||
+ u8 bucket;
|
||||
+
|
||||
+ /* find hwpwm in waveform generator bucket */
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (pc->bucket[i].used & BIT_ULL(pwm->hwpwm)) {
|
||||
+ state->enabled = pc->initialized & BIT_ULL(pwm->hwpwm);
|
||||
+ state->polarity = PWM_POLARITY_NORMAL;
|
||||
+ state->period = pc->bucket[i].period_ns;
|
||||
+ state->duty_cycle = pc->bucket[i].duty_ns;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift);
|
||||
+
|
||||
+ if (i == ARRAY_SIZE(pc->bucket))
|
||||
+ state->enabled = false;
|
||||
+ ret = regmap_read(pc->regmap, addr, &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ state->enabled = FIELD_GET(AIROHA_PWM_GPIO_FLASH_EN, val >> shift);
|
||||
+ if (!state->enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ state->polarity = PWM_POLARITY_NORMAL;
|
||||
+
|
||||
+ bucket = FIELD_GET(AIROHA_PWM_GPIO_FLASH_SET_ID, val >> shift);
|
||||
+ airoha_pwm_get_bucket(pc, bucket, &state->period,
|
||||
+ &state->duty_cycle);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops airoha_pwm_ops = {
|
||||
+ .get_state = airoha_pwm_get_state,
|
||||
+ .apply = airoha_pwm_apply,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .get_state = airoha_pwm_get_state,
|
||||
+};
|
||||
+
|
||||
+static int airoha_pwm_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct airoha_pwm *pc;
|
||||
+ struct pwm_chip *chip;
|
||||
+ int ret;
|
||||
+
|
||||
+ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
|
||||
+ if (!pc)
|
||||
+ return -ENOMEM;
|
||||
+ chip = devm_pwmchip_alloc(dev, AIROHA_PWM_MAX_CHANNELS, sizeof(*pc));
|
||||
+ if (IS_ERR(chip))
|
||||
+ return PTR_ERR(chip);
|
||||
+
|
||||
+ pc->np = dev->of_node;
|
||||
+ pc->chip.dev = dev;
|
||||
+ pc->chip.ops = &airoha_pwm_ops;
|
||||
+ pc->chip.npwm = PWM_NUM_GPIO + PWM_NUM_SIPO;
|
||||
+ chip->ops = &airoha_pwm_ops;
|
||||
+ pc = pwmchip_get_drvdata(chip);
|
||||
+
|
||||
+ pc->regmap = device_node_to_regmap(dev->parent->of_node);
|
||||
+ if (IS_ERR(pc->regmap))
|
||||
+ return PTR_ERR(pc->regmap);
|
||||
+ return dev_err_probe(dev, PTR_ERR(pc->regmap), "Failed to get PWM regmap\n");
|
||||
+
|
||||
+ return devm_pwmchip_add(&pdev->dev, &pc->chip);
|
||||
+ ret = devm_pwmchip_add(&pdev->dev, chip);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_pwm_of_match[] = {
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
From 38d2c6aafc5bbcad3ec36f6d3356b3debd40f6fd Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Wed, 16 Oct 2024 20:26:05 +0200
|
||||
Subject: [RFC PATCH v2 1/3] spinlock: extend guard with spinlock_bh variants
|
||||
|
||||
Extend guard APIs with missing raw/spinlock_bh variants.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
include/linux/spinlock.h | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
--- a/include/linux/spinlock.h
|
||||
+++ b/include/linux/spinlock.h
|
||||
@@ -519,6 +519,10 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_irq, ra
|
||||
|
||||
DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->lock))
|
||||
|
||||
+DEFINE_LOCK_GUARD_1(raw_spinlock_bh, raw_spinlock_t,
|
||||
+ raw_spin_lock_bh(_T->lock),
|
||||
+ raw_spin_unlock_bh(_T->lock))
|
||||
+
|
||||
DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t,
|
||||
raw_spin_lock_irqsave(_T->lock, _T->flags),
|
||||
raw_spin_unlock_irqrestore(_T->lock, _T->flags),
|
||||
@@ -540,6 +544,10 @@ DEFINE_LOCK_GUARD_1(spinlock_irq, spinlo
|
||||
DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try,
|
||||
spin_trylock_irq(_T->lock))
|
||||
|
||||
+DEFINE_LOCK_GUARD_1(spinlock_bh, spinlock_t,
|
||||
+ spin_lock_bh(_T->lock),
|
||||
+ spin_unlock_bh(_T->lock))
|
||||
+
|
||||
DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t,
|
||||
spin_lock_irqsave(_T->lock, _T->flags),
|
||||
spin_unlock_irqrestore(_T->lock, _T->flags),
|
||||
Loading…
Reference in New Issue
Block a user